Salome HOME
Method name corrected.
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_ZLevelsModel.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_ZLevelsModel.h"
24
25 #include <SUIT_Session.h>
26 #include <SUIT_ResourceMgr.h>
27
28 #include <QMimeData>
29
30 const QString OBJ_LIST_MIME_TYPE = "application/hydro.objects.list";
31
32 HYDROGUI_ZLevelsModel::HYDROGUI_ZLevelsModel( QObject* theParent )
33  : QAbstractListModel( theParent )
34 {
35   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
36
37   myEmpty = QPixmap( 16, 16 );
38   myEmpty.fill( Qt::white );
39   myEye = aResMgr->loadPixmap( "HYDRO", tr( "EYE_ICO" ) );
40   setSupportedDragActions( Qt::MoveAction | Qt::CopyAction );
41 }
42
43 HYDROGUI_ZLevelsModel::~HYDROGUI_ZLevelsModel()
44 {
45 }
46
47 QVariant HYDROGUI_ZLevelsModel::data( const QModelIndex &theIndex, int theRole ) const
48 {
49   QVariant aVariant;
50
51   int aRow = theIndex.row();
52   int aColumn = theIndex.column();
53
54   switch( theRole )
55   {
56   case Qt::DisplayRole:
57     {
58       if( aColumn==0 && aRow >=0 && aRow < myObjects.count() )
59         return myObjects.at( aRow ).first->GetName();
60       else
61         return QVariant();
62     }
63     break;
64
65   case Qt::DecorationRole:
66     {
67       if( aColumn==0 && aRow >=0 && aRow < myObjects.count() )
68       {
69         bool isVisible = isObjectVisible( aRow );
70         if( isVisible )
71           return myEye;
72         else
73           return myEmpty;
74       }
75       return QVariant();
76     }
77     break;
78
79   case HYDROGUI_VisibleRole:
80     {
81       bool isVisible = isObjectVisible( aRow );
82       return QVariant( isVisible ).toString();
83     }
84     break;
85   }
86
87   return aVariant;
88 }
89
90 int HYDROGUI_ZLevelsModel::rowCount( const QModelIndex &theParent ) const
91 {
92   return myObjects.count();
93 }
94
95 void HYDROGUI_ZLevelsModel::setObjects( const Object2VisibleList& theObjects )
96 {
97   myObjects = theObjects;
98
99   reset();
100 }
101
102 HYDROGUI_ZLevelsModel::ObjectList HYDROGUI_ZLevelsModel::getObjects() const
103 {
104   ObjectList anObjects;
105
106   foreach( const Object2Visible& anItem, myObjects ) {
107     anObjects << anItem.first;
108   }
109
110   return anObjects;
111 }
112
113 bool HYDROGUI_ZLevelsModel::isObjectVisible( int theIndex ) const
114 {
115   bool isVisible = false;
116
117   if ( theIndex >= 0 && theIndex < myObjects.count() ) {
118     isVisible = myObjects.at( theIndex ).second;
119   }
120
121   return isVisible;
122 }
123
124 QVariant HYDROGUI_ZLevelsModel::headerData( int theSection,
125                                             Qt::Orientation theOrientation,
126                                             int theRole ) const
127 {
128   if( theOrientation==Qt::Horizontal && theRole==Qt::DisplayRole )
129   {
130     switch( theSection )
131     {
132     case 0:
133       return tr( "VISIBLE" );
134     case 1:
135       return tr( "OBJECT_NAME" );
136     };
137   }
138   return QVariant();
139 }
140
141 Qt::ItemFlags HYDROGUI_ZLevelsModel::flags( const QModelIndex& theIndex ) const
142 {
143   Qt::ItemFlags aDefaultFlags = QAbstractListModel::flags( theIndex );
144   if( theIndex.isValid() )
145     return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | aDefaultFlags;
146   else
147     return Qt::ItemIsDropEnabled | aDefaultFlags;
148 }
149
150 QMimeData* HYDROGUI_ZLevelsModel::mimeData( const QModelIndexList& theIndices ) const
151 {
152   QMimeData* aMimeData = new QMimeData();
153   QByteArray anEncodedData;
154   QDataStream aStream( &anEncodedData, QIODevice::WriteOnly );
155
156   QList<int> anIdsList = getIds( theIndices );
157   foreach( int anId, anIdsList )
158     aStream << anId;
159
160   aMimeData->setData( OBJ_LIST_MIME_TYPE, anEncodedData );
161   return aMimeData;
162 }
163
164 QStringList HYDROGUI_ZLevelsModel::mimeTypes() const
165 {
166   QStringList aTypes;
167   aTypes << OBJ_LIST_MIME_TYPE;
168   return aTypes;
169 }
170
171 bool HYDROGUI_ZLevelsModel::dropMimeData( const QMimeData* theData, Qt::DropAction theAction,
172                                           int theRow, int theColumn, const QModelIndex& theParent )
173 {
174   if( theAction == Qt::IgnoreAction)
175     return true;
176
177   if( !theData->hasFormat( OBJ_LIST_MIME_TYPE ))
178     return false;
179
180   if( theColumn > 0 )
181     return false;
182
183   int aDropItemId = theParent.row();
184
185   QByteArray anEncodedData = theData->data( OBJ_LIST_MIME_TYPE );
186   QDataStream aStream( &anEncodedData, QIODevice::ReadOnly );
187   QList<int> anIdsList;
188   while( !aStream.atEnd() )
189   {
190     int anId;
191     aStream >> anId;
192     anIdsList << anId;
193   }
194   qSort( anIdsList ); // TODO should be moved?
195   move( anIdsList, DragAndDrop, false, aDropItemId ); //TODO set visibility?
196   return true;
197 }
198
199 Qt::DropActions HYDROGUI_ZLevelsModel::supportedDropActions() const
200 {
201   return Qt::MoveAction | Qt::CopyAction;
202 }
203
204 QList<int> HYDROGUI_ZLevelsModel::getIds( const QModelIndexList& theIndexes, bool theIsToSort ) const
205 {
206   QList<int> anIds;
207   foreach( const QModelIndex& anIndex, theIndexes ) {
208     anIds << anIndex.row();
209   }
210
211   if ( theIsToSort ) {
212     qSort( anIds );
213   }
214
215   return anIds;
216 }
217
218 bool HYDROGUI_ZLevelsModel::move( const int theItem, const OpType theType,
219                                   bool theIsVisibleOnly, const int theDropItem )
220 {
221   bool aRes = false;
222   if ( theItem < 0 || theItem >= myObjects.count() ) {
223     return aRes;
224   }
225
226   int aDestinationIndex = -1;
227   bool isInsertBefore = false;
228
229   switch ( theType ) {
230     case Up:
231       isInsertBefore = true;
232       if ( theItem > 0 ) {
233         aDestinationIndex = theItem - 1;
234         if ( theIsVisibleOnly ) {
235           while ( aDestinationIndex >= 0 && !isObjectVisible( aDestinationIndex ) ) {
236             aDestinationIndex--;
237           }
238         }
239       }
240       break;
241     case Down:
242       if ( theItem < myObjects.count() - 1 ) {
243         aDestinationIndex = theItem + 1;
244         if ( theIsVisibleOnly ) {
245           while ( aDestinationIndex < myObjects.count() && !isObjectVisible( aDestinationIndex ) ) {
246             aDestinationIndex++;
247           }
248         }
249       }
250       break;
251     case Top:
252       isInsertBefore = true;
253       if ( theItem > 0 ) {
254         aDestinationIndex = 0;
255       }
256       break;
257     case Bottom:
258       if ( theItem < myObjects.count() - 1 ) {
259         aDestinationIndex = myObjects.count() - 1;
260       }
261       break;
262     case DragAndDrop:
263       if ( theItem > theDropItem ) {
264         isInsertBefore = true;
265         aDestinationIndex = theDropItem;
266       } else {
267         aDestinationIndex = theDropItem - 1;
268       }
269       break;
270   }
271
272   if ( aDestinationIndex >= 0 && aDestinationIndex < myObjects.count() ) {
273     int aDestinationRow = isInsertBefore ? aDestinationIndex : aDestinationIndex + 1;
274     if ( beginMoveRows( QModelIndex(), theItem, theItem, QModelIndex(), aDestinationRow ) ) {
275       myObjects.move( theItem, aDestinationIndex );
276       endMoveRows();
277       aRes = true;
278     }
279   }
280         
281   return aRes;
282 }
283
284 bool HYDROGUI_ZLevelsModel::move( const QList<int>& theItems, const OpType theType, 
285                                   bool theIsVisibleOnly, const int theDropItem )
286 {
287   bool aRes = true;
288
289   QListIterator<int> anIt( theItems );
290   int aDragShift = 0;
291
292   switch ( theType ) {
293     case Top:
294     case Down:
295       // reverse order
296       anIt.toBack();
297       while ( anIt.hasPrevious() ) {
298         int anId = anIt.previous();
299         if ( theType == Top ) {
300           anId += aDragShift;
301           aDragShift++;
302         }
303         if ( !move( anId, theType, theIsVisibleOnly, theDropItem ) ) {
304           aRes = false;
305           break;
306         }
307       }
308       break;
309     case Bottom:
310     case Up:
311       // direct order
312       while ( anIt.hasNext() ) {
313         int anId = anIt.next();
314         if ( theType == Bottom ) {
315           anId -= aDragShift;
316           aDragShift++;
317         }
318         if ( !move( anId, theType, theIsVisibleOnly, theDropItem ) ) {
319           aRes = false;
320           break;
321         }
322       }
323       break;
324     case DragAndDrop:
325       // direct order
326       aRes = isDragAndDropAllowed( theItems, theDropItem );
327       if ( aRes ) {
328         int aDropShift = 0;
329         int aDropItem = theDropItem;
330         while ( anIt.hasNext() ) {
331           int anId = anIt.next();
332           aDropItem = theDropItem + aDropShift;
333           if ( anId > aDropItem ) {
334             aDragShift = 0;
335             aDropShift++;
336           } else {
337             anId -= aDragShift;
338             if ( ( aDropItem - anId ) != 1 ) {
339               aDragShift++;
340             }
341           }
342           move( anId, theType, theIsVisibleOnly, aDropItem );
343         }
344       }
345       break;
346     default:
347       aRes = false;
348   }
349   
350   return aRes;
351 }
352
353 bool HYDROGUI_ZLevelsModel::isDragAndDropAllowed( const QList<int>& theItems, 
354                                                   const int theDropItem ) const
355 {
356   bool isAllowed = false;
357
358   if ( theDropItem >= 0 && theDropItem < myObjects.count() &&
359        !theItems.empty() && theItems.count() < myObjects.count() &&
360        !theItems.contains( theDropItem )) {
361     isAllowed = true;
362   }
363
364   return isAllowed;
365 }