You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
9.4 KiB
360 lines
9.4 KiB
/* |
|
Copyright (c) 2009 Stephen Kelly <steveire@gmail.com> |
|
|
|
This library is free software; you can redistribute it and/or modify it |
|
under the terms of the GNU Library General Public License as published by |
|
the Free Software Foundation; either version 2 of the License, or (at your |
|
option) any later version. |
|
|
|
This library is distributed in the hope that it will be useful, but WITHOUT |
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
|
License for more details. |
|
|
|
You should have received a copy of the GNU Library General Public License |
|
along with this library; see the file COPYING.LIB. If not, write to the |
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
02110-1301, USA. |
|
*/ |
|
|
|
#ifndef DYNAMICTREEMODEL_H |
|
#define DYNAMICTREEMODEL_H |
|
|
|
#include <QAbstractItemModel> |
|
|
|
#include <QHash> |
|
#include <QList> |
|
|
|
#include <QDebug> |
|
|
|
#include "indexfinder.h" |
|
|
|
#include "proxymodeltestsuite_export.h" |
|
|
|
template<typename T> class QList; |
|
|
|
class ModelMoveCommand; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT DynamicTreeModel : public QAbstractItemModel |
|
{ |
|
Q_OBJECT |
|
public: |
|
enum Roles |
|
{ |
|
DynamicTreeModelId = Qt::UserRole, |
|
|
|
LastRole |
|
}; |
|
|
|
explicit DynamicTreeModel(QObject *parent = 0); |
|
|
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; |
|
QModelIndex parent(const QModelIndex &index) const; |
|
int rowCount(const QModelIndex &index = QModelIndex()) const; |
|
int columnCount(const QModelIndex &index = QModelIndex()) const; |
|
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
|
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); |
|
|
|
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); |
|
Qt::ItemFlags flags(const QModelIndex& index) const; |
|
Qt::DropActions supportedDropActions() const; |
|
QStringList mimeTypes() const; |
|
QMimeData* mimeData(const QModelIndexList& indexes) const; |
|
QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits = 1, |
|
Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const; |
|
|
|
void clear(); |
|
QList<int> indexToPath(const QModelIndex &idx) const; |
|
ModelMoveCommand* getMoveCommand(const QList<int> &srcPath, int startRow, int endRow); |
|
|
|
protected Q_SLOTS: |
|
|
|
/** |
|
Finds the parent id of the string with id @p searchId. |
|
|
|
Returns -1 if not found. |
|
*/ |
|
qint64 findParentId(qint64 searchId) const; |
|
|
|
private: |
|
QHash<qint64, QString> m_items; |
|
QHash<qint64, QList<QList<qint64> > > m_childItems; |
|
qint64 nextId; |
|
qint64 newId() { return nextId++; }; |
|
|
|
QModelIndex m_nextParentIndex; |
|
int m_nextRow; |
|
|
|
int m_depth; |
|
int maxDepth; |
|
|
|
friend class ModelInsertCommand; |
|
friend class ModelInsertWithDescendantsCommand; |
|
friend class ModelRemoveCommand; |
|
friend class ModelDataChangeCommand; |
|
friend class ModelMoveCommand; |
|
friend class ModelMoveLayoutChangeCommand; |
|
friend class ModelResetCommand; |
|
friend class ModelLayoutChangeCommand; |
|
// friend class ModelSortIndexCommand; |
|
friend class ModelSortIndexLayoutChangeCommand; |
|
friend class ModelInsertAndRemoveQueuedCommand; |
|
|
|
}; |
|
|
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelChangeCommand : public QObject |
|
{ |
|
Q_OBJECT |
|
public: |
|
|
|
ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 ); |
|
|
|
virtual ~ModelChangeCommand() {} |
|
|
|
void setAncestorRowNumbers(const QList<int> &rowNumbers) { m_rowNumbers = rowNumbers; } |
|
QList<int> srcAncestors() const { return m_rowNumbers; } |
|
|
|
QModelIndex findIndex(const QList<int> &rows) const; |
|
|
|
void setStartRow(int row) { m_startRow = row; } |
|
|
|
void setEndRow(int row) { m_endRow = row; } |
|
|
|
void setNumCols(int cols) { m_numCols = cols; } |
|
|
|
virtual void doCommand() = 0; |
|
|
|
QModelIndex parentIndex() const { return findIndex(m_rowNumbers); } |
|
int startRow() const { return m_startRow; } |
|
int endRow() const { return m_endRow; } |
|
|
|
protected: |
|
DynamicTreeModel* m_model; |
|
QList<int> m_rowNumbers; |
|
int m_startRow; |
|
int m_endRow; |
|
int m_numCols; |
|
|
|
}; |
|
|
|
typedef QList<ModelChangeCommand*> ModelChangeCommandList; |
|
|
|
/** |
|
@brief Inserts a sub tree into the dynamictreemodel. |
|
|
|
As an alternative to setStartRow and setEndRow, the interpret command may be used. |
|
|
|
The interpret command is used to set the structure of the subtree. |
|
|
|
For example, |
|
@code |
|
cmd = new ModelInsertCommand(m_model, this); |
|
cmd->interpret( |
|
"- A" |
|
"- B" |
|
"- - C" |
|
"- D" |
|
); |
|
@endcode |
|
|
|
Will emit an insert for 3 rows, the second of which will have a child row. The interpretation |
|
string may be complex as long as it is valid. The text at the end of each row does not need to be consistent. |
|
There is a define DUMPTREE to make this command print the tree it inserts for better readability. |
|
|
|
@code |
|
cmd->interpret( |
|
"- A" |
|
"- - B" |
|
"- - C" |
|
"- - - C" |
|
"- - C" |
|
"- - - C" |
|
"- - - C" |
|
"- - C" |
|
"- D" |
|
"- - E" |
|
"- - F" |
|
); |
|
@endcode |
|
|
|
The string is valid if (depth of row (N + 1)) <= ( (depth of row N) + 1). For example, the following is invalid |
|
because the depth of B is 2 and the depth of A is 0. |
|
|
|
@code |
|
cmd->interpret( |
|
"- A" |
|
"- - - B" |
|
"- - C" |
|
@endcode |
|
*/ |
|
class PROXYMODELTESTSUITE_EXPORT ModelInsertCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
|
|
struct Token |
|
{ |
|
enum Type { Branch, Leaf }; |
|
Type type; |
|
QString content; |
|
}; |
|
|
|
public: |
|
|
|
explicit ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 ); |
|
virtual ~ModelInsertCommand() {} |
|
|
|
void interpret(const QString &treeString); |
|
|
|
virtual void doCommand(); |
|
void doInsertTree(const QModelIndex &parent); |
|
|
|
protected: |
|
QList<Token> tokenize(const QString &treeString) const; |
|
|
|
QList<int> getDepths(const QString &treeString) const; |
|
|
|
QString m_treeString; |
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelInsertAndRemoveQueuedCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
|
|
explicit ModelInsertAndRemoveQueuedCommand(DynamicTreeModel *model, QObject *parent = 0 ); |
|
virtual ~ModelInsertAndRemoveQueuedCommand() {} |
|
|
|
virtual void doCommand(); |
|
|
|
Q_SIGNALS: |
|
void beginInsertRows(const QModelIndex &parent, int start, int end); |
|
void endInsertRows(); |
|
void beginRemoveRows(const QModelIndex &parent, int start, int end); |
|
void endRemoveRows(); |
|
|
|
protected Q_SLOTS: |
|
void queuedBeginInsertRows(const QModelIndex &parent, int start, int end); |
|
void queuedEndInsertRows(); |
|
void queuedBeginRemoveRows(const QModelIndex &parent, int start, int end); |
|
void queuedEndRemoveRows(); |
|
|
|
protected: |
|
void purgeItem(qint64 parent); |
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelRemoveCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
explicit ModelRemoveCommand(DynamicTreeModel *model, QObject *parent = 0 ); |
|
virtual ~ModelRemoveCommand() {} |
|
|
|
virtual void doCommand(); |
|
|
|
void purgeItem(qint64 parent); |
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelDataChangeCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
explicit ModelDataChangeCommand(DynamicTreeModel *model, QObject *parent = 0); |
|
|
|
virtual ~ModelDataChangeCommand() {} |
|
|
|
virtual void doCommand(); |
|
|
|
void setStartColumn(int column) { m_startColumn = column; } |
|
|
|
protected: |
|
int m_startColumn; |
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelMoveCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
explicit ModelMoveCommand(DynamicTreeModel *model, QObject *parent); |
|
|
|
virtual ~ModelMoveCommand() {} |
|
|
|
virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); |
|
|
|
virtual void doCommand(); |
|
|
|
virtual void emitPostSignal(); |
|
|
|
void setDestAncestors( const QList<int> &rows ) { m_destRowNumbers = rows; } |
|
QList<int> destAncestors() const { return m_destRowNumbers; } |
|
|
|
void setDestRow(int row) { m_destRow = row; } |
|
|
|
protected: |
|
QList<int> m_destRowNumbers; |
|
int m_destRow; |
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelMoveLayoutChangeCommand : public ModelMoveCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
explicit ModelMoveLayoutChangeCommand(DynamicTreeModel* model, QObject* parent); |
|
virtual ~ModelMoveLayoutChangeCommand(); |
|
|
|
virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); |
|
|
|
virtual void emitPostSignal(); |
|
|
|
void setEndOfMoveSourceAncestors(const QList<int> &rows ) { m_endOfMoveSourceAncestors = rows; } |
|
void setEndOfMoveDestAncestors(const QList<int> &rows ) { m_endOfMoveDestAncestors = rows; } |
|
|
|
private: |
|
QModelIndexList m_beforeMoveList; |
|
QList<int> m_endOfMoveSourceAncestors; |
|
QList<int> m_endOfMoveDestAncestors; |
|
|
|
}; |
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelResetCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0); |
|
virtual ~ModelResetCommand(); |
|
|
|
void setInitialTree(const QString &treeString); |
|
|
|
/* reimp */ void doCommand(); |
|
private: |
|
QString m_treeString; |
|
}; |
|
|
|
|
|
class PROXYMODELTESTSUITE_EXPORT ModelLayoutChangeCommand : public ModelChangeCommand |
|
{ |
|
Q_OBJECT |
|
public: |
|
ModelLayoutChangeCommand(DynamicTreeModel* model, QObject* parent = 0); |
|
virtual ~ModelLayoutChangeCommand(); |
|
|
|
struct PersistentChange |
|
{ |
|
QList<int> oldPath; |
|
QList<int> newPath; |
|
}; |
|
|
|
void setPersistentChanges(const QList<PersistentChange> &changes); |
|
|
|
void setInitialTree(const QString &treeString); |
|
|
|
/* reimp */ void doCommand(); |
|
private: |
|
QString m_treeString; |
|
QList<PersistentChange> m_changes; |
|
}; |
|
|
|
|
|
#endif
|
|
|