Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qundoview.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qundoview.h"
6
7#if QT_CONFIG(undogroup)
8#include <QtGui/qundogroup.h>
9#endif
10#include <QtGui/qundostack.h>
11#include <QtCore/qabstractitemmodel.h>
12#include <QtCore/qpointer.h>
13#include <QtGui/qicon.h>
14#include <private/qlistview_p.h>
15
17
19{
21public:
23
24 QUndoStack *stack() const;
25
26 virtual QModelIndex index(int row, int column,
27 const QModelIndex &parent = QModelIndex()) const override;
28 virtual QModelIndex parent(const QModelIndex &child) const override;
29 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
30 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
31 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
32
35
37 void setEmptyLabel(const QString &label);
38
39 void setCleanIcon(const QIcon &icon);
40 QIcon cleanIcon() const;
41
42public slots:
44
45private slots:
46 void stackChanged();
47 void stackDestroyed(QObject *obj);
48 void setStackCurrentIndex(const QModelIndex &index);
49
50private:
51 QUndoStack *m_stack;
52 QItemSelectionModel *m_sel_model;
53 QString m_emty_label;
54 QIcon m_clean_icon;
55};
56
57QUndoModel::QUndoModel(QObject *parent)
58 : QAbstractItemModel(parent)
59{
60 m_stack = nullptr;
61 m_sel_model = new QItemSelectionModel(this, this);
62 connect(m_sel_model, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
63 this, SLOT(setStackCurrentIndex(QModelIndex)));
64 m_emty_label = tr("<empty>");
65}
66
68{
69 return m_sel_model;
70}
71
72QUndoStack *QUndoModel::stack() const
73{
74 return m_stack;
75}
76
77void QUndoModel::setStack(QUndoStack *stack)
78{
79 if (m_stack == stack)
80 return;
81
82 if (m_stack != nullptr) {
83 disconnect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged()));
84 disconnect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged()));
85 disconnect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*)));
86 }
87 m_stack = stack;
88 if (m_stack != nullptr) {
89 connect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged()));
90 connect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged()));
91 connect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*)));
92 }
93
94 stackChanged();
95}
96
97void QUndoModel::stackDestroyed(QObject *obj)
98{
99 if (obj != m_stack)
100 return;
101 m_stack = nullptr;
102
103 stackChanged();
104}
105
106void QUndoModel::stackChanged()
107{
108 beginResetModel();
109 endResetModel();
110 m_sel_model->setCurrentIndex(selectedIndex(), QItemSelectionModel::ClearAndSelect);
111}
112
113void QUndoModel::setStackCurrentIndex(const QModelIndex &index)
114{
115 if (m_stack == nullptr)
116 return;
117
118 if (index == selectedIndex())
119 return;
120
121 if (index.column() != 0)
122 return;
123
124 m_stack->setIndex(index.row());
125}
126
128{
129 return m_stack == nullptr ? QModelIndex() : createIndex(m_stack->index(), 0);
130}
131
132QModelIndex QUndoModel::index(int row, int column, const QModelIndex &parent) const
133{
134 if (m_stack == nullptr)
135 return QModelIndex();
136
137 if (parent.isValid())
138 return QModelIndex();
139
140 if (column != 0)
141 return QModelIndex();
142
143 if (row < 0 || row > m_stack->count())
144 return QModelIndex();
145
146 return createIndex(row, column);
147}
148
149QModelIndex QUndoModel::parent(const QModelIndex&) const
150{
151 return QModelIndex();
152}
153
154int QUndoModel::rowCount(const QModelIndex &parent) const
155{
156 if (m_stack == nullptr)
157 return 0;
158
159 if (parent.isValid())
160 return 0;
161
162 return m_stack->count() + 1;
163}
164
165int QUndoModel::columnCount(const QModelIndex&) const
166{
167 return 1;
168}
169
170QVariant QUndoModel::data(const QModelIndex &index, int role) const
171{
172 if (m_stack == nullptr)
173 return QVariant();
174
175 if (index.column() != 0)
176 return QVariant();
177
178 if (index.row() < 0 || index.row() > m_stack->count())
179 return QVariant();
180
181 if (role == Qt::DisplayRole) {
182 if (index.row() == 0)
183 return m_emty_label;
184 return m_stack->text(index.row() - 1);
185 } else if (role == Qt::DecorationRole) {
186 if (index.row() == m_stack->cleanIndex() && !m_clean_icon.isNull())
187 return m_clean_icon;
188 return QVariant();
189 }
190
191 return QVariant();
192}
193
195{
196 return m_emty_label;
197}
198
199void QUndoModel::setEmptyLabel(const QString &label)
200{
201 m_emty_label = label;
202 stackChanged();
203}
204
205void QUndoModel::setCleanIcon(const QIcon &icon)
206{
207 m_clean_icon = icon;
208 stackChanged();
209}
210
211QIcon QUndoModel::cleanIcon() const
212{
213 return m_clean_icon;
214}
215
216/*!
217 \class QUndoView
218 \brief The QUndoView class displays the contents of a QUndoStack.
219 \since 4.2
220
221 \ingroup advanced
222 \inmodule QtWidgets
223
224 QUndoView is a QListView which displays the list of commands pushed on an undo stack.
225 The most recently executed command is always selected. Selecting a different command
226 results in a call to QUndoStack::setIndex(), rolling the state of the document
227 backwards or forward to the new command.
228
229 The stack can be set explicitly with setStack(). Alternatively, a QUndoGroup object can
230 be set with setGroup(). The view will then update itself automatically whenever the
231 active stack of the group changes.
232
233 \image qundoview.png {Undo stack showing list of commands}
234*/
235
237{
238 Q_DECLARE_PUBLIC(QUndoView)
239public:
241#if QT_CONFIG(undogroup)
242 group(nullptr),
243#endif
244 model(nullptr) {}
245
246#if QT_CONFIG(undogroup)
248#endif
250
251 void init();
252};
253
255{
256 Q_Q(QUndoView);
257
258 model = new QUndoModel(q);
259 q->setModel(model);
260 q->setSelectionModel(model->selectionModel());
261}
262
263/*!
264 Constructs a new view with parent \a parent.
265*/
266
267QUndoView::QUndoView(QWidget *parent)
268 : QListView(*new QUndoViewPrivate(), parent)
269{
270 Q_D(QUndoView);
271 d->init();
272}
273
274/*!
275 Constructs a new view with parent \a parent and sets the observed stack to \a stack.
276*/
277
278QUndoView::QUndoView(QUndoStack *stack, QWidget *parent)
279 : QListView(*new QUndoViewPrivate(), parent)
280{
281 Q_D(QUndoView);
282 d->init();
283 setStack(stack);
284}
285
286#if QT_CONFIG(undogroup)
287
288/*!
289 Constructs a new view with parent \a parent and sets the observed group to \a group.
290
291 The view will update itself autmiatically whenever the active stack of the group changes.
292*/
293
294QUndoView::QUndoView(QUndoGroup *group, QWidget *parent)
295 : QListView(*new QUndoViewPrivate(), parent)
296{
297 Q_D(QUndoView);
298 d->init();
299 setGroup(group);
300}
301
302#endif // QT_CONFIG(undogroup)
303
304/*!
305 Destroys this view.
306*/
307
308QUndoView::~QUndoView()
309{
310}
311
312/*!
313 Returns the stack currently displayed by this view. If the view is looking at a
314 QUndoGroup, this the group's active stack.
315
316 \sa setStack(), setGroup()
317*/
318
319QUndoStack *QUndoView::stack() const
320{
321 Q_D(const QUndoView);
322 return d->model->stack();
323}
324
325/*!
326 Sets the stack displayed by this view to \a stack. If \a stack is \nullptr,
327 the view will be empty.
328
329 If the view was previously looking at a QUndoGroup, the group is set to \nullptr.
330
331 \sa stack(), setGroup()
332*/
333
334void QUndoView::setStack(QUndoStack *stack)
335{
336 Q_D(QUndoView);
337#if QT_CONFIG(undogroup)
338 setGroup(nullptr);
339#endif
340 d->model->setStack(stack);
341}
342
343#if QT_CONFIG(undogroup)
344
345/*!
346 Sets the group displayed by this view to \a group. If \a group is \nullptr,
347 the view will be empty.
348
349 The view will update itself automatically whenever the active stack of the group changes.
350
351 \sa group(), setStack()
352*/
353
354void QUndoView::setGroup(QUndoGroup *group)
355{
356 Q_D(QUndoView);
357
358 if (d->group == group)
359 return;
360
361 if (d->group != nullptr) {
362 disconnect(d->group, SIGNAL(activeStackChanged(QUndoStack*)),
363 d->model, SLOT(setStack(QUndoStack*)));
364 }
365
366 d->group = group;
367
368 if (d->group != nullptr) {
369 connect(d->group, SIGNAL(activeStackChanged(QUndoStack*)),
370 d->model, SLOT(setStack(QUndoStack*)));
371 d->model->setStack(d->group->activeStack());
372 } else {
373 d->model->setStack(nullptr);
374 }
375}
376
377/*!
378 Returns the group displayed by this view.
379
380 If the view is not looking at group, this function returns \nullptr.
381
382 \sa setGroup(), setStack()
383*/
384
385QUndoGroup *QUndoView::group() const
386{
387 Q_D(const QUndoView);
388 return d->group;
389}
390
391#endif // QT_CONFIG(undogroup)
392
393/*!
394 \property QUndoView::emptyLabel
395 \brief the label used for the empty state.
396
397 The empty label is the topmost element in the list of commands, which represents
398 the state of the document before any commands were pushed on the stack. The default
399 is the string "<empty>".
400*/
401
402void QUndoView::setEmptyLabel(const QString &label)
403{
404 Q_D(QUndoView);
405 d->model->setEmptyLabel(label);
406}
407
408QString QUndoView::emptyLabel() const
409{
410 Q_D(const QUndoView);
411 return d->model->emptyLabel();
412}
413
414/*!
415 \property QUndoView::cleanIcon
416 \brief the icon used to represent the clean state.
417
418 A stack may have a clean state set with QUndoStack::setClean(). This is usually
419 the state of the document at the point it was saved. QUndoView can display an
420 icon in the list of commands to show the clean state. If this property is
421 a null icon, no icon is shown. The default value is the null icon.
422*/
423
424void QUndoView::setCleanIcon(const QIcon &icon)
425{
426 Q_D(const QUndoView);
427 d->model->setCleanIcon(icon);
428
429}
430
431QIcon QUndoView::cleanIcon() const
432{
433 Q_D(const QUndoView);
434 return d->model->cleanIcon();
435}
436
437QT_END_NAMESPACE
438
439#include "qundoview.moc"
440#include "moc_qundoview.cpp"
QItemSelectionModel * selectionModel() const
Definition qundoview.cpp:67
void setCleanIcon(const QIcon &icon)
QString emptyLabel() const
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.
void setEmptyLabel(const QString &label)
QUndoStack * stack() const
Definition qundoview.cpp:72
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns for the children of the given parent.
QModelIndex selectedIndex() const
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the item in the model specified by the given row, column and parent index.
QIcon cleanIcon() const
virtual QModelIndex parent(const QModelIndex &child) const override
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows under the given parent.