source: trunk/src/gui/util/qundoview.cpp@ 350

Last change on this file since 350 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qundostack.h"
43#include "qundoview.h"
44
45#ifndef QT_NO_UNDOVIEW
46
47#include "qundogroup.h"
48#include <QtCore/qabstractitemmodel.h>
49#include <QtCore/qpointer.h>
50#include <QtGui/qicon.h>
51#include <private/qlistview_p.h>
52
53QT_BEGIN_NAMESPACE
54
55class QUndoModel : public QAbstractItemModel
56{
57 Q_OBJECT
58public:
59 QUndoModel(QObject *parent = 0);
60
61 QUndoStack *stack() const;
62
63 virtual QModelIndex index(int row, int column,
64 const QModelIndex &parent = QModelIndex()) const;
65 virtual QModelIndex parent(const QModelIndex &child) const;
66 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
67 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
68 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
69
70 QModelIndex selectedIndex() const;
71 QItemSelectionModel *selectionModel() const;
72
73 QString emptyLabel() const;
74 void setEmptyLabel(const QString &label);
75
76 void setCleanIcon(const QIcon &icon);
77 QIcon cleanIcon() const;
78
79public slots:
80 void setStack(QUndoStack *stack);
81
82private slots:
83 void stackChanged();
84 void stackDestroyed(QObject *obj);
85 void setStackCurrentIndex(const QModelIndex &index);
86
87private:
88 QUndoStack *m_stack;
89 QItemSelectionModel *m_sel_model;
90 QString m_emty_label;
91 QIcon m_clean_icon;
92};
93
94QUndoModel::QUndoModel(QObject *parent)
95 : QAbstractItemModel(parent)
96{
97 m_stack = 0;
98 m_sel_model = new QItemSelectionModel(this, this);
99 connect(m_sel_model, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
100 this, SLOT(setStackCurrentIndex(QModelIndex)));
101 m_emty_label = tr("<empty>");
102}
103
104QItemSelectionModel *QUndoModel::selectionModel() const
105{
106 return m_sel_model;
107}
108
109QUndoStack *QUndoModel::stack() const
110{
111 return m_stack;
112}
113
114void QUndoModel::setStack(QUndoStack *stack)
115{
116 if (m_stack == stack)
117 return;
118
119 if (m_stack != 0) {
120 disconnect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged()));
121 disconnect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged()));
122 disconnect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*)));
123 }
124 m_stack = stack;
125 if (m_stack != 0) {
126 connect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged()));
127 connect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged()));
128 connect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*)));
129 }
130
131 stackChanged();
132}
133
134void QUndoModel::stackDestroyed(QObject *obj)
135{
136 if (obj != m_stack)
137 return;
138 m_stack = 0;
139
140 stackChanged();
141}
142
143void QUndoModel::stackChanged()
144{
145 reset();
146 m_sel_model->setCurrentIndex(selectedIndex(), QItemSelectionModel::ClearAndSelect);
147}
148
149void QUndoModel::setStackCurrentIndex(const QModelIndex &index)
150{
151 if (m_stack == 0)
152 return;
153
154 if (index == selectedIndex())
155 return;
156
157 if (index.column() != 0)
158 return;
159
160 m_stack->setIndex(index.row());
161}
162
163QModelIndex QUndoModel::selectedIndex() const
164{
165 return m_stack == 0 ? QModelIndex() : createIndex(m_stack->index(), 0);
166}
167
168QModelIndex QUndoModel::index(int row, int column, const QModelIndex &parent) const
169{
170 if (m_stack == 0)
171 return QModelIndex();
172
173 if (parent.isValid())
174 return QModelIndex();
175
176 if (column != 0)
177 return QModelIndex();
178
179 if (row < 0 || row > m_stack->count())
180 return QModelIndex();
181
182 return createIndex(row, column);
183}
184
185QModelIndex QUndoModel::parent(const QModelIndex&) const
186{
187 return QModelIndex();
188}
189
190int QUndoModel::rowCount(const QModelIndex &parent) const
191{
192 if (m_stack == 0)
193 return 0;
194
195 if (parent.isValid())
196 return 0;
197
198 return m_stack->count() + 1;
199}
200
201int QUndoModel::columnCount(const QModelIndex&) const
202{
203 return 1;
204}
205
206QVariant QUndoModel::data(const QModelIndex &index, int role) const
207{
208 if (m_stack == 0)
209 return QVariant();
210
211 if (index.column() != 0)
212 return QVariant();
213
214 if (index.row() < 0 || index.row() > m_stack->count())
215 return QVariant();
216
217 if (role == Qt::DisplayRole) {
218 if (index.row() == 0)
219 return m_emty_label;
220 return m_stack->text(index.row() - 1);
221 } else if (role == Qt::DecorationRole) {
222 if (index.row() == m_stack->cleanIndex() && !m_clean_icon.isNull())
223 return m_clean_icon;
224 return QVariant();
225 }
226
227 return QVariant();
228}
229
230QString QUndoModel::emptyLabel() const
231{
232 return m_emty_label;
233}
234
235void QUndoModel::setEmptyLabel(const QString &label)
236{
237 m_emty_label = label;
238 stackChanged();
239}
240
241void QUndoModel::setCleanIcon(const QIcon &icon)
242{
243 m_clean_icon = icon;
244 stackChanged();
245}
246
247QIcon QUndoModel::cleanIcon() const
248{
249 return m_clean_icon;
250}
251
252/*!
253 \class QUndoView
254 \brief The QUndoView class displays the contents of a QUndoStack.
255 \since 4.2
256 \ingroup misc
257 \ingroup advanced
258
259 QUndoView is a QListView which displays the list of commands pushed on an undo stack.
260 The most recently executed command is always selected. Selecting a different command
261 results in a call to QUndoStack::setIndex(), rolling the state of the document
262 backwards or forward to the new command.
263
264 The stack can be set explicitly with setStack(). Alternatively, a QUndoGroup object can
265 be set with setGroup(). The view will then update itself automatically whenever the
266 active stack of the group changes.
267
268 \image qundoview.png
269*/
270
271class QUndoViewPrivate : public QListViewPrivate
272{
273 Q_DECLARE_PUBLIC(QUndoView)
274public:
275 QUndoViewPrivate() :
276#ifndef QT_NO_UNDOGROUP
277 group(0),
278#endif
279 model(0) {}
280
281#ifndef QT_NO_UNDOGROUP
282 QPointer<QUndoGroup> group;
283#endif
284 QUndoModel *model;
285
286 void init();
287};
288
289void QUndoViewPrivate::init()
290{
291 Q_Q(QUndoView);
292
293 model = new QUndoModel(q);
294 q->setModel(model);
295 q->setSelectionModel(model->selectionModel());
296}
297
298/*!
299 Constructs a new view with parent \a parent.
300*/
301
302QUndoView::QUndoView(QWidget *parent)
303 : QListView(*new QUndoViewPrivate(), parent)
304{
305 Q_D(QUndoView);
306 d->init();
307}
308
309/*!
310 Constructs a new view with parent \a parent and sets the observed stack to \a stack.
311*/
312
313QUndoView::QUndoView(QUndoStack *stack, QWidget *parent)
314 : QListView(*new QUndoViewPrivate(), parent)
315{
316 Q_D(QUndoView);
317 d->init();
318 setStack(stack);
319}
320
321#ifndef QT_NO_UNDOGROUP
322
323/*!
324 Constructs a new view with parent \a parent and sets the observed group to \a group.
325
326 The view will update itself autmiatically whenever the active stack of the group changes.
327*/
328
329QUndoView::QUndoView(QUndoGroup *group, QWidget *parent)
330 : QListView(*new QUndoViewPrivate(), parent)
331{
332 Q_D(QUndoView);
333 d->init();
334 setGroup(group);
335}
336
337#endif // QT_NO_UNDOGROUP
338
339/*!
340 Destroys this view.
341*/
342
343QUndoView::~QUndoView()
344{
345}
346
347/*!
348 Returns the stack currently displayed by this view. If the view is looking at a
349 QUndoGroup, this the group's active stack.
350
351 \sa setStack() setGroup()
352*/
353
354QUndoStack *QUndoView::stack() const
355{
356 Q_D(const QUndoView);
357 return d->model->stack();
358}
359
360/*!
361 Sets the stack displayed by this view to \a stack. If \a stack is 0, the view
362 will be empty.
363
364 If the view was previously looking at a QUndoGroup, the group is set to 0.
365
366 \sa stack() setGroup()
367*/
368
369void QUndoView::setStack(QUndoStack *stack)
370{
371 Q_D(QUndoView);
372#ifndef QT_NO_UNDOGROUP
373 setGroup(0);
374#endif
375 d->model->setStack(stack);
376}
377
378#ifndef QT_NO_UNDOGROUP
379
380/*!
381 Sets the group displayed by this view to \a group. If \a group is 0, the view will
382 be empty.
383
384 The view will update itself autmiatically whenever the active stack of the group changes.
385
386 \sa group() setStack()
387*/
388
389void QUndoView::setGroup(QUndoGroup *group)
390{
391 Q_D(QUndoView);
392
393 if (d->group == group)
394 return;
395
396 if (d->group != 0) {
397 disconnect(d->group, SIGNAL(activeStackChanged(QUndoStack*)),
398 d->model, SLOT(setStack(QUndoStack*)));
399 }
400
401 d->group = group;
402
403 if (d->group != 0) {
404 connect(d->group, SIGNAL(activeStackChanged(QUndoStack*)),
405 d->model, SLOT(setStack(QUndoStack*)));
406 d->model->setStack(d->group->activeStack());
407 } else {
408 d->model->setStack(0);
409 }
410}
411
412/*!
413 Returns the group displayed by this view.
414
415 If the view is not looking at group, this function returns 0.
416
417 \sa setGroup() setStack()
418*/
419
420QUndoGroup *QUndoView::group() const
421{
422 Q_D(const QUndoView);
423 return d->group;
424}
425
426#endif // QT_NO_UNDOGROUP
427
428/*!
429 \property QUndoView::emptyLabel
430 \brief the label used for the empty state.
431
432 The empty label is the topmost element in the list of commands, which represents
433 the state of the document before any commands were pushed on the stack. The default
434 is the string "<empty>".
435*/
436
437void QUndoView::setEmptyLabel(const QString &label)
438{
439 Q_D(QUndoView);
440 d->model->setEmptyLabel(label);
441}
442
443QString QUndoView::emptyLabel() const
444{
445 Q_D(const QUndoView);
446 return d->model->emptyLabel();
447}
448
449/*!
450 \property QUndoView::cleanIcon
451 \brief the icon used to represent the clean state.
452
453 A stack may have a clean state set with QUndoStack::setClean(). This is usually
454 the state of the document at the point it was saved. QUndoView can display an
455 icon in the list of commands to show the clean state. If this property is
456 a null icon, no icon is shown. The default value is the null icon.
457*/
458
459void QUndoView::setCleanIcon(const QIcon &icon)
460{
461 Q_D(const QUndoView);
462 d->model->setCleanIcon(icon);
463
464}
465
466QIcon QUndoView::cleanIcon() const
467{
468 Q_D(const QUndoView);
469 return d->model->cleanIcon();
470}
471
472QT_END_NAMESPACE
473
474#include "qundoview.moc"
475
476#endif // QT_NO_UNDOVIEW
Note: See TracBrowser for help on using the repository browser.