11#include <config-libkleo.h>
13#include "treewidget.h"
15#include <models/keylist.h>
17#include <KConfigGroup>
18#include <KLocalizedString>
19#include <KSharedConfig>
22#include <QContextMenuEvent>
23#include <QGuiApplication>
29static const int MAX_AUTOMATIC_COLUMN_WIDTH = 400;
31class TreeWidget::Private
36 QMenu *mHeaderPopup =
nullptr;
39 std::vector<bool> mColumnForcedHidden;
41 Private(TreeWidget *qq)
50 void saveColumnLayout();
53TreeWidget::TreeWidget(
QWidget *parent)
55 , d{new Private(this)}
60TreeWidget::~TreeWidget() =
default;
62void TreeWidget::forceColumnHidden(
int column)
64 if (column > columnCount()) {
68 d->mColumnForcedHidden.resize(columnCount(),
false);
69 d->mColumnForcedHidden[column] =
true;
72void TreeWidget::Private::saveColumnLayout()
74 if (mStateGroupName.isEmpty()) {
78 auto header = q->header();
80 QVariantList columnVisibility;
81 QVariantList columnOrder;
82 QVariantList columnWidths;
83 const int headerCount = header->count();
84 columnVisibility.reserve(headerCount);
85 columnWidths.reserve(headerCount);
86 columnOrder.reserve(headerCount);
87 for (
int i = 0; i < headerCount; ++i) {
88 columnVisibility <<
QVariant(!q->isColumnHidden(i));
89 columnWidths <<
QVariant(header->sectionSize(i));
90 columnOrder <<
QVariant(header->visualIndex(i));
93 config.writeEntry(
"ColumnVisibility", columnVisibility);
94 config.writeEntry(
"ColumnOrder", columnOrder);
95 config.writeEntry(
"ColumnWidths", columnWidths);
97 config.writeEntry(
"SortAscending", (
int)header->sortIndicatorOrder());
98 if (header->isSortIndicatorShown()) {
99 config.writeEntry(
"SortColumn", header->sortIndicatorSection());
101 config.writeEntry(
"SortColumn", -1);
106bool TreeWidget::restoreColumnLayout(
const QString &stateGroupName)
108 if (stateGroupName.
isEmpty()) {
112 d->mColumnForcedHidden.resize(columnCount(),
false);
114 d->mStateGroupName = stateGroupName;
116 auto header = this->header();
118 QVariantList columnVisibility = config.readEntry(
"ColumnVisibility", QVariantList());
119 QVariantList columnOrder = config.readEntry(
"ColumnOrder", QVariantList());
120 QVariantList columnWidths = config.readEntry(
"ColumnWidths", QVariantList());
122 if (!columnVisibility.isEmpty() && !columnOrder.isEmpty() && !columnWidths.isEmpty()) {
123 for (
int i = 0; i < header->count(); ++i) {
124 if (d->mColumnForcedHidden[i] || i >= columnOrder.size() || i >= columnWidths.size() || i >= columnVisibility.size()) {
129 bool visible = columnVisibility[i].toBool();
130 int width = columnWidths[i].toInt();
131 int order = columnOrder[i].toInt();
133 header->resizeSection(i, width ? width : header->defaultSectionSize());
134 header->moveSection(header->visualIndex(i), order);
141 for (
int i = 0; i < header->count(); ++i) {
142 if (d->mColumnForcedHidden[i]) {
149 int sortColumn = config.readEntry(
"SortColumn", isSortingEnabled() ? 0 : -1);
150 if (sortColumn >= 0) {
154 d->saveColumnLayout();
157 d->saveColumnLayout();
160 d->saveColumnLayout();
162 return !columnVisibility.isEmpty() && !columnOrder.isEmpty() && !columnWidths.isEmpty();
170 if (!d->mHeaderPopup) {
171 d->mHeaderPopup =
new QMenu(
this);
172 d->mHeaderPopup->setTitle(
i18nc(
"@title:menu",
"View Columns"));
173 for (
int i = 0; i < model()->columnCount(); ++i) {
177 d->mColumnActions << tmp;
181 const int col = action->data().toInt();
182 if (action->isChecked()) {
184 if (columnWidth(col) == 0 || columnWidth(col) == header()->defaultSectionSize()) {
185 resizeColumnToContents(col);
186 setColumnWidth(col, std::min(columnWidth(col), MAX_AUTOMATIC_COLUMN_WIDTH));
193 Q_EMIT columnEnabled(col);
195 Q_EMIT columnDisabled(col);
197 d->saveColumnLayout();
201 for (
QAction *action : std::as_const(d->mColumnActions)) {
202 const int column = action->data().toInt();
203 action->setChecked(!isColumnHidden(column));
206 auto numVisibleColumns = std::count_if(d->mColumnActions.cbegin(), d->mColumnActions.cend(), [](
const auto &action) {
207 return action->isChecked();
210 for (
auto action : std::as_const(d->mColumnActions)) {
211 action->setEnabled(numVisibleColumns != 1 || !action->isChecked());
214 d->mHeaderPopup->popup(mapToGlobal(e->pos()));
228 auto forceAccessibleFocusEventForCurrentItem = [
this]() {
241void TreeWidget::keyPressEvent(
QKeyEvent *event)
245 if (index.
isValid() && model()) {
246 QVariant variant = model()->
data(index, Kleo::ClipboardRole);
268 if ((cursorAction != MoveLeft) && (cursorAction != MoveRight)) {
272 const auto savedSelectionBehavior = selectionBehavior();
273 setSelectionBehavior(SelectItems);
274 const auto savedItemsExpandable = itemsExpandable();
275 setItemsExpandable(
false);
279 setItemsExpandable(savedItemsExpandable);
280 setSelectionBehavior(savedSelectionBehavior);
285void TreeWidget::resizeToContentsLimited()
287 for (
int i = 0; i < model()->columnCount(); i++) {
288 resizeColumnToContents(i);
289 setColumnWidth(i, std::min(columnWidth(i), MAX_AUTOMATIC_COLUMN_WIDTH));
293#include "moc_treewidget.cpp"
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
QString i18nc(const char *context, const char *text, const TYPE &arg...)
virtual bool eventFilter(QObject *object, QEvent *event) override
virtual void focusInEvent(QFocusEvent *event) override
virtual void keyPressEvent(QKeyEvent *event) override
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)=0
bool isChecked() const const
void setData(const QVariant &data)
void setText(const QString &text, Mode mode)
bool isValid() const const
void installEventFilter(QObject *filterObj)
bool isEmpty() const const
typedef KeyboardModifiers
bool canConvert() const const
bool isValid() const const
QString toString() const const