Salome HOME
a693d44fefb490acd14802484c14843e7321ba24
[modules/gui.git] / src / VTKViewer / VTKViewer_MarkerWidget.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "VTKViewer_MarkerWidget.h"
21 #include "VTKViewer_MarkerUtils.h"
22
23 #include <SUIT_ResourceMgr.h>
24 #include <SUIT_Session.h>
25
26 #include <vtkImageData.h>
27
28 #include <QComboBox>
29 #include <QHBoxLayout>
30 #include <QLabel>
31 #include <QSpinBox>
32
33 const int SPACING = 6;
34 enum { TypeRole = Qt::UserRole, IdRole };
35
36 /*!
37   \class VTKViewer_MarkerWidget
38   \brief Widget for specifying point marker parameters
39 */
40
41 /*!
42   \brief Constructor
43   \param parent parent widget
44 */
45 VTKViewer_MarkerWidget::VTKViewer_MarkerWidget( QWidget* parent )
46   : QWidget( parent ), myCurrentIdx( -1 )
47 {
48   // create widgets
49   myTypeLab  = new QLabel( tr( "TYPE" ),  this );
50   myScaleLab = new QLabel( tr( "SCALE" ), this );
51   myType     = new QComboBox( this );
52   myScale    = new QSpinBox( this );
53   // layouting
54   QHBoxLayout* ml = new QHBoxLayout( this );
55   ml->setMargin( 0 );
56   ml->setSpacing( SPACING );
57   ml->addWidget( myTypeLab );
58   ml->addWidget( myType );
59   ml->addWidget( myScaleLab );
60   ml->addWidget( myScale );
61   myType->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
62   myScale->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
63   // connect signals/slots
64   connect( myType, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onTypeChanged( int ) ) );
65   // initialize
66   init();
67 }
68
69 /*!
70   \brief Destructor
71 */
72 VTKViewer_MarkerWidget::~VTKViewer_MarkerWidget()
73 {
74 }
75
76 /*!
77   \brief Set custom markers data
78   \param markerMap custom marker data (a map {index:texture})
79 */
80 void VTKViewer_MarkerWidget::setCustomMarkers( const VTK::MarkerMap& markerMap )
81 {
82   // store custom markers data
83   myCustomMarkers = markerMap;
84   // clear current custom markers
85   for ( int i = myType->count()-1; i >= 0; i-- ) {
86     int type = myType->itemData( i, TypeRole ).toInt();
87     if ( type == VTK::MT_USER )
88       myType->removeItem( i );
89   }
90   // add custom markers
91   VTK::MarkerMap::const_iterator it;
92   for ( it = myCustomMarkers.begin(); it != myCustomMarkers.end(); ++it )
93   {
94     int id = it->first;
95     VTK::MarkerData markerData = it->second;
96     QPixmap icon = markerFromData( markerData );
97     if( !icon.isNull() )
98     {
99       int idx = myType->count()-1;
100       myType->insertItem( idx, icon, QString() );
101       myType->setItemData( idx, VTK::MT_USER, TypeRole );
102       myType->setItemData( idx, id, IdRole );
103     }
104   }
105 }
106
107 /*!
108   \brief Get custom markers data
109   \return custom marker data
110 */
111 VTK::MarkerMap VTKViewer_MarkerWidget::customMarkers() const
112 {
113   return myCustomMarkers;
114 }
115
116 /*!
117   \brief Add standard marker
118   The marker type specified with \a type must be > VTK::MT_USER
119   \param type marker type
120   \param icon marker icon
121 */
122 void VTKViewer_MarkerWidget::addMarker( VTK::MarkerType type, const QPixmap& icon )
123 {
124   if ( type > VTK::MT_USER ) {
125     int idx = (int)VTK::MT_USER - 1;
126     // find insertion index
127     while ( idx < myType->count()-1 ) {
128       if ( myType->itemData( idx, TypeRole ) == VTK::MT_USER )
129         break;
130       ++idx;
131     }
132     myType->insertItem( idx, icon, QString() );
133     myType->setItemData( idx, type, TypeRole );
134   }
135 }
136
137 /*!
138   \brief Select specified standard marker as current one
139   \param type marker type
140   \param scale marker scale (optional parameter; can be omitted for extended markers)
141 */
142 void VTKViewer_MarkerWidget::setMarker( VTK::MarkerType type, VTK::MarkerScale scale )
143 {
144   if ( type != VTK::MT_USER ) {
145     for ( int i = 0; i < myType->count()-1; i++ ) {
146       if ( type == myType->itemData( i, TypeRole ).toInt() ) {
147         myType->setCurrentIndex( i );
148         break;
149       }
150     }
151   }
152   if ( scale != VTK::MS_NONE )
153     myScale->setValue( qMax( (int)VTK::MS_10, qMin( (int)VTK::MS_70, (int)scale ) ) );
154 }
155
156 /*!
157   \brief Select specified custom marker as current one
158   \param id custom marker identifier
159 */
160 void VTKViewer_MarkerWidget::setCustomMarker( int id )
161 {
162   for ( int i = 0; i < myType->count()-1; i++ ) {
163     int type = myType->itemData( i, TypeRole ).toInt();
164     if ( type == VTK::MT_USER && id == myType->itemData( i, IdRole ).toInt() ) {
165       myType->setCurrentIndex( i );
166       break;
167     }
168   }
169 }
170
171 /*!
172   \brief Get current marker's type.
173   For custom marker, VTK::MT_USER is returned and markerId() function 
174   then returns its identifier.
175   \return currently selected marker type
176 */
177 VTK::MarkerType VTKViewer_MarkerWidget::markerType() const
178 {
179   return myType->itemData( myType->currentIndex(), TypeRole ).toInt();
180 }
181
182 /*!
183   \brief Get current marker's scale size.
184   For custom marker return value is undefined.
185   \return currently selected marker scale size
186 */
187 VTK::MarkerScale VTKViewer_MarkerWidget::markerScale() const
188 {
189   return myScale->value();
190 }
191
192 /*!
193   \bried Get currently selected custom marker's identifier.
194   For standard markers return value is VTK::MT_NONE.
195 */
196 int VTKViewer_MarkerWidget::markerId() const
197 {
198   int type = myType->itemData( myType->currentIndex(), TypeRole ).toInt();
199   return type == VTK::MT_USER ? myType->itemData( myType->currentIndex(), IdRole ).toInt() : VTK::MT_NONE;
200 }
201
202 /*!
203   \brief Get access to the internal marker type label
204   \return marker type label widget
205 */
206 QLabel* VTKViewer_MarkerWidget::typeLabel()
207 {
208   return myTypeLab;
209 }
210
211 /*!
212   \brief Get access to the internal marker scale label
213   \return marker scale label widget
214 */
215 QLabel* VTKViewer_MarkerWidget::scaleLabel()
216 {
217   return myScaleLab;
218 }
219
220 /*!
221   \brief Internal initialization
222 */
223 void VTKViewer_MarkerWidget::init()
224 {
225   myType->blockSignals( true );
226
227   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
228   // standard marker types
229   for ( int type = VTK::MT_POINT; type < VTK::MT_USER; type++ ) {
230     QString icoFile = QString( "ICON_VERTEX_MARKER_%1" ).arg( type );
231     QPixmap pixmap = resMgr->loadPixmap( "VTKViewer", tr( qPrintable( icoFile ) ) );
232     myType->addItem( pixmap, QString() );
233     myType->setItemData( myType->count()-1, type, TypeRole );
234   }
235   // standard marker sizes
236   myScale->setMinimum( (int)VTK::MS_10 );
237   myScale->setMaximum( (int)VTK::MS_70 );
238   // add item for loading custom textures
239   myType->addItem( "..." );
240   myType->setItemData( myType->count()-1, VTK::MT_NONE, TypeRole );
241
242   myType->blockSignals( false );
243
244   // set current item to first type in the list
245   myType->setCurrentIndex( 0 );
246 }
247
248 /*!
249   \brief Create icon from the custom marker data (texture)
250   \param markerData custom marker data
251   \return icon generated from texture specified with marker data
252 */
253 QPixmap VTKViewer_MarkerWidget::markerFromData( const VTK::MarkerData& markerData )
254 {
255   // get texture data
256   const VTK::MarkerTexture& texture = markerData.second;
257   // generate VTK image
258   vtkSmartPointer<vtkImageData> image = VTK::MakeVTKImage( texture, false );
259   // convert VTK image to icon
260   QImage qimage = VTK::ConvertToQImage( image.GetPointer() );
261   return qimage.isNull() ? QPixmap() : QPixmap::fromImage( qimage );
262 }
263
264 /*!
265   \brief Called when marker type is changed (by the user or programmatically)
266   \param index index of item being selected
267 */
268 void VTKViewer_MarkerWidget::onTypeChanged( int index )
269 {
270   if ( index == myType->count()-1 ) {
271     // browse new custom texture file item is selected
272     QStringList filters;
273     filters << tr( "Texture files (*.dat)" ) << tr( "All files (*)" );
274     QString fileName = SUIT_Session::session()->activeApplication()->getFileName( true, 
275                                                                                   QString(), 
276                                                                                   filters.join( ";;" ), 
277                                                                                   tr( "LOAD_TEXTURE_TLT" ), 
278                                                                                   parentWidget() );
279     if ( !fileName.isEmpty() ) {
280       // load texture and add new marker
281       VTK::MarkerTexture texture;
282       if ( VTK::LoadTextureData( fileName, VTK::MS_NONE, texture ) ) {
283         int id = VTK::GetUniqueId( myCustomMarkers );
284         VTK::MarkerData& markerData = myCustomMarkers[ id ];
285         markerData.first  = fileName.toStdString();
286         markerData.second = texture;
287         QPixmap icon = markerFromData( markerData );
288         if( !icon.isNull() ) {
289           int idx = myType->count()-1;
290           myType->blockSignals( true );
291           myType->insertItem( idx, icon, QString() );
292           myType->blockSignals( false );
293           myType->setItemData( idx, VTK::MT_USER, TypeRole );
294           myType->setItemData( idx, id, IdRole );
295           myType->setCurrentIndex( idx );
296           return;
297         }
298       }
299     }
300     // if user cancelled texture loading or there was an error when loading texture
301     // reset to the previous item
302     myType->setCurrentIndex( myCurrentIdx );
303     return;
304   }
305   else {
306     myCurrentIdx = index;
307   }
308   int type = myType->itemData( index, TypeRole ).toInt();
309   myScale->setEnabled( type < VTK::MT_USER );
310   myScaleLab->setEnabled( type < VTK::MT_USER );
311 }