Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/modules/hydro
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_PriorityTableModel.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HYDROGUI_PriorityTableModel.h"
24
25
26 /**
27   Constructor.
28   @param theParent the parent object
29 */
30 HYDROGUI_PriorityTableModel::HYDROGUI_PriorityTableModel( QObject* theParent )
31  : QAbstractTableModel( theParent )
32 {
33 }
34
35 /**
36   Destructor.
37 */
38 HYDROGUI_PriorityTableModel::~HYDROGUI_PriorityTableModel()
39 {
40 }
41
42 /**
43  */
44 Qt::ItemFlags   HYDROGUI_PriorityTableModel::flags( const QModelIndex & theIndex ) const
45 {
46   return Qt::ItemIsSelectable   | Qt::ItemIsEditable | Qt::ItemIsEnabled;
47 }
48
49 /**
50  */
51 QVariant HYDROGUI_PriorityTableModel::data( const QModelIndex &theIndex, int theRole ) const
52 {
53   QVariant aVariant;
54
55   int aRow = theIndex.row();
56   int aColumn = theIndex.column();
57
58   if ( !theIndex.isValid() || aRow > myRules.size() ) {
59     return aVariant;
60   }
61   
62   if ( theRole == Qt::DisplayRole ) {
63     HYDROData_CustomRule aRule = myRules.at(aRow);
64
65     if ( aColumn == 0 ) {
66       aVariant = aRule.Object1->GetName();
67     } else if ( aColumn == 1 ) {
68       aVariant = priorityToString( aRule.Priority );
69     } else if ( aColumn == 2 ) {
70       aVariant = aRule.Object2->GetName();
71     } else if ( aColumn == 3 ) {
72       aVariant = mergeTypeToString( aRule.MergeType );
73     }
74   } else if ( theRole == Qt::EditRole ) {
75     HYDROData_CustomRule aRule = myRules.at(aRow);
76
77     if ( aColumn == 0 ) {
78       aVariant = aRule.Object1->GetName();
79     } else if ( aColumn == 1 ) {
80       aVariant = aRule.Priority;
81     } else if ( aColumn == 2 ) {
82       aVariant = aRule.Object2->GetName();
83     } else if ( aColumn == 3 ) {
84       aVariant = aRule.MergeType;
85     }
86   } else if ( theRole ==  Qt::UserRole ) {
87     if ( aColumn == 0 || aColumn == 2 ) {
88       QStringList aNames;
89       HYDROData_CustomRule aRule = myRules.at( aRow );
90       Handle(HYDROData_Object) aUsedObject = aColumn == 0 ? aRule.Object2 : aRule.Object1;
91       if ( !aUsedObject.IsNull() ) {
92         aNames = getAvailablePairs( aUsedObject );
93       }
94       aVariant = aNames;
95     } else if ( aColumn == 1 ) {
96       QMap<QString, QVariant> aMap;
97       aMap.insert( priorityToString( LESS ), LESS );
98       aMap.insert( priorityToString( GREATER ), GREATER );
99       aVariant = QVariant( aMap );
100     } else if ( aColumn == 3 ) {
101       QMap<QString, QVariant> aMap;
102       aMap.insert( mergeTypeToString( HYDROData_Zone::Merge_Object ), HYDROData_Zone::Merge_Object );
103       aMap.insert( mergeTypeToString( HYDROData_Zone::Merge_ZMIN ), HYDROData_Zone::Merge_ZMIN );
104       aMap.insert( mergeTypeToString( HYDROData_Zone::Merge_ZMAX ), HYDROData_Zone::Merge_ZMAX );
105       aVariant = QVariant( aMap );
106     } 
107   } else if ( theRole == Qt::TextAlignmentRole ) {
108     aVariant = Qt::AlignCenter;
109   }
110
111   return aVariant;
112 }
113
114 /**
115  */
116 bool HYDROGUI_PriorityTableModel::setData( const QModelIndex & theIndex, const QVariant & theValue, int theRole )
117 {
118   int aRow = theIndex.row();
119   if ( !theIndex.isValid() || aRow > myRules.size() ) {
120     return false;
121   }
122
123   bool aRes = false;
124
125   if ( theRole ==  Qt::EditRole ) {
126     int aColumn = theIndex.column();
127
128     if ( aColumn == 0 || aColumn == 2 ) {
129       Handle(HYDROData_Object) anObject;
130       QString anObjName = theValue.toString();
131       foreach ( const Handle(HYDROData_Object) anObj, myObjects ) {
132         if ( anObj->GetName() == anObjName ) {
133           anObject = anObj;
134           break;
135         }
136       }
137       if ( !anObject.IsNull() ) {
138         HYDROData_CustomRule anEditedRule = myRules[aRow];
139         
140         if ( aColumn == 0 ) {
141           anEditedRule.Object1 = anObject;
142         } else {
143           anEditedRule.Object2 = anObject;
144         }
145         
146         if ( !isUsed( anEditedRule.Object1, anEditedRule.Object2 ) ) {
147           myRules[aRow] = anEditedRule;
148           aRes = true;
149         } else {
150           emit showError( tr("ALREADY_EXISTS") );
151         }
152       }
153     } else if ( aColumn == 1 ) {
154       myRules[aRow].Priority = (HYDROData_PriorityType)theValue.toInt();
155     } else if ( aColumn == 3 ) {
156       myRules[aRow].MergeType = (HYDROData_Zone::MergeAltitudesType)theValue.toInt();;
157     }
158   }
159
160   return aRes;
161 }
162
163 /**
164  */
165 int HYDROGUI_PriorityTableModel::rowCount( const QModelIndex &theParent ) const
166 {
167   return myRules.count();
168 }
169
170 /**
171  */
172 int HYDROGUI_PriorityTableModel::columnCount( const QModelIndex &theParent ) const
173 {
174   return 4;
175 }
176
177 /**
178   Set rules.
179   @param theRules the list of rules
180 */
181 void HYDROGUI_PriorityTableModel::setRules( const HYDROData_ListOfRules& theRules )
182 {
183   beginResetModel();
184   myRules = theRules;
185   endResetModel();
186 }
187
188 /**
189   Get rules.
190   @return the list of rules
191 */
192 HYDROData_ListOfRules HYDROGUI_PriorityTableModel::getRules() const
193 {
194   return myRules;
195 }
196
197 /**
198 */
199 QVariant HYDROGUI_PriorityTableModel::headerData( int theSection,
200                                                   Qt::Orientation theOrientation,
201                                                   int theRole ) const
202 {
203   QVariant aData;
204
205   if ( theRole != Qt::DisplayRole ) {
206     return aData;
207   }
208
209   if ( theOrientation == Qt::Horizontal ) {
210     switch( theSection )
211     {
212     case 0:
213       aData = tr( "OBJECT1" );
214       break;
215     case 1:
216       aData = tr( "PRIORITY" );
217       break;
218     case 2:
219       aData = tr( "OBJECT2" );
220       break;
221     case 3:
222       aData = tr( "BATHYMETRY" );
223       break;
224     };
225   } else if ( theOrientation == Qt::Vertical ) {
226     aData = theSection + 1;
227   }
228
229   return aData;
230 }
231
232 /**
233   Set objects which could be used for rules definition.
234   @param theObjects the ordered list of objects
235  */
236 void HYDROGUI_PriorityTableModel::setObjects( const QList<Handle(HYDROData_Object)>& theObjects )
237 {
238   myObjects = theObjects;
239     
240   beginResetModel();
241
242   // Remove rules which use objects which are no longer available
243   QStringList aNames = getAvailableObjectNames();
244   QMutableListIterator<HYDROData_CustomRule> anIter( myRules );
245   while ( anIter.hasNext() ) {
246     HYDROData_CustomRule aRule = anIter.next();
247      if ( !aNames.contains( aRule.Object1->GetName() ) || 
248           !aNames.contains( aRule.Object2->GetName() ) ) {
249       anIter.remove();
250     }
251   }
252
253   endResetModel();
254 }
255
256 /**
257  Create new rule.
258  @return true if a rule has been created successfully
259  */
260 bool HYDROGUI_PriorityTableModel::createNewRule() 
261 {
262   if ( !canCreateNewRule() ) {
263     return false;
264   }
265   
266   // Existing pairs of object indexes
267   QStringList aNames = getAvailableObjectNames();
268   QList< QPair<int, int> > aRules;
269   foreach( const HYDROData_CustomRule& aRule, getRules() ) {
270     int anIndex1 = aNames.indexOf( aRule.Object1->GetName() );
271     int anIndex2 = aNames.indexOf( aRule.Object2->GetName() );
272     if ( anIndex1 >= 0 && anIndex2 >= 0 ) {
273       aRules << QPair<int, int>( anIndex1, anIndex2 );
274       aRules << QPair<int, int>( anIndex2, anIndex1 );
275     }
276   }
277     
278   // Try to find:
279   // 1. the new pair of objects 
280   // 2. the priority type corresponding to the objects order
281   Handle(HYDROData_Object) anObject1, anObject2;
282   HYDROData_PriorityType aPriorityType = GREATER;
283
284   int aNbObjects = myObjects.count();
285   for ( int anIndex1 = 0; anIndex1 < aNbObjects; anIndex1++ ) {
286     bool isFound = false;
287
288     for ( int anIndex2 = 0; anIndex2 < aNbObjects; anIndex2++ ) {
289       if ( anIndex1 == anIndex2 ) {
290         continue;
291       }
292
293       if ( !aRules.contains( QPair<int, int>( anIndex1, anIndex2 ) ) ) {
294         anObject1 = myObjects.at( anIndex1 );
295         anObject2 = myObjects.at( anIndex2 );
296         if ( anIndex1 > anIndex2 ) {
297           aPriorityType = LESS;
298         }
299         isFound = true;
300         break;
301       }
302     }
303
304     if ( isFound ) {
305       break;
306     }
307   }
308
309   // Create a new rule
310   bool isCreated = false;
311
312   if ( !anObject1.IsNull() && !anObject2.IsNull() ) {
313     HYDROData_CustomRule aNewRule;
314     aNewRule.Object1 = anObject1;
315     aNewRule.Object2 = anObject2;
316     aNewRule.Priority = aPriorityType;
317     aNewRule.MergeType = HYDROData_Zone::Merge_ZMIN;
318
319     beginResetModel();
320     myRules << aNewRule;
321     endResetModel();
322
323     isCreated = true;
324   }
325
326   return isCreated;
327 }
328
329 /**
330  Check if a new rule can be created.
331  @return true if a new rule could be created
332  */
333 bool HYDROGUI_PriorityTableModel::canCreateNewRule() const
334 {
335   int aNbObjects = myObjects.count();
336
337   return ( myRules.count() < (aNbObjects - 1)*aNbObjects/2 );
338 }
339
340 /**
341  */
342 bool HYDROGUI_PriorityTableModel::removeRows ( int theRow, int theCount, const QModelIndex & theParent )
343 {
344   if ( myRules.isEmpty() || theRow < 0 || theRow >= myRules.count() ) {
345     return false;
346   }
347
348   int aLastRow = theRow + theCount - 1;
349   if ( aLastRow > myRules.count() ) {
350     aLastRow = myRules.count() - 1;
351   }
352
353   beginRemoveRows( theParent, theRow, aLastRow );
354
355   // Remove the corresponding rules
356   for ( int i = 1; i <= theCount; i++ ) {
357     myRules.removeAt( theRow );
358   }
359
360   endRemoveRows();
361
362   return true;
363 }
364
365 /**
366  Remove all data from the model.
367  @return true if at least one row is removed
368  */
369 bool HYDROGUI_PriorityTableModel::removeAll()
370 {
371   return removeRows( 0, rowCount() );
372 }
373
374 /**
375  Get available pairs for the given object.
376  @param theObject the object
377  @return the list of object names
378  */
379 QStringList HYDROGUI_PriorityTableModel::getAvailablePairs(  const Handle(HYDROData_Object)& theObject ) const
380 {
381   QStringList aNames;
382
383   if ( !theObject.IsNull() ) {
384     aNames = getAvailableObjectNames();
385     aNames.removeAll( theObject->GetName() );
386   }
387
388   return aNames;
389 }
390
391 /**
392  Remove the rows.
393  @params theRows the list of rows to remove
394  @return true if at least one row is removed
395  */
396 bool HYDROGUI_PriorityTableModel::removeRows ( const QList<int> theRows )
397 {
398   QList<int> aSortedRows = theRows;
399   qSort( aSortedRows );
400
401   int aRowToRemove = -1;
402   int aNbRemoved = 0;
403   foreach ( int aRow, aSortedRows ) {
404     aRowToRemove = aRow - aNbRemoved;
405     if ( removeRow( aRowToRemove ) ) {
406       aNbRemoved++;
407     }
408   }
409
410   return ( aNbRemoved > 0 );
411 }
412
413 /**
414  Get priority string representation.
415  @param thePriority the priority
416  */
417 QString HYDROGUI_PriorityTableModel::priorityToString( const int thePriority ) const
418 {
419   switch( thePriority )
420   {
421   case LESS:
422     return tr( "LESS" );
423   case GREATER:
424     return tr( "GREATER" );
425   default:
426     return QString();
427   };
428 }
429
430 /**
431  Get merge type string representation.
432  @param theMergeType the merge type
433  */
434 QString HYDROGUI_PriorityTableModel::mergeTypeToString( const int theMergeType ) const
435 {
436   switch( theMergeType )
437   {
438   case HYDROData_Zone::Merge_Object:
439     return tr( "PRIORITY" );
440   case HYDROData_Zone::Merge_ZMIN:
441     return tr( "ZMIN" );
442   case HYDROData_Zone::Merge_ZMAX:
443     return tr( "ZMAX" );
444   default:
445     return QString();
446   };
447 }
448
449 /**
450   Check if the given pair of objects is already used.
451   @return true if the pair is used
452  */
453 bool HYDROGUI_PriorityTableModel::isUsed( const Handle(HYDROData_Object)& theObj1, 
454                                           const Handle(HYDROData_Object)& theObj2 ) const
455 {
456   bool isUsed = false;
457
458   foreach ( const HYDROData_CustomRule& aRule, myRules ) {
459     if ( ( aRule.Object1->GetName() == theObj1->GetName() && 
460            aRule.Object2->GetName() == theObj2->GetName() ) ||
461          ( aRule.Object1->GetName() == theObj2->GetName() && 
462            aRule.Object2->GetName() == theObj1->GetName() ) ) {
463       isUsed = true;
464       break;
465     }
466   }       
467
468   return isUsed;
469 }
470
471 /**
472   Get available object names.
473   @return the list of object names
474  */
475 QStringList HYDROGUI_PriorityTableModel::getAvailableObjectNames() const
476 {
477   QStringList aNames;
478
479   foreach ( const Handle(HYDROData_Object) anObj, myObjects ) {
480     if ( !anObj.IsNull() ) {
481       aNames << anObj->GetName();
482     }
483   }
484
485   return aNames;
486 }