Salome HOME
4ff6bcec0be9eeae7e24f39fc3f927819bc3527d
[modules/geom.git] / src / GEOMToolsGUI / GEOMToolsGUI_MarkerDlg.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 // File   : GEOMToolsGUI_MarkerDlg.cxx
21 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
22
23 #include "GEOMToolsGUI_MarkerDlg.h"
24
25 #include <GeometryGUI.h>
26 #include <GEOM_Constants.h>
27 #include <GEOM_Displayer.h>
28
29 #include <QtxComboBox.h>
30 #include <SUIT_ResourceMgr.h>
31 #include <SUIT_Session.h>
32 #include <SUIT_ViewWindow.h>
33 #include <SUIT_Desktop.h>
34 #include <SUIT_ViewManager.h>
35 #include <LightApp_SelectionMgr.h>
36 #include <SalomeApp_Application.h>
37 #include <SalomeApp_Study.h>
38 #include <SALOME_ListIO.hxx>
39
40 #include <QButtonGroup>
41 #include <QGridLayout>
42 #include <QHBoxLayout>
43 #include <QKeyEvent>
44 #include <QLabel>
45 #include <QPushButton>
46 #include <QRadioButton>
47 #include <QStackedWidget>
48
49 #define MARGIN  9
50 #define SPACING 6
51
52 GEOMToolsGUI_MarkerDlg::GEOMToolsGUI_MarkerDlg( QWidget* parent )
53   : QDialog ( parent )
54 {
55   setWindowTitle( tr( "SET_MARKER_TLT" ) );
56   setSizeGripEnabled( true );
57   setModal( true );
58
59   // ---
60
61   QRadioButton* aStandardTypeRB = new QRadioButton( tr( "STANDARD_MARKER" ), this );
62   QRadioButton* aCustomTypeRB   = new QRadioButton( tr( "CUSTOM_MARKER" ), this );
63   myTypeGroup = new QButtonGroup( this );
64   myTypeGroup->addButton( aStandardTypeRB, 0 );
65   myTypeGroup->addButton( aCustomTypeRB,   1 );
66
67   QHBoxLayout* aRadioLayout = new QHBoxLayout;
68   aRadioLayout->setMargin( 0 );
69   aRadioLayout->setSpacing( SPACING );
70   aRadioLayout->addWidget( aStandardTypeRB );
71   aRadioLayout->addWidget( aCustomTypeRB );
72
73   // ---
74
75   myWGStack = new QStackedWidget( this );
76   myWGStack->setFrameStyle( QFrame::Box | QFrame::Sunken );
77
78   // ---
79
80   QWidget* aStdWidget = new QWidget( myWGStack );
81
82   QLabel* aTypeLab  = new QLabel( tr( "TYPE" ),  aStdWidget );
83   QLabel* aScaleLab = new QLabel( tr( "SCALE" ), aStdWidget );
84
85   myStdTypeCombo  = new QtxComboBox( aStdWidget );
86   myStdScaleCombo = new QtxComboBox( aStdWidget );
87
88   QGridLayout* aStdLayout = new QGridLayout;
89   aStdLayout->setMargin( MARGIN );
90   aStdLayout->setSpacing( SPACING );
91   aStdLayout->addWidget( aTypeLab,        0, 0 );
92   aStdLayout->addWidget( myStdTypeCombo,  0, 1 );
93   aStdLayout->addWidget( aScaleLab,       1, 0 );
94   aStdLayout->addWidget( myStdScaleCombo, 1, 1 );
95   aStdWidget->setLayout( aStdLayout );
96
97   // ---
98
99   QWidget* aCustomWidget = new QWidget( myWGStack );
100
101   QLabel* aCustomLab = new QLabel( tr( "CUSTOM" ), aCustomWidget );
102   myCustomTypeCombo = new QtxComboBox( aCustomWidget );
103   QPushButton* aBrowseBtn = new QPushButton( tr( "BROWSE" ), aCustomWidget );
104
105   QGridLayout* aCustomLayout = new QGridLayout;
106   aCustomLayout->setMargin( MARGIN );
107   aCustomLayout->setSpacing( SPACING );
108   aCustomLayout->addWidget( aCustomLab,        0, 0 );
109   aCustomLayout->addWidget( myCustomTypeCombo, 0, 1 );
110   aCustomLayout->addWidget( aBrowseBtn,       0, 2 );
111   aCustomLayout->setRowStretch( 1, 5 );
112   aCustomWidget->setLayout( aCustomLayout );
113
114   // ---
115   
116   myWGStack->insertWidget( 0, aStdWidget );
117   myWGStack->insertWidget( 1, aCustomWidget );
118
119   // ---
120   
121   QPushButton* aOkBtn     = new QPushButton( tr( "OK_BTN" ),     this );
122   aOkBtn->setAutoDefault( true ); aOkBtn->setDefault( true ); 
123   QPushButton* aCancelBtn = new QPushButton( tr( "CANCEL_BTN" ), this );
124   aCancelBtn->setAutoDefault( true );
125   QPushButton* aHelpBtn   = new QPushButton( tr( "HELP_BTN" ), this );
126   aHelpBtn->setAutoDefault( true );
127
128   QHBoxLayout* aBtnLayout = new QHBoxLayout;
129   aBtnLayout->setMargin( 0 );
130   aBtnLayout->setSpacing( SPACING );
131   aBtnLayout->addWidget( aOkBtn );
132   aBtnLayout->addSpacing( 10 );
133   aBtnLayout->addStretch();
134   aBtnLayout->addWidget( aCancelBtn );
135   aBtnLayout->addWidget( aHelpBtn );
136
137   // ---
138
139   QVBoxLayout* aTopLayout = new QVBoxLayout;
140   aTopLayout->setMargin( MARGIN );
141   aTopLayout->setSpacing( SPACING );
142   aTopLayout->addLayout( aRadioLayout );
143   aTopLayout->addWidget( myWGStack );
144   aTopLayout->addLayout( aBtnLayout );
145   setLayout( aTopLayout );
146
147   // ---
148
149   connect( myTypeGroup, SIGNAL( buttonClicked( int ) ), myWGStack, SLOT( setCurrentIndex( int ) ) );
150   connect( aBrowseBtn,  SIGNAL( clicked() ), this, SLOT( browse() ) );
151   connect( aOkBtn,      SIGNAL( clicked() ), this, SLOT( accept() ) );
152   connect( aCancelBtn,  SIGNAL( clicked() ), this, SLOT( reject() ) );
153   connect( aHelpBtn,    SIGNAL( clicked() ), this, SLOT( help() ) );
154
155   // ---
156
157   aStandardTypeRB->setChecked( true );
158   init();
159 }
160
161 GEOMToolsGUI_MarkerDlg::~GEOMToolsGUI_MarkerDlg()
162 {
163   myOperation->UnRegister();
164 }
165
166 void GEOMToolsGUI_MarkerDlg::setStandardMarker( GEOM::marker_type type, GEOM::marker_size size )
167 {
168   if ( type > GEOM::MT_NONE && type < GEOM::MT_USER ) {
169     myTypeGroup->button( 0 )->setChecked( true );
170     myWGStack->setCurrentIndex( 0 );
171     myStdTypeCombo->setCurrentId( (int)type );
172     int asize = std::max( (int)GEOM::MS_10, std::min( (int)GEOM::MS_70, (int)size ) );
173     myStdScaleCombo->setCurrentId( asize );
174   }
175 }
176
177 void GEOMToolsGUI_MarkerDlg::setCustomMarker( int id )
178 {
179   if ( id > 0 ) {
180     myTypeGroup->button( 1 )->setChecked( true );
181     myWGStack->setCurrentIndex( 1 );
182     addTexture( id );
183     myCustomTypeCombo->setCurrentId( id );
184   }
185 }
186
187 GEOM::marker_type GEOMToolsGUI_MarkerDlg::getMarkerType() const
188 {
189   return myWGStack->currentIndex() == 0 ? (GEOM::marker_type)myStdTypeCombo->currentId().toInt() : GEOM::MT_USER;
190 }
191
192 GEOM::marker_size GEOMToolsGUI_MarkerDlg::getStandardMarkerScale() const
193 {
194   return myWGStack->currentIndex() == 0 ? (GEOM::marker_size)myStdScaleCombo->currentId().toInt() : GEOM::MS_NONE;
195 }
196
197 int GEOMToolsGUI_MarkerDlg::getCustomMarkerID() const
198 {
199   return myWGStack->currentIndex() == 1 ? myCustomTypeCombo->currentId().toInt() : 0;
200 }
201
202 void GEOMToolsGUI_MarkerDlg::accept()
203 {
204   if ( getStudy() ) {
205     LightApp_SelectionMgr* selMgr = qobject_cast<SalomeApp_Application*>( getStudy()->application() )->selectionMgr();
206     
207     SUIT_ViewWindow* window =  getStudy()->application()->desktop()->activeWindow();
208     if (window && window->getViewManager()) {
209       int mgrId = window->getViewManager()->getGlobalId();
210       if ( selMgr ) {
211         SALOME_ListIO selected;
212         selMgr->selectedObjects( selected );
213         if ( !selected.IsEmpty() ) {
214           _PTR(Study) study = getStudy()->studyDS();
215           for ( SALOME_ListIteratorOfListIO it( selected ); it.More(); it.Next() ) {
216             _PTR(SObject) aSObject( study->FindObjectID( it.Value()->getEntry() ) );
217             GEOM::GEOM_Object_var anObject =
218               GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject( aSObject ) );
219             if ( myWGStack->currentIndex() == 0 ) {
220               if ( !anObject->_is_nil() && GeometryGUI::IsInGeomComponent( aSObject )) {
221                 anObject->SetMarkerStd( getMarkerType(), getStandardMarkerScale() );
222               }
223               QString aMarker = "%1%2%3";
224               aMarker = aMarker.arg(getMarkerType());
225               aMarker = aMarker.arg(GEOM::subSectionSeparator());
226               aMarker = aMarker.arg(getStandardMarkerScale());
227               getStudy()->setObjectProperty(mgrId ,it.Value()->getEntry(),GEOM::propertyName( GEOM::PointMarker ), aMarker);
228             }
229             else if ( getCustomMarkerID() > 0 ) {
230               if ( !anObject->_is_nil() && GeometryGUI::IsInGeomComponent( aSObject )) {
231                 anObject->SetMarkerTexture( getCustomMarkerID() );
232               }
233               getStudy()->setObjectProperty(mgrId ,it.Value()->getEntry(),GEOM::propertyName( GEOM::PointMarker ), QString::number(getCustomMarkerID()));
234             }
235           }
236           GEOM_Displayer displayer;
237           displayer.Redisplay( selected, true );
238           selMgr->setSelectedObjects( selected );
239         }
240       }
241     }
242   }
243   QDialog::accept();
244 }
245
246 void GEOMToolsGUI_MarkerDlg::keyPressEvent( QKeyEvent* e )
247 {
248   if ( e->key() == Qt::Key_F1 )
249     help();
250   QDialog::keyPressEvent( e );
251 }
252
253 void GEOMToolsGUI_MarkerDlg::init()
254 {
255   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
256
257   // ---
258
259   for ( int i = GEOM::MT_POINT; i < GEOM::MT_USER; i++ ) {
260     QString icoFile = QString( "ICON_VERTEX_MARKER_%1" ).arg( i );
261     QPixmap pixmap = resMgr->loadPixmap( "GEOM", tr( qPrintable( icoFile ) ) );
262     myStdTypeCombo->addItem( pixmap, QString() );
263     myStdTypeCombo->setId( myStdTypeCombo->count()-1, i );
264   }
265
266   // ---
267
268   for ( int i = GEOM::MS_10; i <= GEOM::MS_70; i++ ) {
269     myStdScaleCombo->addItem( QString::number( (i-1)*0.5 + 1.0 ) );
270     myStdScaleCombo->setId( myStdScaleCombo->count()-1, i );
271   }
272
273   // ---
274   
275   GEOM::GEOM_Gen_var engine = GeometryGUI::GetGeomGen();
276   myOperation = engine->GetIInsertOperations();
277   GEOM::ListOfLong_var ids = myOperation->GetAllTextures();
278   for ( int i = 0; i < (int)ids->length(); i++ )
279     addTexture( ids[i] );
280
281   // ---
282
283   GEOM::marker_type aType    = (GEOM::marker_type)-1;
284   GEOM::marker_size aSize    = (GEOM::marker_size)-1;
285   int               aTexture = 0;
286   if ( getStudy() ) {
287     LightApp_SelectionMgr* selMgr = qobject_cast<SalomeApp_Application*>( getStudy()->application() )->selectionMgr();
288     if ( selMgr ) {
289       SALOME_ListIO selected;
290       selMgr->selectedObjects( selected );
291       if ( !selected.IsEmpty() ) {
292         _PTR(Study) study = getStudy()->studyDS();
293         for ( SALOME_ListIteratorOfListIO it( selected ); it.More(); it.Next() ) {
294           _PTR(SObject) aSObject( study->FindObjectID( it.Value()->getEntry() ) );
295           GEOM::GEOM_Object_var anObject =
296             GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject( aSObject ) );
297           if ( !anObject->_is_nil() && GeometryGUI::IsInGeomComponent( aSObject )) {
298             GEOM::marker_type mtype = anObject->GetMarkerType();
299
300             if ( aType == -1 )
301               aType = mtype;
302             else if ( aType != mtype ) {
303               aType = (GEOM::marker_type)-1;
304               break;
305             }
306             if ( mtype > GEOM::MT_NONE && mtype < GEOM::MT_USER ) {
307               GEOM::marker_size msize = anObject->GetMarkerSize();
308               if ( aSize == -1 )
309                 aSize = msize;
310               else if ( aSize != msize )
311                 break;
312             }
313             else if ( mtype == GEOM::MT_USER ) {
314               int mtexture = anObject->GetMarkerTexture();
315               if ( aTexture == 0 )
316                 aTexture = mtexture;
317               else if ( aTexture != mtexture )
318                 break;
319             }
320           }
321           else {
322             // try study object properties
323             QStringList aMarkerProp;
324             SUIT_ViewWindow* window = getStudy()->application()->desktop()->activeWindow();
325             if (window && window->getViewManager()) {
326               int mgrId = window->getViewManager()->getGlobalId();
327               PropMap aPropMap = getStudy()->getObjectProperties(mgrId, it.Value()->getEntry());
328               aMarkerProp = aPropMap.value(GEOM::propertyName(GEOM::PointMarker)).toString().split( GEOM::subSectionSeparator());
329             }
330             if ( aMarkerProp.size() == 2 ) {
331               // standard marker string contains "TypeOfMarker:ScaleOfMarker"
332               GEOM::marker_type mtype = (GEOM::marker_type)aMarkerProp[0].toInt();
333               GEOM::marker_size msize = (GEOM::marker_size)aMarkerProp[1].toInt();
334
335               if ( aType == -1 )
336                 aType = mtype;
337               else if ( aType != mtype ) {
338                 aType = (GEOM::marker_type)-1;
339                 break;
340               }
341               if ( aSize == -1 )
342                 aSize = msize;
343               else if ( aSize != msize )
344                 break;
345             }
346             else if ( aMarkerProp.size() == 1 ) {
347               // custom marker string contains "IdOfTexture"
348               int mtexture = aMarkerProp[0].toInt();
349
350               if ( aType == -1 )
351                 aType = GEOM::MT_USER;
352               else if ( aType !=  GEOM::MT_USER) {
353                 aType = (GEOM::marker_type)-1;
354                 break;
355               }
356               if ( aTexture == 0 )
357                 aTexture = mtexture;
358               else if ( aTexture != mtexture )
359                 break;
360             }
361           }
362         }
363       }
364     }
365   }
366   if ( aType > GEOM::MT_NONE && aType < GEOM::MT_USER )
367     setStandardMarker( aType, aSize );
368   else if ( aType == GEOM::MT_USER )
369     setCustomMarker( aTexture );
370   else
371     setStandardMarker((GEOM::marker_type)(resMgr->integerValue("Geometry", "type_of_marker", (int)Aspect_TOM_PLUS) + 1),
372                       (GEOM::marker_size)(resMgr->integerValue("Geometry", "marker_scale", 1)));
373 }
374
375 void GEOMToolsGUI_MarkerDlg::addTexture( int id, bool select ) const
376 {
377   if ( id > 0 && myCustomTypeCombo->index( id ) == -1 ) {
378     int tWidth, tHeight;
379
380     Handle(TColStd_HArray1OfByte) texture = GeometryGUI::getTexture(id, tWidth, tHeight);
381
382     if ( !texture.IsNull() && texture->Length() == tWidth*tHeight/8 ) {
383       QImage image( tWidth, tHeight, QImage::Format_Mono );
384       image.setColor( 0, qRgba( 0, 0, 0, 0   ) );
385       image.setColor( 1, qRgba( 0, 0, 0, 255 ) );
386       int bytesperline = tWidth/8;
387       for ( int j = texture->Lower(); j <= texture->Upper(); j++ ) {
388         uchar val = (uchar)texture->Value( j );
389         for ( int k = 0; k < 8; k++ ) {
390           int row = ( j - texture->Lower() ) / bytesperline;
391           int col = ( ( j - texture->Lower() ) % bytesperline ) * 8 + k;
392           image.setPixel( row, col, ( val & (1<<(8-k-1)) ) ? 1 : 0 );
393         }
394       }
395       QPixmap pixmap = QPixmap::fromImage( image );
396       if ( !pixmap.isNull() ) {
397         myCustomTypeCombo->addItem( pixmap, QString::number( id ) );
398         myCustomTypeCombo->setId( myCustomTypeCombo->count()-1, id );
399         if ( select ) myCustomTypeCombo->setCurrentId( id );
400       }
401     }
402   }
403 }
404
405 SalomeApp_Study* GEOMToolsGUI_MarkerDlg::getStudy() const
406 {
407   return qobject_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
408 }
409
410 void GEOMToolsGUI_MarkerDlg::browse()
411 {
412   QStringList filters;
413   filters << tr( "Texture files (*.dat)" ) << tr( "All files (*)" );
414   QString aFileName = SUIT_Session::session()->activeApplication()->getFileName( true, QString(), filters.join( ";;" ), tr( "LOAD_TEXTURE_TLT" ), this );
415   if ( !aFileName.isEmpty() ) {
416     addTexture( myOperation->LoadTexture( aFileName.toUtf8().constData() ), true );
417   }
418 }
419
420 void GEOMToolsGUI_MarkerDlg::help()
421 {
422   if ( getStudy() ) {
423     SalomeApp_Application* app = qobject_cast<SalomeApp_Application*>( getStudy()->application() );
424     app->onHelpContextModule( "GEOM", "point_marker_page.html" );
425   }
426 }