Salome HOME
22ae6a91af390c9713fd6ca09221bae1535c9f03
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_PriorityTableModel.cxx
1 // Copyright (C) 2007-2013  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.
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   QMutableListIterator<HYDROData_CustomRule> anIter( myRules );
244   while ( anIter.hasNext() ) {
245     HYDROData_CustomRule aRule = anIter.next();
246      if ( !myObjects.contains( aRule.Object1 ) || 
247           !myObjects.contains( aRule.Object2 ) ) {
248       anIter.remove();
249     }
250   }
251
252   endResetModel();
253 }
254
255 /**
256  Create new rule.
257  @return true if a rule has been created successfully
258  */
259 bool HYDROGUI_PriorityTableModel::createNewRule() 
260 {
261   if ( !canCreateNewRule() ) {
262     return false;
263   }
264
265   // Existing pairs of object indexes
266   QList< QPair<int, int> > aRules;
267   foreach( const HYDROData_CustomRule& aRule, getRules() ) {
268     int anIndex1 = myObjects.indexOf( aRule.Object1 );
269     int anIndex2 = myObjects.indexOf( aRule.Object2 );
270     if ( anIndex1 >= 0 && anIndex2 >= 0 ) {
271       aRules << QPair<int, int>( anIndex1, anIndex2 );
272       aRules << QPair<int, int>( anIndex2, anIndex1 );
273     }
274   }
275     
276   // Try to find:
277   // 1. the new pair of objects 
278   // 2. the priority type corresponding to the objects order
279   Handle(HYDROData_Object) anObject1, anObject2;
280   HYDROData_PriorityType aPriorityType = GREATER;
281
282   int aNbObjects = myObjects.count();
283   for ( int anIndex1 = 0; anIndex1 < aNbObjects; anIndex1++ ) {
284     bool isFound = false;
285
286     for ( int anIndex2 = 0; anIndex2 < aNbObjects; anIndex2++ ) {
287       if ( anIndex1 == anIndex2 ) {
288         continue;
289       }
290
291       if ( !aRules.contains( QPair<int, int>( anIndex1, anIndex2 ) ) ) {
292         anObject1 = myObjects.at( anIndex1 );
293         anObject2 = myObjects.at( anIndex2 );
294         if ( anIndex1 > anIndex2 ) {
295           aPriorityType = LESS;
296         }
297         isFound = true;
298         break;
299       }
300     }
301
302     if ( isFound ) {
303       break;
304     }
305   }
306
307   // Create a new rule
308   bool isCreated = false;
309
310   if ( !anObject1.IsNull() && !anObject2.IsNull() ) {
311     HYDROData_CustomRule aNewRule;
312     aNewRule.Object1 = anObject1;
313     aNewRule.Object2 = anObject2;
314     aNewRule.Priority = aPriorityType;
315     aNewRule.MergeType = HYDROData_Zone::Merge_ZMIN;
316
317     beginResetModel();
318     myRules << aNewRule;
319     endResetModel();
320
321     isCreated = true;
322   }
323
324   return isCreated;
325 }
326
327 /**
328  Check if a new rule can be created.
329  @return true if a new rule could be created
330  */
331 bool HYDROGUI_PriorityTableModel::canCreateNewRule() const
332 {
333   int aNbObjects = myObjects.count();
334
335   return ( myRules.count() < (aNbObjects - 1)*aNbObjects/2 );
336 }
337
338 /**
339  */
340 bool HYDROGUI_PriorityTableModel::removeRows ( int theRow, int theCount, const QModelIndex & theParent )
341 {
342   if ( myRules.isEmpty() || theRow < 0 || theRow >= myRules.count() ) {
343     return false;
344   }
345
346   int aLastRow = theRow + theCount - 1;
347   if ( aLastRow > myRules.count() ) {
348     aLastRow = myRules.count() - 1;
349   }
350
351   beginRemoveRows( theParent, theRow, aLastRow );
352
353   // Remove the corresponding rules
354   for ( int i = 1; i <= theCount; i++ ) {
355     myRules.removeAt( theRow );
356   }
357
358   endRemoveRows();
359
360   return true;
361 }
362
363 /**
364  Remove all data from the model.
365  @return true if at least one row is removed
366  */
367 bool HYDROGUI_PriorityTableModel::removeAll()
368 {
369   return removeRows( 0, rowCount() );
370 }
371
372 /**
373  Get available pairs for the given object.
374  @param theObject the object
375  @return the list of object names
376  */
377 QStringList HYDROGUI_PriorityTableModel::getAvailablePairs(  const Handle(HYDROData_Object)& theObject ) const
378 {
379   QStringList aNames;
380
381   foreach ( const Handle(HYDROData_Object) anObj, myObjects ) {
382     if ( !anObj.IsNull() && anObj->GetName() != theObject->GetName() ) {
383       aNames << anObj->GetName();
384     }
385   }
386
387   return aNames;
388 }
389
390 /**
391  Remove the rows.
392  @params theRows the list of rows to remove
393  @return true if at least one row is removed
394  */
395 bool HYDROGUI_PriorityTableModel::removeRows ( const QList<int> theRows )
396 {
397   QList<int> aSortedRows = theRows;
398   qSort( aSortedRows );
399
400   int aRowToRemove = -1;
401   int aNbRemoved = 0;
402   foreach ( int aRow, aSortedRows ) {
403     aRowToRemove = aRow - aNbRemoved;
404     if ( removeRow( aRowToRemove ) ) {
405       aNbRemoved++;
406     }
407   }
408
409   return ( aNbRemoved > 0 );
410 }
411
412 /**
413  Get priority string representation.
414  @param thePriority the priority
415  */
416 QString HYDROGUI_PriorityTableModel::priorityToString( const int thePriority ) const
417 {
418   switch( thePriority )
419   {
420   case LESS:
421     return tr( "LESS" );
422   case GREATER:
423     return tr( "GREATER" );
424   default:
425     return QString();
426   };
427 }
428
429 /**
430  Get merge type string representation.
431  @param theMergeType the merge type
432  */
433 QString HYDROGUI_PriorityTableModel::mergeTypeToString( const int theMergeType ) const
434 {
435   switch( theMergeType )
436   {
437   case HYDROData_Zone::Merge_Object:
438     return tr( "PRIORITY" );
439   case HYDROData_Zone::Merge_ZMIN:
440     return tr( "ZMIN" );
441   case HYDROData_Zone::Merge_ZMAX:
442     return tr( "ZMAX" );
443   default:
444     return QString();
445   };
446 }
447
448 /**
449   Check if the given pair of objects is already used.
450   @return true if the pair is used
451  */
452 bool HYDROGUI_PriorityTableModel::isUsed( const Handle(HYDROData_Object)& theObj1, 
453                                           const Handle(HYDROData_Object)& theObj2 ) const
454 {
455   bool isUsed = false;
456
457   foreach ( const HYDROData_CustomRule& aRule, myRules ) {
458     if ( ( aRule.Object1->GetName() == theObj1->GetName() && 
459            aRule.Object2->GetName() == theObj2->GetName() ) ||
460          ( aRule.Object1->GetName() == theObj2->GetName() && 
461            aRule.Object2->GetName() == theObj1->GetName() ) ) {
462       isUsed = true;
463       break;
464     }
465   }       
466
467   return isUsed;
468 }