]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinview.cpp
* allow to toggle the content of split views by the context menu
[dolphin.git] / src / dolphinview.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
3 * Copyright (C) 2006 by Gregor Kališnik <gregor@podnapisi.net> *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include "dolphinview.h"
22
23 #include <QApplication>
24 #include <QClipboard>
25 #include <QKeyEvent>
26 #include <QItemSelection>
27 #include <QBoxLayout>
28 #include <QTimer>
29 #include <QScrollBar>
30
31 #include <kdirmodel.h>
32 #include <kdirlister.h>
33 #include <kfileitemdelegate.h>
34 #include <kglobalsettings.h>
35 #include <klocale.h>
36 #include <kiconeffect.h>
37 #include <kio/netaccess.h>
38 #include <kio/renamedialog.h>
39 #include <kio/previewjob.h>
40 #include <kmimetyperesolver.h>
41 #include <konqmimedata.h>
42 #include <konq_operations.h>
43 #include <kurl.h>
44
45 #include "dolphincolumnview.h"
46 #include "dolphincontroller.h"
47 #include "dolphinsortfilterproxymodel.h"
48 #include "dolphindetailsview.h"
49 #include "dolphiniconsview.h"
50 #include "dolphinitemcategorizer.h"
51 #include "renamedialog.h"
52 #include "viewproperties.h"
53 #include "dolphinsettings.h"
54 #include "dolphin_generalsettings.h"
55
56 DolphinView::DolphinView(QWidget* parent,
57 const KUrl& url,
58 KDirLister* dirLister,
59 KDirModel* dirModel,
60 DolphinSortFilterProxyModel* proxyModel,
61 Mode mode) :
62 QWidget(parent),
63 m_active(true),
64 m_loadingDirectory(false),
65 m_initializeColumnView(false),
66 m_mode(mode),
67 m_topLayout(0),
68 m_controller(0),
69 m_iconsView(0),
70 m_detailsView(0),
71 m_columnView(0),
72 m_fileItemDelegate(0),
73 m_dirModel(dirModel),
74 m_dirLister(dirLister),
75 m_proxyModel(proxyModel)
76 {
77 setFocusPolicy(Qt::StrongFocus);
78 m_topLayout = new QVBoxLayout(this);
79 m_topLayout->setSpacing(0);
80 m_topLayout->setMargin(0);
81
82 QClipboard* clipboard = QApplication::clipboard();
83 connect(clipboard, SIGNAL(dataChanged()),
84 this, SLOT(updateCutItems()));
85
86 connect(m_dirLister, SIGNAL(completed()),
87 this, SLOT(updateCutItems()));
88 connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
89 this, SLOT(generatePreviews(const KFileItemList&)));
90
91 m_controller = new DolphinController(this);
92 m_controller->setUrl(url);
93 connect(m_controller, SIGNAL(requestContextMenu(const QPoint&)),
94 this, SLOT(openContextMenu(const QPoint&)));
95 connect(m_controller, SIGNAL(urlsDropped(const KUrl::List&, const QModelIndex&, QWidget*)),
96 this, SLOT(dropUrls(const KUrl::List&, const QModelIndex&, QWidget*)));
97 connect(m_controller, SIGNAL(sortingChanged(DolphinView::Sorting)),
98 this, SLOT(updateSorting(DolphinView::Sorting)));
99 connect(m_controller, SIGNAL(sortOrderChanged(Qt::SortOrder)),
100 this, SLOT(updateSortOrder(Qt::SortOrder)));
101 connect(m_controller, SIGNAL(itemTriggered(const QModelIndex&)),
102 this, SLOT(triggerItem(const QModelIndex&)));
103 connect(m_controller, SIGNAL(activated()),
104 this, SLOT(activate()));
105 connect(m_controller, SIGNAL(itemEntered(const QModelIndex&)),
106 this, SLOT(showHoverInformation(const QModelIndex&)));
107 connect(m_controller, SIGNAL(viewportEntered()),
108 this, SLOT(clearHoverInformation()));
109
110 createView();
111 m_topLayout->addWidget(itemView());
112 }
113
114 DolphinView::~DolphinView()
115 {
116 }
117
118 const KUrl& DolphinView::url() const
119 {
120 return m_controller->url();
121 }
122
123 KUrl DolphinView::rootUrl() const
124 {
125 return isColumnViewActive() ? m_dirLister->url() : url();
126 }
127
128 void DolphinView::setActive(bool active)
129 {
130 if (active == m_active) {
131 return;
132 }
133
134 m_active = active;
135
136 QColor color = KGlobalSettings::baseColor();
137 if (active) {
138 emit urlChanged(url());
139 emit selectionChanged(selectedItems());
140 } else {
141 color.setAlpha(0);
142 }
143
144 QWidget* viewport = itemView()->viewport();
145 QPalette palette;
146 palette.setColor(viewport->backgroundRole(), color);
147 viewport->setPalette(palette);
148
149 update();
150
151 if (active) {
152 emit activated();
153 }
154 }
155
156 bool DolphinView::isActive() const
157 {
158 return m_active;
159 }
160
161 void DolphinView::setMode(Mode mode)
162 {
163 if (mode == m_mode) {
164 return; // the wished mode is already set
165 }
166
167 m_mode = mode;
168
169 if (isColumnViewActive()) {
170 // When changing the mode in the column view, it makes sense
171 // to go back to the root URL of the column view automatically.
172 // Otherwise there it would not be possible to turn off the column view
173 // without focusing the first column.
174 setUrl(m_dirLister->url());
175 m_controller->setUrl(m_dirLister->url());
176 }
177
178 ViewProperties props(url());
179 props.setViewMode(m_mode);
180
181 createView();
182 startDirLister(url());
183
184 emit modeChanged();
185 }
186
187 DolphinView::Mode DolphinView::mode() const
188 {
189 return m_mode;
190 }
191
192 void DolphinView::setShowPreview(bool show)
193 {
194 ViewProperties props(url());
195 props.setShowPreview(show);
196
197 m_controller->setShowPreview(show);
198 emit showPreviewChanged();
199
200 startDirLister(url(), true);
201 }
202
203 bool DolphinView::showPreview() const
204 {
205 return m_controller->showPreview();
206 }
207
208 void DolphinView::setShowHiddenFiles(bool show)
209 {
210 if (m_dirLister->showingDotFiles() == show) {
211 return;
212 }
213
214 ViewProperties props(url());
215 props.setShowHiddenFiles(show);
216
217 m_dirLister->setShowingDotFiles(show);
218 emit showHiddenFilesChanged();
219
220 startDirLister(url(), true);
221 }
222
223 bool DolphinView::showHiddenFiles() const
224 {
225 return m_dirLister->showingDotFiles();
226 }
227
228 void DolphinView::setCategorizedSorting(bool categorized)
229 {
230 if (!supportsCategorizedSorting() || (categorized == categorizedSorting())) {
231 return;
232 }
233
234 Q_ASSERT(m_iconsView != 0);
235 if (categorized) {
236 Q_ASSERT(m_iconsView->itemCategorizer() == 0);
237 m_iconsView->setItemCategorizer(new DolphinItemCategorizer());
238 } else {
239 KItemCategorizer* categorizer = m_iconsView->itemCategorizer();
240 m_iconsView->setItemCategorizer(0);
241 delete categorizer;
242 }
243
244 ViewProperties props(url());
245 props.setCategorizedSorting(categorized);
246 props.save();
247
248 emit categorizedSortingChanged();
249 }
250
251 bool DolphinView::categorizedSorting() const
252 {
253 if (!supportsCategorizedSorting()) {
254 return false;
255 }
256
257 Q_ASSERT(m_iconsView != 0);
258 return m_iconsView->itemCategorizer() != 0;
259 }
260
261 bool DolphinView::supportsCategorizedSorting() const
262 {
263 return m_iconsView != 0;
264 }
265
266 void DolphinView::selectAll()
267 {
268 selectAll(QItemSelectionModel::Select);
269 }
270
271 void DolphinView::invertSelection()
272 {
273 selectAll(QItemSelectionModel::Toggle);
274 }
275
276 bool DolphinView::hasSelection() const
277 {
278 return itemView()->selectionModel()->hasSelection();
279 }
280
281 void DolphinView::clearSelection()
282 {
283 itemView()->selectionModel()->clear();
284 }
285
286 KFileItemList DolphinView::selectedItems() const
287 {
288 const QAbstractItemView* view = itemView();
289
290 // Our view has a selection, we will map them back to the DirModel
291 // and then fill the KFileItemList.
292 Q_ASSERT((view != 0) && (view->selectionModel() != 0));
293
294 const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection());
295 KFileItemList itemList;
296
297 const QModelIndexList indexList = selection.indexes();
298 QModelIndexList::const_iterator end = indexList.end();
299 for (QModelIndexList::const_iterator it = indexList.begin(); it != end; ++it) {
300 Q_ASSERT((*it).isValid());
301
302 KFileItem* item = m_dirModel->itemForIndex(*it);
303 if (item != 0) {
304 itemList.append(item);
305 }
306 }
307
308 return itemList;
309 }
310
311 KUrl::List DolphinView::selectedUrls() const
312 {
313 KUrl::List urls;
314
315 const KFileItemList list = selectedItems();
316 KFileItemList::const_iterator it = list.begin();
317 const KFileItemList::const_iterator end = list.end();
318 while (it != end) {
319 KFileItem* item = *it;
320 urls.append(item->url());
321 ++it;
322 }
323
324 return urls;
325 }
326
327 KFileItem* DolphinView::fileItem(const QModelIndex index) const
328 {
329 const QModelIndex dirModelIndex = m_proxyModel->mapToSource(index);
330 return m_dirModel->itemForIndex(dirModelIndex);
331 }
332
333 void DolphinView::setContentsPosition(int x, int y)
334 {
335 QAbstractItemView* view = itemView();
336 view->horizontalScrollBar()->setValue(x);
337 view->verticalScrollBar()->setValue(y);
338
339 m_loadingDirectory = false;
340 }
341
342 QPoint DolphinView::contentsPosition() const
343 {
344 const int x = itemView()->horizontalScrollBar()->value();
345 const int y = itemView()->verticalScrollBar()->value();
346 return QPoint(x, y);
347 }
348
349 void DolphinView::zoomIn()
350 {
351 m_controller->triggerZoomIn();
352 }
353
354 void DolphinView::zoomOut()
355 {
356 m_controller->triggerZoomOut();
357 }
358
359 bool DolphinView::isZoomInPossible() const
360 {
361 return m_controller->isZoomInPossible();
362 }
363
364 bool DolphinView::isZoomOutPossible() const
365 {
366 return m_controller->isZoomOutPossible();
367 }
368
369 void DolphinView::setSorting(Sorting sorting)
370 {
371 if (sorting != this->sorting()) {
372 updateSorting(sorting);
373 }
374 }
375
376 DolphinView::Sorting DolphinView::sorting() const
377 {
378 return m_proxyModel->sorting();
379 }
380
381 void DolphinView::setSortOrder(Qt::SortOrder order)
382 {
383 if (sortOrder() != order) {
384 updateSortOrder(order);
385 }
386 }
387
388 Qt::SortOrder DolphinView::sortOrder() const
389 {
390 return m_proxyModel->sortOrder();
391 }
392
393 void DolphinView::setAdditionalInfo(KFileItemDelegate::AdditionalInformation info)
394 {
395 ViewProperties props(url());
396 props.setAdditionalInfo(info);
397
398 m_controller->setShowAdditionalInfo(info != KFileItemDelegate::NoInformation);
399 m_fileItemDelegate->setAdditionalInformation(info);
400
401 emit additionalInfoChanged(info);
402 startDirLister(url(), true);
403 }
404
405 KFileItemDelegate::AdditionalInformation DolphinView::additionalInfo() const
406 {
407 return m_fileItemDelegate->additionalInformation();
408 }
409
410 void DolphinView::reload()
411 {
412 setUrl(url());
413 startDirLister(url(), true);
414 }
415
416 void DolphinView::refresh()
417 {
418 createView();
419 reload();
420 }
421
422 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
423 {
424 QWidget::mouseReleaseEvent(event);
425 setActive(true);;
426 }
427 void DolphinView::activate()
428 {
429 setActive(true);
430 }
431
432 void DolphinView::triggerItem(const QModelIndex& index)
433 {
434 if (!isValidNameIndex(index)) {
435 clearSelection();
436 showHoverInformation(index);
437 return;
438 }
439
440 const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
441 if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) {
442 // items are selected by the user, hence don't trigger the
443 // item specified by 'index'
444 return;
445 }
446
447 KFileItem* item = m_dirModel->itemForIndex(m_proxyModel->mapToSource(index));
448 if (item == 0) {
449 return;
450 }
451
452 // Prefer the local path over the URL. This assures that the
453 // volume space information is correct. Assuming that the URL is media:/sda1,
454 // and the local path is /windows/C: For the URL the space info is related
455 // to the root partition (and hence wrong) and for the local path the space
456 // info is related to the windows partition (-> correct).
457 const QString localPath(item->localPath());
458 KUrl url;
459 if (localPath.isEmpty()) {
460 url = item->url();
461 } else {
462 url = localPath;
463 }
464
465 if (item->isDir()) {
466 setUrl(url);
467 } else if (item->isFile()) {
468 // allow to browse through ZIP and tar files
469 KMimeType::Ptr mime = item->mimeTypePtr();
470 if (mime->is("application/zip")) {
471 url.setProtocol("zip");
472 setUrl(url);
473 } else if (mime->is("application/x-tar") ||
474 mime->is("application/x-tarz") ||
475 mime->is("application/x-bzip-compressed-tar") ||
476 mime->is("application/x-compressed-tar") ||
477 mime->is("application/x-tzo")) {
478 url.setProtocol("tar");
479 setUrl(url);
480 } else {
481 item->run();
482 }
483 } else {
484 item->run();
485 }
486 }
487
488 void DolphinView::generatePreviews(const KFileItemList& items)
489 {
490 if (m_controller->showPreview()) {
491
492 // Must turn QList<KFileItem *> to QList<KFileItem>...
493 QList<KFileItem> itemsToPreview;
494 foreach( KFileItem* it, items )
495 itemsToPreview.append( *it );
496
497 KIO::PreviewJob* job = KIO::filePreview(itemsToPreview, 128);
498 connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
499 this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
500 }
501 }
502
503 void DolphinView::showPreview(const KFileItem& item, const QPixmap& pixmap)
504 {
505 Q_ASSERT(!item.isNull());
506 if (item.url().directory() != m_dirLister->url().path()) {
507 // the preview job is still working on items of an older URL, hence
508 // the item is not part of the directory model anymore
509 return;
510 }
511
512 const QModelIndex idx = m_dirModel->indexForItem(item);
513 if (idx.isValid() && (idx.column() == 0)) {
514 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
515 if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
516 KIconEffect iconEffect;
517 const QPixmap cutPixmap = iconEffect.apply(pixmap, K3Icon::Desktop, K3Icon::DisabledState);
518 m_dirModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole);
519 } else {
520 m_dirModel->setData(idx, QIcon(pixmap), Qt::DecorationRole);
521 }
522 }
523 }
524
525 void DolphinView::emitSelectionChangedSignal()
526 {
527 emit selectionChanged(DolphinView::selectedItems());
528 }
529
530 void DolphinView::startDirLister(const KUrl& url, bool reload)
531 {
532 if (!url.isValid()) {
533 const QString location(url.pathOrUrl());
534 if (location.isEmpty()) {
535 emit errorMessage(i18n("The location is empty."));
536 } else {
537 emit errorMessage(i18n("The location '%1' is invalid.", location));
538 }
539 return;
540 }
541
542 m_cutItemsCache.clear();
543 m_loadingDirectory = true;
544
545 m_dirLister->stop();
546
547 bool openDir = true;
548 bool keepOldDirs = isColumnViewActive() && !m_initializeColumnView;
549 m_initializeColumnView = false;
550
551 if (keepOldDirs) {
552 if (reload) {
553 keepOldDirs = false;
554
555 const KUrl& dirListerUrl = m_dirLister->url();
556 if (dirListerUrl.isValid()) {
557 const KUrl::List dirs = m_dirLister->directories();
558 KUrl url;
559 foreach(url, dirs) {
560 m_dirLister->updateDirectory(url);
561 }
562 openDir = false;
563 }
564 } else if (m_dirLister->directories().contains(url)) {
565 // The dir lister contains the directory already, so
566 // KDirLister::openUrl() may not been invoked twice.
567 m_dirLister->updateDirectory(url);
568 openDir = false;
569 } else {
570 const KUrl& dirListerUrl = m_dirLister->url();
571 if ((dirListerUrl == url) || !m_dirLister->url().isParentOf(url)) {
572 // The current URL is not a child of the dir lister
573 // URL. This may happen when e. g. a bookmark has been selected
574 // and hence the view must be reset.
575 keepOldDirs = false;
576 }
577 }
578 }
579
580 if (openDir) {
581 m_dirLister->openUrl(url, keepOldDirs, reload);
582 }
583 }
584
585 void DolphinView::setUrl(const KUrl& url)
586 {
587 if (m_controller->url() == url) {
588 return;
589 }
590
591 m_controller->setUrl(url);
592
593 const ViewProperties props(url);
594
595 const Mode mode = props.viewMode();
596 bool changeMode = (m_mode != mode);
597 if (changeMode && isColumnViewActive()) {
598 // The column view is active. Only change the
599 // mode if the current URL is no child of the column view.
600 if (m_dirLister->url().isParentOf(url)) {
601 changeMode = false;
602 }
603 }
604
605 if (changeMode) {
606 m_mode = mode;
607 createView();
608 emit modeChanged();
609
610 if (m_mode == ColumnView) {
611 // The mode has been changed to the Column View. When starting the dir
612 // lister with DolphinView::startDirLister() it is important to give a
613 // hint that the dir lister may not keep the current directory
614 // although this is the default for showing a hierarchy.
615 m_initializeColumnView = true;
616 }
617 }
618
619 const bool showHiddenFiles = props.showHiddenFiles();
620 if (showHiddenFiles != m_dirLister->showingDotFiles()) {
621 m_dirLister->setShowingDotFiles(showHiddenFiles);
622 emit showHiddenFilesChanged();
623 }
624
625 const bool categorized = props.categorizedSorting();
626 if (categorized != categorizedSorting()) {
627 if (supportsCategorizedSorting()) {
628 Q_ASSERT(m_iconsView != 0);
629 if (categorized) {
630 Q_ASSERT(m_iconsView->itemCategorizer() == 0);
631 m_iconsView->setItemCategorizer(new DolphinItemCategorizer());
632 } else {
633 KItemCategorizer* categorizer = m_iconsView->itemCategorizer();
634 m_iconsView->setItemCategorizer(0);
635 delete categorizer;
636 }
637 }
638 emit categorizedSortingChanged();
639 }
640
641 const DolphinView::Sorting sorting = props.sorting();
642 if (sorting != m_proxyModel->sorting()) {
643 m_proxyModel->setSorting(sorting);
644 emit sortingChanged(sorting);
645 }
646
647 const Qt::SortOrder sortOrder = props.sortOrder();
648 if (sortOrder != m_proxyModel->sortOrder()) {
649 m_proxyModel->setSortOrder(sortOrder);
650 emit sortOrderChanged(sortOrder);
651 }
652
653 KFileItemDelegate::AdditionalInformation info = props.additionalInfo();
654 if (info != m_fileItemDelegate->additionalInformation()) {
655 m_controller->setShowAdditionalInfo(info != KFileItemDelegate::NoInformation);
656 m_fileItemDelegate->setAdditionalInformation(info);
657 emit additionalInfoChanged(info);
658 }
659
660 const bool showPreview = props.showPreview();
661 if (showPreview != m_controller->showPreview()) {
662 m_controller->setShowPreview(showPreview);
663 emit showPreviewChanged();
664 }
665
666 startDirLister(url);
667 emit urlChanged(url);
668 }
669
670 void DolphinView::changeSelection(const KFileItemList& selection)
671 {
672 clearSelection();
673 if (selection.isEmpty()) {
674 return;
675 }
676 const KUrl& baseUrl = url();
677 KUrl url;
678 QItemSelection new_selection;
679 foreach(KFileItem* item, selection) {
680 url = item->url().upUrl();
681 if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) {
682 QModelIndex index = m_proxyModel->mapFromSource(m_dirModel->indexForItem(*item));
683 new_selection.select(index, index);
684 }
685 }
686 itemView()->selectionModel()->select(new_selection,
687 QItemSelectionModel::ClearAndSelect
688 | QItemSelectionModel::Current);
689 }
690
691 void DolphinView::openContextMenu(const QPoint& pos)
692 {
693 KFileItem* item = 0;
694
695 const QModelIndex index = itemView()->indexAt(pos);
696 if (isValidNameIndex(index)) {
697 item = fileItem(index);
698 }
699
700 emit requestContextMenu(item, url());
701 }
702
703 void DolphinView::dropUrls(const KUrl::List& urls,
704 const QModelIndex& index,
705 QWidget* source)
706 {
707 KFileItem* directory = 0;
708 if (isValidNameIndex(index)) {
709 KFileItem* item = fileItem(index);
710 Q_ASSERT(item != 0);
711 if (item->isDir()) {
712 // the URLs are dropped above a directory
713 directory = item;
714 }
715 }
716
717 if ((directory == 0) && (source == itemView())) {
718 // The dropping is done into the same viewport where
719 // the dragging has been started. Just ignore this...
720 return;
721 }
722
723 const KUrl& destination = (directory == 0) ?
724 url() : directory->url();
725 dropUrls(urls, destination);
726 }
727
728 void DolphinView::dropUrls(const KUrl::List& urls,
729 const KUrl& destination)
730 {
731 emit urlsDropped(urls, destination);
732 }
733
734 void DolphinView::updateSorting(DolphinView::Sorting sorting)
735 {
736 ViewProperties props(url());
737 props.setSorting(sorting);
738
739 m_proxyModel->setSorting(sorting);
740
741 emit sortingChanged(sorting);
742 }
743
744 void DolphinView::updateSortOrder(Qt::SortOrder order)
745 {
746 ViewProperties props(url());
747 props.setSortOrder(order);
748
749 m_proxyModel->setSortOrder(order);
750
751 emit sortOrderChanged(order);
752 }
753
754 void DolphinView::emitContentsMoved()
755 {
756 // only emit the contents moved signal if:
757 // - no directory loading is ongoing (this would reset the contents position
758 // always to (0, 0))
759 // - if the Column View is active: the column view does an automatic
760 // positioning during the loading operation, which must be remembered
761 if (!m_loadingDirectory || isColumnViewActive()) {
762 const QPoint pos(contentsPosition());
763 emit contentsMoved(pos.x(), pos.y());
764 }
765 }
766
767 void DolphinView::updateCutItems()
768 {
769 // restore the icons of all previously selected items to the
770 // original state...
771 QList<CutItem>::const_iterator it = m_cutItemsCache.begin();
772 QList<CutItem>::const_iterator end = m_cutItemsCache.end();
773 while (it != end) {
774 const QModelIndex index = m_dirModel->indexForUrl((*it).url);
775 if (index.isValid()) {
776 m_dirModel->setData(index, QIcon((*it).pixmap), Qt::DecorationRole);
777 }
778 ++it;
779 }
780 m_cutItemsCache.clear();
781
782 // ... and apply an item effect to all currently cut items
783 applyCutItemEffect();
784 }
785
786 void DolphinView::showHoverInformation(const QModelIndex& index)
787 {
788 if (hasSelection()) {
789 return;
790 }
791
792 const KFileItem* item = fileItem(index);
793 if (item != 0) {
794 emit requestItemInfo(item->url());
795 }
796 }
797
798 void DolphinView::clearHoverInformation()
799 {
800 emit requestItemInfo(KUrl());
801 }
802
803
804 void DolphinView::createView()
805 {
806 // delete current view
807 QAbstractItemView* view = itemView();
808 if (view != 0) {
809 m_topLayout->removeWidget(view);
810 view->close();
811 if (view == m_iconsView) {
812 KItemCategorizer* categorizer = m_iconsView->itemCategorizer();
813 m_iconsView->setItemCategorizer(0);
814 delete categorizer;
815 }
816 view->deleteLater();
817 view = 0;
818 m_iconsView = 0;
819 m_detailsView = 0;
820 m_columnView = 0;
821 m_fileItemDelegate = 0;
822 }
823
824 Q_ASSERT(m_iconsView == 0);
825 Q_ASSERT(m_detailsView == 0);
826 Q_ASSERT(m_columnView == 0);
827
828 // ... and recreate it representing the current mode
829 switch (m_mode) {
830 case IconsView:
831 m_iconsView = new DolphinIconsView(this, m_controller);
832 view = m_iconsView;
833 break;
834
835 case DetailsView:
836 m_detailsView = new DolphinDetailsView(this, m_controller);
837 view = m_detailsView;
838 break;
839
840 case ColumnView:
841 m_columnView = new DolphinColumnView(this, m_controller);
842 view = m_columnView;
843 break;
844 }
845
846 Q_ASSERT(view != 0);
847
848 m_fileItemDelegate = new KFileItemDelegate(view);
849 view->setItemDelegate(m_fileItemDelegate);
850
851 view->setModel(m_proxyModel);
852 view->setSelectionMode(QAbstractItemView::ExtendedSelection);
853
854 new KMimeTypeResolver(view, m_dirModel);
855 m_topLayout->insertWidget(1, view);
856
857 connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
858 this, SLOT(emitSelectionChangedSignal()));
859 connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
860 this, SLOT(emitContentsMoved()));
861 connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)),
862 this, SLOT(emitContentsMoved()));
863 }
864
865 void DolphinView::selectAll(QItemSelectionModel::SelectionFlags flags)
866 {
867 QItemSelectionModel* selectionModel = itemView()->selectionModel();
868 const QAbstractItemModel* itemModel = selectionModel->model();
869
870 const QModelIndex topLeft = itemModel->index(0, 0);
871 const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1,
872 itemModel->columnCount() - 1);
873
874 QItemSelection selection(topLeft, bottomRight);
875 selectionModel->select(selection, flags);
876 }
877
878 QAbstractItemView* DolphinView::itemView() const
879 {
880 if (m_detailsView != 0) {
881 return m_detailsView;
882 } else if (m_columnView != 0) {
883 return m_columnView;
884 }
885
886 return m_iconsView;
887 }
888
889 bool DolphinView::isValidNameIndex(const QModelIndex& index) const
890 {
891 return index.isValid() && (index.column() == KDirModel::Name);
892 }
893
894 bool DolphinView::isCutItem(const KFileItem& item) const
895 {
896 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
897 const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
898
899 const KUrl& itemUrl = item.url();
900 KUrl::List::const_iterator it = cutUrls.begin();
901 const KUrl::List::const_iterator end = cutUrls.end();
902 while (it != end) {
903 if (*it == itemUrl) {
904 return true;
905 }
906 ++it;
907 }
908
909 return false;
910 }
911
912 void DolphinView::applyCutItemEffect()
913 {
914 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
915 if (!KonqMimeData::decodeIsCutSelection(mimeData)) {
916 return;
917 }
918
919 KFileItemList items(m_dirLister->items());
920 KFileItemList::const_iterator it = items.begin();
921 const KFileItemList::const_iterator end = items.end();
922 while (it != end) {
923 KFileItem* item = *it;
924 if (isCutItem(*item)) {
925 const QModelIndex index = m_dirModel->indexForItem(*item);
926 const KFileItem* item = m_dirModel->itemForIndex(index);
927 const QVariant value = m_dirModel->data(index, Qt::DecorationRole);
928 if ((value.type() == QVariant::Icon) && (item != 0)) {
929 const QIcon icon(qvariant_cast<QIcon>(value));
930 QPixmap pixmap = icon.pixmap(128, 128);
931
932 // remember current pixmap for the item to be able
933 // to restore it when other items get cut
934 CutItem cutItem;
935 cutItem.url = item->url();
936 cutItem.pixmap = pixmap;
937 m_cutItemsCache.append(cutItem);
938
939 // apply icon effect to the cut item
940 KIconEffect iconEffect;
941 pixmap = iconEffect.apply(pixmap, K3Icon::Desktop, K3Icon::DisabledState);
942 m_dirModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
943 }
944 }
945 ++it;
946 }
947 }
948
949 #include "dolphinview.moc"