Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHannah von Reth <hannah.vonreth@owncloud.com>2021-06-01 16:55:59 +0300
committerHannah von Reth <vonreth@kde.org>2021-06-15 14:43:40 +0300
commite84605055fe576faba9d9245350e281e10403627 (patch)
tree3b5f95a2a8ca36ef0c1c51588d36370d1209987f /src
parentdadf8ceb704e406175862349289e035d3af632d5 (diff)
Change the resize behaviour of the header view
Diffstat (limited to 'src')
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/activitywidget.cpp27
-rw-r--r--src/gui/issueswidget.cpp24
-rw-r--r--src/gui/models/expandingheaderview.cpp113
-rw-r--r--src/gui/models/expandingheaderview.h43
-rw-r--r--src/gui/models/models.cpp8
-rw-r--r--src/gui/models/models.h23
-rw-r--r--src/gui/protocolwidget.cpp33
-rw-r--r--src/gui/protocolwidget.h3
9 files changed, 223 insertions, 52 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 5194120dd..4c5a9f873 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -89,6 +89,7 @@ set(client_SRCS
creds/httpcredentialsgui.cpp
models/activitylistmodel.cpp
+ models/expandingheaderview.cpp
models/models.cpp
models/protocolitemmodel.cpp
diff --git a/src/gui/activitywidget.cpp b/src/gui/activitywidget.cpp
index 51cb8ae8d..5e5014407 100644
--- a/src/gui/activitywidget.cpp
+++ b/src/gui/activitywidget.cpp
@@ -38,6 +38,7 @@
#include "ocsjob.h"
#include "models/activitylistmodel.h"
+#include "models/expandingheaderview.h"
#include "models/models.h"
#include "ui_activitywidget.h"
@@ -62,19 +63,11 @@ ActivityWidget::ActivityWidget(QWidget *parent)
_sortModel->setSourceModel(_model);
_ui->_activityList->setModel(_sortModel);
_sortModel->setSortRole(Models::UnderlyingDataRole);
- _ui->_activityList->hideColumn(static_cast<int>(ActivityListModel::ActivityRole::Path));
- _ui->_activityList->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
- _ui->_activityList->horizontalHeader()->setSectionResizeMode(static_cast<int>(ActivityListModel::ActivityRole::Text), QHeaderView::Stretch);
- _ui->_activityList->horizontalHeader()->setSortIndicator(static_cast<int>(ActivityListModel::ActivityRole::PointInTime), Qt::DescendingOrder);
-
- ConfigFile cfg;
- _ui->_activityList->horizontalHeader()->setObjectName(QStringLiteral("ActivityListModelHeader"));
- cfg.restoreGeometryHeader(_ui->_activityList->horizontalHeader());
-
- connect(qApp, &QApplication::aboutToQuit, this, [this] {
- ConfigFile cfg;
- cfg.saveGeometryHeader(_ui->_activityList->horizontalHeader());
- });
+ auto header = new ExpandingHeaderView(QStringLiteral("ActivityListModelHeader"), _ui->_activityList);
+ _ui->_activityList->setHorizontalHeader(header);
+ header->hideSection(static_cast<int>(ActivityListModel::ActivityRole::Path));
+ header->setSectionResizeMode(QHeaderView::Interactive);
+ header->setSortIndicator(static_cast<int>(ActivityListModel::ActivityRole::PointInTime), Qt::DescendingOrder);
_ui->_notifyLabel->hide();
_ui->_notifyScroll->hide();
@@ -107,9 +100,11 @@ ActivityWidget::ActivityWidget(QWidget *parent)
connect(_model, &QAbstractItemModel::modelReset, this, &ActivityWidget::dataChanged);
connect(_ui->_activityList, &QListView::customContextMenuRequested, this, &ActivityWidget::slotItemContextMenu);
- _ui->_activityList->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(_ui->_activityList->horizontalHeader(), &QListView::customContextMenuRequested, this, [this] {
- Models::displayFilterDialog(AccountManager::instance()->accountNames(), _sortModel, static_cast<int>(ActivityListModel::ActivityRole::Account), Qt::DisplayRole, this);
+ header->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(header, &QListView::customContextMenuRequested, header, [header, this] {
+ auto menu = Models::displayFilterDialog(AccountManager::instance()->accountNames(), _sortModel, static_cast<int>(ActivityListModel::ActivityRole::Account), Qt::DisplayRole, this);
+ menu->addSeparator();
+ menu->addAction(tr("Reset column sizes"), this, [header] { header->resizeColumns(true); });
});
connect(&_removeTimer, &QTimer::timeout, this, &ActivityWidget::slotCheckToCleanWidgets);
diff --git a/src/gui/issueswidget.cpp b/src/gui/issueswidget.cpp
index 01d1c9e20..0b801115f 100644
--- a/src/gui/issueswidget.cpp
+++ b/src/gui/issueswidget.cpp
@@ -24,6 +24,7 @@
#include "folderman.h"
#include "syncfileitem.h"
#include "folder.h"
+#include "models/expandingheaderview.h"
#include "models/models.h"
#include "openfilemanager.h"
#include "protocolwidget.h"
@@ -76,23 +77,18 @@ IssuesWidget::IssuesWidget(QWidget *parent)
_sortModel = new QSortFilterProxyModel(this);
_sortModel->setSourceModel(_model);
_ui->_tableView->setModel(_sortModel);
- connect(_ui->_tableView, &QTreeView::customContextMenuRequested, this, &IssuesWidget::slotItemContextMenu);
- _ui->_tableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(_ui->_tableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, [this] {
- ProtocolWidget::showHeaderContextMenu(this, _sortModel);
- });
- _ui->_tableView->horizontalHeader()->setObjectName(QStringLiteral("ActivityErrorListHeaderV2"));
- _ui->_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
- _ui->_tableView->horizontalHeader()->setSectionResizeMode(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Action), QHeaderView::Stretch);
- _ui->_tableView->horizontalHeader()->setSortIndicator(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Time), Qt::DescendingOrder);
+ auto header = new ExpandingHeaderView(QStringLiteral("ActivityErrorListHeaderV2"), _ui->_tableView);
+ _ui->_tableView->setHorizontalHeader(header);
+ header->setSectionResizeMode(QHeaderView::Interactive);
+ header->setExpandingColumn(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Action));
+ header->setSortIndicator(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Time), Qt::DescendingOrder);
- ConfigFile cfg;
- cfg.restoreGeometryHeader(_ui->_tableView->horizontalHeader());
- connect(qApp, &QApplication::aboutToQuit, this, [this] {
- ConfigFile cfg;
- cfg.saveGeometryHeader(_ui->_tableView->horizontalHeader());
+ connect(_ui->_tableView, &QTreeView::customContextMenuRequested, this, &IssuesWidget::slotItemContextMenu);
+ _ui->_tableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(header, &QHeaderView::customContextMenuRequested, header, [header, this] {
+ ProtocolWidget::showHeaderContextMenu(header, _sortModel);
});
diff --git a/src/gui/models/expandingheaderview.cpp b/src/gui/models/expandingheaderview.cpp
new file mode 100644
index 000000000..0916f7899
--- /dev/null
+++ b/src/gui/models/expandingheaderview.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License
+ * for more details.
+ */
+#include "expandingheaderview.h"
+#include "models.h"
+
+#include "configfile.h"
+
+#include <QScopedValueRollback>
+#include <QApplication>
+#include <QDebug>
+
+using namespace OCC;
+
+ExpandingHeaderView::ExpandingHeaderView(const QString &objectName, QWidget *parent)
+ : QHeaderView(Qt::Horizontal, parent)
+{
+ setSectionsClickable(true);
+ setHighlightSections(true);
+
+ connect(this, &QHeaderView::sectionCountChanged, this, &ExpandingHeaderView::resizeColumns);
+ connect(this, &QHeaderView::sectionResized, this, [this](int index, int oldSize, int newSize) {
+ if (_isResizing) {
+ return;
+ }
+ QScopedValueRollback<bool> guard(_isResizing, true);
+ if (index != _expandingColumn) {
+ // give/take space from _expandingColumn column
+ resizeSection(_expandingColumn, sectionSize(_expandingColumn) - (newSize - oldSize));
+ } else {
+ // distribute space across all columns
+ // use actual width as oldSize/newSize isn't reliable here
+ auto visibleSections = Models::range(count());
+ visibleSections.erase(std::remove_if(visibleSections.begin(), visibleSections.end(), [this](int i) {
+ return isSectionHidden(i);
+ }),
+ visibleSections.end());
+ if (visibleSections.empty()) {
+ return;
+ }
+ int availableWidth = width();
+ for (auto &i : visibleSections) {
+ availableWidth -= sectionSize(i);
+ }
+
+ const int diffPerSection = availableWidth / static_cast<int>(visibleSections.size());
+ const int extraDiff = availableWidth % visibleSections.size();
+ const auto secondLast = visibleSections.cend()[-2];
+ for (auto &i : visibleSections) {
+ if (_expandingColumn == i) {
+ continue;
+ }
+ auto newSize = sectionSize(i) + diffPerSection;
+ if (i == secondLast) {
+ newSize += extraDiff;
+ }
+ resizeSection(i, newSize);
+ }
+ }
+ });
+
+ setObjectName(objectName);
+ ConfigFile cfg;
+ cfg.restoreGeometryHeader(this);
+
+ connect(qApp, &QApplication::aboutToQuit, this, [this] {
+ ConfigFile cfg;
+ cfg.saveGeometryHeader(this);
+ });
+}
+
+int ExpandingHeaderView::expandingColumn() const
+{
+ return _expandingColumn;
+}
+
+void ExpandingHeaderView::setExpandingColumn(int newExpandingColumn)
+{
+ _expandingColumn = newExpandingColumn;
+}
+
+void ExpandingHeaderView::resizeEvent(QResizeEvent *event)
+{
+ QHeaderView::resizeEvent(event);
+ resizeColumns();
+}
+
+void ExpandingHeaderView::resizeColumns(bool reset)
+{
+ QScopedValueRollback<bool> guard(_isResizing, true);
+ int availableWidth = width();
+ const auto defaultSize = defaultSectionSize();
+ for (int i = 0; i < count(); ++i) {
+ if (i == _expandingColumn || isSectionHidden(i)) {
+ continue;
+ }
+ if (reset) {
+ resizeSection(i, defaultSize);
+ }
+ availableWidth -= sectionSize(i);
+ }
+ resizeSection(_expandingColumn, availableWidth);
+}
diff --git a/src/gui/models/expandingheaderview.h b/src/gui/models/expandingheaderview.h
new file mode 100644
index 000000000..bc997a398
--- /dev/null
+++ b/src/gui/models/expandingheaderview.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License
+ * for more details.
+ */
+#pragma once
+
+#include <QHeaderView>
+
+namespace OCC {
+
+// Based on https://github.com/KDAB/hotspot/blob/master/src/costheaderview.cpp
+// thanks to Milian Wolff <milian.wolff@kdab.com>
+
+class ExpandingHeaderView : public QHeaderView
+{
+ Q_OBJECT
+public:
+ ExpandingHeaderView(const QString &objectName, QWidget *parent = nullptr);
+
+ int expandingColumn() const;
+ void setExpandingColumn(int newExpandingColumn);
+
+ void resizeColumns(bool reset = false);
+
+protected:
+ void resizeEvent(QResizeEvent *event) override;
+
+
+private:
+ int _expandingColumn = 0;
+ bool _isResizing = false;
+};
+
+}
diff --git a/src/gui/models/models.cpp b/src/gui/models/models.cpp
index e32d28594..e549aaaf8 100644
--- a/src/gui/models/models.cpp
+++ b/src/gui/models/models.cpp
@@ -18,6 +18,7 @@
#include <QTextStream>
#include <QSortFilterProxyModel>
#include <QMenu>
+#include <QTimer>
#include <functional>
@@ -76,7 +77,7 @@ QString OCC::Models::formatSelection(const QModelIndexList &items, int dataRole)
return out;
}
-void OCC::Models::displayFilterDialog(const QStringList &candidates, QSortFilterProxyModel *model, int column, int role, QWidget *parent)
+QMenu *OCC::Models::displayFilterDialog(const QStringList &candidates, QSortFilterProxyModel *model, int column, int role, QWidget *parent)
{
auto menu = new QMenu(parent);
menu->setAttribute(Qt::WA_DeleteOnClose);
@@ -102,5 +103,8 @@ void OCC::Models::displayFilterDialog(const QStringList &candidates, QSortFilter
for (const auto &c : candidates) {
addAction(c, c);
}
- menu->popup(QCursor::pos());
+ QTimer::singleShot(0, menu, [menu] {
+ menu->popup(QCursor::pos());
+ });
+ return menu;
}
diff --git a/src/gui/models/models.h b/src/gui/models/models.h
index 035d2fdfe..b96519fe2 100644
--- a/src/gui/models/models.h
+++ b/src/gui/models/models.h
@@ -18,6 +18,7 @@
#include <QtGlobal>
class QSortFilterProxyModel;
+class QMenu;
namespace OCC {
@@ -33,8 +34,28 @@ namespace Models {
QString formatSelection(const QModelIndexList &items, int dataRole = Qt::DisplayRole);
- void displayFilterDialog(const QStringList &candidates, QSortFilterProxyModel *model, int column, int role, QWidget *parent = nullptr);
+ QMenu *displayFilterDialog(const QStringList &candidates, QSortFilterProxyModel *model, int column, int role, QWidget *parent = nullptr);
+ /**
+ * Returns a vector with indices
+ * This is handy to iterate over the columns
+ */
+ template <typename T>
+ auto range(T start, T end)
+ {
+ std::vector<T> out;
+ out.reserve(end - start);
+ for (auto i = start; i < end; ++i) {
+ out.push_back(i);
+ }
+ return out;
+ }
+
+ template <typename T>
+ auto range(T end)
+ {
+ return range<T>(0, end);
+ }
};
}
diff --git a/src/gui/protocolwidget.cpp b/src/gui/protocolwidget.cpp
index 3364bae1e..c8f674938 100644
--- a/src/gui/protocolwidget.cpp
+++ b/src/gui/protocolwidget.cpp
@@ -29,8 +29,9 @@
#include "accountstate.h"
#include "syncfileitem.h"
-#include "models/models.h"
#include "models/activitylistmodel.h"
+#include "models/expandingheaderview.h"
+#include "models/models.h"
#include "ui_protocolwidget.h"
@@ -46,10 +47,6 @@ ProtocolWidget::ProtocolWidget(QWidget *parent)
this, &ProtocolWidget::slotItemCompleted);
connect(_ui->_tableView, &QTreeWidget::customContextMenuRequested, this, &ProtocolWidget::slotItemContextMenu);
- _ui->_tableView->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(_ui->_tableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, [this] {
- showHeaderContextMenu(this, _sortModel);
- });
_model = new ProtocolItemModel(this);
_sortModel = new QSortFilterProxyModel(this);
@@ -57,19 +54,17 @@ ProtocolWidget::ProtocolWidget(QWidget *parent)
_sortModel->setSortRole(Models::UnderlyingDataRole);
_ui->_tableView->setModel(_sortModel);
- _ui->_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
- _ui->_tableView->horizontalHeader()->setSectionResizeMode(static_cast<int>(ProtocolItemModel::ProtocolItemRole::File), QHeaderView::Stretch);
- _ui->_tableView->horizontalHeader()->setSortIndicator(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Time), Qt::DescendingOrder);
-
- _ui->_tableView->horizontalHeader()->setObjectName(QStringLiteral("ActivityListHeaderV2"));
- ConfigFile cfg;
- cfg.restoreGeometryHeader(_ui->_tableView->horizontalHeader());
-
- connect(qApp, &QApplication::aboutToQuit, this, [this] {
- ConfigFile cfg;
- cfg.saveGeometryHeader(_ui->_tableView->horizontalHeader());
+ auto header = new ExpandingHeaderView(QStringLiteral("ActivityListHeaderV2"), _ui->_tableView);
+ _ui->_tableView->setHorizontalHeader(header);
+ header->setSectionResizeMode(QHeaderView::Interactive);
+ header->setExpandingColumn(static_cast<int>(ProtocolItemModel::ProtocolItemRole::File));
+ header->setSortIndicator(static_cast<int>(ProtocolItemModel::ProtocolItemRole::Time), Qt::DescendingOrder);
+ header->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(header, &QHeaderView::customContextMenuRequested, header, [header, this] {
+ showHeaderContextMenu(header, _sortModel);
});
+
_ui->_headerLabel->setText(tr("Local sync protocol"));
}
@@ -78,9 +73,11 @@ ProtocolWidget::~ProtocolWidget()
delete _ui;
}
-void ProtocolWidget::showHeaderContextMenu(QWidget *parent, QSortFilterProxyModel *model)
+void ProtocolWidget::showHeaderContextMenu(ExpandingHeaderView *header, QSortFilterProxyModel *model)
{
- Models::displayFilterDialog(AccountManager::instance()->accountNames(), model, static_cast<int>(ProtocolItemModel::ProtocolItemRole::Account), Qt::DisplayRole, parent);
+ auto menu = Models::displayFilterDialog(AccountManager::instance()->accountNames(), model, static_cast<int>(ProtocolItemModel::ProtocolItemRole::Account), Qt::DisplayRole, header);
+ menu->addSeparator();
+ menu->addAction(tr("Reset column sizes"), header, [header] { header->resizeColumns(true); });
}
void ProtocolWidget::showContextMenu(QWidget *parent, ProtocolItemModel *model, const QModelIndexList &items)
diff --git a/src/gui/protocolwidget.h b/src/gui/protocolwidget.h
index fff6c0d3b..3c6a563f9 100644
--- a/src/gui/protocolwidget.h
+++ b/src/gui/protocolwidget.h
@@ -30,6 +30,7 @@ class QPushButton;
class QSortFilterProxyModel;
namespace OCC {
+class ExpandingHeaderView;
namespace Ui {
class ProtocolWidget;
@@ -47,7 +48,7 @@ public:
explicit ProtocolWidget(QWidget *parent = nullptr);
~ProtocolWidget() override;
- static void showHeaderContextMenu(QWidget *parent, QSortFilterProxyModel *model);
+ static void showHeaderContextMenu(ExpandingHeaderView *header, QSortFilterProxyModel *model);
static void showContextMenu(QWidget *parent, ProtocolItemModel *model, const QModelIndexList &items);