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