]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinview.cpp
638e6e7cb0fb33a55657b83d04d1382d5df4e8b9
[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 <kactioncollection.h>
32 #include <kcolorscheme.h>
33 #include <kdirlister.h>
34 #include <kfilepreviewgenerator.h>
35 #include <kiconeffect.h>
36 #include <kfileitem.h>
37 #include <klocale.h>
38 #include <kio/deletejob.h>
39 #include <kio/netaccess.h>
40 #include <kio/previewjob.h>
41 #include <kjob.h>
42 #include <kmenu.h>
43 #include <kmessagebox.h>
44 #include <kmimetyperesolver.h>
45 #include <konq_fileitemcapabilities.h>
46 #include <konq_operations.h>
47 #include <konqmimedata.h>
48 #include <kstringhandler.h>
49 #include <ktoggleaction.h>
50 #include <kurl.h>
51
52 #include "dolphinmodel.h"
53 #include "dolphincolumnview.h"
54 #include "dolphincontroller.h"
55 #include "dolphinfileitemdelegate.h"
56 #include "dolphinsortfilterproxymodel.h"
57 #include "dolphindetailsview.h"
58 #include "dolphin_detailsmodesettings.h"
59 #include "dolphiniconsview.h"
60 #include "settings/dolphinsettings.h"
61 #include "dolphin_generalsettings.h"
62 #include "draganddrophelper.h"
63 #include "folderexpander.h"
64 #include "renamedialog.h"
65 #include "tooltips/tooltipmanager.h"
66 #include "viewproperties.h"
67 #include "zoomlevelinfo.h"
68
69 /**
70 * Helper function for sorting items with qSort() in
71 * DolphinView::renameSelectedItems().
72 */
73 bool lessThan(const KFileItem& item1, const KFileItem& item2)
74 {
75 return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0;
76 }
77
78 DolphinView::DolphinView(QWidget* parent,
79 const KUrl& url,
80 KDirLister* dirLister,
81 DolphinModel* dolphinModel,
82 DolphinSortFilterProxyModel* proxyModel) :
83 QWidget(parent),
84 m_active(true),
85 m_showPreview(false),
86 m_loadingDirectory(false),
87 m_storedCategorizedSorting(false),
88 m_tabsForFiles(false),
89 m_isContextMenuOpen(false),
90 m_ignoreViewProperties(false),
91 m_assureVisibleCurrentIndex(false),
92 m_mode(DolphinView::IconsView),
93 m_topLayout(0),
94 m_controller(0),
95 m_iconsView(0),
96 m_detailsView(0),
97 m_columnView(0),
98 m_fileItemDelegate(0),
99 m_selectionModel(0),
100 m_dolphinModel(dolphinModel),
101 m_dirLister(dirLister),
102 m_proxyModel(proxyModel),
103 m_previewGenerator(0),
104 m_toolTipManager(0),
105 m_rootUrl(),
106 m_currentItemUrl(),
107 m_expandedDragSource(0)
108 {
109 m_topLayout = new QVBoxLayout(this);
110 m_topLayout->setSpacing(0);
111 m_topLayout->setMargin(0);
112
113 m_controller = new DolphinController(this);
114 m_controller->setUrl(url);
115
116 connect(m_controller, SIGNAL(urlChanged(const KUrl&)),
117 this, SIGNAL(urlChanged(const KUrl&)));
118 connect(m_controller, SIGNAL(requestUrlChange(const KUrl&)),
119 this, SLOT(slotRequestUrlChange(const KUrl&)));
120
121 connect(m_controller, SIGNAL(requestContextMenu(const QPoint&, const QList<QAction*>&)),
122 this, SLOT(openContextMenu(const QPoint&, const QList<QAction*>&)));
123 connect(m_controller, SIGNAL(urlsDropped(const KFileItem&, const KUrl&, QDropEvent*)),
124 this, SLOT(dropUrls(const KFileItem&, const KUrl&, QDropEvent*)));
125 connect(m_controller, SIGNAL(sortingChanged(DolphinView::Sorting)),
126 this, SLOT(updateSorting(DolphinView::Sorting)));
127 connect(m_controller, SIGNAL(sortOrderChanged(Qt::SortOrder)),
128 this, SLOT(updateSortOrder(Qt::SortOrder)));
129 connect(m_controller, SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)),
130 this, SLOT(updateAdditionalInfo(const KFileItemDelegate::InformationList&)));
131 connect(m_controller, SIGNAL(itemTriggered(const KFileItem&)),
132 this, SLOT(triggerItem(const KFileItem&)));
133 connect(m_controller, SIGNAL(tabRequested(const KUrl&)),
134 this, SIGNAL(tabRequested(const KUrl&)));
135 connect(m_controller, SIGNAL(activated()),
136 this, SLOT(activate()));
137 connect(m_controller, SIGNAL(itemEntered(const KFileItem&)),
138 this, SLOT(showHoverInformation(const KFileItem&)));
139 connect(m_controller, SIGNAL(viewportEntered()),
140 this, SLOT(clearHoverInformation()));
141
142 connect(m_dirLister, SIGNAL(redirection(KUrl, KUrl)),
143 this, SIGNAL(redirection(KUrl, KUrl)));
144 connect(m_dirLister, SIGNAL(completed()),
145 this, SLOT(restoreCurrentItem()));
146 connect(m_dirLister, SIGNAL(refreshItems(const QList<QPair<KFileItem,KFileItem>>&)),
147 this, SLOT(slotRefreshItems()));
148
149 applyViewProperties(url);
150 m_topLayout->addWidget(itemView());
151 }
152
153 DolphinView::~DolphinView()
154 {
155 delete m_expandedDragSource;
156 m_expandedDragSource = 0;
157 }
158
159 const KUrl& DolphinView::url() const
160 {
161 return m_controller->url();
162 }
163
164 KUrl DolphinView::rootUrl() const
165 {
166 return isColumnViewActive() ? m_columnView->rootUrl() : url();
167 }
168
169 void DolphinView::setActive(bool active)
170 {
171 if (active == m_active) {
172 return;
173 }
174
175 m_active = active;
176
177 QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
178 if (active) {
179 // TODO: emitting urlChanged() is a hack, as the URL hasn't really changed. It
180 // bypasses the problem when having a split view and changing the active view to
181 // update the some URL dependent states. A nicer approach should be no big deal...
182 emit urlChanged(url());
183 emit selectionChanged(selectedItems());
184 } else {
185 color.setAlpha(150);
186 }
187
188 QWidget* viewport = itemView()->viewport();
189 QPalette palette;
190 palette.setColor(viewport->backgroundRole(), color);
191 viewport->setPalette(palette);
192
193 update();
194
195 if (active) {
196 itemView()->setFocus();
197 emit activated();
198 }
199
200 m_controller->indicateActivationChange(active);
201 }
202
203 bool DolphinView::isActive() const
204 {
205 return m_active;
206 }
207
208 void DolphinView::setMode(Mode mode)
209 {
210 if (mode == m_mode) {
211 return; // the wished mode is already set
212 }
213
214 const int oldZoomLevel = m_controller->zoomLevel();
215 m_mode = mode;
216
217 deleteView();
218
219 const KUrl viewPropsUrl = viewPropertiesUrl();
220 ViewProperties props(viewPropsUrl);
221 props.setViewMode(m_mode);
222 createView();
223
224 // the file item delegate has been recreated, apply the current
225 // additional information manually
226 const KFileItemDelegate::InformationList infoList = props.additionalInfo();
227 m_fileItemDelegate->setShowInformation(infoList);
228 emit additionalInfoChanged();
229
230 // Not all view modes support categorized sorting. Adjust the sorting model
231 // if changing the view mode results in a change of the categorized sorting
232 // capabilities.
233 m_storedCategorizedSorting = props.categorizedSorting();
234 const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
235 if (categorized != m_proxyModel->isCategorizedModel()) {
236 m_proxyModel->setCategorizedModel(categorized);
237 emit categorizedSortingChanged();
238 }
239
240 emit modeChanged();
241
242 updateZoomLevel(oldZoomLevel);
243 if (m_showPreview) {
244 loadDirectory(viewPropsUrl);
245 }
246 }
247
248 DolphinView::Mode DolphinView::mode() const
249 {
250 return m_mode;
251 }
252
253 bool DolphinView::showPreview() const
254 {
255 return m_showPreview;
256 }
257
258 bool DolphinView::showHiddenFiles() const
259 {
260 return m_dirLister->showingDotFiles();
261 }
262
263 bool DolphinView::categorizedSorting() const
264 {
265 // If all view modes would support categorized sorting, returning
266 // m_proxyModel->isCategorizedModel() would be the way to go. As
267 // currently only the icons view supports caterized sorting, we remember
268 // the stored view properties state in m_storedCategorizedSorting and
269 // return this state. The application takes care to disable the corresponding
270 // checkbox by checking DolphinView::supportsCategorizedSorting() to indicate
271 // that this setting is not applied to the current view mode.
272 return m_storedCategorizedSorting;
273 }
274
275 bool DolphinView::supportsCategorizedSorting() const
276 {
277 return m_iconsView != 0;
278 }
279
280 void DolphinView::selectAll()
281 {
282 QAbstractItemView* view = itemView();
283 // TODO: there seems to be a bug in QAbstractItemView::selectAll(); if
284 // the Ctrl-key is pressed (e. g. for Ctrl+A), selectAll() inverts the
285 // selection instead of selecting all items. This is bypassed for KDE 4.0
286 // by invoking clearSelection() first.
287 view->clearSelection();
288 view->selectAll();
289 }
290
291 void DolphinView::invertSelection()
292 {
293 if (isColumnViewActive()) {
294 // QAbstractItemView does not offer a virtual method invertSelection()
295 // as counterpart to QAbstractItemView::selectAll(). This makes it
296 // necessary to delegate the inverting of the selection to the
297 // column view, as only the selection of the active column should
298 // get inverted.
299 m_columnView->invertSelection();
300 } else {
301 QItemSelectionModel* selectionModel = itemView()->selectionModel();
302 const QAbstractItemModel* itemModel = selectionModel->model();
303
304 const QModelIndex topLeft = itemModel->index(0, 0);
305 const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1,
306 itemModel->columnCount() - 1);
307
308 const QItemSelection selection(topLeft, bottomRight);
309 selectionModel->select(selection, QItemSelectionModel::Toggle);
310 }
311 }
312
313 bool DolphinView::hasSelection() const
314 {
315 return itemView()->selectionModel()->hasSelection();
316 }
317
318 void DolphinView::clearSelection()
319 {
320 QItemSelectionModel* selModel = itemView()->selectionModel();
321 const QModelIndex currentIndex = selModel->currentIndex();
322 selModel->setCurrentIndex(currentIndex, QItemSelectionModel::Current |
323 QItemSelectionModel::Clear);
324 }
325
326 KFileItemList DolphinView::selectedItems() const
327 {
328 if (isColumnViewActive()) {
329 return m_columnView->selectedItems();
330 }
331
332 const QAbstractItemView* view = itemView();
333
334 // Our view has a selection, we will map them back to the DolphinModel
335 // and then fill the KFileItemList.
336 Q_ASSERT((view != 0) && (view->selectionModel() != 0));
337
338 const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection());
339 KFileItemList itemList;
340
341 const QModelIndexList indexList = selection.indexes();
342 foreach (const QModelIndex &index, indexList) {
343 KFileItem item = m_dolphinModel->itemForIndex(index);
344 if (!item.isNull()) {
345 itemList.append(item);
346 }
347 }
348
349 return itemList;
350 }
351
352 KUrl::List DolphinView::selectedUrls() const
353 {
354 KUrl::List urls;
355 const KFileItemList list = selectedItems();
356 foreach (const KFileItem &item, list) {
357 urls.append(item.url());
358 }
359 return urls;
360 }
361
362 int DolphinView::selectedItemsCount() const
363 {
364 if (isColumnViewActive()) {
365 // TODO: get rid of this special case by adjusting the dir lister
366 // to the current column
367 return m_columnView->selectedItems().count();
368 }
369
370 return itemView()->selectionModel()->selection().count();
371 }
372
373 void DolphinView::setContentsPosition(int x, int y)
374 {
375 QAbstractItemView* view = itemView();
376
377 // the ColumnView takes care itself for the horizontal scrolling
378 if (!isColumnViewActive()) {
379 view->horizontalScrollBar()->setValue(x);
380 }
381 view->verticalScrollBar()->setValue(y);
382
383 m_loadingDirectory = false;
384 }
385
386 QPoint DolphinView::contentsPosition() const
387 {
388 const int x = itemView()->horizontalScrollBar()->value();
389 const int y = itemView()->verticalScrollBar()->value();
390 return QPoint(x, y);
391 }
392
393 void DolphinView::setZoomLevel(int level)
394 {
395 if (level < ZoomLevelInfo::minimumLevel()) {
396 level = ZoomLevelInfo::minimumLevel();
397 } else if (level > ZoomLevelInfo::maximumLevel()) {
398 level = ZoomLevelInfo::maximumLevel();
399 }
400
401 if (level != zoomLevel()) {
402 m_controller->setZoomLevel(level);
403 m_previewGenerator->updatePreviews();
404 emit zoomLevelChanged(level);
405 }
406 }
407
408 int DolphinView::zoomLevel() const
409 {
410 return m_controller->zoomLevel();
411 }
412
413 void DolphinView::setSorting(Sorting sorting)
414 {
415 if (sorting != this->sorting()) {
416 updateSorting(sorting);
417 }
418 }
419
420 DolphinView::Sorting DolphinView::sorting() const
421 {
422 return m_proxyModel->sorting();
423 }
424
425 void DolphinView::setSortOrder(Qt::SortOrder order)
426 {
427 if (sortOrder() != order) {
428 updateSortOrder(order);
429 }
430 }
431
432 Qt::SortOrder DolphinView::sortOrder() const
433 {
434 return m_proxyModel->sortOrder();
435 }
436
437 void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info)
438 {
439 const KUrl viewPropsUrl = viewPropertiesUrl();
440 ViewProperties props(viewPropsUrl);
441 props.setAdditionalInfo(info);
442 m_fileItemDelegate->setShowInformation(info);
443
444 emit additionalInfoChanged();
445
446 if (itemView() != m_detailsView) {
447 // the details view requires no reloading of the directory, as it maps
448 // the file item delegate info to its columns internally
449 loadDirectory(viewPropsUrl);
450 }
451 }
452
453 KFileItemDelegate::InformationList DolphinView::additionalInfo() const
454 {
455 return m_fileItemDelegate->showInformation();
456 }
457
458 void DolphinView::reload()
459 {
460 setUrl(url());
461 loadDirectory(url(), true);
462 }
463
464 void DolphinView::refresh()
465 {
466 m_ignoreViewProperties = false;
467
468 const bool oldActivationState = m_active;
469 const int oldZoomLevel = m_controller->zoomLevel();
470 m_active = true;
471
472 createView();
473 applyViewProperties(m_controller->url());
474 reload();
475
476 setActive(oldActivationState);
477 updateZoomLevel(oldZoomLevel);
478 }
479
480 void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl)
481 {
482 if (m_controller->url() == url) {
483 return;
484 }
485
486 m_previewGenerator->cancelPreviews();
487 m_controller->setUrl(url); // emits urlChanged, which we forward
488
489 if (!rootUrl.isEmpty() && rootUrl.isParentOf(url)) {
490 applyViewProperties(rootUrl);
491 loadDirectory(rootUrl);
492 if (itemView() == m_columnView) {
493 m_columnView->setRootUrl(rootUrl);
494 m_columnView->showColumn(url);
495 }
496 } else {
497 applyViewProperties(url);
498 loadDirectory(url);
499 }
500
501 emit startedPathLoading(url);
502 }
503
504 void DolphinView::setNameFilter(const QString& nameFilter)
505 {
506 m_proxyModel->setFilterRegExp(nameFilter);
507
508 if (isColumnViewActive()) {
509 // adjusting the directory lister is not enough in the case of the
510 // column view, as each column has its own directory lister internally...
511 m_columnView->setNameFilter(nameFilter);
512 }
513 }
514
515 void DolphinView::calculateItemCount(int& fileCount,
516 int& folderCount,
517 KIO::filesize_t& totalFileSize) const
518 {
519 foreach (const KFileItem& item, m_dirLister->items()) {
520 if (item.isDir()) {
521 ++folderCount;
522 } else {
523 ++fileCount;
524 totalFileSize += item.size();
525 }
526 }
527 }
528
529 QString DolphinView::statusBarText() const
530 {
531 QString text;
532 int folderCount = 0;
533 int fileCount = 0;
534 KIO::filesize_t totalFileSize = 0;
535
536 if (hasSelection()) {
537 // give a summary of the status of the selected files
538 const KFileItemList list = selectedItems();
539 if (list.isEmpty()) {
540 // when an item is triggered, it is temporary selected but selectedItems()
541 // will return an empty list
542 return text;
543 }
544
545 KFileItemList::const_iterator it = list.begin();
546 const KFileItemList::const_iterator end = list.end();
547 while (it != end) {
548 const KFileItem& item = *it;
549 if (item.isDir()) {
550 ++folderCount;
551 } else {
552 ++fileCount;
553 totalFileSize += item.size();
554 }
555 ++it;
556 }
557
558 if (folderCount + fileCount == 1) {
559 // if only one item is selected, show the filename
560 const QString name = list.first().name();
561 text = (folderCount == 1) ? i18nc("@info:status", "<filename>%1</filename> selected", name) :
562 i18nc("@info:status", "<filename>%1</filename> selected (%2)",
563 name, KIO::convertSize(totalFileSize));
564 } else {
565 // at least 2 items are selected
566 const QString foldersText = i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount);
567 const QString filesText = i18ncp("@info:status", "1 File selected", "%1 Files selected", fileCount);
568 if ((folderCount > 0) && (fileCount > 0)) {
569 text = i18nc("@info:status folders, files (size)", "%1, %2 (%3)",
570 foldersText, filesText, KIO::convertSize(totalFileSize));
571 } else if (fileCount > 0) {
572 text = i18nc("@info:status files (size)", "%1 (%2)", filesText, KIO::convertSize(totalFileSize));
573 } else {
574 Q_ASSERT(folderCount > 0);
575 text = foldersText;
576 }
577 }
578 } else {
579 calculateItemCount(fileCount, folderCount, totalFileSize);
580 text = KIO::itemsSummaryString(fileCount + folderCount,
581 fileCount, folderCount,
582 totalFileSize, true);
583 }
584
585 return text;
586 }
587
588 void DolphinView::setUrl(const KUrl& url)
589 {
590 // remember current item candidate (see restoreCurrentItem())
591 m_currentItemUrl = url;
592 updateView(url, KUrl());
593 }
594
595 void DolphinView::changeSelection(const KFileItemList& selection)
596 {
597 clearSelection();
598 if (selection.isEmpty()) {
599 return;
600 }
601 const KUrl& baseUrl = url();
602 KUrl url;
603 QItemSelection new_selection;
604 foreach(const KFileItem& item, selection) {
605 url = item.url().upUrl();
606 if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) {
607 QModelIndex index = m_proxyModel->mapFromSource(m_dolphinModel->indexForItem(item));
608 new_selection.select(index, index);
609 }
610 }
611 itemView()->selectionModel()->select(new_selection,
612 QItemSelectionModel::ClearAndSelect
613 | QItemSelectionModel::Current);
614 }
615
616 void DolphinView::renameSelectedItems()
617 {
618 KFileItemList items = selectedItems();
619 const int itemCount = items.count();
620 if (itemCount < 1) {
621 return;
622 }
623
624 if (itemCount > 1) {
625 // More than one item has been selected for renaming. Open
626 // a rename dialog and rename all items afterwards.
627 RenameDialog dialog(this, items);
628 if (dialog.exec() == QDialog::Rejected) {
629 return;
630 }
631
632 const QString newName = dialog.newName();
633 if (newName.isEmpty()) {
634 emit errorMessage(dialog.errorString());
635 return;
636 }
637
638 // TODO: check how this can be integrated into KIO::FileUndoManager/KonqOperations
639 // as one operation instead of n rename operations like it is done now...
640 Q_ASSERT(newName.contains('#'));
641
642 // currently the items are sorted by the selection order, resort
643 // them by the file name
644 qSort(items.begin(), items.end(), lessThan);
645
646 // iterate through all selected items and rename them...
647 int index = 1;
648 foreach (const KFileItem& item, items) {
649 const KUrl& oldUrl = item.url();
650 QString number;
651 number.setNum(index++);
652
653 QString name = newName;
654 name.replace('#', number);
655
656 if (oldUrl.fileName() != name) {
657 KUrl newUrl = oldUrl;
658 newUrl.setFileName(name);
659 KonqOperations::rename(this, oldUrl, newUrl);
660 }
661 }
662 } else if (DolphinSettings::instance().generalSettings()->renameInline()) {
663 Q_ASSERT(itemCount == 1);
664
665 if (isColumnViewActive()) {
666 m_columnView->editItem(items.first());
667 } else {
668 const QModelIndex dirIndex = m_dolphinModel->indexForItem(items.first());
669 const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
670 itemView()->edit(proxyIndex);
671 }
672 } else {
673 Q_ASSERT(itemCount == 1);
674
675 RenameDialog dialog(this, items);
676 if (dialog.exec() == QDialog::Rejected) {
677 return;
678 }
679
680 const QString& newName = dialog.newName();
681 if (newName.isEmpty()) {
682 emit errorMessage(dialog.errorString());
683 return;
684 }
685
686 const KUrl& oldUrl = items.first().url();
687 KUrl newUrl = oldUrl;
688 newUrl.setFileName(newName);
689 KonqOperations::rename(this, oldUrl, newUrl);
690 }
691
692 // assure that the current index remains visible when KDirLister
693 // will notify the view about changed items
694 m_assureVisibleCurrentIndex = true;
695 }
696
697 void DolphinView::trashSelectedItems()
698 {
699 const KUrl::List list = simplifiedSelectedUrls();
700 KonqOperations::del(this, KonqOperations::TRASH, list);
701 }
702
703 void DolphinView::deleteSelectedItems()
704 {
705 const KUrl::List list = simplifiedSelectedUrls();
706 const bool del = KonqOperations::askDeleteConfirmation(list,
707 KonqOperations::DEL,
708 KonqOperations::DEFAULT_CONFIRMATION,
709 this);
710
711 if (del) {
712 KIO::Job* job = KIO::del(list);
713 connect(job, SIGNAL(result(KJob*)),
714 this, SLOT(slotDeleteFileFinished(KJob*)));
715 }
716 }
717
718 void DolphinView::cutSelectedItems()
719 {
720 QMimeData* mimeData = selectionMimeData();
721 KonqMimeData::addIsCutSelection(mimeData, true);
722 QApplication::clipboard()->setMimeData(mimeData);
723 }
724
725 void DolphinView::copySelectedItems()
726 {
727 QMimeData* mimeData = selectionMimeData();
728 QApplication::clipboard()->setMimeData(mimeData);
729 }
730
731 void DolphinView::paste()
732 {
733 pasteToUrl(url());
734 }
735
736 void DolphinView::pasteIntoFolder()
737 {
738 const KFileItemList items = selectedItems();
739 if ((items.count() == 1) && items.first().isDir()) {
740 pasteToUrl(items.first().url());
741 }
742 }
743
744 void DolphinView::setShowPreview(bool show)
745 {
746 if (m_showPreview == show) {
747 return;
748 }
749
750 const KUrl viewPropsUrl = viewPropertiesUrl();
751 ViewProperties props(viewPropsUrl);
752 props.setShowPreview(show);
753
754 m_showPreview = show;
755 m_previewGenerator->setPreviewShown(show);
756
757 const int oldZoomLevel = m_controller->zoomLevel();
758 emit showPreviewChanged();
759
760 // Enabling or disabling the preview might change the icon size of the view.
761 // As the view does not emit a signal when the icon size has been changed,
762 // the used zoom level of the controller must be adjusted manually:
763 updateZoomLevel(oldZoomLevel);
764
765 loadDirectory(viewPropsUrl);
766 }
767
768 void DolphinView::setShowHiddenFiles(bool show)
769 {
770 if (m_dirLister->showingDotFiles() == show) {
771 return;
772 }
773
774 const KUrl viewPropsUrl = viewPropertiesUrl();
775 ViewProperties props(viewPropsUrl);
776 props.setShowHiddenFiles(show);
777
778 m_dirLister->setShowingDotFiles(show);
779 emit showHiddenFilesChanged();
780
781 loadDirectory(viewPropsUrl);
782 }
783
784 void DolphinView::setCategorizedSorting(bool categorized)
785 {
786 if (categorized == categorizedSorting()) {
787 return;
788 }
789
790 // setCategorizedSorting(true) may only get invoked
791 // if the view supports categorized sorting
792 Q_ASSERT(!categorized || supportsCategorizedSorting());
793
794 ViewProperties props(viewPropertiesUrl());
795 props.setCategorizedSorting(categorized);
796 props.save();
797
798 m_storedCategorizedSorting = categorized;
799 m_proxyModel->setCategorizedModel(categorized);
800
801 emit categorizedSortingChanged();
802 }
803
804 void DolphinView::toggleSortOrder()
805 {
806 const Qt::SortOrder order = (sortOrder() == Qt::AscendingOrder) ?
807 Qt::DescendingOrder :
808 Qt::AscendingOrder;
809 setSortOrder(order);
810 }
811
812 void DolphinView::toggleAdditionalInfo(QAction* action)
813 {
814 const KFileItemDelegate::Information info =
815 static_cast<KFileItemDelegate::Information>(action->data().toInt());
816
817 KFileItemDelegate::InformationList list = additionalInfo();
818
819 const bool show = action->isChecked();
820
821 const int index = list.indexOf(info);
822 const bool containsInfo = (index >= 0);
823 if (show && !containsInfo) {
824 list.append(info);
825 setAdditionalInfo(list);
826 } else if (!show && containsInfo) {
827 list.removeAt(index);
828 setAdditionalInfo(list);
829 Q_ASSERT(list.indexOf(info) < 0);
830 }
831 }
832
833 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
834 {
835 QWidget::mouseReleaseEvent(event);
836 setActive(true);
837 }
838
839 void DolphinView::wheelEvent(QWheelEvent* event)
840 {
841 if (event->modifiers() & Qt::ControlModifier) {
842 const int delta = event->delta();
843 const int level = zoomLevel();
844 if (delta > 0) {
845 setZoomLevel(level + 1);
846 } else if (delta < 0) {
847 setZoomLevel(level - 1);
848 }
849 event->accept();
850 }
851 }
852
853 bool DolphinView::eventFilter(QObject* watched, QEvent* event)
854 {
855 switch (event->type()) {
856 case QEvent::FocusIn:
857 if (watched == itemView()) {
858 m_controller->requestActivation();
859 }
860 break;
861
862 case QEvent::MouseButtonPress:
863 if ((watched == itemView()->viewport()) && (m_expandedDragSource != 0)) {
864 // Listening to a mousebutton press event to delete expanded views is a
865 // workaround, as it seems impossible for the FolderExpander to know when
866 // a dragging outside a view has been finished. However it works quite well:
867 // A mousebutton press event indicates that a drag operation must be
868 // finished already.
869 m_expandedDragSource->deleteLater();
870 m_expandedDragSource = 0;
871 }
872 break;
873
874 case QEvent::DragEnter:
875 if (watched == itemView()->viewport()) {
876 setActive(true);
877 }
878 break;
879
880 case QEvent::KeyPress:
881 if (watched == itemView()) {
882 if (m_toolTipManager != 0) {
883 m_toolTipManager->hideTip();
884 }
885
886 // clear the selection when Escape has been pressed
887 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
888 if (keyEvent->key() == Qt::Key_Escape) {
889 clearSelection();
890 }
891 }
892 break;
893
894 default:
895 break;
896 }
897
898 return QWidget::eventFilter(watched, event);
899 }
900
901 void DolphinView::activate()
902 {
903 setActive(true);
904 }
905
906 void DolphinView::triggerItem(const KFileItem& item)
907 {
908 const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
909 if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) {
910 // items are selected by the user, hence don't trigger the
911 // item specified by 'index'
912 return;
913 }
914
915 // TODO: the m_isContextMenuOpen check is a workaround for Qt-issue 207192
916 if (item.isNull() || m_isContextMenuOpen) {
917 return;
918 }
919
920 if (m_toolTipManager != 0) {
921 m_toolTipManager->hideTip();
922 }
923 emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
924 }
925
926 void DolphinView::emitSelectionChangedSignal()
927 {
928 emit selectionChanged(DolphinView::selectedItems());
929 }
930
931 void DolphinView::openContextMenu(const QPoint& pos,
932 const QList<QAction*>& customActions)
933 {
934 KFileItem item;
935 if (isColumnViewActive()) {
936 item = m_columnView->itemAt(pos);
937 } else {
938 const QModelIndex index = itemView()->indexAt(pos);
939 if (index.isValid() && (index.column() == DolphinModel::Name)) {
940 const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
941 item = m_dolphinModel->itemForIndex(dolphinModelIndex);
942 }
943 }
944
945 if (m_toolTipManager != 0) {
946 m_toolTipManager->hideTip();
947 }
948
949 m_isContextMenuOpen = true; // TODO: workaround for Qt-issue 207192
950 emit requestContextMenu(item, url(), customActions);
951 m_isContextMenuOpen = false;
952 }
953
954 void DolphinView::dropUrls(const KFileItem& destItem,
955 const KUrl& destPath,
956 QDropEvent* event)
957 {
958 DragAndDropHelper::instance().dropUrls(destItem, destPath, event, this);
959 }
960
961 void DolphinView::updateSorting(DolphinView::Sorting sorting)
962 {
963 ViewProperties props(viewPropertiesUrl());
964 props.setSorting(sorting);
965
966 m_proxyModel->setSorting(sorting);
967
968 emit sortingChanged(sorting);
969 }
970
971 void DolphinView::updateSortOrder(Qt::SortOrder order)
972 {
973 ViewProperties props(viewPropertiesUrl());
974 props.setSortOrder(order);
975
976 m_proxyModel->setSortOrder(order);
977
978 emit sortOrderChanged(order);
979 }
980
981 void DolphinView::updateAdditionalInfo(const KFileItemDelegate::InformationList& info)
982 {
983 ViewProperties props(viewPropertiesUrl());
984 props.setAdditionalInfo(info);
985 props.save();
986
987 m_fileItemDelegate->setShowInformation(info);
988
989 emit additionalInfoChanged();
990 }
991
992 void DolphinView::updateAdditionalInfoActions(KActionCollection* collection)
993 {
994 const bool enable = (m_mode == DolphinView::DetailsView) ||
995 (m_mode == DolphinView::IconsView);
996
997 QAction* showSizeInfo = collection->action("show_size_info");
998 QAction* showDateInfo = collection->action("show_date_info");
999 QAction* showPermissionsInfo = collection->action("show_permissions_info");
1000 QAction* showOwnerInfo = collection->action("show_owner_info");
1001 QAction* showGroupInfo = collection->action("show_group_info");
1002 QAction* showMimeInfo = collection->action("show_mime_info");
1003
1004 showSizeInfo->setChecked(false);
1005 showDateInfo->setChecked(false);
1006 showPermissionsInfo->setChecked(false);
1007 showOwnerInfo->setChecked(false);
1008 showGroupInfo->setChecked(false);
1009 showMimeInfo->setChecked(false);
1010
1011 showSizeInfo->setEnabled(enable);
1012 showDateInfo->setEnabled(enable);
1013 showPermissionsInfo->setEnabled(enable);
1014 showOwnerInfo->setEnabled(enable);
1015 showGroupInfo->setEnabled(enable);
1016 showMimeInfo->setEnabled(enable);
1017
1018 foreach (KFileItemDelegate::Information info, m_fileItemDelegate->showInformation()) {
1019 switch (info) {
1020 case KFileItemDelegate::Size:
1021 showSizeInfo->setChecked(true);
1022 break;
1023 case KFileItemDelegate::ModificationTime:
1024 showDateInfo->setChecked(true);
1025 break;
1026 case KFileItemDelegate::Permissions:
1027 showPermissionsInfo->setChecked(true);
1028 break;
1029 case KFileItemDelegate::Owner:
1030 showOwnerInfo->setChecked(true);
1031 break;
1032 case KFileItemDelegate::OwnerAndGroup:
1033 showGroupInfo->setChecked(true);
1034 break;
1035 case KFileItemDelegate::FriendlyMimeType:
1036 showMimeInfo->setChecked(true);
1037 break;
1038 default:
1039 break;
1040 }
1041 }
1042 }
1043
1044 QPair<bool, QString> DolphinView::pasteInfo() const
1045 {
1046 QPair<bool, QString> ret;
1047 QClipboard* clipboard = QApplication::clipboard();
1048 const QMimeData* mimeData = clipboard->mimeData();
1049
1050 KUrl::List urls = KUrl::List::fromMimeData(mimeData);
1051 if (!urls.isEmpty()) {
1052 // disable the paste action if no writing is supported
1053 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url());
1054 ret.first = KonqFileItemCapabilities(KFileItemList() << item).supportsWriting();
1055
1056 if (urls.count() == 1) {
1057 const KFileItem item(KFileItem::Unknown, KFileItem::Unknown, urls.first(), true);
1058 ret.second = item.isDir() ? i18nc("@action:inmenu", "Paste One Folder") :
1059 i18nc("@action:inmenu", "Paste One File");
1060
1061 } else {
1062 ret.second = i18ncp("@action:inmenu", "Paste One Item", "Paste %1 Items", urls.count());
1063 }
1064 } else {
1065 ret.first = false;
1066 ret.second = i18nc("@action:inmenu", "Paste");
1067 }
1068
1069 return ret;
1070 }
1071
1072 void DolphinView::setTabsForFilesEnabled(bool tabsForFiles)
1073 {
1074 m_tabsForFiles = tabsForFiles;
1075 }
1076
1077 bool DolphinView::isTabsForFilesEnabled() const
1078 {
1079 return m_tabsForFiles;
1080 }
1081
1082 bool DolphinView::itemsExpandable() const
1083 {
1084 return (m_detailsView != 0) && m_detailsView->itemsExpandable();
1085 }
1086
1087 void DolphinView::deleteWhenNotDragSource(QAbstractItemView *view)
1088 {
1089 if (view == 0)
1090 return;
1091
1092 if (DragAndDropHelper::instance().isDragSource(view)) {
1093 // We must store for later deletion.
1094 if (m_expandedDragSource != 0) {
1095 // The old stored view is obviously not the drag source anymore.
1096 m_expandedDragSource->deleteLater();
1097 m_expandedDragSource = 0;
1098 }
1099 view->hide();
1100 m_expandedDragSource = view;
1101 }
1102 else {
1103 view->deleteLater();
1104 }
1105 }
1106
1107 void DolphinView::emitContentsMoved()
1108 {
1109 // only emit the contents moved signal if:
1110 // - no directory loading is ongoing (this would reset the contents position
1111 // always to (0, 0))
1112 // - if the Column View is active: the column view does an automatic
1113 // positioning during the loading operation, which must be remembered
1114 if (!m_loadingDirectory || isColumnViewActive()) {
1115 const QPoint pos(contentsPosition());
1116 emit contentsMoved(pos.x(), pos.y());
1117 }
1118 }
1119
1120 void DolphinView::showHoverInformation(const KFileItem& item)
1121 {
1122 emit requestItemInfo(item);
1123 }
1124
1125 void DolphinView::clearHoverInformation()
1126 {
1127 emit requestItemInfo(KFileItem());
1128 }
1129
1130 void DolphinView::slotDeleteFileFinished(KJob* job)
1131 {
1132 if (job->error() == 0) {
1133 emit operationCompletedMessage(i18nc("@info:status", "Delete operation completed."));
1134 } else if (job->error() != KIO::ERR_USER_CANCELED) {
1135 emit errorMessage(job->errorString());
1136 }
1137 }
1138
1139 void DolphinView::slotRequestUrlChange(const KUrl& url)
1140 {
1141 emit requestUrlChange(url);
1142 m_controller->setUrl(url);
1143 }
1144
1145 void DolphinView::restoreCurrentItem()
1146 {
1147 const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_currentItemUrl);
1148 if (dirIndex.isValid()) {
1149 const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
1150 QAbstractItemView* view = itemView();
1151 const bool clearSelection = !hasSelection();
1152 view->setCurrentIndex(proxyIndex);
1153 if (clearSelection) {
1154 view->clearSelection();
1155 }
1156 }
1157 }
1158
1159 void DolphinView::slotRefreshItems()
1160 {
1161 if (m_assureVisibleCurrentIndex) {
1162 m_assureVisibleCurrentIndex = false;
1163 // Invoking itemView()->scrollTo(itemView()->currentIndex()) is
1164 // not sufficient, as QListView and QTreeView have an inconsistent
1165 // default behavior.
1166 m_controller->triggerScrollToCurrentItem();
1167 }
1168 }
1169
1170 void DolphinView::loadDirectory(const KUrl& url, bool reload)
1171 {
1172 if (!url.isValid()) {
1173 const QString location(url.pathOrUrl());
1174 if (location.isEmpty()) {
1175 emit errorMessage(i18nc("@info:status", "The location is empty."));
1176 } else {
1177 emit errorMessage(i18nc("@info:status", "The location '%1' is invalid.", location));
1178 }
1179 return;
1180 }
1181
1182 m_loadingDirectory = true;
1183
1184 m_dirLister->stop();
1185 m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags);
1186
1187 if (isColumnViewActive()) {
1188 // adjusting the directory lister is not enough in the case of the
1189 // column view, as each column has its own directory lister internally...
1190 if (reload) {
1191 m_columnView->reload();
1192 } else {
1193 m_columnView->showColumn(url);
1194 }
1195 }
1196 }
1197
1198 KUrl DolphinView::viewPropertiesUrl() const
1199 {
1200 if (isColumnViewActive()) {
1201 return m_columnView->rootUrl();
1202 }
1203
1204 return url();
1205 }
1206
1207 void DolphinView::applyViewProperties(const KUrl& url)
1208 {
1209 if (m_ignoreViewProperties) {
1210 return;
1211 }
1212
1213 if (isColumnViewActive() && rootUrl().isParentOf(url)) {
1214 // The column view is active, hence don't apply the view properties
1215 // of sub directories (represented by columns) to the view. The
1216 // view always represents the properties of the first column.
1217 return;
1218 }
1219
1220 const ViewProperties props(url);
1221
1222 const Mode mode = props.viewMode();
1223 if (m_mode != mode) {
1224 const int oldZoomLevel = m_controller->zoomLevel();
1225
1226 m_mode = mode;
1227 createView();
1228 emit modeChanged();
1229
1230 updateZoomLevel(oldZoomLevel);
1231 }
1232 if (itemView() == 0) {
1233 createView();
1234 }
1235 Q_ASSERT(itemView() != 0);
1236 Q_ASSERT(m_fileItemDelegate != 0);
1237
1238 const bool showHiddenFiles = props.showHiddenFiles();
1239 if (showHiddenFiles != m_dirLister->showingDotFiles()) {
1240 m_dirLister->setShowingDotFiles(showHiddenFiles);
1241 emit showHiddenFilesChanged();
1242 }
1243
1244 m_storedCategorizedSorting = props.categorizedSorting();
1245 const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
1246 if (categorized != m_proxyModel->isCategorizedModel()) {
1247 m_proxyModel->setCategorizedModel(categorized);
1248 emit categorizedSortingChanged();
1249 }
1250
1251 const DolphinView::Sorting sorting = props.sorting();
1252 if (sorting != m_proxyModel->sorting()) {
1253 m_proxyModel->setSorting(sorting);
1254 emit sortingChanged(sorting);
1255 }
1256
1257 const Qt::SortOrder sortOrder = props.sortOrder();
1258 if (sortOrder != m_proxyModel->sortOrder()) {
1259 m_proxyModel->setSortOrder(sortOrder);
1260 emit sortOrderChanged(sortOrder);
1261 }
1262
1263 KFileItemDelegate::InformationList info = props.additionalInfo();
1264 if (info != m_fileItemDelegate->showInformation()) {
1265 m_fileItemDelegate->setShowInformation(info);
1266 emit additionalInfoChanged();
1267 }
1268
1269 const bool showPreview = props.showPreview();
1270 if (showPreview != m_showPreview) {
1271 m_showPreview = showPreview;
1272 m_previewGenerator->setPreviewShown(showPreview);
1273
1274 const int oldZoomLevel = m_controller->zoomLevel();
1275 emit showPreviewChanged();
1276
1277 // Enabling or disabling the preview might change the icon size of the view.
1278 // As the view does not emit a signal when the icon size has been changed,
1279 // the used zoom level of the controller must be adjusted manually:
1280 updateZoomLevel(oldZoomLevel);
1281 }
1282
1283 if (DolphinSettings::instance().generalSettings()->globalViewProps()) {
1284 // During the lifetime of a DolphinView instance the global view properties
1285 // should not be changed. This allows e. g. to split a view and use different
1286 // view properties for each view.
1287 m_ignoreViewProperties = true;
1288 }
1289 }
1290
1291 void DolphinView::createView()
1292 {
1293 deleteView();
1294 Q_ASSERT(m_iconsView == 0);
1295 Q_ASSERT(m_detailsView == 0);
1296 Q_ASSERT(m_columnView == 0);
1297
1298 QAbstractItemView* view = 0;
1299 switch (m_mode) {
1300 case IconsView: {
1301 m_iconsView = new DolphinIconsView(this, m_controller);
1302 view = m_iconsView;
1303 break;
1304 }
1305
1306 case DetailsView:
1307 m_detailsView = new DolphinDetailsView(this, m_controller);
1308 view = m_detailsView;
1309 break;
1310
1311 case ColumnView:
1312 m_columnView = new DolphinColumnView(this, m_controller);
1313 view = m_columnView;
1314 break;
1315 }
1316
1317 Q_ASSERT(view != 0);
1318 view->installEventFilter(this);
1319 view->viewport()->installEventFilter(this);
1320 setFocusProxy(view);
1321
1322 if (m_mode != ColumnView) {
1323 // Give the view the ability to auto-expand its directories on hovering
1324 // (the column view takes care about this itself). If the details view
1325 // uses expandable folders, the auto-expanding should be used always.
1326 DolphinSettings& settings = DolphinSettings::instance();
1327 const bool enabled = settings.generalSettings()->autoExpandFolders() ||
1328 ((m_detailsView != 0) && settings.detailsModeSettings()->expandableFolders());
1329
1330 FolderExpander* folderExpander = new FolderExpander(view, m_proxyModel);
1331 folderExpander->setEnabled(enabled);
1332 connect(folderExpander, SIGNAL(enterDir(const QModelIndex&)),
1333 m_controller, SLOT(triggerItem(const QModelIndex&)));
1334 }
1335 else {
1336 // Listen out for requests to delete the current column.
1337 connect(m_columnView, SIGNAL(requestColumnDeletion(QAbstractItemView*)),
1338 this, SLOT(deleteWhenNotDragSource(QAbstractItemView*)));
1339 }
1340
1341 m_controller->setItemView(view);
1342
1343 m_fileItemDelegate = new DolphinFileItemDelegate(view);
1344 m_fileItemDelegate->setShowToolTipWhenElided(false);
1345 m_fileItemDelegate->setMinimizedNameColumn(m_mode == DetailsView);
1346 view->setItemDelegate(m_fileItemDelegate);
1347
1348 view->setModel(m_proxyModel);
1349 if (m_selectionModel != 0) {
1350 view->setSelectionModel(m_selectionModel);
1351 } else {
1352 m_selectionModel = view->selectionModel();
1353 }
1354
1355 // reparent the selection model, as it should not be deleted
1356 // when deleting the model
1357 m_selectionModel->setParent(this);
1358
1359 view->setSelectionMode(QAbstractItemView::ExtendedSelection);
1360
1361 m_previewGenerator = new KFilePreviewGenerator(view);
1362 m_previewGenerator->setPreviewShown(m_showPreview);
1363
1364 if (DolphinSettings::instance().generalSettings()->showToolTips()) {
1365 m_toolTipManager = new ToolTipManager(view, m_proxyModel);
1366 connect(m_controller, SIGNAL(hideToolTip()),
1367 m_toolTipManager, SLOT(hideTip()));
1368 }
1369
1370 m_topLayout->insertWidget(1, view);
1371
1372 connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
1373 this, SLOT(emitSelectionChangedSignal()));
1374 connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
1375 this, SLOT(emitContentsMoved()));
1376 connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)),
1377 this, SLOT(emitContentsMoved()));
1378 }
1379
1380 void DolphinView::deleteView()
1381 {
1382 QAbstractItemView* view = itemView();
1383 if (view != 0) {
1384 // It's important to set the keyboard focus to the parent
1385 // before deleting the view: Otherwise when having a split
1386 // view the other view will get the focus and will request
1387 // an activation (see DolphinView::eventFilter()).
1388 setFocusProxy(0);
1389 setFocus();
1390
1391 m_topLayout->removeWidget(view);
1392 view->close();
1393
1394 // m_previewGenerator's parent is not always destroyed, and we
1395 // don't want two active at once - manually delete.
1396 delete m_previewGenerator;
1397 m_previewGenerator = 0;
1398
1399 disconnect(view);
1400 m_controller->disconnect(view);
1401 view->disconnect();
1402
1403 deleteWhenNotDragSource(view);
1404 view = 0;
1405
1406 m_iconsView = 0;
1407 m_detailsView = 0;
1408 m_columnView = 0;
1409 m_fileItemDelegate = 0;
1410 m_toolTipManager = 0;
1411 }
1412 }
1413
1414 QAbstractItemView* DolphinView::itemView() const
1415 {
1416 if (m_detailsView != 0) {
1417 return m_detailsView;
1418 } else if (m_columnView != 0) {
1419 return m_columnView;
1420 }
1421
1422 return m_iconsView;
1423 }
1424
1425 bool DolphinView::isCutItem(const KFileItem& item) const
1426 {
1427 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
1428 const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
1429
1430 const KUrl& itemUrl = item.url();
1431 KUrl::List::const_iterator it = cutUrls.begin();
1432 const KUrl::List::const_iterator end = cutUrls.end();
1433 while (it != end) {
1434 if (*it == itemUrl) {
1435 return true;
1436 }
1437 ++it;
1438 }
1439
1440 return false;
1441 }
1442
1443 void DolphinView::pasteToUrl(const KUrl& url)
1444 {
1445 QClipboard* clipboard = QApplication::clipboard();
1446 const QMimeData* mimeData = clipboard->mimeData();
1447
1448 const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData);
1449 if (KonqMimeData::decodeIsCutSelection(mimeData)) {
1450 KonqOperations::copy(this, KonqOperations::MOVE, sourceUrls, url);
1451 clipboard->clear();
1452 } else {
1453 KonqOperations::copy(this, KonqOperations::COPY, sourceUrls, url);
1454 }
1455 }
1456
1457 void DolphinView::updateZoomLevel(int oldZoomLevel)
1458 {
1459 const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(itemView()->iconSize());
1460 if (oldZoomLevel != newZoomLevel) {
1461 m_controller->setZoomLevel(newZoomLevel);
1462 emit zoomLevelChanged(newZoomLevel);
1463 }
1464 }
1465
1466 KUrl::List DolphinView::simplifiedSelectedUrls() const
1467 {
1468 KUrl::List list = selectedUrls();
1469 if (itemsExpandable() ) {
1470 list = KDirModel::simplifiedUrlList(list);
1471 }
1472 return list;
1473 }
1474
1475 QMimeData* DolphinView::selectionMimeData() const
1476 {
1477 if (isColumnViewActive()) {
1478 return m_columnView->selectionMimeData();
1479 }
1480
1481 const QAbstractItemView* view = itemView();
1482 Q_ASSERT((view != 0) && (view->selectionModel() != 0));
1483 const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection());
1484 return m_dolphinModel->mimeData(selection.indexes());
1485 }
1486
1487 #include "dolphinview.moc"