1 /***************************************************************************
2 File : Folder.cpp
3 Project : SciDAVis
4 --------------------------------------------------------------------
5 Copyright : (C) 2006 by Ion Vasilief,
6 Tilman Benkert,
7 Knut Franke
8 Email (use @ for *) : ion_vasilief*yahoo.fr, thzs*gmx.net,
9 knut.franke*gmx.de
10 Description : Folder for the project explorer
11
12 ***************************************************************************/
13
14 /***************************************************************************
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 * This program is distributed in the hope that it will be useful, *
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
24 * GNU General Public License for more details. *
25 * *
26 * You should have received a copy of the GNU General Public License *
27 * along with this program; if not, write to the Free Software *
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
29 * Boston, MA 02110-1301 USA *
30 * *
31 ***************************************************************************/
32 #include "Folder.h"
33
34 #include <qobject.h>
35 #include <qdatetime.h>
36 #include <qpixmap.h>
37
38 #include <qevent.h>
39 #include <qpoint.h>
40 #include <qmessagebox.h>
41 #include <qstringlist.h>
42 #include <qapplication.h>
43 #include <qcursor.h>
44 // Added by qt3to4:
45 #include <QKeyEvent>
46 #include <QDropEvent>
47 #include <QMouseEvent>
48 #include <QDrag>
49
Folder(const QString & name)50 Folder::Folder(const QString &name) : d_active_window(0)
51 {
52 QObject::setObjectName(name);
53 birthdate = QLocale().toString(QDateTime::currentDateTime());
54
55 // FIXME: This doesn't work anymore in Qt4, need alternative method
56 // lstWindows.setAutoDelete( true );
57 }
58
folders() const59 QList<Folder *> Folder::folders() const
60 {
61 QList<Folder *> lst;
62 foreach (QObject *f, children())
63 lst.append((Folder *)f);
64 return lst;
65 }
66
subfolders()67 QStringList Folder::subfolders()
68 {
69 QStringList list = QStringList();
70 QObjectList folderList = children();
71 if (!folderList.isEmpty()) {
72 QObject *f;
73 foreach (f, folderList)
74 list << static_cast<Folder *>(f)->name();
75 }
76 return list;
77 }
78
path()79 QString Folder::path()
80 {
81 QString s = "/" + QString(name()) + "/";
82 Folder *parentFolder = (Folder *)parent();
83 while (parentFolder) {
84 s.prepend("/" + QString(parentFolder->name()));
85 parentFolder = (Folder *)parentFolder->parent();
86 }
87 return s;
88 }
89
findSubfolder(const QString & s,bool caseSensitive,bool partialMatch)90 Folder *Folder::findSubfolder(const QString &s, bool caseSensitive, bool partialMatch)
91 {
92 QObjectList folderList = children();
93 if (!folderList.isEmpty()) {
94 QObject *f;
95
96 foreach (f, folderList) {
97 QString name = static_cast<Folder *>(f)->name();
98 if (partialMatch) {
99 if (caseSensitive && name.startsWith(s, Qt::CaseSensitive))
100 return static_cast<Folder *>(f);
101 else if (!caseSensitive && name.startsWith(s, Qt::CaseInsensitive))
102 return static_cast<Folder *>(f);
103 } else // partialMatch == false
104 {
105 if (caseSensitive && name == s)
106 return static_cast<Folder *>(f);
107 else if (!caseSensitive && (name.toLower() == s.toLower()))
108 return static_cast<Folder *>(f);
109 }
110 }
111 }
112 return 0;
113 }
114
findWindow(const QString & s,bool windowNames,bool labels,bool caseSensitive,bool partialMatch)115 MyWidget *Folder::findWindow(const QString &s, bool windowNames, bool labels, bool caseSensitive,
116 bool partialMatch)
117 {
118 Qt::CaseSensitivity cs = Qt::CaseSensitive;
119 if (!caseSensitive)
120 cs = Qt::CaseInsensitive;
121 MyWidget *w;
122 foreach (w, lstWindows) {
123 if (windowNames) {
124 QString name = w->name();
125 if (partialMatch && name.startsWith(s, cs))
126 return w;
127 else if (caseSensitive && name == s)
128 return w;
129 else {
130 QString text = s;
131 if (name == text.toLower())
132 return w;
133 }
134 }
135
136 if (labels) {
137 QString label = w->windowLabel();
138 if (partialMatch && label.startsWith(s, cs))
139 return w;
140 else if (caseSensitive && label == s)
141 return w;
142 else {
143 QString text = s;
144 if (label == text.toLower())
145 return w;
146 }
147 }
148 }
149 return 0;
150 }
151
window(const QString & name,const char * cls,bool recursive)152 MyWidget *Folder::window(const QString &name, const char *cls, bool recursive)
153 {
154 foreach (MyWidget *w, lstWindows)
155 if (w->inherits(cls) && name == w->name().mid(0, w->name().indexOf("@")))
156 return w;
157 if (!recursive)
158 return NULL;
159 foreach (QObject *f, children()) {
160 MyWidget *w = ((Folder *)f)->window(name, cls, true);
161 if (w)
162 return w;
163 }
164 return NULL;
165 }
166
rootFolder()167 Folder *Folder::rootFolder()
168 {
169 Folder *i = this;
170 while (i->parent())
171 i = (Folder *)i->parent();
172 return i;
173 }
174
175 /*****************************************************************************
176 *
177 * Class FolderListItem
178 *
179 *****************************************************************************/
180
FolderListItem(QTreeWidget * parent,Folder * f)181 FolderListItem::FolderListItem(QTreeWidget *parent, Folder *f)
182 : QTreeWidgetItem(parent, FolderListItem::FolderType)
183 {
184 myFolder = f;
185
186 setText(0, f->name());
187 setExpanded(true);
188 setActive(true);
189 setFlags(flags() | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
190 }
191
FolderListItem(FolderListItem * parent,Folder * f)192 FolderListItem::FolderListItem(FolderListItem *parent, Folder *f)
193 : QTreeWidgetItem(parent, FolderListItem::FolderType)
194 {
195 myFolder = f;
196
197 setText(0, f->name());
198 setExpanded(true);
199 setActive(true);
200 }
201
setActive(bool o)202 void FolderListItem::setActive(bool o)
203 {
204 if (o)
205 setIcon(0, QIcon(QPixmap(":/folder_open.xpm")));
206 else
207 setIcon(0, QIcon(QPixmap(":/folder_closed.xpm")));
208
209 setSelected(o);
210 }
211
isChildOf(FolderListItem * src)212 bool FolderListItem::isChildOf(FolderListItem *src)
213 {
214 FolderListItem *parent = (FolderListItem *)this->parent();
215 while (parent) {
216 if (parent == src)
217 return true;
218
219 parent = (FolderListItem *)parent->parent();
220 }
221 return false;
222 }
223
depth()224 int FolderListItem::depth()
225 {
226 int c = 0;
227 FolderListItem *parent = (FolderListItem *)this->parent();
228 while (parent) {
229 c++;
230 parent = (FolderListItem *)parent->parent();
231 }
232 return c;
233 }
234
setData(int column,int role,const QVariant & value)235 void FolderListItem::setData(int column, int role, const QVariant &value)
236 {
237 if ((role == Qt::EditRole) && (column == 0)
238 && (value
239 != this->text(
240 0))) { // data should be accepted or rejected on slot connected to this signal
241 emit this->folderListView()->itemRenamed(this, column, value.toString());
242 } else {
243 QTreeWidgetItem::setData(column, role, value);
244 }
245 }
246 /*****************************************************************************
247 *
248 * Class FolderListView
249 *
250 *****************************************************************************/
251
FolderListView(const QString & name)252 FolderListView::FolderListView(const QString &name) : mousePressed(false)
253 {
254 setObjectName(name.toLocal8Bit());
255 setAcceptDrops(true);
256 viewport()->setAcceptDrops(true);
257 setDropIndicatorShown(true);
258 }
259
startDrag(Qt::DropActions supportedActions)260 void FolderListView::startDrag(Qt::DropActions supportedActions)
261 {
262 QTreeWidgetItem *item = currentItem();
263 if (!item)
264 return;
265
266 if (item == topLevelItem(0) && item->treeWidget()->rootIsDecorated())
267 return; // it's the project folder so we don't want the user to move it
268
269 QPixmap pix;
270 if (item->type() == FolderListItem::FolderType)
271 pix = QPixmap(":/folder_closed.xpm");
272 else
273 pix = item->icon(0).pixmap(QSize());
274
275 QDrag *drag = new QDrag(viewport());
276 drag->setPixmap(pix);
277 drag->setHotSpot(QPoint(pix.width() / 2, pix.height() / 2));
278
279 QList<QTreeWidgetItem *> lst;
280 QTreeWidgetItemIterator it(this);
281 while (*it) {
282 if ((*it)->isSelected())
283 lst.append(*it);
284 it++;
285 }
286
287 emit dragItems(lst);
288 drag->setMimeData(mimeData(lst));
289 drag->exec(supportedActions);
290 }
291
dropEvent(QDropEvent * e)292 void FolderListView::dropEvent(QDropEvent *e)
293 {
294 QTreeWidgetItem *dest = itemAt(e->pos());
295 if (dest && dest->type() == FolderListItem::FolderType) {
296 if (dropIndicatorPosition() != QAbstractItemView::OnItem) {
297 e->ignore();
298 } else {
299 emit dropItems(dest);
300 e->accept();
301 this->setState(QAbstractItemView::NoState); // hack to clear DraggingState
302 }
303 mousePressed = false;
304 } else
305 e->ignore();
306 }
307
keyPressEvent(QKeyEvent * e)308 void FolderListView::keyPressEvent(QKeyEvent *e)
309 {
310 if (isRenaming()) {
311 e->ignore();
312 return;
313 }
314 QTreeWidgetItem *item = currentItem();
315 if (!item) {
316 QTreeWidget::keyPressEvent(e);
317 return;
318 }
319
320 if (item->type() == FolderListItem::FolderType
321 && (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return)) {
322 emit itemDoubleClicked(item, 0);
323 e->accept();
324 } else if (e->key() == Qt::Key_F2) {
325 if (item)
326 emit renameItem(item, 0);
327 e->accept();
328 } else if (e->key() == Qt::Key_A && e->modifiers() == Qt::ControlModifier) {
329 selectAll();
330 e->accept();
331 } else if (e->key() == Qt::Key_F7) {
332 emit addFolderItem();
333 e->accept();
334 } else if (e->key() == Qt::Key_F8) {
335 emit deleteSelection();
336 e->accept();
337 } else
338 QTreeWidget::keyPressEvent(e);
339 }
340
mouseDoubleClickEvent(QMouseEvent * e)341 void FolderListView::mouseDoubleClickEvent(QMouseEvent *e)
342 {
343 if (isRenaming()) {
344 e->ignore();
345 return;
346 }
347
348 QTreeWidget::mouseDoubleClickEvent(e);
349 }
350
mousePressEvent(QMouseEvent * e)351 void FolderListView::mousePressEvent(QMouseEvent *e)
352 {
353 QTreeWidget::mousePressEvent(e);
354 if (e->button() == Qt::LeftButton) {
355 presspos = e->pos();
356 mousePressed = true;
357 }
358 }
359
mouseMoveEvent(QMouseEvent * e)360 void FolderListView::mouseMoveEvent(QMouseEvent *e)
361 {
362 if (mousePressed
363 && (presspos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
364 mousePressed = false;
365 QTreeWidgetItem *item = itemAt(presspos);
366 if (item)
367 startDrag();
368 }
369 }
370
adjustColumns()371 void FolderListView::adjustColumns()
372 {
373 for (int i = 0; i < columnCount(); i++)
374 resizeColumnToContents(i);
375 }
376
377 /*****************************************************************************
378 *
379 * Class WindowListItem
380 *
381 *****************************************************************************/
382
WindowListItem(QTreeWidget * parent,MyWidget * w)383 WindowListItem::WindowListItem(QTreeWidget *parent, MyWidget *w)
384 : QTreeWidgetItem(parent, WindowListItem::WindowType)
385 {
386 myWindow = w;
387 this->treeWidget()->setCurrentItem(
388 this, 0, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
389
390 setFlags((flags() | Qt::ItemIsDragEnabled) & ~Qt::ItemIsDropEnabled);
391 }
392
setData(int column,int role,const QVariant & value)393 void WindowListItem::setData(int column, int role, const QVariant &value)
394 {
395 if (role
396 == Qt::EditRole) { // data should be accepted or rejected on slot connected to this signal
397 if (column == 0)
398 emit this->folderListView()->itemRenamed(this, column, value.toString());
399 } else {
400 QTreeWidgetItem::setData(column, role, value);
401 }
402 }
403