X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/8dc8c5d21fae81979c1010dc9c24c5f4e54b6dbe..bbf9faa05396d66b3dbe101a0c309459e3ffacb1:/src/dolphinview.cpp diff --git a/src/dolphinview.cpp b/src/dolphinview.cpp index 94ed99b69..c280b40d0 100644 --- a/src/dolphinview.cpp +++ b/src/dolphinview.cpp @@ -19,6 +19,8 @@ ***************************************************************************/ #include "dolphinview.h" +#include +#include #include #include @@ -59,8 +61,8 @@ DolphinView::DolphinView(QWidget* parent, DolphinSortFilterProxyModel* proxyModel) : QWidget(parent), m_active(true), + m_showPreview(false), m_loadingDirectory(false), - m_initializeColumnView(false), m_storedCategorizedSorting(false), m_mode(DolphinView::IconsView), m_topLayout(0), @@ -89,22 +91,32 @@ DolphinView::DolphinView(QWidget* parent, m_controller = new DolphinController(this); m_controller->setUrl(url); + + // Receiver of the DolphinView signal 'urlChanged()' don't need + // to care whether the internal controller changed the URL already or whether + // the controller just requested an URL change and will be updated later. + // In both cases the URL has been changed: connect(m_controller, SIGNAL(urlChanged(const KUrl&)), this, SIGNAL(urlChanged(const KUrl&))); + connect(m_controller, SIGNAL(requestUrlChange(const KUrl&)), + this, SIGNAL(urlChanged(const KUrl&))); + connect(m_controller, SIGNAL(requestContextMenu(const QPoint&)), this, SLOT(openContextMenu(const QPoint&))); - connect(m_controller, SIGNAL(urlsDropped(const KUrl::List&, const KUrl&, const QModelIndex&, QWidget*)), - this, SLOT(dropUrls(const KUrl::List&, const KUrl&, const QModelIndex&, QWidget*))); + connect(m_controller, SIGNAL(urlsDropped(const KUrl::List&, const KUrl&, const KFileItem&, QWidget*)), + this, SLOT(dropUrls(const KUrl::List&, const KUrl&, const KFileItem&, QWidget*))); connect(m_controller, SIGNAL(sortingChanged(DolphinView::Sorting)), this, SLOT(updateSorting(DolphinView::Sorting))); connect(m_controller, SIGNAL(sortOrderChanged(Qt::SortOrder)), this, SLOT(updateSortOrder(Qt::SortOrder))); - connect(m_controller, SIGNAL(itemTriggered(const QModelIndex&)), - this, SLOT(triggerItem(const QModelIndex&))); + connect(m_controller, SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)), + this, SLOT(updateAdditionalInfo(const KFileItemDelegate::InformationList&))); + connect(m_controller, SIGNAL(itemTriggered(const KFileItem&)), + this, SLOT(triggerItem(const KFileItem&))); connect(m_controller, SIGNAL(activated()), this, SLOT(activate())); - connect(m_controller, SIGNAL(itemEntered(const QModelIndex&)), - this, SLOT(showHoverInformation(const QModelIndex&))); + connect(m_controller, SIGNAL(itemEntered(const KFileItem&)), + this, SLOT(showHoverInformation(const KFileItem&))); connect(m_controller, SIGNAL(viewportEntered()), this, SLOT(clearHoverInformation())); @@ -123,7 +135,7 @@ const KUrl& DolphinView::url() const KUrl DolphinView::rootUrl() const { - return isColumnViewActive() ? m_dirLister->url() : url(); + return isColumnViewActive() ? m_columnView->rootUrl() : url(); } void DolphinView::setActive(bool active) @@ -134,12 +146,29 @@ void DolphinView::setActive(bool active) m_active = active; - updateViewportColor(); + QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color(); + if (active) { + // TODO: emitting urlChanged() is a hack, as the URL hasn't really changed. It + // bypasses the problem when having a split view and changing the active view to + // update the some URL dependent states. A nicer approach should be no big deal... + emit urlChanged(url()); + emit selectionChanged(selectedItems()); + } else { + color.setAlpha(150); + } + + QWidget* viewport = itemView()->viewport(); + QPalette palette; + palette.setColor(viewport->backgroundRole(), color); + viewport->setPalette(palette); + update(); if (active) { emit activated(); } + + m_controller->indicateActivationChange(active); } bool DolphinView::isActive() const @@ -160,8 +189,9 @@ void DolphinView::setMode(Mode mode) // 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()); - m_controller->setUrl(m_dirLister->url()); + const KUrl root = rootUrl(); + setUrl(root); + m_controller->setUrl(root); } const KUrl viewPropsUrl = viewPropertiesUrl(); @@ -170,6 +200,12 @@ void DolphinView::setMode(Mode mode) createView(); + // the file item delegate has been recreated, apply the current + // additional information manually + const KFileItemDelegate::InformationList infoList = props.additionalInfo(); + m_fileItemDelegate->setShowInformation(infoList); + emit additionalInfoChanged(infoList); + // Not all view modes support categorized sorting. Adjust the sorting model // if changing the view mode results in a change of the categorized sorting // capabilities. @@ -177,11 +213,10 @@ void DolphinView::setMode(Mode mode) const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting(); if (categorized != m_proxyModel->isCategorizedModel()) { m_proxyModel->setCategorizedModel(categorized); - m_proxyModel->sort(m_proxyModel->sortColumn(), m_proxyModel->sortOrder()); emit categorizedSortingChanged(); } - startDirLister(viewPropsUrl); + loadDirectory(viewPropsUrl); emit modeChanged(); } @@ -193,19 +228,24 @@ DolphinView::Mode DolphinView::mode() const void DolphinView::setShowPreview(bool show) { + if (m_showPreview == show) { + return; + } + const KUrl viewPropsUrl = viewPropertiesUrl(); ViewProperties props(viewPropsUrl); props.setShowPreview(show); - m_controller->setShowPreview(show); + m_showPreview = show; + emit showPreviewChanged(); - startDirLister(viewPropsUrl, true); + loadDirectory(viewPropsUrl, true); } bool DolphinView::showPreview() const { - return m_controller->showPreview(); + return m_showPreview; } void DolphinView::setShowHiddenFiles(bool show) @@ -221,7 +261,7 @@ void DolphinView::setShowHiddenFiles(bool show) m_dirLister->setShowingDotFiles(show); emit showHiddenFilesChanged(); - startDirLister(viewPropsUrl, true); + loadDirectory(viewPropsUrl, true); } bool DolphinView::showHiddenFiles() const @@ -245,7 +285,6 @@ void DolphinView::setCategorizedSorting(bool categorized) m_storedCategorizedSorting = categorized; m_proxyModel->setCategorizedModel(categorized); - m_proxyModel->sort(m_proxyModel->sortColumn(), m_proxyModel->sortOrder()); emit categorizedSortingChanged(); } @@ -278,8 +317,8 @@ void DolphinView::invertSelection() // QAbstractItemView does not offer a virtual method invertSelection() // as counterpart to QAbstractItemView::selectAll(). This makes it // necessary to delegate the inverting of the selection to the - // column view, as only the selection of the active column should get - // inverted. + // column view, as only the selection of the active column should + // get inverted. m_columnView->invertSelection(); } else { QItemSelectionModel* selectionModel = itemView()->selectionModel(); @@ -411,12 +450,15 @@ void DolphinView::setAdditionalInfo(KFileItemDelegate::InformationList info) const KUrl viewPropsUrl = viewPropertiesUrl(); ViewProperties props(viewPropsUrl); props.setAdditionalInfo(info); - - m_controller->setAdditionalInfoCount(info.count()); m_fileItemDelegate->setShowInformation(info); emit additionalInfoChanged(info); - startDirLister(viewPropsUrl, true); + + if (itemView() != m_detailsView) { + // the details view requires no reloading of the directory, as it maps + // the file item delegate info to its columns internally + loadDirectory(viewPropsUrl, true); + } } KFileItemDelegate::InformationList DolphinView::additionalInfo() const @@ -427,15 +469,19 @@ KFileItemDelegate::InformationList DolphinView::additionalInfo() const void DolphinView::reload() { setUrl(url()); - startDirLister(url(), true); + loadDirectory(url(), true); } void DolphinView::refresh() { + const bool oldActivationState = m_active; + m_active = true; + createView(); applyViewProperties(m_controller->url()); reload(); - updateViewportColor(); + + setActive(oldActivationState); } void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl) @@ -444,31 +490,45 @@ void DolphinView::updateView(const KUrl& url, const KUrl& rootUrl) return; } - const bool restoreColumnView = !rootUrl.isEmpty() - && !rootUrl.equals(url, KUrl::CompareWithoutTrailingSlash) - && rootUrl.isParentOf(url); - m_controller->setUrl(url); // emits urlChanged, which we forward - if (restoreColumnView) { + if (!rootUrl.isEmpty() && rootUrl.isParentOf(url)) { applyViewProperties(rootUrl); - startDirLister(rootUrl); - // Restoring the column view relies on the URL-history. It might be possible - // that the view properties have been changed or deleted in the meantime, so - // it cannot be asserted that really a column view has been created: + loadDirectory(rootUrl); if (itemView() == m_columnView) { + m_columnView->setRootUrl(rootUrl); m_columnView->showColumn(url); } } else { applyViewProperties(url); - startDirLister(url); + loadDirectory(url); } - itemView()->setFocus(); - emit startedPathLoading(url); } +void DolphinView::setNameFilter(const QString& nameFilter) +{ + m_proxyModel->setFilterRegExp(nameFilter); + + if (isColumnViewActive()) { + // adjusting the directory lister is not enough in the case of the + // column view, as each column has its own directory lister internally... + m_columnView->setNameFilter(nameFilter); + } +} + +void DolphinView::calculateItemCount(int& fileCount, int& folderCount) +{ + foreach (KFileItem item, m_dirLister->items()) { + if (item.isDir()) { + ++folderCount; + } else { + ++fileCount; + } + } +} + void DolphinView::setUrl(const KUrl& url) { updateView(url, KUrl()); @@ -484,10 +544,8 @@ void DolphinView::activate() setActive(true); } -void DolphinView::triggerItem(const QModelIndex& index) +void DolphinView::triggerItem(const KFileItem& item) { - Q_ASSERT(index.isValid()); - const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers(); if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) { // items are selected by the user, hence don't trigger the @@ -495,8 +553,6 @@ void DolphinView::triggerItem(const QModelIndex& index) return; } - const KFileItem item = m_dolphinModel->itemForIndex(m_proxyModel->mapToSource(index)); - if (item.isNull()) { return; } @@ -506,7 +562,7 @@ void DolphinView::triggerItem(const QModelIndex& index) void DolphinView::generatePreviews(const KFileItemList& items) { - if (m_controller->showPreview()) { + if (m_controller->dolphinView()->showPreview()) { KIO::PreviewJob* job = KIO::filePreview(items, 128); connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), this, SLOT(showPreview(const KFileItem&, const QPixmap&))); @@ -540,7 +596,7 @@ void DolphinView::emitSelectionChangedSignal() emit selectionChanged(DolphinView::selectedItems()); } -void DolphinView::startDirLister(const KUrl& url, bool reload) +void DolphinView::loadDirectory(const KUrl& url, bool reload) { if (!url.isValid()) { const QString location(url.pathOrUrl()); @@ -556,32 +612,16 @@ void DolphinView::startDirLister(const KUrl& url, bool reload) m_loadingDirectory = true; m_dirLister->stop(); + m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); - bool keepOldDirs = isColumnViewActive() && !m_initializeColumnView; - m_initializeColumnView = false; - - if (keepOldDirs) { - // keeping old directories is only necessary for hierarchical views - // like the column view + if (isColumnViewActive()) { + // adjusting the directory lister is not enough in the case of the + // column view, as each column has its own directory lister internally... if (reload) { - // for the column view it is not enough to reload the directory lister, - // so this task is delegated to the column view directly m_columnView->reload(); - } else if (m_dirLister->directories().contains(url)) { - // The dir lister contains the directory already, so - // KDirLister::openUrl() may not get invoked twice. - m_dirLister->updateDirectory(url); } 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 - // URL. This may happen when e. g. a place has been selected - // and hence the view must be reset. - m_dirLister->openUrl(url, KDirLister::NoFlags); - } + m_columnView->showColumn(url); } - } else { - m_dirLister->openUrl(url, reload ? KDirLister::Reload : KDirLister::NoFlags); } } @@ -596,7 +636,7 @@ KUrl DolphinView::viewPropertiesUrl() const void DolphinView::applyViewProperties(const KUrl& url) { - if (isColumnViewActive() && m_dirLister->url().isParentOf(url)) { + if (isColumnViewActive() && rootUrl().isParentOf(url)) { // The column view is active, hence don't apply the view properties // of sub directories (represented by columns) to the view. The // view always represents the properties of the first column. @@ -610,14 +650,6 @@ void DolphinView::applyViewProperties(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; - } } if (itemView() == 0) { createView(); @@ -635,7 +667,6 @@ void DolphinView::applyViewProperties(const KUrl& url) const bool categorized = m_storedCategorizedSorting && supportsCategorizedSorting(); if (categorized != m_proxyModel->isCategorizedModel()) { m_proxyModel->setCategorizedModel(categorized); - m_proxyModel->sort(m_proxyModel->sortColumn(), m_proxyModel->sortOrder()); emit categorizedSortingChanged(); } @@ -653,14 +684,13 @@ void DolphinView::applyViewProperties(const KUrl& url) KFileItemDelegate::InformationList info = props.additionalInfo(); if (info != m_fileItemDelegate->showInformation()) { - m_controller->setAdditionalInfoCount(info.count()); m_fileItemDelegate->setShowInformation(info); emit additionalInfoChanged(info); } const bool showPreview = props.showPreview(); - if (showPreview != m_controller->showPreview()) { - m_controller->setShowPreview(showPreview); + if (showPreview != m_showPreview) { + m_showPreview = showPreview; emit showPreviewChanged(); } } @@ -691,7 +721,7 @@ void DolphinView::openContextMenu(const QPoint& pos) KFileItem item; const QModelIndex index = itemView()->indexAt(pos); - if (isValidNameIndex(index)) { + if (index.isValid() && (index.column() == DolphinModel::Name)) { item = fileItem(index); } @@ -700,27 +730,23 @@ void DolphinView::openContextMenu(const QPoint& pos) void DolphinView::dropUrls(const KUrl::List& urls, const KUrl& destPath, - const QModelIndex& destIndex, + const KFileItem& destItem, QWidget* source) { - KFileItem directory; - if (isValidNameIndex(destIndex)) { - KFileItem item = fileItem(destIndex); - Q_ASSERT(!item.isNull()); - if (item.isDir()) { - // the URLs are dropped above a directory - directory = item; + bool dropAboveDir = false; + if (!destItem.isNull()) { + dropAboveDir = destItem.isDir(); + if (!dropAboveDir) { + // the dropping is done above a file + return; } - } - - if ((directory.isNull()) && (source == itemView())) { - // The dropping is done into the same viewport where - // the dragging has been started. Just ignore this... + } else if (source == itemView()) { + // the dropping is done into the same viewport where the dragging + // has been started return; } - const KUrl& destination = (directory.isNull()) ? - destPath : directory.url(); + const KUrl& destination = dropAboveDir ? destItem.url() : destPath; dropUrls(urls, destination); } @@ -750,6 +776,17 @@ void DolphinView::updateSortOrder(Qt::SortOrder order) emit sortOrderChanged(order); } +void DolphinView::updateAdditionalInfo(const KFileItemDelegate::InformationList& info) +{ + ViewProperties props(viewPropertiesUrl()); + props.setAdditionalInfo(info); + + m_fileItemDelegate->setShowInformation(info); + + emit additionalInfoChanged(info); + +} + void DolphinView::emitContentsMoved() { // only emit the contents moved signal if: @@ -782,16 +819,13 @@ void DolphinView::updateCutItems() applyCutItemEffect(); } -void DolphinView::showHoverInformation(const QModelIndex& index) +void DolphinView::showHoverInformation(const KFileItem& item) { if (hasSelection()) { return; } - const KFileItem item = fileItem(index); - if (!item.isNull()) { - emit requestItemInfo(item); - } + emit requestItemInfo(item); } void DolphinView::clearHoverInformation() @@ -802,11 +836,6 @@ void DolphinView::clearHoverInformation() void DolphinView::createView() { - KFileItemDelegate::InformationList infoList; - if (m_fileItemDelegate != 0) { - infoList = m_fileItemDelegate->showInformation(); - } - // delete current view QAbstractItemView* view = itemView(); if (view != 0) { @@ -846,7 +875,6 @@ void DolphinView::createView() Q_ASSERT(view != 0); m_fileItemDelegate = new KFileItemDelegate(view); - m_fileItemDelegate->setShowInformation(infoList); view->setItemDelegate(m_fileItemDelegate); view->setModel(m_proxyModel); @@ -861,7 +889,6 @@ void DolphinView::createView() this, SLOT(emitContentsMoved())); connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(emitContentsMoved())); - view->setFocus(); } QAbstractItemView* DolphinView::itemView() const @@ -875,11 +902,6 @@ QAbstractItemView* DolphinView::itemView() const return m_iconsView; } -bool DolphinView::isValidNameIndex(const QModelIndex& index) const -{ - return index.isValid() && (index.column() == DolphinModel::Name); -} - bool DolphinView::isCutItem(const KFileItem& item) const { const QMimeData* mimeData = QApplication::clipboard()->mimeData(); @@ -912,8 +934,6 @@ void DolphinView::applyCutItemEffect() const KFileItem item = *it; if (isCutItem(item)) { const QModelIndex index = m_dolphinModel->indexForItem(item); - // Huh? the item is already known - //const KFileItem item = m_dolphinModel->itemForIndex(index); const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole); if (value.type() == QVariant::Icon) { const QIcon icon(qvariant_cast(value)); @@ -936,20 +956,47 @@ void DolphinView::applyCutItemEffect() } } -void DolphinView::updateViewportColor() +KToggleAction* DolphinView::iconsModeAction(KActionCollection* actionCollection) { - QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color(); - if (m_active) { - emit urlChanged(url()); // Hmm, this is a hack; the url hasn't really changed. - emit selectionChanged(selectedItems()); - } else { - color.setAlpha(0); - } + KToggleAction* iconsView = actionCollection->add("icons"); + iconsView->setText(i18nc("@action:inmenu View Mode", "Icons")); + iconsView->setShortcut(Qt::CTRL | Qt::Key_1); + iconsView->setIcon(KIcon("fileview-icon")); + iconsView->setData(QVariant::fromValue(IconsView)); + return iconsView; +} - QWidget* viewport = itemView()->viewport(); - QPalette palette; - palette.setColor(viewport->backgroundRole(), color); - viewport->setPalette(palette); +KToggleAction* DolphinView::detailsModeAction(KActionCollection* actionCollection) +{ + KToggleAction* detailsView = actionCollection->add("details"); + detailsView->setText(i18nc("@action:inmenu View Mode", "Details")); + detailsView->setShortcut(Qt::CTRL | Qt::Key_2); + detailsView->setIcon(KIcon("fileview-detailed")); + detailsView->setData(QVariant::fromValue(DetailsView)); + return detailsView; +} + +KToggleAction* DolphinView::columnsModeAction(KActionCollection* actionCollection) +{ + KToggleAction* columnView = actionCollection->add("columns"); + columnView->setText(i18nc("@action:inmenu View Mode", "Columns")); + columnView->setShortcut(Qt::CTRL | Qt::Key_3); + columnView->setIcon(KIcon("fileview-column")); + columnView->setData(QVariant::fromValue(ColumnView)); + return columnView; +} + +QString DolphinView::currentViewModeActionName() const +{ + switch (m_mode) { + case DolphinView::IconsView: + return "icons"; + case DolphinView::DetailsView: + return "details"; + case DolphinView::ColumnView: + return "columns"; + } + return QString(); // can't happen } #include "dolphinview.moc"