X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/bbc814c7fa79b545ceef3e6f7eaf00398eef896c..19dadee2cfd4471d795b2b72ac0541124aa505ce:/src/dolphinview.cpp diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index bb84d32c0..1a33668e0 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -20,17 +20,18 @@ #include "dolphinview.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -50,9 +51,10 @@ #include "dolphindetailsview.h" #include "dolphiniconsview.h" #include "dolphincontextmenu.h" +#include "dolphinitemcategorizer.h" #include "filterbar.h" #include "renamedialog.h" -#include "urlnavigator.h" +#include "kurlnavigator.h" #include "viewproperties.h" #include "dolphinsettings.h" #include "dolphin_generalsettings.h" @@ -65,6 +67,7 @@ DolphinView::DolphinView(DolphinMainWindow* mainWindow, QWidget(parent), m_showProgress(false), m_blockContentsMovedSignal(false), + m_initializeColumnView(false), m_mode(mode), m_iconSize(0), m_folderCount(0), @@ -96,18 +99,20 @@ DolphinView::DolphinView(DolphinMainWindow* mainWindow, connect(clipboard, SIGNAL(dataChanged()), this, SLOT(updateCutItems())); - m_urlNavigator = new UrlNavigator(DolphinSettings::instance().bookmarkManager(), url, this); - m_urlNavigator->setUrlEditable(DolphinSettings::instance().generalSettings()->editableUrl()); - m_urlNavigator->setHomeUrl(DolphinSettings::instance().generalSettings()->homeUrl()); - m_urlNavigator->setShowHiddenFiles(showHiddenFiles); + m_urlNavigator = new KUrlNavigator(DolphinSettings::instance().placesModel(), url, this); + + const GeneralSettings* settings = DolphinSettings::instance().generalSettings(); + m_urlNavigator->setUrlEditable(settings->editableUrl()); + m_urlNavigator->setHomeUrl(settings->homeUrl()); + connect(m_urlNavigator, SIGNAL(urlChanged(const KUrl&)), - this, SLOT(loadDirectory(const KUrl&))); + this, SLOT(changeDirectory(const KUrl&))); connect(m_urlNavigator, SIGNAL(urlsDropped(const KUrl::List&, const KUrl&)), this, SLOT(dropUrls(const KUrl::List&, const KUrl&))); connect(m_urlNavigator, SIGNAL(activated()), this, SLOT(requestActivation())); connect(this, SIGNAL(contentsMoved(int, int)), - m_urlNavigator, SLOT(storeContentsPosition(int, int))); + m_urlNavigator, SLOT(savePosition(int, int))); m_statusBar = new DolphinStatusBar(this); @@ -156,15 +161,19 @@ DolphinView::DolphinView(DolphinMainWindow* mainWindow, this, SLOT(emitSelectionChangedSignal())); connect(m_controller, SIGNAL(activated()), this, SLOT(requestActivation())); + connect(m_controller, SIGNAL(itemEntered(const QModelIndex&)), + this, SLOT(showHoverInformation(const QModelIndex&))); + connect(m_controller, SIGNAL(viewportEntered()), + this, SLOT(clearHoverInformation())); createView(); m_iconSize = K3Icon::SizeMedium; m_filterBar = new FilterBar(this); - m_filterBar->hide(); + m_filterBar->setVisible(settings->filterBar()); connect(m_filterBar, SIGNAL(filterChanged(const QString&)), - this, SLOT(changeNameFilter(const QString&))); + this, SLOT(changeNameFilter(const QString&))); connect(m_filterBar, SIGNAL(closeRequest()), this, SLOT(closeFilterBar())); @@ -191,6 +200,11 @@ const KUrl& DolphinView::url() const return m_urlNavigator->url(); } +KUrl DolphinView::rootUrl() const +{ + return isColumnViewActive() ? m_dirLister->url() : url(); +} + bool DolphinView::isActive() const { return m_mainWindow->activeView() == this; @@ -204,6 +218,14 @@ void DolphinView::setMode(Mode mode) m_mode = mode; + if (isColumnViewActive()) { + // When changing the mode in the column view, it makes sense + // to go back to the root URL of the column view automatically. + // Otherwise there it would not be possible to turn off the column view + // without focusing the first column. + setUrl(m_dirLister->url()); + } + ViewProperties props(m_urlNavigator->url()); props.setViewMode(m_mode); @@ -224,9 +246,9 @@ void DolphinView::setShowPreview(bool show) props.setShowPreview(show); m_controller->setShowPreview(show); - emit showPreviewChanged(); - reload(); + + startDirLister(m_urlNavigator->url(), true); } bool DolphinView::showPreview() const @@ -242,14 +264,11 @@ void DolphinView::setShowHiddenFiles(bool show) ViewProperties props(m_urlNavigator->url()); props.setShowHiddenFiles(show); - props.save(); m_dirLister->setShowingDotFiles(show); - m_urlNavigator->setShowHiddenFiles(show); - emit showHiddenFilesChanged(); - reload(); + startDirLister(m_urlNavigator->url(), true); } bool DolphinView::showHiddenFiles() const @@ -257,6 +276,44 @@ bool DolphinView::showHiddenFiles() const return m_dirLister->showingDotFiles(); } +void DolphinView::setCategorizedSorting(bool categorized) +{ + if (!supportsCategorizedSorting() || (categorized == categorizedSorting())) { + return; + } + + Q_ASSERT(m_iconsView != 0); + if (categorized) { + Q_ASSERT(m_iconsView->itemCategorizer() == 0); + m_iconsView->setItemCategorizer(new DolphinItemCategorizer()); + } else { + KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); + m_iconsView->setItemCategorizer(0); + delete categorizer; + } + + ViewProperties props(m_urlNavigator->url()); + props.setCategorizedSorting(categorized); + props.save(); + + emit categorizedSortingChanged(); +} + +bool DolphinView::categorizedSorting() const +{ + if (!supportsCategorizedSorting()) { + return false; + } + + Q_ASSERT(m_iconsView != 0); + return m_iconsView->itemCategorizer() != 0; +} + +bool DolphinView::supportsCategorizedSorting() const +{ + return m_iconsView != 0; +} + void DolphinView::renameSelectedItems() { DolphinView* view = mainWindow()->activeView(); @@ -273,8 +330,7 @@ void DolphinView::renameSelectedItems() if (newName.isEmpty()) { view->statusBar()->setMessage(dialog.errorString(), DolphinStatusBar::Error); - } - else { + } else { // TODO: check how this can be integrated into KonqUndoManager/KonqOperations // as one operation instead of n rename operations like it is done now... Q_ASSERT(newName.contains('#')); @@ -302,8 +358,7 @@ void DolphinView::renameSelectedItems() ++it; } } - } - else { + } else { // Only one item has been selected for renaming. Use the custom // renaming mechanism from the views. Q_ASSERT(urls.count() == 1); @@ -320,8 +375,7 @@ void DolphinView::renameSelectedItems() if (newName.isEmpty()) { view->statusBar()->setMessage(dialog.errorString(), DolphinStatusBar::Error); - } - else { + } else { const KUrl& oldUrl = urls.first(); KUrl newUrl = oldUrl; newUrl.setFileName(newName); @@ -355,14 +409,9 @@ int DolphinView::contentsY() const return itemView()->verticalScrollBar()->value(); } -void DolphinView::emitRequestItemInfo(const KUrl& url) -{ - emit requestItemInfo(url); -} - bool DolphinView::isFilterBarVisible() const { - return m_filterBar->isVisible(); + return m_filterBar->isVisible(); } bool DolphinView::isUrlEditable() const @@ -419,10 +468,11 @@ void DolphinView::setAdditionalInfo(KFileItemDelegate::AdditionalInformation inf ViewProperties props(m_urlNavigator->url()); props.setAdditionalInfo(info); + m_controller->setShowAdditionalInfo(info != KFileItemDelegate::NoInformation); m_fileItemDelegate->setAdditionalInformation(info); emit additionalInfoChanged(info); - reload(); + startDirLister(m_urlNavigator->url(), true); } KFileItemDelegate::AdditionalInformation DolphinView::additionalInfo() const @@ -524,8 +574,8 @@ void DolphinView::rename(const KUrl& source, const QString& newName) dest.addPath(newName); const bool destExists = KIO::NetAccess::exists(dest, - false, - mainWindow()->activeView()); + false, + mainWindow()->activeView()); if (destExists) { // the destination already exists, hence ask the user // how to proceed... @@ -535,25 +585,23 @@ void DolphinView::rename(const KUrl& source, const QString& newName) dest.path(), KIO::M_OVERWRITE); switch (renameDialog.exec()) { - case KIO::R_OVERWRITE: - // the destination should be overwritten - ok = KIO::NetAccess::file_move(source, dest, -1, true); - break; - - case KIO::R_RENAME: { - // a new name for the destination has been used - KUrl newDest(renameDialog.newDestUrl()); - ok = KIO::NetAccess::file_move(source, newDest); - break; - } + case KIO::R_OVERWRITE: + // the destination should be overwritten + ok = KIO::NetAccess::file_move(source, dest, -1, true); + break; - default: - // the renaming operation has been canceled - reload(); - return; + case KIO::R_RENAME: { + // a new name for the destination has been used + KUrl newDest(renameDialog.newDestUrl()); + ok = KIO::NetAccess::file_move(source, newDest); + break; } - } - else { + + default: + // the renaming operation has been canceled + return; + } + } else { // no destination exists, hence just move the file to // do the renaming ok = KIO::NetAccess::file_move(source, dest); @@ -561,21 +609,27 @@ void DolphinView::rename(const KUrl& source, const QString& newName) const QString destFileName = dest.fileName(); if (ok) { - m_statusBar->setMessage(i18n("Renamed file '%1' to '%2'.",source.fileName(), destFileName), + m_statusBar->setMessage(i18n("Renamed file '%1' to '%2'.", source.fileName(), destFileName), DolphinStatusBar::OperationCompleted); KonqOperations::rename(this, source, destFileName); - } - else { - m_statusBar->setMessage(i18n("Renaming of file '%1' to '%2' failed.",source.fileName(), destFileName), + } else { + m_statusBar->setMessage(i18n("Renaming of file '%1' to '%2' failed.", source.fileName(), destFileName), DolphinStatusBar::Error); - reload(); } } void DolphinView::reload() { - startDirLister(m_urlNavigator->url(), true); + const KUrl& url = m_urlNavigator->url(); + changeDirectory(url); + startDirLister(url, true); +} + +void DolphinView::refresh() +{ + createView(); + reload(); } void DolphinView::mouseReleaseEvent(QMouseEvent* event) @@ -589,9 +643,9 @@ DolphinMainWindow* DolphinView::mainWindow() const return m_mainWindow; } -void DolphinView::loadDirectory(const KUrl& url) +void DolphinView::changeDirectory(const KUrl& url) { - if(!isActive()) { + if (!isActive()) { requestActivation(); } @@ -611,6 +665,14 @@ void DolphinView::loadDirectory(const KUrl& url) m_mode = mode; createView(); emit modeChanged(); + + if (m_mode == ColumnView) { + // The mode has been changed to the Column View. When starting the dir + // lister with DolphinView::startDirLister() it is important to give a + // hint that the dir lister may not keep the current directory + // although this is the default for showing a hierarchy. + m_initializeColumnView = true; + } } const bool showHiddenFiles = props.showHiddenFiles(); @@ -619,6 +681,22 @@ void DolphinView::loadDirectory(const KUrl& url) emit showHiddenFilesChanged(); } + const bool categorized = props.categorizedSorting(); + if (categorized != categorizedSorting()) { + if (supportsCategorizedSorting()) { + Q_ASSERT(m_iconsView != 0); + if (categorized) { + Q_ASSERT(m_iconsView->itemCategorizer() == 0); + m_iconsView->setItemCategorizer(new DolphinItemCategorizer()); + } else { + KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); + m_iconsView->setItemCategorizer(0); + delete categorizer; + } + } + emit categorizedSortingChanged(); + } + const DolphinView::Sorting sorting = props.sorting(); if (sorting != m_proxyModel->sorting()) { m_proxyModel->setSorting(sorting); @@ -633,8 +711,8 @@ void DolphinView::loadDirectory(const KUrl& url) KFileItemDelegate::AdditionalInformation info = props.additionalInfo(); if (info != m_fileItemDelegate->additionalInformation()) { + m_controller->setShowAdditionalInfo(info != KFileItemDelegate::NoInformation); m_fileItemDelegate->setAdditionalInformation(info); - emit additionalInfoChanged(info); } @@ -653,6 +731,8 @@ void DolphinView::loadDirectory(const KUrl& url) void DolphinView::triggerItem(const QModelIndex& index) { if (!isValidNameIndex(index)) { + clearSelection(); + showHoverInformation(index); return; } @@ -677,34 +757,29 @@ void DolphinView::triggerItem(const QModelIndex& index) KUrl url; if (localPath.isEmpty()) { url = item->url(); - } - else { + } else { url = localPath; } if (item->isDir()) { setUrl(url); - } - else if (item->isFile()) { + } else if (item->isFile()) { // allow to browse through ZIP and tar files KMimeType::Ptr mime = item->mimeTypePtr(); if (mime->is("application/zip")) { url.setProtocol("zip"); setUrl(url); - } - else if (mime->is("application/x-tar") || - mime->is("application/x-tarz") || - mime->is("application/x-bzip-compressed-tar") || - mime->is("application/x-compressed-tar") || - mime->is("application/x-tzo")) { + } else if (mime->is("application/x-tar") || + mime->is("application/x-tarz") || + mime->is("application/x-bzip-compressed-tar") || + mime->is("application/x-compressed-tar") || + mime->is("application/x-tzo")) { url.setProtocol("tar"); setUrl(url); - } - else { + } else { item->run(); } - } - else { + } else { item->run(); } } @@ -735,8 +810,7 @@ void DolphinView::updateItemCount() KFileItem* item = *it; if (item->isDir()) { ++m_folderCount; - } - else { + } else { ++m_fileCount; } ++it; @@ -751,24 +825,35 @@ void DolphinView::updateItemCount() void DolphinView::generatePreviews(const KFileItemList& items) { if (m_controller->showPreview()) { - KIO::PreviewJob* job = KIO::filePreview(items, 128); - connect(job, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), - this, SLOT(showPreview(const KFileItem*, const QPixmap&))); + + // Must turn QList to QList... + QList itemsToPreview; + foreach( KFileItem* it, items ) + itemsToPreview.append( *it ); + + KIO::PreviewJob* job = KIO::filePreview(itemsToPreview, 128); + connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), + this, SLOT(showPreview(const KFileItem&, const QPixmap&))); } } -void DolphinView::showPreview(const KFileItem* item, const QPixmap& pixmap) +void DolphinView::showPreview(const KFileItem& item, const QPixmap& pixmap) { - Q_ASSERT(item != 0); - const QModelIndex idx = m_dirModel->indexForItem(*item); + Q_ASSERT(!item.isNull()); + if (item.url().directory() != m_dirLister->url().path()) { + // the preview job is still working on items of an older URL, hence + // the item is not part of the directory model anymore + return; + } + + const QModelIndex idx = m_dirModel->indexForItem(item); if (idx.isValid() && (idx.column() == 0)) { const QMimeData* mimeData = QApplication::clipboard()->mimeData(); - if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(*item)) { + if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) { KIconEffect iconEffect; const QPixmap cutPixmap = iconEffect.apply(pixmap, K3Icon::Desktop, K3Icon::DisabledState); m_dirModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole); - } - else { + } else { m_dirModel->setData(idx, QIcon(pixmap), Qt::DecorationRole); } } @@ -813,9 +898,8 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) const QString location(url.pathOrUrl()); if (location.isEmpty()) { m_statusBar->setMessage(i18n("The location is empty."), DolphinStatusBar::Error); - } - else { - m_statusBar->setMessage(i18n("The location '%1' is invalid.",location), + } else { + m_statusBar->setMessage(i18n("The location '%1' is invalid.", location), DolphinStatusBar::Error); } return; @@ -826,9 +910,9 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) // the directory loading progress information has the lowest priority. const QString progressText(m_statusBar->progressText()); m_showProgress = progressText.isEmpty() || - (progressText == i18n("Loading directory...")); + (progressText == i18n("Loading folder...")); if (m_showProgress) { - m_statusBar->setProgressText(i18n("Loading directory...")); + m_statusBar->setProgressText(i18n("Loading folder...")); m_statusBar->setProgress(0); } @@ -837,7 +921,9 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) m_dirLister->stop(); bool openDir = true; - bool keepOldDirs = isColumnViewActive(); + bool keepOldDirs = isColumnViewActive() && !m_initializeColumnView; + m_initializeColumnView = false; + if (keepOldDirs) { if (reload) { keepOldDirs = false; @@ -846,19 +932,17 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) if (dirListerUrl.isValid()) { const KUrl::List dirs = m_dirLister->directories(); KUrl url; - foreach (url, dirs) { + foreach(url, dirs) { m_dirLister->updateDirectory(url); } openDir = false; } - } - else if (m_dirLister->directories().contains(url)) { + } else if (m_dirLister->directories().contains(url)) { // The dir lister contains the directory already, so // KDirLister::openUrl() may not been invoked twice. m_dirLister->updateDirectory(url); openDir = false; - } - else { + } else { const KUrl& dirListerUrl = m_dirLister->url(); if ((dirListerUrl == url) || !m_dirLister->url().isParentOf(url)) { // The current URL is not a child of the dir lister @@ -897,12 +981,11 @@ QString DolphinView::selectionStatusBarText() const KIO::filesize_t byteSize = 0; KFileItemList::const_iterator it = list.begin(); const KFileItemList::const_iterator end = list.end(); - while (it != end){ + while (it != end) { KFileItem* item = *it; if (item->isDir()) { ++folderCount; - } - else { + } else { ++fileCount; byteSize += item->size(); } @@ -929,8 +1012,7 @@ void DolphinView::showFilterBar(bool show) Q_ASSERT(m_filterBar != 0); if (show) { m_filterBar->show(); - } - else { + } else { m_filterBar->hide(); } } @@ -972,7 +1054,7 @@ void DolphinView::changeSelection(const KFileItemList& selection) KUrl baseUrl = url(); KUrl url; QItemSelection new_selection; - foreach (KFileItem* item, selection) { + foreach(KFileItem* item, selection) { url = item->url().upUrl(); if (baseUrl.equals(url, KUrl::CompareWithoutTrailingSlash)) { QModelIndex index = m_proxyModel->mapFromSource(m_dirModel->indexForItem(*item)); @@ -1005,7 +1087,7 @@ void DolphinView::changeNameFilter(const QString& nameFilter) m_dirLister->setNameFilter(adjustedFilter); m_dirLister->emitChanges(); #else - m_proxyModel->setFilterRegExp( nameFilter ); + m_proxyModel->setFilterRegExp(nameFilter); #endif } @@ -1043,7 +1125,7 @@ void DolphinView::dropUrls(const KUrl::List& urls, } const KUrl& destination = (directory == 0) ? url() : - directory->url(); + directory->url(); dropUrls(urls, destination); } @@ -1083,10 +1165,23 @@ void DolphinView::emitContentsMoved() void DolphinView::updateActivationState() { m_urlNavigator->setActive(isActive()); - if(isActive()) { + + QColor color = KGlobalSettings::baseColor(); + if (isActive()) { emit urlChanged(url()); emit selectionChanged(selectedItems()); + } else { + // darken the background if the view is inactive + // TODO: does not work for a black background + color = color.darker(105); } + + QWidget* viewport = itemView()->viewport(); + QPalette palette; + palette.setColor(viewport->backgroundRole(), color); + viewport->setPalette(palette); + + update(); } void DolphinView::updateCutItems() @@ -1108,6 +1203,26 @@ void DolphinView::updateCutItems() applyCutItemEffect(); } +void DolphinView::showHoverInformation(const QModelIndex& index) +{ + if (hasSelection()) { + return; + } + + const KFileItem* item = fileItem(index); + if (item != 0) { + m_statusBar->setMessage(item->getStatusBarInfo(), DolphinStatusBar::Default); + emit requestItemInfo(item->url()); + } +} + +void DolphinView::clearHoverInformation() +{ + m_statusBar->clear(); + emit requestItemInfo(KUrl()); +} + + void DolphinView::createView() { // delete current view @@ -1115,6 +1230,11 @@ void DolphinView::createView() if (view != 0) { m_topLayout->removeWidget(view); view->close(); + if (view == m_iconsView) { + KItemCategorizer* categorizer = m_iconsView->itemCategorizer(); + m_iconsView->setItemCategorizer(0); + delete categorizer; + } view->deleteLater(); view = 0; m_iconsView = 0; @@ -1129,20 +1249,20 @@ void DolphinView::createView() // ... and recreate it representing the current mode switch (m_mode) { - case IconsView: - m_iconsView = new DolphinIconsView(this, m_controller); - view = m_iconsView; - break; - - case DetailsView: - m_detailsView = new DolphinDetailsView(this, m_controller); - view = m_detailsView; - break; - - case ColumnView: - m_columnView = new DolphinColumnView(this, m_controller); - view = m_columnView; - break; + case IconsView: + m_iconsView = new DolphinIconsView(this, m_controller); + view = m_iconsView; + break; + + case DetailsView: + m_detailsView = new DolphinDetailsView(this, m_controller); + view = m_detailsView; + break; + + case ColumnView: + m_columnView = new DolphinColumnView(this, m_controller); + view = m_columnView; + break; } Q_ASSERT(view != 0); @@ -1171,7 +1291,7 @@ void DolphinView::selectAll(QItemSelectionModel::SelectionFlags flags) const QModelIndex topLeft = itemModel->index(0, 0); const QModelIndex bottomRight = itemModel->index(itemModel->rowCount() - 1, - itemModel->columnCount() - 1); + itemModel->columnCount() - 1); QItemSelection selection(topLeft, bottomRight); selectionModel->select(selection, flags); @@ -1181,8 +1301,7 @@ QAbstractItemView* DolphinView::itemView() const { if (m_detailsView != 0) { return m_detailsView; - } - else if (m_columnView != 0) { + } else if (m_columnView != 0) { return m_columnView; } @@ -1202,7 +1321,7 @@ bool DolphinView::isCutItem(const KFileItem& item) const const KUrl& itemUrl = item.url(); KUrl::List::const_iterator it = cutUrls.begin(); const KUrl::List::const_iterator end = cutUrls.end(); - while (it != end){ + while (it != end) { if (*it == itemUrl) { return true; }