src/gui/util/qundoview.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 class QUndoModel : public QAbstractItemModel
       
    56 {
       
    57     Q_OBJECT
       
    58 public:
       
    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 
       
    79 public slots:
       
    80     void setStack(QUndoStack *stack);
       
    81 
       
    82 private slots:
       
    83     void stackChanged();
       
    84     void stackDestroyed(QObject *obj);
       
    85     void setStackCurrentIndex(const QModelIndex &index);
       
    86 
       
    87 private:
       
    88     QUndoStack *m_stack;
       
    89     QItemSelectionModel *m_sel_model;
       
    90     QString m_emty_label;
       
    91     QIcon m_clean_icon;
       
    92 };
       
    93 
       
    94 QUndoModel::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 
       
   104 QItemSelectionModel *QUndoModel::selectionModel() const
       
   105 {
       
   106     return m_sel_model;
       
   107 }
       
   108 
       
   109 QUndoStack *QUndoModel::stack() const
       
   110 {
       
   111     return m_stack;
       
   112 }
       
   113 
       
   114 void 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 
       
   134 void QUndoModel::stackDestroyed(QObject *obj)
       
   135 {
       
   136     if (obj != m_stack)
       
   137         return;
       
   138     m_stack = 0;
       
   139 
       
   140     stackChanged();
       
   141 }
       
   142 
       
   143 void QUndoModel::stackChanged()
       
   144 {
       
   145     reset();
       
   146     m_sel_model->setCurrentIndex(selectedIndex(), QItemSelectionModel::ClearAndSelect);
       
   147 }
       
   148 
       
   149 void 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 
       
   163 QModelIndex QUndoModel::selectedIndex() const
       
   164 {
       
   165     return m_stack == 0 ? QModelIndex() : createIndex(m_stack->index(), 0);
       
   166 }
       
   167 
       
   168 QModelIndex 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 
       
   185 QModelIndex QUndoModel::parent(const QModelIndex&) const
       
   186 {
       
   187     return QModelIndex();
       
   188 }
       
   189 
       
   190 int 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 
       
   201 int QUndoModel::columnCount(const QModelIndex&) const
       
   202 {
       
   203     return 1;
       
   204 }
       
   205 
       
   206 QVariant 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 
       
   230 QString QUndoModel::emptyLabel() const
       
   231 {
       
   232     return m_emty_label;
       
   233 }
       
   234 
       
   235 void QUndoModel::setEmptyLabel(const QString &label)
       
   236 {
       
   237     m_emty_label = label;
       
   238     stackChanged();
       
   239 }
       
   240 
       
   241 void QUndoModel::setCleanIcon(const QIcon &icon)
       
   242 {
       
   243     m_clean_icon = icon;
       
   244     stackChanged();
       
   245 }
       
   246 
       
   247 QIcon 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 
       
   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 
       
   271 class QUndoViewPrivate : public QListViewPrivate
       
   272 {
       
   273     Q_DECLARE_PUBLIC(QUndoView)
       
   274 public:
       
   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 
       
   289 void 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 
       
   302 QUndoView::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 
       
   313 QUndoView::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 
       
   329 QUndoView::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 
       
   343 QUndoView::~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 
       
   354 QUndoStack *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 
       
   369 void 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 
       
   389 void 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 
       
   420 QUndoGroup *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 
       
   437 void QUndoView::setEmptyLabel(const QString &label)
       
   438 {
       
   439     Q_D(QUndoView);
       
   440     d->model->setEmptyLabel(label);
       
   441 }
       
   442 
       
   443 QString 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 
       
   459 void QUndoView::setCleanIcon(const QIcon &icon)
       
   460 {
       
   461     Q_D(const QUndoView);
       
   462     d->model->setCleanIcon(icon);
       
   463 
       
   464 }
       
   465 
       
   466 QIcon QUndoView::cleanIcon() const
       
   467 {
       
   468     Q_D(const QUndoView);
       
   469     return d->model->cleanIcon();
       
   470 }
       
   471 
       
   472 QT_END_NAMESPACE
       
   473 
       
   474 #include "qundoview.moc"
       
   475 
       
   476 #endif // QT_NO_UNDOVIEW