Salome HOME
Fix for bug 10438: Crash during Explode on Blocks operation (Global selection on...
[modules/gui.git] / src / Qtx / QtxActionMgr.cxx
1 // File:      QtxActionMgr.cxx
2 // Author:    Alexander SOLOVYEV, Sergey TELKOV
3
4 #include "Qtx.h"
5 #include "QtxActionMgr.h"
6 #include "QtxAction.h"
7
8 #include <qwidget.h>
9 #include <qtoolbar.h>
10 #include <qpopupmenu.h>
11 #include <qwidgetlist.h>
12 #include <qobjectlist.h>
13 #include <qfile.h>
14 #include <qdom.h>
15
16 static QAction* qtx_separator_action = 0;
17
18 void qtxSeparatorActionCleanup()
19 {
20   delete qtx_separator_action;
21   qtx_separator_action = 0;
22 }
23
24 /*!
25         Class: QtxActionMenuMgr::SeparatorAction
26         Level: Internal
27 */
28
29 class QtxActionMgr::SeparatorAction : public QtxAction
30 {
31 public:
32   SeparatorAction( QObject* = 0 );
33   virtual ~SeparatorAction();
34
35   virtual bool addTo( QWidget* );
36   virtual bool removeFrom( QWidget* );
37
38 private:
39   QMap<QPopupMenu*, QIntList>  myMenus;
40   QMap<QToolBar*, QWidgetList> myTools;
41 };
42
43 QtxActionMgr::SeparatorAction::SeparatorAction( QObject* parent )
44 : QtxAction( parent )
45 {
46 }
47
48 QtxActionMgr::SeparatorAction::~SeparatorAction()
49 {
50 }
51
52 bool QtxActionMgr::SeparatorAction::addTo( QWidget* wid )
53 {
54   if ( !wid )
55     return false;
56
57   bool res = true;
58   if ( wid->inherits( "QPopupMenu" ) )
59   {
60     QPopupMenu* popup = (QPopupMenu*)wid;
61     myMenus[popup].append( popup->insertSeparator() );
62   }
63   else if ( wid->inherits( "QToolBar" ) )
64   {
65     QToolBar* tb = (QToolBar*)wid;
66     tb->addSeparator();
67     myTools[tb].append( (QWidget*)tb->children()->getLast() );
68   }
69   else
70     res = false;
71
72   return res;
73 }
74
75 bool QtxActionMgr::SeparatorAction::removeFrom( QWidget* wid )
76 {
77   if ( !wid )
78     return false;
79
80   bool res = true;
81   if ( wid->inherits( "QPopupMenu" ) )
82   {
83     QPopupMenu* popup = (QPopupMenu*)wid;
84     if ( myMenus.contains( popup ) )
85     {
86       const QIntList& list = myMenus[popup];
87       for ( QIntList::const_iterator it = list.begin(); it != list.end(); ++it )
88         popup->removeItem( *it );
89
90       myMenus.remove( popup );
91     }
92   }
93   else if ( wid->inherits( "QToolBar" ) )
94   {
95     QToolBar* tb = (QToolBar*)wid;
96     if ( myTools.contains( tb ) )
97     {
98       QMap<QObject*, int> childMap;
99       if ( tb->children() )
100       {
101         for ( QObjectListIt it( *tb->children() ); it.current(); ++it )
102           childMap.insert( it.current(), 0 );
103       }
104       const QWidgetList& list = myTools[tb];
105       for ( QWidgetListIt it( list ); it.current(); ++it )
106       {
107         if ( childMap.contains( it.current() ) )
108         delete it.current();
109       }
110
111       myTools.remove( tb );
112     }
113   }
114   else
115     res = false;
116
117   return res;
118 }
119
120 /*!
121         Class: QtxActionMgr
122         Level: Public
123 */
124
125 QtxActionMgr::QtxActionMgr( QObject* parent )
126 : QObject( parent ),
127 myUpdate( true )
128 {
129 }
130
131 QtxActionMgr::~QtxActionMgr()
132 {
133 }
134
135 int QtxActionMgr::registerAction( QAction* a, const int userId )
136 {
137   if ( !a )
138     return -1;
139
140   int theId = userId < 0 ? generateId() : userId;
141
142   if ( contains( theId ) )
143     unRegisterAction( theId );
144
145   int cur = actionId( a );
146   if ( cur != -1 )
147   {
148     if ( userId == -1 )
149       return cur;
150     else
151       unRegisterAction( cur );
152   }
153
154   myActions.insert( theId, a );
155
156   return theId;
157 }
158
159 void QtxActionMgr::unRegisterAction( const int id )
160 {
161   if( contains( id ) )
162     myActions.remove( id );
163 }
164
165 QAction* QtxActionMgr::action( const int id ) const
166 {
167   if ( contains( id ) )
168     return myActions[ id ];
169   else
170     return 0;
171 }
172
173 int QtxActionMgr::actionId( const QAction* a ) const
174 {
175   if ( !a )
176     return -1;
177
178   int theId = -1;
179   for ( ActionMap::ConstIterator it = myActions.begin(); it != myActions.end() && theId == -1; ++it )
180   {
181     if ( it.data() == a )
182       theId = it.key();
183   }
184
185   return theId;
186 }
187
188 bool QtxActionMgr::contains( const int id ) const
189 {
190   return myActions.contains( id );
191 }
192
193 int QtxActionMgr::count() const
194 {
195   return myActions.count();
196 }
197
198 bool QtxActionMgr::isEmpty() const
199 {
200   return myActions.isEmpty();
201 }
202
203 void QtxActionMgr::idList( QIntList& lst ) const
204 {
205   lst = myActions.keys();
206 }
207
208 bool QtxActionMgr::isUpdatesEnabled() const
209 {
210   return myUpdate;
211 }
212
213 void QtxActionMgr::setUpdatesEnabled( const bool upd )
214 {
215   myUpdate = upd;
216 }
217
218 bool QtxActionMgr::isVisible( const int, const int ) const
219 {
220   return true;
221 }
222
223 void QtxActionMgr::setVisible( const int, const int, const bool )
224 {
225 }
226
227 void QtxActionMgr::update()
228 {
229   if ( isUpdatesEnabled() )
230     internalUpdate();
231 }
232
233 void QtxActionMgr::internalUpdate()
234 {
235 }
236
237 int QtxActionMgr::generateId() const
238 {
239   static int id = -1;
240   return --id;
241 }
242
243 bool QtxActionMgr::isEnabled( const int id ) const
244 {
245   QAction* a = action( id );
246   if ( a )
247     return a->isEnabled();
248   else
249     return false;
250 }
251
252 void QtxActionMgr::setEnabled( const int id, const bool en )
253 {
254   QAction* a = action( id );
255   if ( a )
256     a->setEnabled( en );
257 }
258
259 QAction* QtxActionMgr::separator( const bool individual )
260 {
261   if ( individual )
262     return new SeparatorAction();
263
264   if ( !qtx_separator_action )
265   {
266     qtx_separator_action = new SeparatorAction();
267     qAddPostRoutine( qtxSeparatorActionCleanup );
268   }
269   return qtx_separator_action;
270 }
271
272 /*!
273         Class: QtxActionMgr::Reader
274         Level: Public
275 */
276
277 QtxActionMgr::Reader::Reader()
278 {
279 }
280
281 QtxActionMgr::Reader::~Reader()
282 {
283 }
284
285 QStringList QtxActionMgr::Reader::options() const
286 {
287   return myOptions.keys();
288 }
289
290 QString QtxActionMgr::Reader::option( const QString& name, const QString& def ) const
291 {
292   if( myOptions.contains( name ) )
293     return myOptions[ name ];
294   else
295     return def;
296 }
297
298 void QtxActionMgr::Reader::setOption( const QString& name, const QString& value )
299 {
300   myOptions[ name ] = value;
301 }
302
303
304 /*!
305         Class: QtxActionMgr::XMLReader
306         Level: Public
307 */
308 QtxActionMgr::XMLReader::XMLReader( const QString& root,
309                                     const QString& item,
310                                     const QString& dir )
311 : Reader()
312 {
313   setOption( QString( "root_tag" ),  root );
314   setOption( QString( "menu_item" ), item );
315   setOption( QString( "icons_dir" ), dir  );
316   setOption( QString( "id" ),        QString( "item-id" ) );
317   setOption( QString( "pos" ),       QString( "pos-id" ) );
318   setOption( QString( "group" ),     QString( "group-id" ) );
319   setOption( QString( "label" ),     QString( "label-id" ) );
320   setOption( QString( "tooltip" ),   QString( "tooltip-id" ) );
321   setOption( QString( "accel" ),     QString( "accel-id" ) );
322   setOption( QString( "separator" ), QString( "separator" ) );
323   setOption( QString( "icon" ),      QString( "icon-id" ) );
324   setOption( QString( "toggle" ),    QString( "toggle-id" ) );
325 }
326
327 QtxActionMgr::XMLReader::~XMLReader()
328 {
329 }
330
331 bool QtxActionMgr::XMLReader::read( const QString& fname, Creator& cr ) const
332 {
333   bool res = false;  
334
335 #ifndef QT_NO_DOM
336
337   QFile file( fname );
338   if ( !file.open( IO_ReadOnly ) )
339     return res;
340
341   QDomDocument doc;
342
343   res = doc.setContent( &file );
344   file.close();
345
346   if ( !res )
347     return res;
348
349   QString root = option( "root_tag" );
350   for( QDomNode cur = doc.documentElement(); !cur.isNull(); )
351   {
352     if( cur.isElement() && isNodeSimilar( cur, root ) )
353       read( cur, -1, cr );
354     else if( cur.hasChildNodes() )
355     {
356       cur = cur.firstChild();
357       continue;
358     }
359
360     while( !cur.isNull() && cur.nextSibling().isNull() )
361       cur = cur.parentNode();
362     if( !cur.isNull() )
363       cur = cur.nextSibling();
364   }
365
366 #endif
367
368   return res;
369 }
370
371 void QtxActionMgr::XMLReader::read( const QDomNode& parent_node,
372                                     const int parent_id,
373                                     Creator& cr ) const
374 {
375   if( parent_node.isNull() )
376     return;
377
378   QStringList items = QStringList::split( "|", option( QString( "menu_item" ) ) );
379
380   const QDomNodeList& children = parent_node.childNodes();
381   for( int i=0, n=children.count(); i<n; i++ )
382   {
383     QDomNode node = children.item( i );
384     //QString n = node.nodeName();
385     if( node.isElement() /*&& node.hasAttributes()*/ &&
386         ( items.contains( node.nodeName() ) || node.nodeName()==option( "separator" ) ) )
387     {
388       QDomNamedNodeMap map = node.attributes();
389       ItemAttributes attrs;
390
391       for( int i=0, n=map.count(); i<n; i++ )
392         if( map.item( i ).isAttr() )
393         {
394           QDomAttr a = map.item( i ).toAttr();
395           attrs.insert( a.name(), a.value() );
396         }
397
398       int newId = cr.append( node.nodeName(), node.hasChildNodes(), attrs, parent_id );
399       if( node.hasChildNodes() )
400         read( node, newId, cr );
401     }
402   }
403 }
404
405 bool QtxActionMgr::XMLReader::isNodeSimilar( const QDomNode& node,
406                                              const QString& pattern ) const
407 {
408   if( node.nodeName()==pattern )
409     return true;
410   
411   QDomDocument temp;
412   QString mes;
413   temp.setContent( pattern, true, &mes );
414
415   const QDomNamedNodeMap &temp_map = temp.documentElement().attributes(),
416                          &cur_map = node.attributes();
417   bool ok = temp_map.count()>0;
418   for( int i=0, n=temp_map.count(); i<n && ok; i++ )
419   {
420     QDomAttr a = temp_map.item( i ).toAttr(),
421              b = cur_map.namedItem( a.name() ).toAttr();
422     ok = !b.isNull() && a.name()==b.name() && a.value()==b.value();
423   }
424
425   return ok;
426 }
427
428
429 /*!
430         Class: QtxActionMgr::Creator
431         Level: Public
432 */
433 int QtxActionMgr::Creator::intValue( const ItemAttributes& attrs,
434                                      const QString& name, int def )
435 {
436   if( attrs.contains( name ) )
437   {
438     bool ok; 
439     int res = attrs[ name ].toInt( &ok );
440     if( ok )
441       return res;
442   }
443   return def;
444 }
445
446 QString QtxActionMgr::Creator::strValue( const ItemAttributes& attrs,
447                                          const QString& name,
448                                          const QString& def  )
449 {
450   if( attrs.contains( name ) )
451     return attrs[ name ];
452   else
453     return def;
454 }
455
456 QtxActionMgr::Creator::Creator( QtxActionMgr::Reader* r )
457 : myReader( r )
458 {
459 }
460
461 QtxActionMgr::Creator::~Creator()
462 {
463 }
464
465 QtxActionMgr::Reader* QtxActionMgr::Creator::reader() const
466 {
467   return myReader;
468 }
469
470 void QtxActionMgr::Creator::connect( QAction* ) const
471 {
472 }
473
474 bool QtxActionMgr::Creator::loadPixmap( const QString& fname, QPixmap& pix ) const
475 {
476   if( !reader() )
477     return false;
478
479   QStringList dirlist = QStringList::split( ";", reader()->option( "icons_dir", "." ) );
480   QStringList::const_iterator anIt = dirlist.begin(),
481                               aLast = dirlist.end();
482   bool res = false;
483   for( ; anIt!=aLast && !res; anIt++ )
484     res = pix.load( Qtx::addSlash( *anIt ) + fname );
485
486   return res;
487 }