Salome HOME
Operation which can lead to data model modifying removed from non-transactional place.
[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 #include <QMimeData>
25
26 const QString OBJ_LIST_MIME_TYPE = "application/hydro.objects.list";
27
28 HYDROGUI_ZLevelsModel::HYDROGUI_ZLevelsModel( QObject* theParent )
29  : QAbstractListModel( theParent )
30 {
31   myEmpty = QPixmap( 16, 16 );
32   myEmpty.fill( Qt::white );
33   myEye = QPixmap( "eye.png" );//TODO: loading from resources
34   setSupportedDragActions( Qt::MoveAction | Qt::CopyAction );
35 }
36
37 HYDROGUI_ZLevelsModel::~HYDROGUI_ZLevelsModel()
38 {
39 }
40
41 QVariant HYDROGUI_ZLevelsModel::data( const QModelIndex &theIndex, int theRole ) const
42 {
43   QVariant aVariant;
44
45   int aRow = theIndex.row();
46   int aColumn = theIndex.column();
47
48   switch( theRole )
49   {
50   case Qt::DisplayRole:
51     {
52       if( aColumn==0 && aRow >=0 && aRow < myObjects.count() )
53         return myObjects.at( aRow ).first->GetName();
54       else
55         return QVariant();
56     }
57     break;
58
59   case Qt::DecorationRole:
60     {
61       if( aColumn==0 && aRow >=0 && aRow < myObjects.count() )
62       {
63         bool isVisible = isObjectVisible( aRow );
64         if( isVisible )
65           return myEye;
66         else
67           return myEmpty;
68       }
69       return QVariant();
70     }
71     break;
72
73   case HYDROGUI_VisibleRole:
74     {
75       bool isVisible = isObjectVisible( aRow );
76       return QVariant( isVisible ).toString();
77     }
78     break;
79   }
80
81   return aVariant;
82 }
83
84 int HYDROGUI_ZLevelsModel::rowCount( const QModelIndex &theParent ) const
85 {
86   return myObjects.count();
87 }
88
89 void HYDROGUI_ZLevelsModel::setObjects( const Object2VisibleList& theObjects )
90 {
91   myObjects = theObjects;
92
93   reset();
94 }
95
96 HYDROGUI_ZLevelsModel::ObjectList HYDROGUI_ZLevelsModel::getObjects() const
97 {
98   ObjectList anObjects;
99
100   foreach( const Object2Visible& anItem, myObjects ) {
101     anObjects << anItem.first;
102   }
103
104   return anObjects;
105 }
106
107 bool HYDROGUI_ZLevelsModel::isObjectVisible( int theIndex ) const
108 {
109   bool isVisible = false;
110
111   if ( theIndex >= 0 && theIndex < myObjects.count() ) {
112     isVisible = myObjects.at( theIndex ).second;
113   }
114
115   return isVisible;
116 }
117
118 QVariant HYDROGUI_ZLevelsModel::headerData( int theSection,
119                                             Qt::Orientation theOrientation,
120                                             int theRole ) const
121 {
122   if( theOrientation==Qt::Horizontal && theRole==Qt::DisplayRole )
123   {
124     switch( theSection )
125     {
126     case 0:
127       return tr( "VISIBLE" );
128     case 1:
129       return tr( "OBJECT_NAME" );
130     };
131   }
132   return QVariant();
133 }
134
135 Qt::ItemFlags HYDROGUI_ZLevelsModel::flags( const QModelIndex& theIndex ) const
136 {
137   Qt::ItemFlags aDefaultFlags = QAbstractListModel::flags( theIndex );
138   if( theIndex.isValid() )
139     return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | aDefaultFlags;
140   else
141     return Qt::ItemIsDropEnabled | aDefaultFlags;
142 }
143
144 QMimeData* HYDROGUI_ZLevelsModel::mimeData( const QModelIndexList& theIndices ) const
145 {
146   QMimeData* aMimeData = new QMimeData();
147   QByteArray anEncodedData;
148   QDataStream aStream( &anEncodedData, QIODevice::WriteOnly );
149
150   QList<int> anIdsList = getIds( theIndices );
151   foreach( int anId, anIdsList )
152     aStream << anId;
153
154   aMimeData->setData( OBJ_LIST_MIME_TYPE, anEncodedData );
155   return aMimeData;
156 }
157
158 QStringList HYDROGUI_ZLevelsModel::mimeTypes() const
159 {
160   QStringList aTypes;
161   aTypes << OBJ_LIST_MIME_TYPE;
162   return aTypes;
163 }
164
165 bool HYDROGUI_ZLevelsModel::dropMimeData( const QMimeData* theData, Qt::DropAction theAction,
166                                           int theRow, int theColumn, const QModelIndex& theParent )
167 {
168   if( theAction == Qt::IgnoreAction)
169     return true;
170
171   if( !theData->hasFormat( OBJ_LIST_MIME_TYPE ))
172     return false;
173
174   if( theColumn > 0 )
175     return false;
176
177   int aDropItemId = theParent.row();
178
179   QByteArray anEncodedData = theData->data( OBJ_LIST_MIME_TYPE );
180   QDataStream aStream( &anEncodedData, QIODevice::ReadOnly );
181   QList<int> anIdsList;
182   while( !aStream.atEnd() )
183   {
184     int anId;
185     aStream >> anId;
186     anIdsList << anId;
187   }
188   move( anIdsList, DragAndDrop, aDropItemId );
189   return true;
190 }
191
192 Qt::DropActions HYDROGUI_ZLevelsModel::supportedDropActions() const
193 {
194   return Qt::MoveAction | Qt::CopyAction;
195 }
196
197 QList<int> HYDROGUI_ZLevelsModel::getIds( const QModelIndexList& theIndexes, bool theIsToSort ) const
198 {
199   QList<int> anIds;
200   foreach( const QModelIndex& anIndex, theIndexes ) {
201     anIds << anIndex.row();
202   }
203
204   if ( theIsToSort ) {
205     qSort( anIds );
206   }
207
208   return anIds;
209 }
210
211 bool HYDROGUI_ZLevelsModel::move( const int theItem, const OpType theType,
212                                   bool theIsVisibleOnly, const int theDropItem )
213 {
214   bool aRes = false;
215   if ( theItem < 0 || theItem >= myObjects.count() ) {
216     return aRes;
217   }
218
219   int aDestinationIndex = -1;
220
221   switch ( theType ) {
222     case Up:
223       if ( theItem > 0 ) {
224         aDestinationIndex = theItem - 1;
225         if ( theIsVisibleOnly ) {
226           while ( aDestinationIndex >= 0 && !isObjectVisible( aDestinationIndex ) ) {
227             aDestinationIndex--;
228           }
229         }
230       }
231       break;
232     case Down:
233       if ( theItem < myObjects.count() - 1 ) {
234         aDestinationIndex = theItem + 1;
235         if ( theIsVisibleOnly ) {
236           while ( aDestinationIndex < myObjects.count() && !isObjectVisible( aDestinationIndex ) ) {
237             aDestinationIndex++;
238           }
239         }
240       }
241       break;
242     case Top:
243       if ( theItem > 0 ) {
244         aDestinationIndex = 0;
245       }
246       break;
247     case Bottom:
248       if ( theItem < myObjects.count() - 1 ) {
249         aDestinationIndex = myObjects.count() - 1;
250       }
251       break;
252   }
253
254   if ( aDestinationIndex >= 0 && aDestinationIndex < myObjects.count() ) {
255     int aDestinationRow = (theType == Up || theType == Top) ? aDestinationIndex : aDestinationIndex + 1;
256     if ( beginMoveRows( QModelIndex(), theItem, theItem, QModelIndex(), aDestinationRow ) ) {
257       myObjects.move( theItem, aDestinationIndex );
258       endMoveRows();
259       aRes = true;
260     }
261   }
262         
263   return aRes;
264 }
265
266 bool HYDROGUI_ZLevelsModel::move( const QList<int>& theItems, const OpType theType, 
267                                   bool theIsVisibleOnly, const int theDropItem )
268 {
269   bool aRes = true;
270
271   bool isReverse = theType == Top || theType == Down;
272   QListIterator<int> anIt( theItems );
273   int aShift = 0;
274   if ( isReverse ) {
275     anIt.toBack();
276     while ( anIt.hasPrevious() ) {
277       int anId = anIt.previous();
278       if ( theType == Top ) {
279         anId += aShift;
280         aShift++;
281       }
282       if ( !move( anId, theType, theIsVisibleOnly, theDropItem ) ) {
283         aRes = false;
284         break;
285       }
286     }
287   } else {
288     while ( anIt.hasNext() ) {
289       int anId = anIt.next();
290       if ( theType == Bottom ) {
291         anId -= aShift;
292         aShift++;
293       }
294       if ( !move( anId, theType, theIsVisibleOnly, theDropItem ) ) {
295         aRes = false;
296         break;
297       }
298     }
299   }
300
301   // reset(); //TODO dataChanged?
302
303   return aRes;
304 }
305