]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphiniconsview.cpp
commited initial version of Dolphin
[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 <kurldrag.h>
35 #include <qclipboard.h>
36 #include <assert.h>
37 #include <kaction.h>
38 #include <kstdaction.h>
39 #include <kfileitem.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(KIconView::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 < KIcon::SizeEnormous;
220 }
221
222 bool DolphinIconsView::isZoomOutPossible() const
223 {
224 IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
225 return settings->iconSize() > KIcon::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 KFileItemListIterator it(*KFileView::selectedItems());
314 while (it.current() != 0) {
315 urls.append((*it)->url());
316 ++it;
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 Q3DragObject* dragObj = new KURLDrag(urls, widget());
335 dragObj->setPixmap(pixmap);
336 return dragObj;
337 }
338
339 void DolphinIconsView::contentsDragEnterEvent(QDragEnterEvent* event)
340 {
341 // TODO: The method KFileIconView::contentsDragEnterEvent() does
342 // not allow drag and drop inside itself, which prevents the possability
343 // to move a file into a directory. As the method KFileIconView::acceptDrag()
344 // is not virtual, we must overwrite the method
345 // KFileIconView::contentsDragEnterEvent() and do some cut/copy/paste for this
346 // usecase. Corresponding to the documentation the method KFileIconView::acceptDrag()
347 // will get virtual in KDE 4, which will simplify the code.
348
349 if (event->source() != this) {
350 KFileIconView::contentsDragEnterEvent(event);
351 return;
352 }
353
354 const bool accept = KURLDrag::canDecode(event) &&
355 (event->action() == QDropEvent::Copy ||
356 event->action() == QDropEvent::Move ||
357 event->action() == QDropEvent::Link );
358 if (accept) {
359 event->acceptAction();
360 }
361 else {
362 event->ignore();
363 }
364 }
365
366 void DolphinIconsView::contentsDragMoveEvent(QDragMoveEvent* event)
367 {
368 KFileIconView::contentsDragMoveEvent(event);
369
370 // If a dragging is done above a directory, show the icon as 'active' for
371 // a visual feedback
372 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos())));
373
374 bool showActive = false;
375 if (item != 0) {
376 const KFileItem* fileInfo = item->fileInfo();
377 showActive = (fileInfo != 0) && fileInfo->isDir();
378 }
379
380 if (showActive) {
381 slotOnItem(item);
382 }
383 else {
384 slotOnViewport();
385 }
386 }
387
388 void DolphinIconsView::contentsDropEvent(QDropEvent* event)
389 {
390 // TODO: Most of the following code is a copy of
391 // KFileIconView::contentsDropEvent. See comment in
392 // DolphinIconsView::contentsDragEnterEvent for details.
393
394 if (event->source() != this) {
395 KFileIconView::contentsDropEvent(event);
396 return;
397 }
398
399 KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos())));
400 const bool accept = KURLDrag::canDecode(event) &&
401 (event->action() == QDropEvent::Copy ||
402 event->action() == QDropEvent::Move ||
403 event->action() == QDropEvent::Link ) &&
404 (item != 0);
405 if (!accept) {
406 return;
407 }
408
409 KFileItem* fileItem = item->fileInfo();
410 if (!fileItem->isDir()) {
411 // the file is not a directory, hence don't accept any drop
412 return;
413 }
414 emit dropped(event, fileItem);
415 KURL::List urls;
416 if (KURLDrag::decode(event, urls) && !urls.isEmpty()) {
417 emit dropped(event, urls, fileItem != 0 ? fileItem->url() : KURL());
418 sig->dropURLs(fileItem, event, urls);
419 }
420 }
421
422 void DolphinIconsView::slotOnItem(Q3IconViewItem* item)
423 {
424 assert(item != 0);
425 activateItem(reinterpret_cast<void*>(item));
426
427 KFileItem* fileItem = static_cast<KFileIconViewItem*>(item)->fileInfo();
428 m_dolphinView->requestItemInfo(fileItem->url());
429 }
430
431 void DolphinIconsView::slotOnViewport()
432 {
433 resetActivatedItem();
434 m_dolphinView->requestItemInfo(KURL());
435 }
436
437 void DolphinIconsView::slotContextMenuRequested(Q3IconViewItem* item,
438 const QPoint& pos)
439 {
440 KFileItem* fileInfo = 0;
441 if (item != 0) {
442 fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo();
443 }
444 m_dolphinView->openContextMenu(fileInfo, pos);
445 }
446
447 void DolphinIconsView::slotItemRenamed(Q3IconViewItem* item,
448 const QString& name)
449 {
450 KFileItem* fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo();
451 m_dolphinView->rename(KURL(fileInfo->url()), name);
452 }
453
454 void DolphinIconsView::slotActivationUpdate()
455 {
456 update();
457
458 // TODO: there must be a simpler way to say
459 // "update all children"
460 const QObjectList* list = children();
461 if (list == 0) {
462 return;
463 }
464
465 QObjectListIterator it(*list);
466 QObject* object = 0;
467 while ((object = it.current()) != 0) {
468 if (object->inherits("QWidget")) {
469 QWidget* widget = static_cast<QWidget*>(object);
470 widget->update();
471 }
472 ++it;
473 }
474 }
475
476 void DolphinIconsView::slotUpdateDisabledItems()
477 {
478 updateDisabledItems();
479 }
480
481 int DolphinIconsView::increasedIconSize(int size) const
482 {
483 int incSize = 0;
484 switch (size) {
485 case KIcon::SizeSmall: incSize = KIcon::SizeSmallMedium; break;
486 case KIcon::SizeSmallMedium: incSize = KIcon::SizeMedium; break;
487 case KIcon::SizeMedium: incSize = KIcon::SizeLarge; break;
488 case KIcon::SizeLarge: incSize = KIcon::SizeHuge; break;
489 case KIcon::SizeHuge: incSize = KIcon::SizeEnormous; break;
490 default: assert(false); break;
491 }
492 return incSize;
493 }
494
495 int DolphinIconsView::decreasedIconSize(int size) const
496 {
497 int decSize = 0;
498 switch (size) {
499 case KIcon::SizeSmallMedium: decSize = KIcon::SizeSmall; break;
500 case KIcon::SizeMedium: decSize = KIcon::SizeSmallMedium; break;
501 case KIcon::SizeLarge: decSize = KIcon::SizeMedium; break;
502 case KIcon::SizeHuge: decSize = KIcon::SizeLarge; break;
503 case KIcon::SizeEnormous: decSize = KIcon::SizeHuge; break;
504 default: assert(false); break;
505 }
506 return decSize;
507 }
508
509 #include "dolphiniconsview.moc"