]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphiniconsview.cpp
compile++
[dolphin.git] / src / dolphiniconsview.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz *
3 * peter.penz@gmx.at *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 #include "dolphiniconsview.h"
22 #include <qpainter.h>
23 //Added by qt3to4:
24 #include <QDragMoveEvent>
25 #include <QDropEvent>
26 #include <Q3ValueList>
27 #include <QPixmap>
28 #include <QMouseEvent>
29 #include <QDragEnterEvent>
30 #include <kiconeffect.h>
31 #include <kapplication.h>
32 #include <qobject.h>
33 #include <kglobalsettings.h>
34 #include <qclipboard.h>
35 #include <assert.h>
36 #include <kaction.h>
37 #include <kstdaction.h>
38 #include <kfileitem.h>
39 #include <kactioncollection.h>
40
41 #include "dolphinview.h"
42 #include "viewproperties.h"
43 #include "dolphin.h"
44 #include "dolphinstatusbar.h"
45 #include "dolphinsettings.h"
46 #include "iconsmodesettings.h"
47
48 DolphinIconsView::DolphinIconsView(DolphinView* parent, LayoutMode layoutMode) :
49 KFileIconView(parent, 0),
50 m_previewIconSize(-1),
51 m_layoutMode(layoutMode),
52 m_dolphinView(parent)
53 {
54 setAcceptDrops(true);
55 setMode(K3IconView::Execute);
56 setSelectionMode(KFile::Extended);
57 Dolphin& dolphin = Dolphin::mainWin();
58
59 connect(this, SIGNAL(onItem(Q3IconViewItem*)),
60 this, SLOT(slotOnItem(Q3IconViewItem*)));
61 connect(this, SIGNAL(onViewport()),
62 this, SLOT(slotOnViewport()));
63 connect(this, SIGNAL(contextMenuRequested(Q3IconViewItem*, const QPoint&)),
64 this, SLOT(slotContextMenuRequested(Q3IconViewItem*, const QPoint&)));
65 connect(this, SIGNAL(selectionChanged()),
66 &dolphin, SLOT(slotSelectionChanged()));
67 connect(&dolphin, SIGNAL(activeViewChanged()),
68 this, SLOT(slotActivationUpdate()));
69 connect(this, SIGNAL(itemRenamed(Q3IconViewItem*, const QString&)),
70 this, SLOT(slotItemRenamed(Q3IconViewItem*, const QString&)));
71 connect(this, SIGNAL(dropped(QDropEvent*, const KURL::List&, const KURL&)),
72 parent, SLOT(slotURLListDropped(QDropEvent*, const KURL::List&, const KURL&)));
73
74 QClipboard* clipboard = QApplication::clipboard();
75 connect(clipboard, SIGNAL(dataChanged()),
76 this, SLOT(slotUpdateDisabledItems()));
77
78 // KFileIconView creates two actions for zooming, which are directly connected to the
79 // slots KFileIconView::zoomIn() and KFileIconView::zoomOut(). As this behavior is not
80 // wanted and the slots are not virtual, the actions are disabled here.
81 KAction* zoomInAction = actionCollection()->action("zoomIn");
82 assert(zoomInAction != 0);
83 zoomInAction->setEnabled(false);
84
85 KAction* zoomOutAction = actionCollection()->action("zoomOut");
86 assert(zoomOutAction != 0);
87 zoomOutAction->setEnabled(false);
88
89 setItemsMovable(true);
90 setWordWrapIconText(true);
91 if (m_layoutMode == Previews) {
92 showPreviews();
93 }
94 refreshSettings();
95 }
96
97 DolphinIconsView::~DolphinIconsView()
98 {
99 }
100
101 void DolphinIconsView::setLayoutMode(LayoutMode mode)
102 {
103 if (m_layoutMode != mode) {
104 m_layoutMode = mode;
105 refreshSettings();
106 }
107 }
108
109 void DolphinIconsView::beginItemUpdates()
110 {
111 }
112
113 void DolphinIconsView::endItemUpdates()
114 {
115 arrangeItemsInGrid();
116
117 // TODO: KFileIconView does not emit any signal when the preview
118 // has been finished. Using a delay of 300 ms is a temporary workaround
119 // until the DolphinIconsView will implement the previews by it's own in
120 // future releases.
121 QTimer::singleShot(300, this, SLOT(slotUpdateDisabledItems()));
122
123 const KFileIconViewItem* item = static_cast<const KFileIconViewItem*>(firstItem());
124 if (item != 0) {
125 setCurrentItem(item->fileInfo());
126 }
127
128 int index = 0;
129 const Q3ValueList<URLNavigator::HistoryElem> history = m_dolphinView->urlHistory(index);
130 if (!history.isEmpty()) {
131 KFileView* fileView = static_cast<KFileView*>(this);
132 fileView->setCurrentItem(history[index].currentFileName());
133 setContentsPos(history[index].contentsX(), history[index].contentsY());
134 }
135 }
136
137 void DolphinIconsView::refreshSettings()
138 {
139 const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
140 assert(settings != 0);
141
142 setIconSize(settings->iconSize());
143
144 const Q3IconView::Arrangement arrangement = settings->arrangement() == "LeftToRight" ? // TODO: use enum directly in settings
145 Q3IconView::LeftToRight : Q3IconView::TopToBottom;
146 const Q3IconView::ItemTextPos textPos = (arrangement == Q3IconView::LeftToRight) ?
147 Q3IconView::Bottom :
148 Q3IconView::Right;
149 setArrangement(arrangement);
150 setItemTextPos(textPos);
151
152 // TODO: tempory crash; will get changed anyway for KDE 4
153 /*setGridX(settings->gridWidth());
154 setGridY(settings->gridHeight());
155 setSpacing(settings->gridSpacing());*/
156
157 QFont adjustedFont(font());
158 adjustedFont.setFamily(settings->fontFamily());
159 adjustedFont.setPointSize(settings->fontSize());
160 setFont(adjustedFont);
161 setIconTextHeight(settings->numberOfTexlines());
162
163 if (m_layoutMode == Previews) {
164 // There is no getter method for the current size in KFileIconView. To
165 // prevent a flickering the current size is stored in m_previewIconSize and
166 // setPreviewSize is only invoked if the size really has changed.
167 showPreviews();
168
169 const int size = settings->previewSize();
170 if (size != m_previewIconSize) {
171 m_previewIconSize = size;
172 setPreviewSize(size);
173 }
174 }
175 }
176
177 void DolphinIconsView::zoomIn()
178 {
179 if (isZoomInPossible()) {
180 IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
181 const int textWidthHint = DolphinSettings::instance().textWidthHint(); // TODO: remove for KDE4
182
183 const int iconSize = increasedIconSize(settings->iconSize());
184 settings->setIconSize(iconSize);
185
186 if (m_layoutMode == Previews) {
187 const int previewSize = increasedIconSize(settings->previewSize());
188 settings->setPreviewSize(previewSize);
189 }
190
191 DolphinSettings::instance().calculateGridSize(textWidthHint); // TODO: remove for KDE4
192 ItemEffectsManager::zoomIn();
193 }
194 }
195
196 void DolphinIconsView::zoomOut()
197 {
198 if (isZoomOutPossible()) {
199 IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
200 const int textWidthHint = DolphinSettings::instance().textWidthHint(); // TODO: remove for KDE4
201
202 const int iconSize = decreasedIconSize(settings->iconSize());
203 settings->setIconSize(iconSize);
204
205 if (m_layoutMode == Previews) {
206 const int previewSize = decreasedIconSize(settings->previewSize());
207 settings->setPreviewSize(previewSize);
208 }
209
210 DolphinSettings::instance().calculateGridSize(textWidthHint); // TODO: remove for KDE4
211 ItemEffectsManager::zoomOut();
212 }
213 }
214
215 bool DolphinIconsView::isZoomInPossible() const
216 {
217 IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
218 const int size = (m_layoutMode == Icons) ? settings->iconSize() : settings->previewSize();
219 return size < K3Icon::SizeEnormous;
220 }
221
222 bool DolphinIconsView::isZoomOutPossible() const
223 {
224 IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
225 return settings->iconSize() > K3Icon::SizeSmall;
226 }
227
228 void DolphinIconsView::arrangeItemsInGrid( bool updated )
229 {
230
231 KFileIconView::arrangeItemsInGrid(updated);
232
233 if (m_layoutMode == Previews) {
234 // The class KFileIconView has a bug when the size of the previews differs from the size
235 // of the icons: For specific MIME types the y-position and the height is calculated in
236 // a wrong manner. The following code bypasses this issue. No bugreport has been submitted
237 // as this functionality is not used by any KDE3 application and the core developers are
238 // busy enough for KDE4 now :-)
239
240 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(Q3IconView::firstItem());
241 QString mimetype;
242 while (item != 0) {
243 mimetype = item->fileInfo()->mimetype();
244 const bool fixSize = mimetype.contains("text") ||
245 mimetype.contains("application/x-");
246 if (fixSize) {
247 item->setPixmapSize(QSize(m_previewIconSize, m_previewIconSize));
248 }
249 item = static_cast<KFileIconViewItem *>(item->nextItem());
250 }
251 }
252 }
253
254 void DolphinIconsView::setContextPixmap(void* context,
255 const QPixmap& pixmap)
256 {
257 reinterpret_cast<KFileIconViewItem*>(context)->setPixmap(pixmap);
258 }
259
260 const QPixmap* DolphinIconsView::contextPixmap(void* context)
261 {
262 return reinterpret_cast<KFileIconViewItem*>(context)->pixmap();
263 }
264
265 void* DolphinIconsView::firstContext()
266 {
267 return reinterpret_cast<void*>(firstItem());
268 }
269
270 void* DolphinIconsView::nextContext(void* context)
271 {
272 KFileIconViewItem* iconViewItem = reinterpret_cast<KFileIconViewItem*>(context);
273 return reinterpret_cast<void*>(iconViewItem->nextItem());
274 }
275
276 KFileItem* DolphinIconsView::contextFileInfo(void* context)
277 {
278 return reinterpret_cast<KFileIconViewItem*>(context)->fileInfo();
279 }
280
281 void DolphinIconsView::contentsMousePressEvent(QMouseEvent* event)
282 {
283 KFileIconView::contentsMousePressEvent(event);
284 resetActivatedItem();
285 emit signalRequestActivation();
286 m_dolphinView->statusBar()->clear();
287 }
288
289 void DolphinIconsView::contentsMouseReleaseEvent(QMouseEvent* event)
290 {
291 KFileIconView::contentsMouseReleaseEvent(event);
292
293 // The KFileIconView does not send any selectionChanged signal if
294 // a selection is done by using the "select-during-button-pressed" feature.
295 // Hence inform Dolphin about the selection change manually:
296 Dolphin::mainWin().slotSelectionChanged();
297 }
298
299 void DolphinIconsView::drawBackground(QPainter* painter, const QRect& rect)
300 {
301 if (m_dolphinView->isActive()) {
302 KFileIconView::drawBackground(painter, rect);
303 }
304 else {
305 const QBrush brush(colorGroup().background());
306 painter->fillRect(0, 0, width(), height(), brush);
307 }
308 }
309
310 Q3DragObject* DolphinIconsView::dragObject()
311 {
312 KUrl::List urls;
313 QListIterator<KFileItem*> it(*KFileView::selectedItems());
314 while (it.hasNext()) {
315 KFileItem *item = it.next();
316 urls.append(item->url());
317 }
318
319 QPixmap pixmap;
320 if(urls.count() > 1) {
321 pixmap = DesktopIcon("kmultiple", iconSize());
322 }
323 else {
324 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(currentItem());
325 if ((item != 0) && (item->pixmap() != 0)) {
326 pixmap = *(item->pixmap());
327 }
328 }
329
330 if (pixmap.isNull()) {
331 pixmap = currentFileItem()->pixmap(iconSize());
332 }
333
334 /* This should be ported to QMimeData
335 Q3DragObject* dragObj = new KURLDrag(urls, widget());
336 dragObj->setPixmap(pixmap);
337 return dragObj;
338 */
339 return 0;
340 }
341
342 void DolphinIconsView::contentsDragEnterEvent(QDragEnterEvent* event)
343 {
344 // TODO: The method KFileIconView::contentsDragEnterEvent() does
345 // not allow drag and drop inside itself, which prevents the possability
346 // to move a file into a directory. As the method KFileIconView::acceptDrag()
347 // is not virtual, we must overwrite the method
348 // KFileIconView::contentsDragEnterEvent() and do some cut/copy/paste for this
349 // usecase. Corresponding to the documentation the method KFileIconView::acceptDrag()
350 // will get virtual in KDE 4, which will simplify the code.
351
352 if (event->source() != this) {
353 KFileIconView::contentsDragEnterEvent(event);
354 return;
355 }
356
357 KUrl::List uriList = KUrl::List::fromMimeData( event->mimeData() );
358 const bool accept = !uriList.isEmpty() &&
359 (event->action() == QDropEvent::Copy ||
360 event->action() == QDropEvent::Move ||
361 event->action() == QDropEvent::Link );
362 if (accept) {
363 event->acceptAction();
364 }
365 else {
366 event->ignore();
367 }
368 }
369
370 void DolphinIconsView::contentsDragMoveEvent(QDragMoveEvent* event)
371 {
372 KFileIconView::contentsDragMoveEvent(event);
373
374 // If a dragging is done above a directory, show the icon as 'active' for
375 // a visual feedback
376 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos())));
377
378 bool showActive = false;
379 if (item != 0) {
380 const KFileItem* fileInfo = item->fileInfo();
381 showActive = (fileInfo != 0) && fileInfo->isDir();
382 }
383
384 if (showActive) {
385 slotOnItem(item);
386 }
387 else {
388 slotOnViewport();
389 }
390 }
391
392 void DolphinIconsView::contentsDropEvent(QDropEvent* event)
393 {
394 // TODO: Most of the following code is a copy of
395 // KFileIconView::contentsDropEvent. See comment in
396 // DolphinIconsView::contentsDragEnterEvent for details.
397
398 if (event->source() != this) {
399 KFileIconView::contentsDropEvent(event);
400 return;
401 }
402
403 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos())));
404 KUrl::List urls = KUrl::List::fromMimeData( event->mimeData() );
405 const bool accept = !urls.isEmpty() &&
406 (event->action() == QDropEvent::Copy ||
407 event->action() == QDropEvent::Move ||
408 event->action() == QDropEvent::Link ) &&
409 (item != 0);
410 if (!accept) {
411 return;
412 }
413
414 KFileItem* fileItem = item->fileInfo();
415 if (!fileItem->isDir()) {
416 // the file is not a directory, hence don't accept any drop
417 return;
418 }
419 emit dropped(event, fileItem);
420 if (!urls.isEmpty()) {
421 emit dropped(event, urls, fileItem != 0 ? fileItem->url() : KUrl());
422 sig->dropURLs(fileItem, event, urls);
423 }
424 }
425
426 void DolphinIconsView::slotOnItem(Q3IconViewItem* item)
427 {
428 assert(item != 0);
429 activateItem(reinterpret_cast<void*>(item));
430
431 KFileItem* fileItem = static_cast<KFileIconViewItem*>(item)->fileInfo();
432 m_dolphinView->requestItemInfo(fileItem->url());
433 }
434
435 void DolphinIconsView::slotOnViewport()
436 {
437 resetActivatedItem();
438 m_dolphinView->requestItemInfo(KUrl());
439 }
440
441 void DolphinIconsView::slotContextMenuRequested(Q3IconViewItem* item,
442 const QPoint& pos)
443 {
444 KFileItem* fileInfo = 0;
445 if (item != 0) {
446 fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo();
447 }
448 m_dolphinView->openContextMenu(fileInfo, pos);
449 }
450
451 void DolphinIconsView::slotItemRenamed(Q3IconViewItem* item,
452 const QString& name)
453 {
454 KFileItem* fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo();
455 m_dolphinView->rename(KUrl(fileInfo->url()), name);
456 }
457
458 void DolphinIconsView::slotActivationUpdate()
459 {
460 update();
461
462 // TODO: there must be a simpler way to say
463 // "update all children"
464 const QList<QObject*> list = children();
465 if (list.isEmpty()) {
466 return;
467 }
468
469 QListIterator<QObject*> it(list);
470 QObject* object = 0;
471 while (it.hasNext()) {
472 object = it.next();
473 if (object->inherits("QWidget")) {
474 QWidget* widget = static_cast<QWidget*>(object);
475 widget->update();
476 }
477 }
478 }
479
480 void DolphinIconsView::slotUpdateDisabledItems()
481 {
482 updateDisabledItems();
483 }
484
485 int DolphinIconsView::increasedIconSize(int size) const
486 {
487 int incSize = 0;
488 switch (size) {
489 case K3Icon::SizeSmall: incSize = K3Icon::SizeSmallMedium; break;
490 case K3Icon::SizeSmallMedium: incSize = K3Icon::SizeMedium; break;
491 case K3Icon::SizeMedium: incSize = K3Icon::SizeLarge; break;
492 case K3Icon::SizeLarge: incSize = K3Icon::SizeHuge; break;
493 case K3Icon::SizeHuge: incSize = K3Icon::SizeEnormous; break;
494 default: assert(false); break;
495 }
496 return incSize;
497 }
498
499 int DolphinIconsView::decreasedIconSize(int size) const
500 {
501 int decSize = 0;
502 switch (size) {
503 case K3Icon::SizeSmallMedium: decSize = K3Icon::SizeSmall; break;
504 case K3Icon::SizeMedium: decSize = K3Icon::SizeSmallMedium; break;
505 case K3Icon::SizeLarge: decSize = K3Icon::SizeMedium; break;
506 case K3Icon::SizeHuge: decSize = K3Icon::SizeLarge; break;
507 case K3Icon::SizeEnormous: decSize = K3Icon::SizeHuge; break;
508 default: assert(false); break;
509 }
510 return decSize;
511 }
512
513 #include "dolphiniconsview.moc"