1 /***************************************************************************
2 * Copyright (C) 2006-2009 by Peter Penz <peter.penz19@gmail.com> *
3 * Copyright (C) 2006 by Gregor Kališnik <gregor@podnapisi.net> *
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. *
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. *
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 ***************************************************************************/
21 #include "dolphinview.h"
23 #include <QAbstractItemView>
24 #include <QApplication>
27 #include <QItemSelection>
32 #include <KActionCollection>
33 #include <KColorScheme>
35 #include <KIconEffect>
37 #include <KFileItemListProperties>
39 #include <kitemviews/kfileitemmodel.h>
40 #include <kitemviews/kfileitemlistview.h>
41 #include <kitemviews/kitemlistview.h>
42 #include <kitemviews/kitemlistcontroller.h>
43 #include <KIO/DeleteJob>
44 #include <KIO/NetAccess>
45 #include <KIO/PreviewJob>
48 #include <KMessageBox>
49 #include <konq_fileitemcapabilities.h>
50 #include <konq_operations.h>
51 #include <konqmimedata.h>
52 #include <KToggleAction>
55 #include "additionalinfoaccessor.h"
56 #include "dolphindirlister.h"
57 #include "dolphinnewfilemenuobserver.h"
58 #include "dolphin_detailsmodesettings.h"
59 #include "dolphin_generalsettings.h"
60 #include "renamedialog.h"
61 #include "settings/dolphinsettings.h"
62 #include "viewmodecontroller.h"
63 #include "viewproperties.h"
64 #include "zoomlevelinfo.h"
67 #include "dolphinitemlistcontainer.h"
70 const int MaxModeEnum
= DolphinView::CompactView
;
71 const int MaxSortingEnum
= DolphinView::SortByPath
;
74 DolphinView::DolphinView(const KUrl
& url
, QWidget
* parent
) :
77 m_tabsForFiles(false),
78 m_assureVisibleCurrentIndex(false),
79 m_expanderActive(false),
80 m_isFolderWritable(true),
82 m_mode(DolphinView::IconsView
),
83 m_additionalInfoList(),
87 m_selectionChangedTimer(0),
89 m_restoredContentsPosition(),
94 m_topLayout
= new QVBoxLayout(this);
95 m_topLayout
->setSpacing(0);
96 m_topLayout
->setMargin(0);
98 //m_dolphinViewController = new DolphinViewController(this);
100 //m_viewModeController = new ViewModeController(this);
101 //m_viewModeController->setUrl(url);
103 /*connect(m_viewModeController, SIGNAL(urlChanged(const KUrl&)),
104 this, SIGNAL(urlChanged(const KUrl&)));
106 connect(m_dolphinViewController, SIGNAL(requestContextMenu(const QPoint&, const QList<QAction*>&)),
107 this, SLOT(openContextMenu(const QPoint&, const QList<QAction*>&)));
108 connect(m_dolphinViewController, SIGNAL(urlsDropped(const KFileItem&, const KUrl&, QDropEvent*)),
109 this, SLOT(dropUrls(const KFileItem&, const KUrl&, QDropEvent*)));
110 connect(m_dolphinViewController, SIGNAL(sortingChanged(DolphinView::Sorting)),
111 this, SLOT(updateSorting(DolphinView::Sorting)));
112 connect(m_dolphinViewController, SIGNAL(sortOrderChanged(Qt::SortOrder)),
113 this, SLOT(updateSortOrder(Qt::SortOrder)));
114 connect(m_dolphinViewController, SIGNAL(sortFoldersFirstChanged(bool)),
115 this, SLOT(updateSortFoldersFirst(bool)));
116 connect(m_dolphinViewController, SIGNAL(additionalInfoChanged(const QList<DolphinView::AdditionalInfo>&)),
117 this, SLOT(updateAdditionalInfo(const QList<DolphinView::AdditionalInfo>&)));*/
118 //connect(m_dolphinViewController, SIGNAL(itemTriggered(const KFileItem&)),
119 // this, SLOT(triggerItem(const KFileItem&)));
120 //connect(m_dolphinViewController, SIGNAL(tabRequested(const KUrl&)),
121 // this, SIGNAL(tabRequested(const KUrl&)));
122 /*connect(m_dolphinViewController, SIGNAL(activated()),
123 this, SLOT(activate()));
124 connect(m_dolphinViewController, SIGNAL(itemEntered(const KFileItem&)),
125 this, SLOT(showHoverInformation(const KFileItem&)));
126 connect(m_dolphinViewController, SIGNAL(viewportEntered()),
127 this, SLOT(clearHoverInformation()));
128 connect(m_dolphinViewController, SIGNAL(urlChangeRequested(KUrl)),
129 this, SLOT(slotUrlChangeRequested(KUrl)));*/
131 // When a new item has been created by the "Create New..." menu, the item should
132 // get selected and it must be assured that the item will get visible. As the
133 // creation is done asynchronously, several signals must be checked:
134 connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(itemCreated(const KUrl
&)),
135 this, SLOT(observeCreatedItem(const KUrl
&)));
137 m_selectionChangedTimer
= new QTimer(this);
138 m_selectionChangedTimer
->setSingleShot(true);
139 m_selectionChangedTimer
->setInterval(300);
140 connect(m_selectionChangedTimer
, SIGNAL(timeout()),
141 this, SLOT(emitSelectionChangedSignal()));
143 m_dirLister
= new DolphinDirLister(this);
144 m_dirLister
->setAutoUpdate(true);
145 m_dirLister
->setDelayedMimeTypes(true);
147 connect(m_dirLister
, SIGNAL(redirection(KUrl
,KUrl
)), this, SLOT(slotRedirection(KUrl
,KUrl
)));
148 connect(m_dirLister
, SIGNAL(started(KUrl
)), this, SLOT(slotDirListerStarted(KUrl
)));
149 connect(m_dirLister
, SIGNAL(completed()), this, SLOT(slotDirListerCompleted()));
150 connect(m_dirLister
, SIGNAL(refreshItems(const QList
<QPair
<KFileItem
,KFileItem
>>&)),
151 this, SLOT(slotRefreshItems()));
153 connect(m_dirLister
, SIGNAL(clear()), this, SIGNAL(itemCountChanged()));
154 connect(m_dirLister
, SIGNAL(newItems(KFileItemList
)), this, SIGNAL(itemCountChanged()));
155 connect(m_dirLister
, SIGNAL(infoMessage(const QString
&)), this, SIGNAL(infoMessage(const QString
&)));
156 connect(m_dirLister
, SIGNAL(errorMessage(const QString
&)), this, SIGNAL(infoMessage(const QString
&)));
157 connect(m_dirLister
, SIGNAL(percent(int)), this, SIGNAL(pathLoadingProgress(int)));
158 connect(m_dirLister
, SIGNAL(urlIsFileError(const KUrl
&)), this, SIGNAL(urlIsFileError(const KUrl
&)));
159 connect(m_dirLister
, SIGNAL(itemsDeleted(const KFileItemList
&)), this, SIGNAL(itemCountChanged()));
161 m_container
= new DolphinItemListContainer(m_dirLister
, this);
162 QHash
<QByteArray
, int> visibleRoles
;
163 visibleRoles
.insert("name", 0);
164 m_container
->setVisibleRoles(visibleRoles
);
166 KItemListController
* controller
= m_container
->controller();
167 connect(controller
, SIGNAL(itemClicked(int, Qt::MouseButton
)),
168 this, SLOT(slotItemClicked(int, Qt::MouseButton
)));
169 connect(controller
, SIGNAL(itemExpansionToggleClicked(int)), this, SLOT(slotItemExpansionToggleClicked(int)));
171 applyViewProperties();
172 m_topLayout
->addWidget(m_container
);
177 DolphinView::~DolphinView()
181 KUrl
DolphinView::url() const
186 void DolphinView::setActive(bool active
)
188 if (active
== m_active
) {
194 QColor color
= KColorScheme(QPalette::Active
, KColorScheme::View
).background().color();
199 /*QAbstractItemView* view = m_viewAccessor.itemView();
200 QWidget* viewport = view ? view->viewport() : 0;
203 palette.setColor(viewport->backgroundRole(), color);
204 viewport->setPalette(palette);
214 emitSelectionChangedSignal();
215 emit
writeStateChanged(m_isFolderWritable
);
218 //m_viewModeController->indicateActivationChange(active);
221 bool DolphinView::isActive() const
226 void DolphinView::setMode(Mode mode
)
228 if (mode
!= m_mode
) {
229 ViewProperties
props(url());
230 props
.setViewMode(mode
);
233 applyViewProperties();
237 DolphinView::Mode
DolphinView::mode() const
242 bool DolphinView::previewsShown() const
244 return m_container
->previewsShown();
247 bool DolphinView::hiddenFilesShown() const
249 return m_dirLister
->showingDotFiles();
252 bool DolphinView::categorizedSorting() const
254 return false; //m_storedCategorizedSorting;
257 KFileItemList
DolphinView::items() const
259 return m_dirLister
->items();
262 KFileItemList
DolphinView::selectedItems() const
264 return KFileItemList();
265 /* KFileItemList itemList;
266 const QAbstractItemView* view = m_viewAccessor.itemView();
271 const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection());
273 const QModelIndexList indexList = selection.indexes();
274 foreach (const QModelIndex &index, indexList) {
275 KFileItem item = m_viewAccessor.dirModel()->itemForIndex(index);
276 if (!item.isNull()) {
277 itemList.append(item);
284 int DolphinView::selectedItemsCount() const
287 /*const QAbstractItemView* view = m_viewAccessor.itemView();
292 return view->selectionModel()->selectedIndexes().count();*/
295 void DolphinView::markUrlsAsSelected(const QList
<KUrl
>& urls
)
297 foreach (const KUrl
& url
, urls
) {
298 KFileItem
item(KFileItem::Unknown
, KFileItem::Unknown
, url
);
299 m_selectedItems
.append(item
);
303 void DolphinView::setItemSelectionEnabled(const QRegExp
& pattern
, bool enabled
)
307 /*const QItemSelection matchingIndexes = childrenMatchingPattern(QModelIndex(), pattern);
308 const QItemSelectionModel::SelectionFlags command = enabled
309 ? QItemSelectionModel::Select
310 : QItemSelectionModel::Deselect;
311 m_viewAccessor.itemView()->selectionModel()->select(matchingIndexes, command);*/
314 void DolphinView::setZoomLevel(int level
)
316 const int oldZoomLevel
= zoomLevel();
317 m_container
->setZoomLevel(level
);
318 if (zoomLevel() != oldZoomLevel
) {
319 emit
zoomLevelChanged(zoomLevel(), oldZoomLevel
);
323 int DolphinView::zoomLevel() const
325 return m_container
->zoomLevel();
328 void DolphinView::setSorting(Sorting sorting
)
330 if (sorting
!= this->sorting()) {
331 updateSorting(sorting
);
335 DolphinView::Sorting
DolphinView::sorting() const
337 return DolphinView::SortByName
;
338 //return m_viewAccessor.proxyModel()->sorting();
341 void DolphinView::setSortOrder(Qt::SortOrder order
)
343 if (sortOrder() != order
) {
344 updateSortOrder(order
);
348 Qt::SortOrder
DolphinView::sortOrder() const
350 return Qt::AscendingOrder
; // m_viewAccessor.proxyModel()->sortOrder();
353 void DolphinView::setSortFoldersFirst(bool foldersFirst
)
355 if (sortFoldersFirst() != foldersFirst
) {
356 updateSortFoldersFirst(foldersFirst
);
360 bool DolphinView::sortFoldersFirst() const
362 return true; // m_viewAccessor.proxyModel()->sortFoldersFirst();
365 void DolphinView::setAdditionalInfoList(const QList
<AdditionalInfo
>& info
)
367 const QList
<AdditionalInfo
> previousList
= info
;
369 ViewProperties
props(url());
370 props
.setAdditionalInfoList(info
);
372 m_additionalInfoList
= info
;
373 applyAdditionalInfoListToView();
375 emit
additionalInfoListChanged(m_additionalInfoList
, previousList
);
378 QList
<DolphinView::AdditionalInfo
> DolphinView::additionalInfoList() const
380 return m_additionalInfoList
;
383 void DolphinView::reload()
385 QByteArray viewState
;
386 QDataStream
saveStream(&viewState
, QIODevice::WriteOnly
);
387 saveState(saveStream
);
388 m_selectedItems
= selectedItems();
391 loadDirectory(url(), true);
393 QDataStream
restoreStream(viewState
);
394 restoreState(restoreStream
);
397 void DolphinView::stopLoading()
402 void DolphinView::refresh()
404 const bool oldActivationState
= m_active
;
405 const int oldZoomLevel
= zoomLevel();
408 applyViewProperties();
411 setActive(oldActivationState
);
412 updateZoomLevel(oldZoomLevel
);
415 void DolphinView::setNameFilter(const QString
& nameFilter
)
417 Q_UNUSED(nameFilter
);
418 //m_viewModeController->setNameFilter(nameFilter);
421 QString
DolphinView::nameFilter() const
423 return QString(); //m_viewModeController->nameFilter();
426 void DolphinView::calculateItemCount(int& fileCount
,
428 KIO::filesize_t
& totalFileSize
) const
430 foreach (const KFileItem
& item
, m_dirLister
->items()) {
435 totalFileSize
+= item
.size();
440 QString
DolphinView::statusBarText() const
445 KIO::filesize_t totalFileSize
= 0;
447 if (hasSelection()) {
448 // give a summary of the status of the selected files
449 const KFileItemList list
= selectedItems();
450 if (list
.isEmpty()) {
451 // when an item is triggered, it is temporary selected but selectedItems()
452 // will return an empty list
456 KFileItemList::const_iterator it
= list
.begin();
457 const KFileItemList::const_iterator end
= list
.end();
459 const KFileItem
& item
= *it
;
464 totalFileSize
+= item
.size();
469 if (folderCount
+ fileCount
== 1) {
470 // if only one item is selected, show the filename
471 const QString name
= list
.first().text();
472 text
= (folderCount
== 1) ? i18nc("@info:status", "<filename>%1</filename> selected", name
) :
473 i18nc("@info:status", "<filename>%1</filename> selected (%2)",
474 name
, KIO::convertSize(totalFileSize
));
476 // at least 2 items are selected
477 const QString foldersText
= i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount
);
478 const QString filesText
= i18ncp("@info:status", "1 File selected", "%1 Files selected", fileCount
);
479 if ((folderCount
> 0) && (fileCount
> 0)) {
480 text
= i18nc("@info:status folders, files (size)", "%1, %2 (%3)",
481 foldersText
, filesText
, KIO::convertSize(totalFileSize
));
482 } else if (fileCount
> 0) {
483 text
= i18nc("@info:status files (size)", "%1 (%2)", filesText
, KIO::convertSize(totalFileSize
));
485 Q_ASSERT(folderCount
> 0);
490 calculateItemCount(fileCount
, folderCount
, totalFileSize
);
491 text
= KIO::itemsSummaryString(fileCount
+ folderCount
,
492 fileCount
, folderCount
,
493 totalFileSize
, true);
499 QList
<QAction
*> DolphinView::versionControlActions(const KFileItemList
& items
) const
502 return QList
<QAction
*>(); //m_dolphinViewController->versionControlActions(items);
505 void DolphinView::setUrl(const KUrl
& url
)
511 emit
urlAboutToBeChanged(url
);
513 const bool hadSelection
= hasSelection();
514 m_newFileNames
.clear();
517 // It is important to clear the items from the model before
518 // applying the view properties, otherwise expensive operations
519 // might be done on the existing items although they get cleared
520 // anyhow afterwards by loadDirectory().
521 fileItemModel()->clear();
522 applyViewProperties();
525 emit
urlChanged(url
);
526 if (hadSelection
|| hasSelection()) {
527 emitSelectionChangedSignal();
531 void DolphinView::selectAll()
533 //m_viewAccessor.itemView()->selectAll();
536 void DolphinView::invertSelection()
538 /* // Implementation note: Using selectionModel->select(selection, QItemSelectionModel::Toggle) does not
539 // work, as QItemSelectionModel::hasSelection() provides invalid values in this case. This might be a Qt-issue -
540 // when changing the implementation with an updated Qt-version don't forget to run the Dolphin-unit-tests that
541 // verify this usecase.
542 const KFileItemList selItems = selectedItems();
545 QItemSelection invertedSelection;
546 foreach (const KFileItem& item, items()) {
547 if (!selItems.contains(item)) {
548 const QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item));
549 invertedSelection.select(index, index);
553 QItemSelectionModel* selectionModel = m_viewAccessor.itemView()->selectionModel();
554 selectionModel->select(invertedSelection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current);
558 void DolphinView::clearSelection()
560 //m_viewAccessor.itemView()->clearSelection();
563 void DolphinView::renameSelectedItems()
565 KFileItemList items
= selectedItems();
566 const int itemCount
= items
.count();
571 /*if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) {
572 const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForItem(items.first());
573 const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
574 m_viewAccessor.itemView()->edit(proxyIndex);
576 RenameDialog
* dialog
= new RenameDialog(this, items
);
577 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
580 dialog
->activateWindow();
583 // assure that the current index remains visible when KDirLister
584 // will notify the view about changed items
585 m_assureVisibleCurrentIndex
= true;
588 void DolphinView::trashSelectedItems()
590 const KUrl::List list
= simplifiedSelectedUrls();
591 KonqOperations::del(this, KonqOperations::TRASH
, list
);
594 void DolphinView::deleteSelectedItems()
596 const KUrl::List list
= simplifiedSelectedUrls();
597 const bool del
= KonqOperations::askDeleteConfirmation(list
,
599 KonqOperations::DEFAULT_CONFIRMATION
,
603 KIO::Job
* job
= KIO::del(list
);
604 connect(job
, SIGNAL(result(KJob
*)),
605 this, SLOT(slotDeleteFileFinished(KJob
*)));
609 void DolphinView::cutSelectedItems()
611 QMimeData
* mimeData
= selectionMimeData();
612 KonqMimeData::addIsCutSelection(mimeData
, true);
613 QApplication::clipboard()->setMimeData(mimeData
);
616 void DolphinView::copySelectedItems()
618 QMimeData
* mimeData
= selectionMimeData();
619 QApplication::clipboard()->setMimeData(mimeData
);
622 void DolphinView::paste()
627 void DolphinView::pasteIntoFolder()
629 const KFileItemList items
= selectedItems();
630 if ((items
.count() == 1) && items
.first().isDir()) {
631 pasteToUrl(items
.first().url());
635 void DolphinView::setPreviewsShown(bool show
)
637 if (previewsShown() == show
) {
641 ViewProperties
props(url());
642 props
.setPreviewsShown(show
);
644 m_container
->setPreviewsShown(show
);
645 emit
previewsShownChanged(show
);
648 void DolphinView::setHiddenFilesShown(bool show
)
650 if (m_dirLister
->showingDotFiles() == show
) {
654 m_selectedItems
= selectedItems();
656 ViewProperties
props(url());
657 props
.setHiddenFilesShown(show
);
659 m_dirLister
->setShowingDotFiles(show
);
660 m_dirLister
->emitChanges();
661 emit
hiddenFilesShownChanged(show
);
664 void DolphinView::setCategorizedSorting(bool categorized
)
666 if (categorized
== categorizedSorting()) {
670 ViewProperties
props(url());
671 props
.setCategorizedSorting(categorized
);
674 //m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
676 emit
categorizedSortingChanged(categorized
);
679 void DolphinView::mouseReleaseEvent(QMouseEvent
* event
)
681 QWidget::mouseReleaseEvent(event
);
685 void DolphinView::contextMenuEvent(QContextMenuEvent
* event
)
689 const QPoint pos
= m_container
->mapFromGlobal(QCursor::pos());
690 const KItemListView
* view
= m_container
->controller()->view();
691 if (view
->itemAt(pos
) < 0) {
692 // Only open the context-menu if the cursor is above the viewport
693 // (the context-menu for items is handled in slotItemClicked())
694 requestContextMenu(KFileItem(), url(), QList
<QAction
*>());
698 void DolphinView::activate()
703 void DolphinView::slotItemClicked(int index
, Qt::MouseButton button
)
705 const KFileItem item
= fileItemModel()->fileItem(index
);
707 if (button
& Qt::LeftButton
) {
708 emit
itemTriggered(item
); // caught by DolphinViewContainer or DolphinPart
709 } else if (button
& Qt::MidButton
) {
710 if (item
.isDir() || isTabsForFilesEnabled()) {
711 emit
tabRequested(item
.url());
713 } else if (button
& Qt::RightButton
) {
714 // TODO: attach customActions for the details-view
715 emit
requestContextMenu(item
, url(), QList
<QAction
*>());
719 void DolphinView::slotItemExpansionToggleClicked(int index
)
721 KFileItemModel
* model
= fileItemModel();
722 const bool expanded
= model
->isExpanded(index
);
723 model
->setExpanded(index
, !expanded
);
726 void DolphinView::slotSelectionChanged(const QItemSelection
& selected
, const QItemSelection
& deselected
)
728 const int count
= selectedItemsCount();
729 const bool selectionStateChanged
= ((count
> 0) && (selected
.count() == count
)) ||
730 ((count
== 0) && !deselected
.isEmpty());
732 // If nothing has been selected before and something got selected (or if something
733 // was selected before and now nothing is selected) the selectionChangedSignal must
734 // be emitted asynchronously as fast as possible to update the edit-actions.
735 m_selectionChangedTimer
->setInterval(selectionStateChanged
? 0 : 300);
736 m_selectionChangedTimer
->start();
739 void DolphinView::emitSelectionChangedSignal()
741 m_selectionChangedTimer
->stop();
742 emit
selectionChanged(selectedItems());
745 void DolphinView::openContextMenu(const QPoint
& pos
,
746 const QList
<QAction
*>& customActions
)
750 /*QAbstractItemView* view = m_viewAccessor.itemView();
753 index = view->indexAt(pos);
756 if (index.isValid() && (index.column() == DolphinModel::Name)) {
757 const QModelIndex dolphinModelIndex = m_viewAccessor.proxyModel()->mapToSource(index);
758 item = m_viewAccessor.dirModel()->itemForIndex(dolphinModelIndex);
761 emit
requestContextMenu(item
, url(), customActions
);
764 void DolphinView::dropUrls(const KFileItem
& destItem
,
765 const KUrl
& destPath
,
770 addNewFileNames(event
->mimeData());
771 //DragAndDropHelper::instance().dropUrls(destItem, destPath, event, this);
774 void DolphinView::updateSorting(DolphinView::Sorting sorting
)
776 ViewProperties
props(url());
777 props
.setSorting(sorting
);
779 KItemModelBase
* model
= m_container
->controller()->model();
780 model
->setSortRole(sortRoleForSorting(sorting
));
782 emit
sortingChanged(sorting
);
785 void DolphinView::updateSortOrder(Qt::SortOrder order
)
787 ViewProperties
props(url());
788 props
.setSortOrder(order
);
790 //m_viewAccessor.proxyModel()->setSortOrder(order);
792 emit
sortOrderChanged(order
);
795 void DolphinView::updateSortFoldersFirst(bool foldersFirst
)
797 ViewProperties
props(url());
798 props
.setSortFoldersFirst(foldersFirst
);
800 //m_viewAccessor.proxyModel()->setSortFoldersFirst(foldersFirst);
802 emit
sortFoldersFirstChanged(foldersFirst
);
805 QPair
<bool, QString
> DolphinView::pasteInfo() const
807 return KonqOperations::pasteInfo(url());
810 void DolphinView::setTabsForFilesEnabled(bool tabsForFiles
)
812 m_tabsForFiles
= tabsForFiles
;
815 bool DolphinView::isTabsForFilesEnabled() const
817 return m_tabsForFiles
;
820 bool DolphinView::itemsExpandable() const
822 return false; //m_viewAccessor.itemsExpandable();
825 void DolphinView::restoreState(QDataStream
& stream
)
827 // Restore the URL of the current item that had the keyboard focus
828 stream
>> m_activeItemUrl
;
830 // Restore the view position
831 stream
>> m_restoredContentsPosition
;
833 // Restore expanded folders (only relevant for the details view - will be ignored by the view in other view modes)
834 QSet
<KUrl
> urlsToExpand
;
835 stream
>> urlsToExpand
;
836 /*const DolphinDetailsViewExpander* expander = m_viewAccessor.setExpandedUrls(urlsToExpand);
838 m_expanderActive = true;
839 connect (expander, SIGNAL(completed()), this, SLOT(slotLoadingCompleted()));
842 m_expanderActive = false;
846 void DolphinView::saveState(QDataStream
& stream
)
848 // Save the URL of the current item that has the keyboard focus
851 //if (!currentItem.isNull()) {
852 // currentItemUrl = currentItem.url();
855 stream
<< currentItemUrl
;
857 // Save view position
858 const qreal x
= m_container
->horizontalScrollBar()->value();
859 const qreal y
= m_container
->verticalScrollBar()->value();
860 stream
<< QPoint(x
, y
);
861 kDebug() << "saving view state" << QPoint(x
, y
);
863 // Save expanded folders (only relevant for the details view - the set will be empty in other view modes)
864 //stream << m_viewAccessor.expandedUrls();
867 bool DolphinView::hasSelection() const
869 //const QAbstractItemView* view = m_viewAccessor.itemView();
870 //return view && view->selectionModel()->hasSelection();
874 KFileItem
DolphinView::rootItem() const
876 return m_dirLister
->rootItem();
879 void DolphinView::observeCreatedItem(const KUrl
& url
)
881 m_createdItemUrl
= url
;
882 //connect(m_dirModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
883 // this, SLOT(selectAndScrollToCreatedItem()));
886 void DolphinView::selectAndScrollToCreatedItem()
888 /*const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_createdItemUrl);
889 if (dirIndex.isValid()) {
890 const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
891 QAbstractItemView* view = m_viewAccessor.itemView();
893 view->setCurrentIndex(proxyIndex);
897 disconnect(m_viewAccessor.dirModel(), SIGNAL(rowsInserted(const QModelIndex&, int, int)),
898 this, SLOT(selectAndScrollToCreatedItem()));*/
899 m_createdItemUrl
= KUrl();
902 void DolphinView::slotRedirection(const KUrl
& oldUrl
, const KUrl
& newUrl
)
904 if (oldUrl
.equals(url(), KUrl::CompareWithoutTrailingSlash
)) {
905 emit
redirection(oldUrl
, newUrl
);
906 m_url
= newUrl
; // #186947
910 void DolphinView::restoreContentsPosition()
912 if (!m_restoredContentsPosition
.isNull()) {
913 const int x
= m_restoredContentsPosition
.x();
914 const int y
= m_restoredContentsPosition
.y();
915 m_restoredContentsPosition
= QPoint();
917 m_container
->horizontalScrollBar()->setValue(x
);
918 m_container
->verticalScrollBar()->setValue(y
);
922 /*void DolphinView::slotUrlChangeRequested(const KUrl& url)
924 m_viewModeController->setUrl(url);
925 updateWritableState();
928 void DolphinView::showHoverInformation(const KFileItem
& item
)
930 emit
requestItemInfo(item
);
933 void DolphinView::clearHoverInformation()
935 emit
requestItemInfo(KFileItem());
938 void DolphinView::slotDeleteFileFinished(KJob
* job
)
940 if (job
->error() == 0) {
941 emit
operationCompletedMessage(i18nc("@info:status", "Delete operation completed."));
942 } else if (job
->error() != KIO::ERR_USER_CANCELED
) {
943 emit
errorMessage(job
->errorString());
947 void DolphinView::slotDirListerStarted(const KUrl
& url
)
949 // Disable the writestate temporary until it can be determined in a fast way
950 // in DolphinView::slotDirListerCompleted()
951 if (m_isFolderWritable
) {
952 m_isFolderWritable
= false;
953 emit
writeStateChanged(m_isFolderWritable
);
956 emit
startedPathLoading(url
);
959 void DolphinView::slotDirListerCompleted()
961 if (!m_expanderActive
) {
962 slotLoadingCompleted();
965 if (!m_newFileNames
.isEmpty()) {
966 // select all newly added items created by a paste operation or
967 // a drag & drop operation, and clear the previous selection
968 /*QAbstractItemView* view = m_viewAccessor.itemView();
970 view->clearSelection();
971 const int rowCount = m_viewAccessor.proxyModel()->rowCount();
972 QItemSelection selection;
973 for (int row = 0; row < rowCount; ++row) {
974 const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->index(row, 0);
975 const QModelIndex dirIndex = m_viewAccessor.proxyModel()->mapToSource(proxyIndex);
976 const KUrl url = m_viewAccessor.dirModel()->itemForIndex(dirIndex).url();
977 if (m_newFileNames.contains(url.fileName())) {
978 selection.merge(QItemSelection(proxyIndex, proxyIndex), QItemSelectionModel::Select);
981 view->selectionModel()->select(selection, QItemSelectionModel::Select);
984 m_newFileNames
.clear();
987 updateWritableState();
990 void DolphinView::slotLoadingCompleted()
992 m_expanderActive
= false;
994 if (!m_activeItemUrl
.isEmpty()) {
995 // assure that the current item remains visible
996 /*const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForUrl(m_activeItemUrl);
997 if (dirIndex.isValid()) {
998 const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex);
999 QAbstractItemView* view = m_viewAccessor.itemView();
1001 const bool clearSelection = !hasSelection();
1002 view->setCurrentIndex(proxyIndex);
1003 if (clearSelection) {
1004 view->clearSelection();
1007 m_activeItemUrl.clear();
1011 if (!m_selectedItems
.isEmpty()) {
1012 /*const KUrl& baseUrl = url();
1014 QItemSelection newSelection;
1015 foreach(const KFileItem& item, m_selectedItems) {
1016 url = item.url().upUrl();
1017 if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) {
1018 const QModelIndex index = m_viewAccessor.proxyModel()->mapFromSource(m_viewAccessor.dirModel()->indexForItem(item));
1019 newSelection.select(index, index);
1022 QAbstractItemView* view = m_viewAccessor.itemView();
1024 view->selectionModel()->select(newSelection,
1025 QItemSelectionModel::ClearAndSelect
1026 | QItemSelectionModel::Current);
1028 m_selectedItems
.clear();
1031 // Restore the contents position. This has to be done using a Qt::QueuedConnection
1032 // because the view might not be in its final state yet.
1033 QTimer::singleShot(0, this, SLOT(restoreContentsPosition()));
1035 emit
finishedPathLoading(url());
1038 void DolphinView::slotRefreshItems()
1040 if (m_assureVisibleCurrentIndex
) {
1041 m_assureVisibleCurrentIndex
= false;
1042 //QAbstractItemView* view = m_viewAccessor.itemView();
1044 // m_viewAccessor.itemView()->scrollTo(m_viewAccessor.itemView()->currentIndex());
1049 KFileItemModel
* DolphinView::fileItemModel() const
1051 return static_cast<KFileItemModel
*>(m_container
->controller()->model());
1054 void DolphinView::loadDirectory(const KUrl
& url
, bool reload
)
1056 if (!url
.isValid()) {
1057 const QString
location(url
.pathOrUrl());
1058 if (location
.isEmpty()) {
1059 emit
errorMessage(i18nc("@info:status", "The location is empty."));
1061 emit
errorMessage(i18nc("@info:status", "The location '%1' is invalid.", location
));
1066 m_dirLister
->openUrl(url
, reload
? KDirLister::Reload
: KDirLister::NoFlags
);
1069 void DolphinView::applyViewProperties()
1071 m_container
->beginTransaction();
1073 const ViewProperties
props(url());
1075 const Mode mode
= props
.viewMode();
1076 if (m_mode
!= mode
) {
1077 const Mode previousMode
= m_mode
;
1080 // Changing the mode might result in changing
1081 // the zoom level. Remember the old zoom level so
1082 // that zoomLevelChanged() can get emitted.
1083 const int oldZoomLevel
= m_container
->zoomLevel();
1086 case IconsView
: m_container
->setItemLayout(KFileItemListView::IconsLayout
); break;
1087 case CompactView
: m_container
->setItemLayout(KFileItemListView::CompactLayout
); break;
1088 case DetailsView
: m_container
->setItemLayout(KFileItemListView::DetailsLayout
); break;
1089 default: Q_ASSERT(false); break;
1092 emit
modeChanged(m_mode
, previousMode
);
1094 if (m_container
->zoomLevel() != oldZoomLevel
) {
1095 emit
zoomLevelChanged(m_container
->zoomLevel(), oldZoomLevel
);
1099 const bool hiddenFilesShown
= props
.hiddenFilesShown();
1100 if (hiddenFilesShown
!= m_dirLister
->showingDotFiles()) {
1101 m_dirLister
->setShowingDotFiles(hiddenFilesShown
);
1102 m_dirLister
->emitChanges();
1103 emit
hiddenFilesShownChanged(hiddenFilesShown
);
1106 /* m_storedCategorizedSorting = props.categorizedSorting();
1107 const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting();
1108 if (categorized != m_viewAccessor.proxyModel()->isCategorizedModel()) {
1109 m_viewAccessor.proxyModel()->setCategorizedModel(categorized);
1110 emit categorizedSortingChanged();
1113 const DolphinView::Sorting sorting
= props
.sorting();
1114 KItemModelBase
* model
= m_container
->controller()->model();
1115 const QByteArray newSortRole
= sortRoleForSorting(sorting
);
1116 if (newSortRole
!= model
->sortRole()) {
1117 model
->setSortRole(newSortRole
);
1118 emit
sortingChanged(sorting
);
1121 const Qt::SortOrder sortOrder = props.sortOrder();
1122 if (sortOrder != m_viewAccessor.proxyModel()->sortOrder()) {
1123 m_viewAccessor.proxyModel()->setSortOrder(sortOrder);
1124 emit sortOrderChanged(sortOrder);
1127 const bool sortFoldersFirst = props.sortFoldersFirst();
1128 if (sortFoldersFirst != m_viewAccessor.proxyModel()->sortFoldersFirst()) {
1129 m_viewAccessor.proxyModel()->setSortFoldersFirst(sortFoldersFirst);
1130 emit sortFoldersFirstChanged(sortFoldersFirst);
1133 const QList
<DolphinView::AdditionalInfo
> infoList
= props
.additionalInfoList();
1134 if (infoList
!= m_additionalInfoList
) {
1135 const QList
<DolphinView::AdditionalInfo
> previousList
= m_additionalInfoList
;
1136 m_additionalInfoList
= infoList
;
1137 applyAdditionalInfoListToView();
1138 emit
additionalInfoListChanged(m_additionalInfoList
, previousList
);
1141 const bool previewsShown
= props
.previewsShown();
1142 if (previewsShown
!= m_container
->previewsShown()) {
1143 const int oldZoomLevel
= zoomLevel();
1145 m_container
->setPreviewsShown(previewsShown
);
1146 emit
previewsShownChanged(previewsShown
);
1148 // Changing the preview-state might result in a changed zoom-level
1149 if (oldZoomLevel
!= zoomLevel()) {
1150 emit
zoomLevelChanged(zoomLevel(), oldZoomLevel
);
1154 m_container
->endTransaction();
1157 void DolphinView::applyAdditionalInfoListToView()
1159 const AdditionalInfoAccessor
& infoAccessor
= AdditionalInfoAccessor::instance();
1161 QHash
<QByteArray
, int> visibleRoles
;
1162 visibleRoles
.insert("name", 0);
1165 foreach (AdditionalInfo info
, m_additionalInfoList
) {
1166 visibleRoles
.insert(infoAccessor
.role(info
), index
);
1170 m_container
->setVisibleRoles(visibleRoles
);
1173 void DolphinView::pasteToUrl(const KUrl
& url
)
1175 addNewFileNames(QApplication::clipboard()->mimeData());
1176 KonqOperations::doPaste(this, url
);
1179 void DolphinView::updateZoomLevel(int oldZoomLevel
)
1181 Q_UNUSED(oldZoomLevel
);
1182 /* const int newZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(m_viewAccessor.itemView()->iconSize());
1183 if (oldZoomLevel != newZoomLevel) {
1184 m_viewModeController->setZoomLevel(newZoomLevel);
1185 emit zoomLevelChanged(newZoomLevel);
1189 KUrl::List
DolphinView::simplifiedSelectedUrls() const
1191 Q_ASSERT(false); // TODO
1194 const KFileItemList items = selectedItems();
1195 foreach (const KFileItem &item, items) {
1196 urls.append(item.url());
1200 if (itemsExpandable()) {
1201 urls = KDirModel::simplifiedUrlList(urls);
1207 QMimeData
* DolphinView::selectionMimeData() const
1209 /*const QAbstractItemView* view = m_viewAccessor.itemView();
1210 Q_ASSERT((view) && (view->selectionModel()));
1211 const QItemSelection selection = m_viewAccessor.proxyModel()->mapSelectionToSource(view->selectionModel()->selection());
1212 return m_viewAccessor.dirModel()->mimeData(selection.indexes());*/
1216 void DolphinView::addNewFileNames(const QMimeData
* mimeData
)
1218 const KUrl::List urls
= KUrl::List::fromMimeData(mimeData
);
1219 foreach (const KUrl
& url
, urls
) {
1220 m_newFileNames
.insert(url
.fileName());
1224 QItemSelection
DolphinView::childrenMatchingPattern(const QModelIndex
& parent
, const QRegExp
& pattern
) const
1228 QItemSelection matchingIndexes
;
1229 /*const DolphinSortFilterProxyModel* proxyModel = m_viewAccessor.proxyModel();
1230 const DolphinModel* dolphinModel = m_viewAccessor.dirModel();
1232 const int rowCount = proxyModel->rowCount(parent);
1234 for (int row = 0; row < rowCount; ++row) {
1235 QModelIndex index = proxyModel->index(row, 0, parent);
1236 QModelIndex sourceIndex = proxyModel->mapToSource(index);
1238 if (sourceIndex.isValid() && pattern.exactMatch(dolphinModel->data(sourceIndex).toString())) {
1239 matchingIndexes += QItemSelectionRange(index);
1242 if (proxyModel->hasChildren(index)) {
1243 matchingIndexes += childrenMatchingPattern(index, pattern);
1247 return matchingIndexes
;
1250 void DolphinView::updateWritableState()
1252 const bool wasFolderWritable
= m_isFolderWritable
;
1253 m_isFolderWritable
= true;
1255 const KFileItem item
; // = m_viewAccessor.dirLister()->rootItem();
1256 if (!item
.isNull()) {
1257 KFileItemListProperties
capabilities(KFileItemList() << item
);
1258 m_isFolderWritable
= capabilities
.supportsWriting();
1260 if (m_isFolderWritable
!= wasFolderWritable
) {
1261 emit
writeStateChanged(m_isFolderWritable
);
1265 QByteArray
DolphinView::sortRoleForSorting(Sorting sorting
) const
1268 case SortByName
: return "name";
1269 case SortBySize
: return "size";
1270 case SortByDate
: return "date";
1271 case SortByPermissions
: return "permissions";
1272 case SortByOwner
: return "owner";
1273 case SortByGroup
: return "group";
1274 case SortByType
: return "type";
1275 case SortByDestination
: return "destination";
1276 case SortByPath
: return "path";
1280 return QByteArray();
1283 #include "dolphinview.moc"