diff --git a/src/filewidgets/CMakeLists.txt b/src/filewidgets/CMakeLists.txt --- a/src/filewidgets/CMakeLists.txt +++ b/src/filewidgets/CMakeLists.txt @@ -15,6 +15,7 @@ kdiroperator.cpp kdiroperatordetailview.cpp + kdiroperatoriconview.cpp kdirsortfilterproxymodel.cpp #used in combination with kdirmodel.cpp kencodingfiledialog.cpp kfilebookmarkhandler.cpp diff --git a/src/filewidgets/kdiroperator.h b/src/filewidgets/kdiroperator.h --- a/src/filewidgets/kdiroperator.h +++ b/src/filewidgets/kdiroperator.h @@ -926,6 +926,7 @@ Q_PRIVATE_SLOT(d, void _k_slotSimpleView()) Q_PRIVATE_SLOT(d, void _k_slotTreeView()) Q_PRIVATE_SLOT(d, void _k_slotDetailedTreeView()) + Q_PRIVATE_SLOT(d, void _k_slotToggleAllowExpansion(bool)) Q_PRIVATE_SLOT(d, void _k_slotToggleHidden(bool)) Q_PRIVATE_SLOT(d, void _k_togglePreview(bool)) Q_PRIVATE_SLOT(d, void _k_toggleInlinePreviews(bool)) @@ -936,6 +937,9 @@ Q_PRIVATE_SLOT(d, void _k_slotSortByType()) Q_PRIVATE_SLOT(d, void _k_slotSortReversed(bool)) Q_PRIVATE_SLOT(d, void _k_slotToggleDirsFirst()) + Q_PRIVATE_SLOT(d, void _k_slotToggleIconsView()) + Q_PRIVATE_SLOT(d, void _k_slotToggleCompactView()) + Q_PRIVATE_SLOT(d, void _k_slotToggleDetailsView()) Q_PRIVATE_SLOT(d, void _k_slotToggleIgnoreCase()) Q_PRIVATE_SLOT(d, void _k_slotStarted()) Q_PRIVATE_SLOT(d, void _k_slotProgress(int)) diff --git a/src/filewidgets/kdiroperator.cpp b/src/filewidgets/kdiroperator.cpp --- a/src/filewidgets/kdiroperator.cpp +++ b/src/filewidgets/kdiroperator.cpp @@ -147,6 +147,7 @@ void _k_slotDirectoryCreated(const QUrl &); int iconSizeForViewType(QAbstractItemView *itemView) const; + void writeIconZoomSettings(KConfigGroup &configGroup); // private members KDirOperator * const parent; @@ -510,24 +511,44 @@ void KDirOperator::Private::_k_slotDetailedView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + KFile::FileView view = static_cast((viewKind & ~allViews()) | KFile::Detail); parent->setView(view); } void KDirOperator::Private::_k_slotSimpleView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + KFile::FileView view = static_cast((viewKind & ~allViews()) | KFile::Simple); parent->setView(view); } void KDirOperator::Private::_k_slotTreeView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + KFile::FileView view = static_cast((viewKind & ~allViews()) | KFile::Tree); parent->setView(view); } void KDirOperator::Private::_k_slotDetailedTreeView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + KFile::FileView view = static_cast((viewKind & ~allViews()) | KFile::DetailTree); parent->setView(view); } @@ -634,6 +655,11 @@ void KDirOperator::Private::_k_slotToggleIconsView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + // Put the icons on top actionCollection->action(QStringLiteral("decorationAtTop"))->setChecked(true); decorationPosition = QStyleOptionViewItem::Top; @@ -645,6 +671,11 @@ void KDirOperator::Private::_k_slotToggleCompactView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + // Put the icons on the side actionCollection->action(QStringLiteral("decorationAtLeft"))->setChecked(true); decorationPosition = QStyleOptionViewItem::Left; @@ -656,6 +687,11 @@ void KDirOperator::Private::_k_slotToggleDetailsView() { + if (configGroup && itemView) { + // save old zoom settings + writeIconZoomSettings(*configGroup); + } + KFile::FileView view; if (actionCollection->action(QStringLiteral("allow expansion"))->isChecked()) { view = static_cast((viewKind & ~allViews()) | KFile::DetailTree); @@ -2291,16 +2327,32 @@ if (d->inlinePreviewState == Private::NotForced) { configGroup.writeEntry(QStringLiteral("Show Inline Previews"), d->showPreviews); - if (qobject_cast(d->itemView)) { - configGroup.writeEntry(QStringLiteral("listViewIconSize"), d->iconsZoom); - } else { - configGroup.writeEntry(QStringLiteral("detailedViewIconSize"), d->iconsZoom); - } + d->writeIconZoomSettings(configGroup); } configGroup.writeEntry(QStringLiteral("Decoration position"), (int) d->decorationPosition); } +void KDirOperator::Private::writeIconZoomSettings(KConfigGroup &configGroup) { + // must match behavior of iconSizeForViewType + KFile::FileView fv = static_cast(viewKind); + + if (KFile::isSimpleView(fv)) { + if (decorationPosition == QStyleOptionViewItem::Top){ + // Simple view decoration above, aka Icons View + configGroup.writeEntry("iconViewIconSize", iconsZoom); + } else { + // Simple view decoration left, aka compact view + configGroup.writeEntry("listViewIconSize", iconsZoom); + } + } else { + if (KFile::isTreeView(fv)) { + configGroup.writeEntry(QStringLiteral("treeViewIconSize"), iconsZoom); + } else if (KFile::isDetailTreeView(fv) || KFile::isDetailView(fv)) { + configGroup.writeEntry(QStringLiteral("detailViewIconSize"), iconsZoom); + } + } +} void KDirOperator::resizeEvent(QResizeEvent *) { @@ -2637,15 +2689,31 @@ int KDirOperator::Private::iconSizeForViewType(QAbstractItemView *itemView) const { + // must match behavior of writeIconZoomSettings if (!itemView || !configGroup) { return 0; } - if (qobject_cast(itemView)) { - return configGroup->readEntry("listViewIconSize", 0); + KFile::FileView fv = static_cast(viewKind); + + if (KFile::isSimpleView(fv)) { + if (decorationPosition == QStyleOptionViewItem::Top){ + // Simple view decoration above, aka Icons View + // default to 43% aka 64px + return configGroup->readEntry("iconViewIconSize", 43); + } else { + // Simple view decoration left, aka compact view + return configGroup->readEntry("listViewIconSize", 0); + } } else { - return configGroup->readEntry("detailedViewIconSize", 0); + if (KFile::isTreeView(fv)) { + return configGroup->readEntry(QStringLiteral("treeViewIconSize"), 0); + } else if (KFile::isDetailView(fv) || KFile::isDetailTreeView(fv)) { + return configGroup->readEntry(QStringLiteral("detailViewIconSize"), 0); + } } + + return 0; } void KDirOperator::setViewConfig(KConfigGroup &configGroup) diff --git a/src/filewidgets/kdiroperatoriconview.cpp b/src/filewidgets/kdiroperatoriconview.cpp new file mode 100644 --- /dev/null +++ b/src/filewidgets/kdiroperatoriconview.cpp @@ -0,0 +1,149 @@ +/***************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * Copyright (C) 2019 by Méven Car * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public License * + * along with this library; see the file COPYING.LIB. If not, write to * + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301, USA. * + *****************************************************************************/ + +#include "kdiroperatoriconview_p.h" + +#include +#include +#include +#include + +#include +#include + +KDirOperatorIconView::KDirOperatorIconView(QWidget *parent, QStyleOptionViewItem::Position aDecorationPosition) : + QListView(parent) +{ + setViewMode(QListView::IconMode); + setResizeMode(QListView::Adjust); + setSpacing(0); + setMovement(QListView::Static); + setDragDropMode(QListView::DragOnly); + setVerticalScrollMode(QListView::ScrollPerPixel); + setHorizontalScrollMode(QListView::ScrollPerPixel); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setWordWrap(true); + setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall)); + + decorationPosition = aDecorationPosition; + + updateLayout(); + connect(this, &QListView::iconSizeChanged, this, &KDirOperatorIconView::updateLayout); +} + +KDirOperatorIconView::~KDirOperatorIconView() +{ +} + +void KDirOperatorIconView::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + updateLayout(); +} + +QStyleOptionViewItem KDirOperatorIconView::viewOptions() const +{ + QStyleOptionViewItem viewOptions = QListView::viewOptions(); + viewOptions.showDecorationSelected = true; + viewOptions.decorationPosition = decorationPosition; + if (viewOptions.decorationPosition == QStyleOptionViewItem::Left) { + viewOptions.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter; + } else { + viewOptions.displayAlignment = Qt::AlignCenter; + } + + return viewOptions; +} + +void KDirOperatorIconView::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } +} + +void KDirOperatorIconView::mousePressEvent(QMouseEvent *event) +{ + if (!indexAt(event->pos()).isValid()) { + const Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); + if (!(modifiers & Qt::ShiftModifier) && !(modifiers & Qt::ControlModifier)) { + clearSelection(); + } + } + + QListView::mousePressEvent(event); +} + +void KDirOperatorIconView::wheelEvent(QWheelEvent *event) +{ + QListView::wheelEvent(event); + + // apply the vertical wheel event to the horizontal scrollbar, as + // the items are aligned from left to right + if (event->orientation() == Qt::Vertical) { + QWheelEvent horizEvent(event->pos(), + event->delta(), + event->buttons(), + event->modifiers(), + Qt::Horizontal); + QApplication::sendEvent(horizontalScrollBar(), &horizEvent); + } +} + +void KDirOperatorIconView::updateLayout() { + if (decorationPosition == QStyleOptionViewItem::Position::Top) { + // Icons view + setFlow(QListView::LeftToRight); + const QFontMetrics metrics(viewport()->font()); + + const int height = iconSize().height() + metrics.height() * 2.5; + const int minWidth = qMax(height, metrics.height() * 5); + + const int scrollBarWidth = verticalScrollBar()->sizeHint().width(); + + // Subtract 1 px to prevent flickering when resizing the window + // For Oxygen a column is missing after showing the dialog without resizing it, + // therefore subtract 4 more (scaled) pixels + const int viewPortWidth = contentsRect().width() - scrollBarWidth - 1 - 4 * devicePixelRatioF(); + const int itemsInRow = qMax(1, viewPortWidth / minWidth); + const int remainingWidth = viewPortWidth - (minWidth * itemsInRow); + const int width = minWidth + (remainingWidth / itemsInRow); + + const QSize itemSize(width, height); + + setGridSize(itemSize); + KFileItemDelegate *delegate = qobject_cast(itemDelegate()); + if (delegate) { + delegate->setMaximumSize(itemSize); + } + } else { + // compact view + setFlow(QListView::TopToBottom); + setGridSize(QSize()); + KFileItemDelegate *delegate = qobject_cast(itemDelegate()); + if (delegate) { + delegate->setMaximumSize(QSize()); + } + } +} +void KDirOperatorIconView::setDecorationPosition(QStyleOptionViewItem::Position newDecorationPosition) +{ + decorationPosition = newDecorationPosition; + updateLayout(); +} diff --git a/src/filewidgets/kdiroperatoriconview_p.h b/src/filewidgets/kdiroperatoriconview_p.h new file mode 100644 --- /dev/null +++ b/src/filewidgets/kdiroperatoriconview_p.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (C) 2007 by Peter Penz * + * Copyright (C) 2019 by Méven Car * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public License * + * along with this library; see the file COPYING.LIB. If not, write to * + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301, USA. * + *****************************************************************************/ + +#ifndef KDIROPERATORICONVIEW_P_H +#define KDIROPERATORICONVIEW_P_H + +#include + +/** + * Default icon view for KDirOperator using + * custom view options. + */ +class KDirOperatorIconView : public QListView +{ + Q_OBJECT +public: + KDirOperatorIconView(QWidget *parent = nullptr, QStyleOptionViewItem::Position decorationPosition = QStyleOptionViewItem::Position::Top); + virtual ~KDirOperatorIconView(); + void setDecorationPosition(QStyleOptionViewItem::Position decorationPosition); + +protected: + QStyleOptionViewItem viewOptions() const override; + void dragEnterEvent(QDragEnterEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void wheelEvent(QWheelEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +protected Q_SLOT: + void updateLayout(); +private: + QStyleOptionViewItem::Position decorationPosition; +}; + + +#endif // KDIROPERATORICONVIEW_P_H diff --git a/src/filewidgets/kfilewidget.cpp b/src/filewidgets/kfilewidget.cpp --- a/src/filewidgets/kfilewidget.cpp +++ b/src/filewidgets/kfilewidget.cpp @@ -487,6 +487,7 @@ connect(showBookmarksAction, SIGNAL(toggled(bool)), SLOT(_k_toggleBookmarks(bool))); + // Build the settings menu KActionMenu *menu = new KActionMenu(QIcon::fromTheme(QStringLiteral("configure")), i18n("Options"), this); coll->addAction(QStringLiteral("extra menu"), menu); menu->setWhatsThis(i18n("This is the preferences menu for the file dialog. " @@ -497,12 +498,10 @@ "
  • the Places panel
  • " "
  • file previews
  • " "
  • separating folders from files
  • ")); - menu->addAction(coll->action(QStringLiteral("view menu"))); - menu->addSeparator(); - menu->addAction(coll->action(QStringLiteral("decoration menu"))); + + menu->addAction(coll->action(QStringLiteral("allow expansion"))); menu->addSeparator(); menu->addAction(coll->action(QStringLiteral("show hidden"))); - menu->addSeparator(); menu->addAction(showSidebarAction); menu->addAction(showBookmarksAction); menu->addAction(coll->action(QStringLiteral("preview"))); @@ -543,6 +542,10 @@ d->toolbar->addAction(coll->action(QStringLiteral("up"))); d->toolbar->addAction(coll->action(QStringLiteral("reload"))); d->toolbar->addSeparator(); + d->toolbar->addAction(coll->action(QStringLiteral("icons view"))); + d->toolbar->addAction(coll->action(QStringLiteral("compact view"))); + d->toolbar->addAction(coll->action(QStringLiteral("details view"))); + d->toolbar->addSeparator(); d->toolbar->addAction(coll->action(QStringLiteral("inline preview"))); d->toolbar->addAction(coll->action(QStringLiteral("sorting menu"))); d->toolbar->addWidget(midSpacer);