Eventviews

todoviewview.cpp
1/*
2 This file is part of KOrganizer.
3
4 SPDX-FileCopyrightText: 2008 Thomas Thrainer <tom_t@gmx.at>
5
6 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
7*/
8
9#include "todoviewview.h"
10
11#include <KDatePickerPopup>
12#include <KLocalizedString>
13#include <QMenu>
14
15#include <QAction>
16#include <QContextMenuEvent>
17#include <QEvent>
18#include <QHeaderView>
19#include <QMouseEvent>
20#include <chrono>
21
22using namespace std::chrono_literals;
23
24TodoViewView::TodoViewView(QWidget *parent)
25 : QTreeView(parent)
26{
27 header()->installEventFilter(this);
28 setAlternatingRowColors(true);
29 connect(&mExpandTimer, &QTimer::timeout, this, &TodoViewView::expandParent);
30 mExpandTimer.setInterval(1s);
31 header()->setStretchLastSection(false);
33}
34
35bool TodoViewView::isEditing(const QModelIndex &index) const
36{
37 return state() & QAbstractItemView::EditingState && currentIndex() == index;
38}
39
40bool TodoViewView::eventFilter(QObject *watched, QEvent *event)
41{
42 Q_UNUSED(watched)
43 if (event->type() == QEvent::ContextMenu) {
44 auto e = static_cast<QContextMenuEvent *>(event);
45
46 if (!mHeaderPopup) {
47 mHeaderPopup = new QMenu(this);
48 mHeaderPopup->setTitle(i18n("View Columns"));
49 // First entry can't be disabled
50 for (int i = 1; i < model()->columnCount(); ++i) {
51 QAction *tmp = mHeaderPopup->addAction(model()->headerData(i, Qt::Horizontal).toString());
52 tmp->setData(QVariant(i));
53 tmp->setCheckable(true);
54 mColumnActions << tmp;
55 }
56
57 connect(mHeaderPopup, &QMenu::triggered, this, &TodoViewView::toggleColumnHidden);
58 }
59
60 for (QAction *action : std::as_const(mColumnActions)) {
61 int column = action->data().toInt();
62 action->setChecked(!isColumnHidden(column));
63 }
64
65 mHeaderPopup->popup(mapToGlobal(e->pos()));
66 return true;
67 }
68
69 return false;
70}
71
72KDatePickerPopup *TodoViewView::startPopupMenu()
73{
74 return mStartPopupMenu;
75}
76
77void TodoViewView::toggleColumnHidden(QAction *action)
78{
79 if (action->isChecked()) {
80 showColumn(action->data().toInt());
81 } else {
82 hideColumn(action->data().toInt());
83 }
84
85 Q_EMIT visibleColumnCountChanged();
86}
87
88QModelIndex TodoViewView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
89{
90 QModelIndex current = currentIndex();
91 if (!current.isValid()) {
92 return QTreeView::moveCursor(cursorAction, modifiers);
93 }
94
95 switch (cursorAction) {
96 case MoveNext: {
97 // try to find an editable item right of the current one
98 QModelIndex tmp = getNextEditableIndex(current.sibling(current.row(), current.column() + 1), 1);
99 if (tmp.isValid()) {
100 return tmp;
101 }
102
103 // check if the current item is expanded, and find an editable item
104 // just below it if so
105 current = current.sibling(current.row(), 0);
106 if (isExpanded(current)) {
107 tmp = getNextEditableIndex(model()->index(0, 0, current), 1);
108 if (tmp.isValid()) {
109 return tmp;
110 }
111 }
112
113 // find an editable item in the item below the currently edited one
114 tmp = getNextEditableIndex(current.sibling(current.row() + 1, 0), 1);
115 if (tmp.isValid()) {
116 return tmp;
117 }
118
119 // step back a hierarchy level, and search for an editable item there
120 while (current.isValid()) {
121 current = current.parent();
122 tmp = getNextEditableIndex(current.sibling(current.row() + 1, 0), 1);
123 if (tmp.isValid()) {
124 return tmp;
125 }
126 }
127 return {};
128 }
129 case MovePrevious: {
130 // try to find an editable item left of the current one
131 QModelIndex tmp = getNextEditableIndex(current.sibling(current.row(), current.column() - 1), -1);
132 if (tmp.isValid()) {
133 return tmp;
134 }
135
136 int lastCol = model()->columnCount(QModelIndex()) - 1;
137
138 // search on top of the item, also include expanded items
139 tmp = current.sibling(current.row() - 1, 0);
140 while (tmp.isValid() && isExpanded(tmp)) {
141 tmp = model()->index(model()->rowCount(tmp) - 1, 0, tmp);
142 }
143 if (tmp.isValid()) {
144 tmp = getNextEditableIndex(tmp.sibling(tmp.row(), lastCol), -1);
145 if (tmp.isValid()) {
146 return tmp;
147 }
148 }
149
150 // step back a hierarchy level, and search for an editable item there
151 current = current.parent();
152 return getNextEditableIndex(current.sibling(current.row(), lastCol), -1);
153 }
154 default:
155 break;
156 }
157
158 return QTreeView::moveCursor(cursorAction, modifiers);
159}
160
161QModelIndex TodoViewView::getNextEditableIndex(const QModelIndex &cur, int inc)
162{
163 if (!cur.isValid()) {
164 return {};
165 }
166
167 QModelIndex tmp;
168 int colCount = model()->columnCount(QModelIndex());
169 int end = inc == 1 ? colCount : -1;
170
171 for (int c = cur.column(); c != end; c += inc) {
172 tmp = cur.sibling(cur.row(), c);
173 if ((tmp.flags() & Qt::ItemIsEditable) && !isIndexHidden(tmp)) {
174 return tmp;
175 }
176 }
177 return {};
178}
179
180void TodoViewView::mouseReleaseEvent(QMouseEvent *event)
181{
182 mExpandTimer.stop();
183
184 if (mIgnoreNextMouseRelease) {
185 mIgnoreNextMouseRelease = false;
186 return;
187 }
188
189 if (!indexAt(event->pos()).isValid()) {
191 event->accept();
192 } else {
194 }
195}
196
197void TodoViewView::mouseMoveEvent(QMouseEvent *event)
198{
199 mExpandTimer.stop();
201}
202
203void TodoViewView::mousePressEvent(QMouseEvent *event)
204{
205 mExpandTimer.stop();
206 QModelIndex index = indexAt(event->pos());
207 if (index.isValid() && event->button() == Qt::LeftButton) {
208 mExpandTimer.start();
209 }
210
212}
213
214void TodoViewView::expandParent()
215{
217 if (index.isValid()) {
218 mIgnoreNextMouseRelease = true;
220 QTreeView::keyPressEvent(&keyEvent);
221 }
222}
223
224#include "moc_todoviewview.cpp"
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
const QList< QKeySequence > & end()
virtual int columnCount(const QModelIndex &parent) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
QModelIndex currentIndex() const const
virtual bool event(QEvent *event) override
QAbstractItemModel * model() const const
State state() const const
QWidget * viewport() const const
void setCheckable(bool)
bool isChecked() const const
QVariant data() const const
void setData(const QVariant &data)
QPoint pos()
QDate currentDate()
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
void popup(const QPoint &p, QAction *atAction)
void setTitle(const QString &title)
void triggered(QAction *action)
int column() const const
Qt::ItemFlags flags() const const
bool isValid() const const
QModelIndex parent() const const
int row() const const
QModelIndex sibling(int row, int column) const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void installEventFilter(QObject *filterObj)
ItemIsEditable
Key_Asterisk
typedef KeyboardModifiers
LeftButton
Horizontal
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void start()
void stop()
void timeout()
void hideColumn(int column)
virtual QModelIndex indexAt(const QPoint &point) const const override
bool isColumnHidden(int column) const const
bool isExpanded(const QModelIndex &index) const const
virtual bool isIndexHidden(const QModelIndex &index) const const override
virtual void keyPressEvent(QKeyEvent *event) override
virtual void mouseMoveEvent(QMouseEvent *event) override
virtual void mousePressEvent(QMouseEvent *event) override
virtual void mouseReleaseEvent(QMouseEvent *event) override
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
void showColumn(int column)
int toInt(bool *ok) const const
QPoint mapFromGlobal(const QPoint &pos) const const
QPoint mapToGlobal(const QPoint &pos) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:57:56 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.