X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/f5deeadebbb67b4b20eae13f55e0ef66f4127eea..87cd992e85effd14938f67c0671ef2e7cb93a8a7:/src/dolphindetailsview.cpp diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index 1bf5f75e0..961bd7872 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -20,14 +20,16 @@ #include "dolphindetailsview.h" +#include "additionalinfoaccessor.h" #include "dolphinmodel.h" -#include "dolphincontroller.h" +#include "dolphinviewcontroller.h" #include "dolphinfileitemdelegate.h" #include "settings/dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" #include "dolphinviewautoscroller.h" #include "draganddrophelper.h" #include "viewextensionsfactory.h" +#include "viewmodecontroller.h" #include "viewproperties.h" #include "zoomlevelinfo.h" @@ -46,7 +48,8 @@ #include DolphinDetailsView::DolphinDetailsView(QWidget* parent, - DolphinController* controller, + DolphinViewController* dolphinViewController, + const ViewModeController* viewModeController, DolphinSortFilterProxyModel* proxyModel) : QTreeView(parent), m_autoResize(true), @@ -54,7 +57,8 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, m_keyPressed(false), m_useDefaultIndexAt(true), m_ignoreScrollTo(false), - m_controller(controller), + m_dolphinViewController(dolphinViewController), + m_viewModeController(viewModeController), m_extensionsFactory(0), m_expandableFoldersAction(0), m_expandedUrls(), @@ -64,7 +68,8 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, { const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); Q_ASSERT(settings != 0); - Q_ASSERT(controller != 0); + Q_ASSERT(dolphinViewController != 0); + Q_ASSERT(viewModeController != 0); setLayoutDirection(Qt::LeftToRight); setAcceptDrops(true); @@ -81,7 +86,7 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, setMouseTracking(true); - const ViewProperties props(controller->url()); + const ViewProperties props(viewModeController->url()); setSortIndicatorSection(props.sorting()); setSortIndicatorOrder(props.sortOrder()); @@ -102,39 +107,40 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, this, SLOT(setSortIndicatorOrder(Qt::SortOrder))); connect(this, SIGNAL(clicked(const QModelIndex&)), - controller, SLOT(requestTab(const QModelIndex&))); + dolphinViewController, SLOT(requestTab(const QModelIndex&))); if (KGlobalSettings::singleClick()) { connect(this, SIGNAL(clicked(const QModelIndex&)), - controller, SLOT(triggerItem(const QModelIndex&))); + dolphinViewController, SLOT(triggerItem(const QModelIndex&))); } else { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), - controller, SLOT(triggerItem(const QModelIndex&))); + dolphinViewController, SLOT(triggerItem(const QModelIndex&))); } connect(this, SIGNAL(entered(const QModelIndex&)), this, SLOT(slotEntered(const QModelIndex&))); connect(this, SIGNAL(viewportEntered()), - controller, SLOT(emitViewportEntered())); - connect(controller, SIGNAL(zoomLevelChanged(int)), + dolphinViewController, SLOT(emitViewportEntered())); + connect(viewModeController, SIGNAL(zoomLevelChanged(int)), this, SLOT(setZoomLevel(int))); - connect(controller->dolphinView(), SIGNAL(additionalInfoChanged()), + connect(dolphinViewController->view(), SIGNAL(additionalInfoChanged()), this, SLOT(updateColumnVisibility())); - connect(controller, SIGNAL(activationChanged(bool)), + connect(viewModeController, SIGNAL(activationChanged(bool)), this, SLOT(slotActivationChanged(bool))); if (settings->useSystemFont()) { m_font = KGlobalSettings::generalFont(); } else { m_font = QFont(settings->fontFamily(), - settings->fontSize(), + qRound(settings->fontSize()), settings->fontWeight(), settings->italicFont()); + m_font.setPointSizeF(settings->fontSize()); } setVerticalScrollMode(QTreeView::ScrollPerPixel); setHorizontalScrollMode(QTreeView::ScrollPerPixel); - const DolphinView* view = controller->dolphinView(); + const DolphinView* view = dolphinViewController->view(); connect(view, SIGNAL(showPreviewChanged()), this, SLOT(slotShowPreviewChanged())); @@ -157,7 +163,7 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, updateDecorationSize(view->showPreview()); - m_extensionsFactory = new ViewExtensionsFactory(this, controller); + m_extensionsFactory = new ViewExtensionsFactory(this, dolphinViewController, viewModeController); m_extensionsFactory->fileItemDelegate()->setMinimizedNameColumn(true); m_extensionsFactory->setAutoFolderExpandingEnabled(settings->expandableFolders()); } @@ -171,11 +177,38 @@ QSet DolphinDetailsView::expandedUrls() const return m_expandedUrls; } +QRegion DolphinDetailsView::visualRegionForSelection(const QItemSelection& selection) const +{ + // We have to make sure that the visualRect of each model index is inside the region. + // QTreeView::visualRegionForSelection does not do it right because it assumes implicitly + // that all visualRects have the same width, which is in general not the case here. + QRegion selectionRegion; + const QModelIndexList indexes = selection.indexes(); + + foreach(const QModelIndex& index, indexes) { + selectionRegion += visualRect(index); + } + + return selectionRegion; +} + bool DolphinDetailsView::event(QEvent* event) { - if (event->type() == QEvent::Polish) { + switch (event->type()) { + case QEvent::Polish: header()->setResizeMode(QHeaderView::Interactive); updateColumnVisibility(); + break; + + case QEvent::FocusOut: + // If a key-press triggers an action that e. g. opens a dialog, the + // widget gets no key-release event. Assure that the pressed state + // is reset to prevent accidently setting the current index during a selection. + m_keyPressed = false; + break; + + default: + break; } return QTreeView::event(event); @@ -185,6 +218,7 @@ QStyleOptionViewItem DolphinDetailsView::viewOptions() const { QStyleOptionViewItem viewOptions = QTreeView::viewOptions(); viewOptions.font = m_font; + viewOptions.fontMetrics = QFontMetrics(m_font); viewOptions.showDecorationSelected = true; viewOptions.decorationSize = m_decorationSize; return viewOptions; @@ -196,13 +230,13 @@ void DolphinDetailsView::contextMenuEvent(QContextMenuEvent* event) DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); m_expandableFoldersAction->setChecked(settings->expandableFolders()); - m_controller->triggerContextMenuRequest(event->pos(), + m_dolphinViewController->triggerContextMenuRequest(event->pos(), QList() << m_expandableFoldersAction); } void DolphinDetailsView::mousePressEvent(QMouseEvent* event) { - m_controller->requestActivation(); + m_dolphinViewController->requestActivation(); const QModelIndex current = currentIndex(); QTreeView::mousePressEvent(event); @@ -220,7 +254,7 @@ void DolphinDetailsView::mousePressEvent(QMouseEvent* event) if (!index.isValid() || (index.column() != DolphinModel::Name)) { // the mouse press is done somewhere outside the filename column if (QApplication::mouseButtons() & Qt::MidButton) { - m_controller->replaceUrlByClipboard(); + m_dolphinViewController->replaceUrlByClipboard(); } const Qt::KeyboardModifiers mod = QApplication::keyboardModifiers(); @@ -307,7 +341,7 @@ void DolphinDetailsView::mouseReleaseEvent(QMouseEvent* event) void DolphinDetailsView::startDrag(Qt::DropActions supportedActions) { - DragAndDropHelper::instance().startDrag(this, supportedActions, m_controller); + DragAndDropHelper::instance().startDrag(this, supportedActions, m_dolphinViewController); m_band.show = false; } @@ -337,7 +371,7 @@ void DolphinDetailsView::dragMoveEvent(QDragMoveEvent* event) setDirtyRegion(m_dropRect); const QModelIndex index = indexAt(event->pos()); if (index.isValid() && (index.column() == DolphinModel::Name)) { - const KFileItem item = m_controller->itemForIndex(index); + const KFileItem item = m_dolphinViewController->itemForIndex(index); if (!item.isNull() && item.isDir()) { m_dropRect = visualRect(index); } else { @@ -357,9 +391,9 @@ void DolphinDetailsView::dropEvent(QDropEvent* event) const QModelIndex index = indexAt(event->pos()); KFileItem item; if (index.isValid() && (index.column() == DolphinModel::Name)) { - item = m_controller->itemForIndex(index); + item = m_dolphinViewController->itemForIndex(index); } - m_controller->indicateDroppedUrls(item, m_controller->url(), event); + m_dolphinViewController->indicateDroppedUrls(item, m_viewModeController->url(), event); QTreeView::dropEvent(event); } @@ -391,7 +425,7 @@ void DolphinDetailsView::keyPressEvent(QKeyEvent* event) m_keyPressed = !(event->modifiers() & Qt::ControlModifier); QTreeView::keyPressEvent(event); - m_controller->handleKeyPressEvent(event); + m_dolphinViewController->handleKeyPressEvent(event); } void DolphinDetailsView::keyReleaseEvent(QKeyEvent* event) @@ -410,8 +444,7 @@ void DolphinDetailsView::resizeEvent(QResizeEvent* event) void DolphinDetailsView::wheelEvent(QWheelEvent* event) { - const int height = m_decorationSize.height(); - const int step = (height >= KIconLoader::SizeHuge) ? height / 10 : (KIconLoader::SizeHuge - height) / 2; + const int step = m_decorationSize.height(); verticalScrollBar()->setSingleStep(step); QTreeView::wheelEvent(event); } @@ -426,6 +459,10 @@ void DolphinDetailsView::currentChanged(const QModelIndex& current, const QModel if (m_keyPressed) { setCurrentIndex(current); } + + // If folders are expanded, the width which is available for editing may have changed + // because it depends on the level of the current item in the folder hierarchy. + adjustMaximumSizeForEditing(current); } bool DolphinDetailsView::eventFilter(QObject* watched, QEvent* event) @@ -434,7 +471,7 @@ bool DolphinDetailsView::eventFilter(QObject* watched, QEvent* event) // if the mouse is above an item and moved very fast outside the widget, // no viewportEntered() signal might be emitted although the mouse has been moved // above the viewport - m_controller->emitViewportEntered(); + m_dolphinViewController->emitViewportEntered(); } return QTreeView::eventFilter(watched, event); @@ -452,7 +489,7 @@ QModelIndex DolphinDetailsView::indexAt(const QPoint& point) const QRect DolphinDetailsView::visualRect(const QModelIndex& index) const { QRect rect = QTreeView::visualRect(index); - const KFileItem item = m_controller->itemForIndex(index); + const KFileItem item = m_dolphinViewController->itemForIndex(index); if (!item.isNull()) { const int width = DolphinFileItemDelegate::nameColumnWidth(item.text(), viewOptions()); rect.setWidth(width); @@ -498,16 +535,16 @@ void DolphinDetailsView::synchronizeSortingState(int column) // invoked, but Dolphin is not informed about this. DolphinView::Sorting sorting = DolphinSortFilterProxyModel::sortingForColumn(column); const Qt::SortOrder sortOrder = header()->sortIndicatorOrder(); - m_controller->indicateSortingChange(sorting); - m_controller->indicateSortOrderChange(sortOrder); + m_dolphinViewController->indicateSortingChange(sorting); + m_dolphinViewController->indicateSortOrderChange(sortOrder); } void DolphinDetailsView::slotEntered(const QModelIndex& index) { if (index.column() == DolphinModel::Name) { - m_controller->emitItemEntered(index); + m_dolphinViewController->emitItemEntered(index); } else { - m_controller->emitViewportEntered(); + m_dolphinViewController->emitViewportEntered(); } } @@ -544,7 +581,7 @@ void DolphinDetailsView::setZoomLevel(int level) const int size = ZoomLevelInfo::iconSizeForZoomLevel(level); DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); - const bool showPreview = m_controller->dolphinView()->showPreview(); + const bool showPreview = m_dolphinViewController->view()->showPreview(); if (showPreview) { settings->setPreviewSize(size); } else { @@ -556,7 +593,7 @@ void DolphinDetailsView::setZoomLevel(int level) void DolphinDetailsView::slotShowPreviewChanged() { - const DolphinView* view = m_controller->dolphinView(); + const DolphinView* view = m_dolphinViewController->view(); updateDecorationSize(view->showPreview()); } @@ -571,11 +608,13 @@ void DolphinDetailsView::configureSettings(const QPoint& pos) for (int i = 0; i < columns; ++i) { const int logicalIndex = headerView->logicalIndex(i); const QString text = model()->headerData(logicalIndex, Qt::Horizontal).toString(); - QAction* action = popup.addAction(text); - action->setCheckable(true); - action->setChecked(!headerView->isSectionHidden(logicalIndex)); - action->setData(logicalIndex); - action->setEnabled(logicalIndex != DolphinModel::Name); + if (!text.isEmpty()) { + QAction* action = popup.addAction(text); + action->setCheckable(true); + action->setChecked(!headerView->isSectionHidden(logicalIndex)); + action->setData(logicalIndex); + action->setEnabled(logicalIndex != DolphinModel::Name); + } } popup.addSeparator(); @@ -584,7 +623,7 @@ void DolphinDetailsView::configureSettings(const QPoint& pos) const bool show = activatedAction->isChecked(); const int columnIndex = activatedAction->data().toInt(); - KFileItemDelegate::InformationList list = m_controller->dolphinView()->additionalInfo(); + KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo(); const KFileItemDelegate::Information info = infoForColumn(columnIndex); if (show) { Q_ASSERT(!list.contains(info)); @@ -595,7 +634,7 @@ void DolphinDetailsView::configureSettings(const QPoint& pos) list.removeAt(index); } - m_controller->indicateAdditionalInfoChange(list); + m_dolphinViewController->indicateAdditionalInfoChange(list); setColumnHidden(columnIndex, !show); resizeColumns(); } @@ -609,30 +648,40 @@ void DolphinDetailsView::updateColumnVisibility() const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); const QList columnPositions = settings->columnPositions(); - - const KFileItemDelegate::InformationList list = m_controller->dolphinView()->additionalInfo(); - for (int i = DolphinModel::Name; i <= DolphinModel::Version; ++i) { + + const KFileItemDelegate::InformationList list = m_dolphinViewController->view()->additionalInfo(); + for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) { const KFileItemDelegate::Information info = infoForColumn(i); const bool hide = !list.contains(info) && (i != DolphinModel::Name); if (isColumnHidden(i) != hide) { setColumnHidden(i, hide); } - - const int from = headerView->visualIndex(i); - headerView->moveSection(from, columnPositions[i]); + + // If the list columnPositions has been written by an older Dolphin version, + // its length might be smaller than DolphinModel::ExtraColumnCount. Therefore, + // we have to check if item number i exists before accessing it. + if (i < columnPositions.length()) { + const int position = columnPositions[i]; + + // The position might be outside the correct range if the list columnPositions + // has been written by a newer Dolphin version with more columns. + if (position < DolphinModel::ExtraColumnCount) { + const int from = headerView->visualIndex(i); + headerView->moveSection(from, position); + } + } } - + resizeColumns(); connect(headerView, SIGNAL(sectionMoved(int, int, int)), this, SLOT(saveColumnPositions())); - } void DolphinDetailsView::saveColumnPositions() { QList columnPositions; - for (int i = DolphinModel::Name; i <= DolphinModel::Version; ++i) { + for (int i = DolphinModel::Name; i < DolphinModel::ExtraColumnCount; ++i) { columnPositions.append(header()->visualIndex(i)); } @@ -653,6 +702,8 @@ void DolphinDetailsView::slotHeaderSectionResized(int logicalIndex, int oldSize, if ((QApplication::mouseButtons() & Qt::LeftButton) && header()->underMouse()) { disableAutoResizing(); } + + adjustMaximumSizeForEditing(currentIndex()); } void DolphinDetailsView::slotActivationChanged(bool active) @@ -667,7 +718,7 @@ void DolphinDetailsView::disableAutoResizing() void DolphinDetailsView::requestActivation() { - m_controller->requestActivation(); + m_dolphinViewController->requestActivation(); } void DolphinDetailsView::slotGlobalSettingsChanged(int category) @@ -680,12 +731,12 @@ void DolphinDetailsView::slotGlobalSettingsChanged(int category) m_font = KGlobalSettings::generalFont(); } //Disconnect then reconnect, since the settings have been changed, the connection requirements may have also. - disconnect(this, SIGNAL(clicked(QModelIndex)), m_controller, SLOT(triggerItem(QModelIndex))); - disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_controller, SLOT(triggerItem(QModelIndex))); + disconnect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex))); + disconnect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex))); if (KGlobalSettings::singleClick()) { - connect(this, SIGNAL(clicked(QModelIndex)), m_controller, SLOT(triggerItem(QModelIndex))); + connect(this, SIGNAL(clicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex))); } else { - connect(this, SIGNAL(doubleClicked(QModelIndex)), m_controller, SLOT(triggerItem(QModelIndex))); + connect(this, SIGNAL(doubleClicked(QModelIndex)), m_dolphinViewController, SLOT(triggerItem(QModelIndex))); } } @@ -750,8 +801,7 @@ void DolphinDetailsView::updateElasticBandSelection() return; } } - } - else { + } else { // This is the only piece of optimization data that needs to be explicitly // discarded. m_band.lastSelectionOrigin = QPoint(); @@ -865,6 +915,7 @@ void DolphinDetailsView::updateElasticBandSelection() currIndex = nextIndex; } while (!allItemsInBoundDone); + selectionModel()->select(itemsToToggle, QItemSelectionModel::Toggle); m_band.lastSelectionOrigin = m_band.origin; @@ -886,11 +937,15 @@ void DolphinDetailsView::setFoldersExpandable(bool expandable) settings->setExpandableFolders(expandable); setRootIsDecorated(expandable); setItemsExpandable(expandable); + + // The width of the space which is available for editing has changed + // because of the (dis)appearance of the expanding toggles + adjustMaximumSizeForEditing(currentIndex()); } void DolphinDetailsView::slotExpanded(const QModelIndex& index) { - KFileItem item = m_controller->itemForIndex(index); + KFileItem item = m_dolphinViewController->itemForIndex(index); if (!item.isNull()) { m_expandedUrls.insert(item.url()); } @@ -898,7 +953,7 @@ void DolphinDetailsView::slotExpanded(const QModelIndex& index) void DolphinDetailsView::slotCollapsed(const QModelIndex& index) { - KFileItem item = m_controller->itemForIndex(index); + KFileItem item = m_dolphinViewController->itemForIndex(index); if (!item.isNull()) { m_expandedUrls.remove(item.url()); } @@ -937,19 +992,7 @@ void DolphinDetailsView::updateDecorationSize(bool showPreview) KFileItemDelegate::Information DolphinDetailsView::infoForColumn(int columnIndex) const { - KFileItemDelegate::Information info = KFileItemDelegate::NoInformation; - - switch (columnIndex) { - case DolphinModel::Size: info = KFileItemDelegate::Size; break; - case DolphinModel::ModifiedTime: info = KFileItemDelegate::ModificationTime; break; - case DolphinModel::Permissions: info = KFileItemDelegate::Permissions; break; - case DolphinModel::Owner: info = KFileItemDelegate::Owner; break; - case DolphinModel::Group: info = KFileItemDelegate::OwnerAndGroup; break; - case DolphinModel::Type: info = KFileItemDelegate::FriendlyMimeType; break; - default: break; - } - - return info; + return AdditionalInfoAccessor::instance().keyForColumn(columnIndex); } void DolphinDetailsView::resizeColumns() @@ -963,17 +1006,30 @@ void DolphinDetailsView::resizeColumns() QHeaderView* headerView = header(); QFontMetrics fontMetrics(viewport()->font()); - int columnWidth[DolphinModel::Version + 1]; - columnWidth[DolphinModel::Size] = fontMetrics.width("00000 Items"); - columnWidth[DolphinModel::ModifiedTime] = fontMetrics.width("0000-00-00 00:00"); - columnWidth[DolphinModel::Permissions] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[DolphinModel::Owner] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[DolphinModel::Group] = fontMetrics.width("xxxxxxxxxx"); - columnWidth[DolphinModel::Type] = fontMetrics.width("XXXX Xxxxxxx"); - columnWidth[DolphinModel::Version] = fontMetrics.width("xxxxxxxx"); + // Calculate the required with for each column and store it in columnWidth[] + int columnWidth[DolphinModel::ExtraColumnCount]; + const int defaultWidth = fontMetrics.width("xxxxxxxxxx"); + + for (int i = 0; i < DolphinModel::ExtraColumnCount; ++i) { + const int logicalIndex = headerView->logicalIndex(i); + const QString headline = model()->headerData(logicalIndex, Qt::Horizontal).toString(); + const int headlineWidth = fontMetrics.width(headline); + + columnWidth[i] = qMax(defaultWidth, headlineWidth); + } + + const int defaultSizeWidth = fontMetrics.width("00000 Items"); + if (defaultSizeWidth > columnWidth[DolphinModel::Size]) { + columnWidth[DolphinModel::Size] = defaultSizeWidth; + } + + const int defaultTimeWidth = fontMetrics.width("0000-00-00 00:00"); + if (defaultTimeWidth > columnWidth[DolphinModel::ModifiedTime]) { + columnWidth[DolphinModel::ModifiedTime] = defaultTimeWidth; + } int requiredWidth = 0; - for (int i = KDirModel::Size; i <= KDirModel::Type; ++i) { + for (int i = KDirModel::Size; i < DolphinModel::ExtraColumnCount; ++i) { if (!isColumnHidden(i)) { columnWidth[i] += 20; // provide a default gap requiredWidth += columnWidth[i]; @@ -981,7 +1037,7 @@ void DolphinDetailsView::resizeColumns() } } - // resize the name column in a way that the whole available width is used + // Resize the name column in a way that the whole available width is used columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth; const int minNameWidth = 300; @@ -1034,6 +1090,12 @@ bool DolphinDetailsView::isAboveExpandingToggle(const QPoint& pos) const return false; } +void DolphinDetailsView::adjustMaximumSizeForEditing(const QModelIndex& index) +{ + // Make sure that the full width of the "Name" column is available for "Rename Inline" + m_extensionsFactory->fileItemDelegate()->setMaximumSize(QTreeView::visualRect(index).size()); +} + DolphinDetailsView::ElasticBand::ElasticBand() : show(false), origin(),