]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinview.cpp
KrushDays-fix: fixed issue that F6 does not apply the focus to the URL navigator...
[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 #include <ktoggleaction.h>
23 #include <kactioncollection.h>
24
25 #include <QApplication>
26 #include <QClipboard>
27 #include <QKeyEvent>
28 #include <QItemSelection>
29 #include <QBoxLayout>
30 #include <QTimer>
31 #include <QScrollBar>
32
33 #include <kcolorscheme.h>
34 #include <kdirlister.h>
35 #include <kfileitemdelegate.h>
36 #include <klocale.h>
37 #include <kiconeffect.h>
38 #include <kio/netaccess.h>
39 #include <kio/renamedialog.h>
40 #include <kio/previewjob.h>
41 #include <kmimetyperesolver.h>
42 #include <konqmimedata.h>
43 #include <konq_operations.h>
44 #include <kurl.h>
45
46 #include "dolphinmodel.h"
47 #include "dolphincolumnview.h"
48 #include "dolphincontroller.h"
49 #include "dolphinsortfilterproxymodel.h"
50 #include "dolphindetailsview.h"
51 #include "dolphiniconsview.h"
52 #include "renamedialog.h"
53 #include "viewproperties.h"
54 #include "dolphinsettings.h"
55 #include "dolphin_generalsettings.h"
56
57 DolphinView::DolphinView(QWidget* parent,
58 const KUrl& url,
59 KDirLister* dirLister,
60 DolphinModel* dolphinModel,
61 DolphinSortFilterProxyModel* proxyModel) :
62 QWidget(parent),
63 m_active(true),
64 m_showPreview(false),
65 m_loadingDirectory(false),
66 m_storedCategorizedSorting(false),
67 m_mode(DolphinView::IconsView),
68 m_topLayout(0),
69 m_controller(0),
70 m_iconsView(0),
71 m_detailsView(0),
72 m_columnView(0),
73 m_fileItemDelegate(0),
74 m_dolphinModel(dolphinModel),
75 m_dirLister(dirLister),
76 m_proxyModel(proxyModel)
77 {
78 setFocusPolicy(Qt::StrongFocus);
79 m_topLayout = new QVBoxLayout(this);
80 m_topLayout->setSpacing(0);
81 m_topLayout->setMargin(0);
82
83 QClipboard* clipboard = QApplication::clipboard();
84 connect(clipboard, SIGNAL(dataChanged()),
85 this, SLOT(updateCutItems()));
86
87 connect(m_dirLister, SIGNAL(completed()),
88 this, SLOT(updateCutItems()));
89 connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
90 this, SLOT(generatePreviews(const KFileItemList&)));
91
92 m_controller = new DolphinController(this);
93 m_controller->setUrl(url);
94
95 // Receiver of the DolphinView signal 'urlChanged()' don't need
96 // to care whether the internal controller changed the URL already or whether
97 // the controller just requested an URL change and will be updated later.
98 // In both cases the URL has been changed:
99 connect(m_controller, SIGNAL(urlChanged(const KUrl&)),
100 this, SIGNAL(urlChanged(const KUrl&)));
101 connect(m_controller, SIGNAL(requestUrlChange(const KUrl&)),
102 this, SIGNAL(urlChanged(const KUrl&)));
103
104 connect(m_controller, SIGNAL(requestContextMenu(const QPoint&)),
105 this, SLOT(openContextMenu(const QPoint&)));
106 connect(m_controller, SIGNAL(urlsDropped(const KUrl::List&, const KUrl&, const KFileItem&)),
107 this, SLOT(dropUrls(const KUrl::List&, const KUrl&, const KFileItem&)));
108 connect(m_controller, SIGNAL(sortingChanged(DolphinView::Sorting)),
109 this, SLOT(updateSorting(DolphinView::Sorting)));
110 connect(m_controller, SIGNAL(sortOrderChanged(Qt::SortOrder)),
111 this, SLOT(updateSortOrder(Qt::SortOrder)));
112 connect(m_controller, SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)),
113 this, SLOT(updateAdditionalInfo(const KFileItemDelegate::InformationList&)));
114 connect(m_controller, SIGNAL(itemTriggered(const KFileItem&)),
115 this, SLOT(triggerItem(const KFileItem&)));
116 connect(m_controller, SIGNAL(activated()),
117 this, SLOT(activate()));
118 connect(m_controller, SIGNAL(itemEntered(const KFileItem&)),
119 this, SLOT(showHoverInformation(const KFileItem&)));
120 connect(m_controller, SIGNAL(viewportEntered()),
121 this, SLOT(clearHoverInformation()));
122
123 applyViewProperties(url);
124 m_topLayout->addWidget(itemView());
125 }
126
127 DolphinView::~DolphinView()
128 {
129 }
130
131 const KUrl& DolphinView::url() const
132 {
133 return m_controller->url();
134 }
135
136 KUrl DolphinView::rootUrl() const
137 {
138 return isColumnViewActive() ? m_columnView->rootUrl() : url();
139 }
140
141 void DolphinView::setActive(bool active)
142 {
143 if (active == m_active) {
144 return;
145 }
146
147 m_active = active;
148
149 QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
150 if (active) {
151 // TODO: emitting urlChanged() is a hack, as the URL hasn't really changed. It
152 // bypasses the problem when having a split view and changing the active view to
153 // update the some URL dependent states. A nicer approach should be no big deal...
154 emit urlChanged(url());
155 emit selectionChanged(selectedItems());
156 } else {
157 color.setAlpha(150);
158 }
159
160 QWidget* viewport = itemView()->viewport();
161 QPalette palette;
162 palette.setColor(viewport->backgroundRole(), color);
163 viewport->setPalette(palette);
164
165 update();
166
167 if (active) {
168 emit activated();
169 }
170
171 m_controller->indicateActivationChange(active);
172 }
173
174 bool DolphinView::isActive() const
175 {
176 return m_active;
177 }
178
179 void DolphinView::setMode(Mode mode)
180 {
181 if (mode == m_mode) {
182 return; // the wished mode is already set
183 }
184
185 m_mode = mode;
186
187 if (isColumnViewActive()) {
188 // When changing the mode in the column view, it makes sense
189 // to go back to the root URL of the column view automatically.
190 // Otherwise there it would not be possible to turn off the column view
191 // without focusing the first column.
192 const KUrl root = rootUrl();
193 setUrl(root);
194 m_controller->setUrl(root);
195 }
196
197 const KUrl viewPropsUrl = viewPropertiesUrl();
198 ViewProperties props(viewPropsUrl);
199 props.setViewMode(m_mode);
200
201 createView();
202
203 // the file item delegate has been recreated, apply the current
204 // additional information manually
205 const KFileItemDelegate::InformationList infoList = props.additionalInfo();
206 m_fileItemDelegate->setShowInformation(infoList);
207 emit additionalInfoChanged(infoList);
208
209 // Not all view modes support categorized sorting. Adjust the sorting model
210 // if changing the view mode results in a change of the categorized sorting
211 // capabilities.
212 m_storedCategorizedSorting = props.categorizedSorting();
213 const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
214 if (categorized != m_proxyModel->isCategorizedModel()) {
215 m_proxyModel->setCategorizedModel(categorized);
216 emit categorizedSortingChanged();
217 }
218
219 loadDirectory(viewPropsUrl);
220
221 emit modeChanged();
222 }
223
224 DolphinView::Mode DolphinView::mode() const
225 {
226 return m_mode;
227 }
228
229 void DolphinView::setShowPreview(bool show)
230 {
231 if (m_showPreview == show) {
232 return;
233 }
234
235 const KUrl viewPropsUrl = viewPropertiesUrl();
236 ViewProperties props(viewPropsUrl);
237 props.setShowPreview(show);
238
239 m_showPreview = show;
240
241 emit showPreviewChanged();
242
243 loadDirectory(viewPropsUrl, true);
244 }
245
246 bool DolphinView::showPreview() const
247 {
248 return m_showPreview;
249 }
250
251 void DolphinView::setShowHiddenFiles(bool show)
252 {
253 if (m_dirLister->showingDotFiles() == show) {
254 return;
255 }
256
257 const KUrl viewPropsUrl = viewPropertiesUrl();
258 ViewProperties props(viewPropsUrl);
259 props.setShowHiddenFiles(show);
260
261 m_dirLister->setShowingDotFiles(show);
262 emit showHiddenFilesChanged();
263
264 loadDirectory(viewPropsUrl, true);
265 }
266
267 bool DolphinView::showHiddenFiles() const
268 {
269 return m_dirLister->showingDotFiles();
270 }
271
272 void DolphinView::setCategorizedSorting(bool categorized)
273 {
274 if (categorized == categorizedSorting()) {
275 return;
276 }
277
278 // setCategorizedSorting(true) may only get invoked
279 // if the view supports categorized sorting
280 Q_ASSERT(!categorized || supportsCategorizedSorting());
281
282 ViewProperties props(viewPropertiesUrl());
283 props.setCategorizedSorting(categorized);
284 props.save();
285
286 m_storedCategorizedSorting = categorized;
287 m_proxyModel->setCategorizedModel(categorized);
288
289 emit categorizedSortingChanged();
290 }
291
292 bool DolphinView::categorizedSorting() const
293 {
294 // If all view modes would support categorized sorting, returning
295 // m_proxyModel->isCategorizedModel() would be the way to go. As
296 // currently only the icons view supports caterized sorting, we remember
297 // the stored view properties state in m_storedCategorizedSorting and
298 // return this state. The application takes care to disable the corresponding
299 // checkbox by checking DolphinView::supportsCategorizedSorting() to indicate
300 // that this setting is not applied to the current view mode.
301 return m_storedCategorizedSorting;
302 }
303
304 bool DolphinView::supportsCategorizedSorting() const
305 {
306 return m_iconsView != 0;
307 }
308
309 void DolphinView::selectAll()
310 {
311 itemView()->selectAll();
312 }
313
314 void DolphinView::invertSelection()
315 {
316 if (isColumnViewActive()) {
317 // QAbstractItemView does not offer a virtual method invertSelection()
318 // as counterpart to QAbstractItemView::selectAll(). This makes it
319 // necessary to delegate the inverting of the selection to the
320 // column view, as only the selection of the active column should
321 // get inverted.
322 m_columnView->invertSelection();
323 } else {
324 QItemSelectionModel* selectionModel = itemView()->selectionModel();
325 const QAbstractItemModel* itemModel = selectionModel->model();
326
327 const QModelIndex topLeft = itemModel->index(0, 0);
328 const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1,
329 itemModel->columnCount() - 1);
330
331 const QItemSelection selection(topLeft, bottomRight);
332 selectionModel->select(selection, QItemSelectionModel::Toggle);
333 }
334 }
335
336 bool DolphinView::hasSelection() const
337 {
338 return itemView()->selectionModel()->hasSelection();
339 }
340
341 void DolphinView::clearSelection()
342 {
343 itemView()->selectionModel()->clear();
344 }
345
346 KFileItemList DolphinView::selectedItems() const
347 {
348 const QAbstractItemView* view = itemView();
349
350 // Our view has a selection, we will map them back to the DolphinModel
351 // and then fill the KFileItemList.
352 Q_ASSERT((view != 0) && (view->selectionModel() != 0));
353
354 const QItemSelection selection = m_proxyModel->mapSelectionToSource(view->selectionModel()->selection());
355 KFileItemList itemList;
356
357 const QModelIndexList indexList = selection.indexes();
358 foreach (QModelIndex index, indexList) {
359 KFileItem item = m_dolphinModel->itemForIndex(index);
360 if (!item.isNull()) {
361 itemList.append(item);
362 }
363 }
364
365 return itemList;
366 }
367
368 KUrl::List DolphinView::selectedUrls() const
369 {
370 KUrl::List urls;
371 const KFileItemList list = selectedItems();
372 foreach (KFileItem item, list) {
373 urls.append(item.url());
374 }
375 return urls;
376 }
377
378 KFileItem DolphinView::fileItem(const QModelIndex& index) const
379 {
380 const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
381 return m_dolphinModel->itemForIndex(dolphinModelIndex);
382 }
383
384 void DolphinView::setContentsPosition(int x, int y)
385 {
386 QAbstractItemView* view = itemView();
387
388 // the ColumnView takes care itself for the horizontal scrolling
389 if (!isColumnViewActive()) {
390 view->horizontalScrollBar()->setValue(x);
391 }
392 view->verticalScrollBar()->setValue(y);
393
394 m_loadingDirectory = false;
395 }
396
397 QPoint DolphinView::contentsPosition() const
398 {
399 const int x = itemView()->horizontalScrollBar()->value();
400 const int y = itemView()->verticalScrollBar()->value();
401 return QPoint(x, y);
402 }
403
404 void DolphinView::zoomIn()
405 {
406 m_controller->triggerZoomIn();
407 }
408
409 void DolphinView::zoomOut()
410 {
411 m_controller->triggerZoomOut();
412 }
413
414 bool DolphinView::isZoomInPossible() const
415 {
416 return m_controller->isZoomInPossible();
417 }
418
419 bool DolphinView::isZoomOutPossible() const
420 {
421 return m_controller->isZoomOutPossible();
422 }
423
424 void DolphinView::setSorting(Sorting sorting)
425 {
426 if (sorting != this->sorting()) {
427 updateSorting(sorting);
428 }
429 }
430
431 DolphinView::Sorting DolphinView::sorting() const
432 {
433 return m_proxyModel->sorting();
434 }
435
436 void DolphinView::setSortOrder(Qt::SortOrder order)
437 {
438 if (sortOrder() != order) {
439 updateSortOrder(order);
440 }
441 }
442
443 Qt::SortOrder DolphinView::sortOrder() const
444 {
445 return m_proxyModel->sortOrder();
446 }
447
448 void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info)
449 {
450 const KUrl viewPropsUrl = viewPropertiesUrl();
451 ViewProperties props(viewPropsUrl);
452 props.setAdditionalInfo(info);
453 m_fileItemDelegate->setShowInformation(info);
454
455 emit additionalInfoChanged(info);
456
457 if (itemView() != m_detailsView) {
458 // the details view requires no reloading of the directory, as it maps
459 // the file item delegate info to its columns internally
460 loadDirectory(viewPropsUrl, true);
461 }
462 }
463
464 KFileItemDelegate::InformationList DolphinView::additionalInfo() const
465 {
466 return m_fileItemDelegate->showInformation();
467 }
468
469 void DolphinView::reload()
470 {
471 setUrl(url());
472 loadDirectory(url(), true);
473 }
474
475 void DolphinView::refresh()
476 {
477 const bool oldActivationState = m_active;
478 m_active = true;
479
480 createView();
481 applyViewProperties(m_controller->url());
482 reload();
483
484 setActive(oldActivationState);
485 }
486
487 void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl)
488 {
489 if (m_controller->url() == url) {
490 return;
491 }
492
493 m_controller->setUrl(url); // emits urlChanged, which we forward
494
495 if (!rootUrl.isEmpty() && rootUrl.isParentOf(url)) {
496 applyViewProperties(rootUrl);
497 loadDirectory(rootUrl);
498 if (itemView() == m_columnView) {
499 m_columnView->setRootUrl(rootUrl);
500 m_columnView->showColumn(url);
501 }
502 } else {
503 applyViewProperties(url);
504 loadDirectory(url);
505 }
506
507 emit startedPathLoading(url);
508 }
509
510 void DolphinView::setNameFilter(const QString& nameFilter)
511 {
512 m_proxyModel->setFilterRegExp(nameFilter);
513
514 if (isColumnViewActive()) {
515 // adjusting the directory lister is not enough in the case of the
516 // column view, as each column has its own directory lister internally...
517 m_columnView->setNameFilter(nameFilter);
518 }
519 }
520
521 void DolphinView::calculateItemCount(int& fileCount, int& folderCount)
522 {
523 foreach (KFileItem item, m_dirLister->items()) {
524 if (item.isDir()) {
525 ++folderCount;
526 } else {
527 ++fileCount;
528 }
529 }
530 }
531
532 void DolphinView::setUrl(const KUrl& url)
533 {
534 updateView(url, KUrl());
535 }
536
537 void DolphinView::mouseReleaseEvent(QMouseEvent* event)
538 {
539 QWidget::mouseReleaseEvent(event);
540 setActive(true);
541 }
542 void DolphinView::activate()
543 {
544 setActive(true);
545 }
546
547 void DolphinView::triggerItem(const KFileItem& item)
548 {
549 const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
550 if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) {
551 // items are selected by the user, hence don't trigger the
552 // item specified by 'index'
553 return;
554 }
555
556 if (item.isNull()) {
557 return;
558 }
559
560 emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
561 }
562
563 void DolphinView::generatePreviews(const KFileItemList& items)
564 {
565 if (m_controller->dolphinView()->showPreview()) {
566 KIO::PreviewJob* job = KIO::filePreview(items, 128);
567 connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
568 this, SLOT(showPreview(const KFileItem&, const QPixmap&)));
569 }
570 }
571
572 void DolphinView::showPreview(const KFileItem& item, const QPixmap& pixmap)
573 {
574 Q_ASSERT(!item.isNull());
575 if (item.url().directory() != m_dirLister->url().path()) {
576 // the preview job is still working on items of an older URL, hence
577 // the item is not part of the directory model anymore
578 return;
579 }
580
581 const QModelIndex idx = m_dolphinModel->indexForItem(item);
582 if (idx.isValid() && (idx.column() == 0)) {
583 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
584 if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
585 KIconEffect iconEffect;
586 const QPixmap cutPixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
587 m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole);
588 } else {
589 m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole);
590 }
591 }
592 }
593
594 void DolphinView::emitSelectionChangedSignal()
595 {
596 emit selectionChanged(DolphinView::selectedItems());
597 }
598
599 void DolphinView::loadDirectory(const KUrl& url, bool reload)
600 {
601 if (!url.isValid()) {
602 const QString location(url.pathOrUrl());
603 if (location.isEmpty()) {
604 emit errorMessage(i18nc("@info:status", "The location is empty."));
605 } else {
606 emit errorMessage(i18nc("@info:status", "The location '%1' is invalid.", location));
607 }
608 return;
609 }
610
611 m_cutItemsCache.clear();
612 m_loadingDirectory = true;
613
614 m_dirLister->stop();
615 m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags);
616
617 if (isColumnViewActive()) {
618 // adjusting the directory lister is not enough in the case of the
619 // column view, as each column has its own directory lister internally...
620 if (reload) {
621 m_columnView->reload();
622 } else {
623 m_columnView->showColumn(url);
624 }
625 }
626 }
627
628 KUrl DolphinView::viewPropertiesUrl() const
629 {
630 if (isColumnViewActive()) {
631 return m_dirLister->url();
632 }
633
634 return url();
635 }
636
637 void DolphinView::applyViewProperties(const KUrl& url)
638 {
639 if (isColumnViewActive() && rootUrl().isParentOf(url)) {
640 // The column view is active, hence don't apply the view properties
641 // of sub directories (represented by columns) to the view. The
642 // view always represents the properties of the first column.
643 return;
644 }
645
646 const ViewProperties props(url);
647
648 const Mode mode = props.viewMode();
649 if (m_mode != mode) {
650 m_mode = mode;
651 createView();
652 emit modeChanged();
653 }
654 if (itemView() == 0) {
655 createView();
656 }
657 Q_ASSERT(itemView() != 0);
658 Q_ASSERT(m_fileItemDelegate != 0);
659
660 const bool showHiddenFiles = props.showHiddenFiles();
661 if (showHiddenFiles != m_dirLister->showingDotFiles()) {
662 m_dirLister->setShowingDotFiles(showHiddenFiles);
663 emit showHiddenFilesChanged();
664 }
665
666 m_storedCategorizedSorting = props.categorizedSorting();
667 const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
668 if (categorized != m_proxyModel->isCategorizedModel()) {
669 m_proxyModel->setCategorizedModel(categorized);
670 emit categorizedSortingChanged();
671 }
672
673 const DolphinView::Sorting sorting = props.sorting();
674 if (sorting != m_proxyModel->sorting()) {
675 m_proxyModel->setSorting(sorting);
676 emit sortingChanged(sorting);
677 }
678
679 const Qt::SortOrder sortOrder = props.sortOrder();
680 if (sortOrder != m_proxyModel->sortOrder()) {
681 m_proxyModel->setSortOrder(sortOrder);
682 emit sortOrderChanged(sortOrder);
683 }
684
685 KFileItemDelegate::InformationList info = props.additionalInfo();
686 if (info != m_fileItemDelegate->showInformation()) {
687 m_fileItemDelegate->setShowInformation(info);
688 emit additionalInfoChanged(info);
689 }
690
691 const bool showPreview = props.showPreview();
692 if (showPreview != m_showPreview) {
693 m_showPreview = showPreview;
694 emit showPreviewChanged();
695 }
696 }
697
698 void DolphinView::changeSelection(const KFileItemList& selection)
699 {
700 clearSelection();
701 if (selection.isEmpty()) {
702 return;
703 }
704 const KUrl& baseUrl = url();
705 KUrl url;
706 QItemSelection new_selection;
707 foreach(const KFileItem& item, selection) {
708 url = item.url().upUrl();
709 if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) {
710 QModelIndex index = m_proxyModel->mapFromSource(m_dolphinModel->indexForItem(item));
711 new_selection.select(index, index);
712 }
713 }
714 itemView()->selectionModel()->select(new_selection,
715 QItemSelectionModel::ClearAndSelect
716 | QItemSelectionModel::Current);
717 }
718
719 void DolphinView::openContextMenu(const QPoint& pos)
720 {
721 KFileItem item;
722
723 const QModelIndex index = itemView()->indexAt(pos);
724 if (index.isValid() && (index.column() == DolphinModel::Name)) {
725 item = fileItem(index);
726 }
727
728 emit requestContextMenu(item, url());
729 }
730
731 void DolphinView::dropUrls(const KUrl::List& urls,
732 const KUrl& destPath,
733 const KFileItem& destItem)
734 {
735 const KUrl& destination = !destItem.isNull() && destItem.isDir() ?
736 destItem.url() : destPath;
737 const KUrl sourceDir = KUrl(urls.first().directory());
738 if (sourceDir != destination) {
739 dropUrls(urls, destination);
740 }
741 }
742
743 void DolphinView::dropUrls(const KUrl::List& urls,
744 const KUrl& destination)
745 {
746 emit urlsDropped(urls, destination);
747 }
748
749 void DolphinView::updateSorting(DolphinView::Sorting sorting)
750 {
751 ViewProperties props(viewPropertiesUrl());
752 props.setSorting(sorting);
753
754 m_proxyModel->setSorting(sorting);
755
756 emit sortingChanged(sorting);
757 }
758
759 void DolphinView::updateSortOrder(Qt::SortOrder order)
760 {
761 ViewProperties props(viewPropertiesUrl());
762 props.setSortOrder(order);
763
764 m_proxyModel->setSortOrder(order);
765
766 emit sortOrderChanged(order);
767 }
768
769 void DolphinView::updateAdditionalInfo(const KFileItemDelegate::InformationList& info)
770 {
771 ViewProperties props(viewPropertiesUrl());
772 props.setAdditionalInfo(info);
773
774 m_fileItemDelegate->setShowInformation(info);
775
776 emit additionalInfoChanged(info);
777
778 }
779
780 void DolphinView::emitContentsMoved()
781 {
782 // only emit the contents moved signal if:
783 // - no directory loading is ongoing (this would reset the contents position
784 // always to (0, 0))
785 // - if the Column View is active: the column view does an automatic
786 // positioning during the loading operation, which must be remembered
787 if (!m_loadingDirectory || isColumnViewActive()) {
788 const QPoint pos(contentsPosition());
789 emit contentsMoved(pos.x(), pos.y());
790 }
791 }
792
793 void DolphinView::updateCutItems()
794 {
795 // restore the icons of all previously selected items to the
796 // original state...
797 QList<CutItem>::const_iterator it = m_cutItemsCache.begin();
798 QList<CutItem>::const_iterator end = m_cutItemsCache.end();
799 while (it != end) {
800 const QModelIndex index = m_dolphinModel->indexForUrl((*it).url);
801 if (index.isValid()) {
802 m_dolphinModel->setData(index, QIcon((*it).pixmap), Qt::DecorationRole);
803 }
804 ++it;
805 }
806 m_cutItemsCache.clear();
807
808 // ... and apply an item effect to all currently cut items
809 applyCutItemEffect();
810 }
811
812 void DolphinView::showHoverInformation(const KFileItem& item)
813 {
814 if (hasSelection()) {
815 return;
816 }
817
818 emit requestItemInfo(item);
819 }
820
821 void DolphinView::clearHoverInformation()
822 {
823 emit requestItemInfo(KFileItem());
824 }
825
826
827 void DolphinView::createView()
828 {
829 // delete current view
830 QAbstractItemView* view = itemView();
831 if (view != 0) {
832 m_topLayout->removeWidget(view);
833 view->close();
834 view->deleteLater();
835 view = 0;
836 m_iconsView = 0;
837 m_detailsView = 0;
838 m_columnView = 0;
839 m_fileItemDelegate = 0;
840 }
841
842 Q_ASSERT(m_iconsView == 0);
843 Q_ASSERT(m_detailsView == 0);
844 Q_ASSERT(m_columnView == 0);
845
846 // ... and recreate it representing the current mode
847 switch (m_mode) {
848 case IconsView: {
849 m_iconsView = new DolphinIconsView(this, m_controller);
850 view = m_iconsView;
851 break;
852 }
853
854 case DetailsView:
855 m_detailsView = new DolphinDetailsView(this, m_controller);
856 view = m_detailsView;
857 break;
858
859 case ColumnView:
860 m_columnView = new DolphinColumnView(this, m_controller);
861 view = m_columnView;
862 break;
863 }
864
865 Q_ASSERT(view != 0);
866
867 m_fileItemDelegate = new KFileItemDelegate(view);
868 view->setItemDelegate(m_fileItemDelegate);
869
870 view->setModel(m_proxyModel);
871 view->setSelectionMode(QAbstractItemView::ExtendedSelection);
872
873 new KMimeTypeResolver(view, m_dolphinModel);
874 m_topLayout->insertWidget(1, view);
875
876 connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
877 this, SLOT(emitSelectionChangedSignal()));
878 connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
879 this, SLOT(emitContentsMoved()));
880 connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)),
881 this, SLOT(emitContentsMoved()));
882 }
883
884 QAbstractItemView* DolphinView::itemView() const
885 {
886 if (m_detailsView != 0) {
887 return m_detailsView;
888 } else if (m_columnView != 0) {
889 return m_columnView;
890 }
891
892 return m_iconsView;
893 }
894
895 bool DolphinView::isCutItem(const KFileItem& item) const
896 {
897 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
898 const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
899
900 const KUrl& itemUrl = item.url();
901 KUrl::List::const_iterator it = cutUrls.begin();
902 const KUrl::List::const_iterator end = cutUrls.end();
903 while (it != end) {
904 if (*it == itemUrl) {
905 return true;
906 }
907 ++it;
908 }
909
910 return false;
911 }
912
913 void DolphinView::applyCutItemEffect()
914 {
915 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
916 if (!KonqMimeData::decodeIsCutSelection(mimeData)) {
917 return;
918 }
919
920 KFileItemList items(m_dirLister->items());
921 KFileItemList::const_iterator it = items.begin();
922 const KFileItemList::const_iterator end = items.end();
923 while (it != end) {
924 const KFileItem item = *it;
925 if (isCutItem(item)) {
926 const QModelIndex index = m_dolphinModel->indexForItem(item);
927 const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole);
928 if (value.type() == QVariant::Icon) {
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, KIconLoader::Desktop, KIconLoader::DisabledState);
942 m_dolphinModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
943 }
944 }
945 ++it;
946 }
947 }
948
949 KToggleAction* DolphinView::iconsModeAction(KActionCollection* actionCollection)
950 {
951 KToggleAction* iconsView = actionCollection->add<KToggleAction>("icons");
952 iconsView->setText(i18nc("@action:inmenu View Mode", "Icons"));
953 iconsView->setShortcut(Qt::CTRL | Qt::Key_1);
954 iconsView->setIcon(KIcon("fileview-icon"));
955 iconsView->setData(QVariant::fromValue(IconsView));
956 return iconsView;
957 }
958
959 KToggleAction* DolphinView::detailsModeAction(KActionCollection* actionCollection)
960 {
961 KToggleAction* detailsView = actionCollection->add<KToggleAction>("details");
962 detailsView->setText(i18nc("@action:inmenu View Mode", "Details"));
963 detailsView->setShortcut(Qt::CTRL | Qt::Key_2);
964 detailsView->setIcon(KIcon("fileview-detailed"));
965 detailsView->setData(QVariant::fromValue(DetailsView));
966 return detailsView;
967 }
968
969 KToggleAction* DolphinView::columnsModeAction(KActionCollection* actionCollection)
970 {
971 KToggleAction* columnView = actionCollection->add<KToggleAction>("columns");
972 columnView->setText(i18nc("@action:inmenu View Mode", "Columns"));
973 columnView->setShortcut(Qt::CTRL | Qt::Key_3);
974 columnView->setIcon(KIcon("fileview-column"));
975 columnView->setData(QVariant::fromValue(ColumnView));
976 return columnView;
977 }
978
979 QString DolphinView::currentViewModeActionName() const
980 {
981 switch (m_mode) {
982 case DolphinView::IconsView:
983 return "icons";
984 case DolphinView::DetailsView:
985 return "details";
986 case DolphinView::ColumnView:
987 return "columns";
988 }
989 return QString(); // can't happen
990 }
991
992 #include "dolphinview.moc"