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.
532 lines
20 KiB
532 lines
20 KiB
/* |
|
* Copyright (C) 2015-2018 Département de l'Instruction Publique (DIP-SEM) |
|
* |
|
* Copyright (C) 2013 Open Education Foundation |
|
* |
|
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour |
|
* l'Education Numérique en Afrique (GIP ENA) |
|
* |
|
* This file is part of OpenBoard. |
|
* |
|
* OpenBoard is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, version 3 of the License, |
|
* with a specific linking exception for the OpenSSL project's |
|
* "OpenSSL" library (or with modified versions of it that use the |
|
* same license as the "OpenSSL" library). |
|
* |
|
* OpenBoard 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 General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with OpenBoard. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
|
|
|
|
#ifndef UBDOCUMENTCONTROLLER_H_ |
|
#define UBDOCUMENTCONTROLLER_H_ |
|
|
|
#include <QtGui> |
|
#include "document/UBDocumentContainer.h" |
|
#include "core/UBApplicationController.h" |
|
#include "core/UBApplication.h" |
|
|
|
|
|
#include "document/UBSortFilterProxyModel.h" |
|
|
|
namespace Ui |
|
{ |
|
class documents; |
|
} |
|
|
|
#include "gui/UBMessageWindow.h" |
|
|
|
class UBGraphicsScene; |
|
class QDialog; |
|
class UBDocumentProxy; |
|
class UBBoardController; |
|
class UBThumbnailsScene; |
|
class UBDocumentGroupTreeItem; |
|
class UBDocumentProxyTreeItem; |
|
class UBMainWindow; |
|
class UBDocumentToolsPalette; |
|
|
|
|
|
class UBDocumentReplaceDialog : public QDialog |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
UBDocumentReplaceDialog(const QString &pIncommingName, const QStringList &pFileList, QWidget *parent = 0, Qt::WindowFlags pFlags = 0); |
|
void setRegexp(const QRegExp pRegExp); |
|
bool validString(const QString &pStr); |
|
void setFileNameAndList(const QString &fileName, const QStringList &pLst); |
|
QString labelTextWithName(const QString &documentName) const; |
|
QString lineEditText() const {return mLineEdit->text();} |
|
|
|
signals: |
|
void createNewFolder(QString str); |
|
void closeDialog(); |
|
|
|
private slots: |
|
void accept(); |
|
void reject(); |
|
|
|
void reactOnTextChanged(const QString &pStr); |
|
|
|
private: |
|
QLineEdit *mLineEdit; |
|
QRegExpValidator *mValidator; |
|
QStringList mFileNameList; |
|
QString mIncommingName; |
|
QPushButton *acceptButton; |
|
const QString acceptText; |
|
const QString replaceText; |
|
const QString cancelText; |
|
QLabel *mLabelText; |
|
}; |
|
|
|
|
|
class UBDocumentTreeNode |
|
{ |
|
public: |
|
friend class UBDocumentTreeModel; |
|
|
|
enum Type { |
|
Catalog = 0 |
|
, Document |
|
}; |
|
|
|
UBDocumentTreeNode(Type pType, const QString &pName, const QString &pDisplayName = QString(), UBDocumentProxy *pProxy = 0); |
|
UBDocumentTreeNode() : mType(Catalog), mParent(0), mProxy(0) {;} |
|
~UBDocumentTreeNode(); |
|
|
|
QList<UBDocumentTreeNode*> children() const {return mChildren;} |
|
UBDocumentTreeNode *parentNode() {return mParent;} |
|
Type nodeType() const {return mType;} |
|
QString nodeName() const {return mName;} |
|
QString displayName() const {return mDisplayName;} |
|
void setNodeName(const QString &str) {mName = str; mDisplayName = str;} |
|
void addChild(UBDocumentTreeNode *pChild); |
|
void insertChild(int pIndex, UBDocumentTreeNode *pChild); |
|
void moveChild(UBDocumentTreeNode *child, int index, UBDocumentTreeNode *newParent); |
|
void removeChild(int index); |
|
UBDocumentProxy *proxyData() const {return mProxy;} |
|
bool isRoot() {return !mParent;} |
|
bool isTopLevel() |
|
{ |
|
if (mParent) |
|
{ |
|
return !mParent->mParent; |
|
} |
|
else return false; |
|
} |
|
UBDocumentTreeNode *clone(); |
|
QString dirPathInHierarchy(); |
|
|
|
//issue 1629 - NNE - 20131105 : Add some utility methods |
|
bool findNode(UBDocumentTreeNode *node); |
|
UBDocumentTreeNode *nextSibling(); |
|
UBDocumentTreeNode *previousSibling(); |
|
//issue 1629 - NNE - 20131105 : END |
|
|
|
private: |
|
Type mType; |
|
QString mName; |
|
QString mDisplayName; |
|
UBDocumentTreeNode *mParent; |
|
QList<UBDocumentTreeNode*> mChildren; |
|
QPointer<UBDocumentProxy> mProxy; |
|
}; |
|
Q_DECLARE_METATYPE(UBDocumentTreeNode*) |
|
|
|
class UBDocumentTreeModel : public QAbstractItemModel { |
|
Q_OBJECT |
|
|
|
public: |
|
enum eAncestors { |
|
aMyDocuments |
|
, aUntitledDocuments |
|
, aModel |
|
, aTrash |
|
}; |
|
|
|
enum eCopyMode { |
|
aReference |
|
, aContentCopy |
|
}; |
|
|
|
enum eAddItemMode { |
|
aEnd = 0 //Add to the end of the children list |
|
, aDetectPosition //Detect the appropriate position (sorting) |
|
}; |
|
|
|
enum eDocumentData{ |
|
DataNode = Qt::UserRole +1, |
|
CreationDate, |
|
UpdateDate |
|
}; |
|
|
|
UBDocumentTreeModel(QObject *parent = 0); |
|
~UBDocumentTreeModel(); |
|
|
|
QModelIndex index(int row, int column, const QModelIndex &parent) const; |
|
QModelIndex parent(const QModelIndex &child) const; |
|
|
|
int rowCount(const QModelIndex &parent) const; |
|
int columnCount(const QModelIndex &parent) const; |
|
QVariant data(const QModelIndex &index, int role) const; |
|
bool setData(const QModelIndex &index, const QVariant &value, int role); |
|
Qt::ItemFlags flags ( const QModelIndex & index ) const; |
|
Qt::DropActions supportedDropActions() const {return Qt::MoveAction | Qt::CopyAction;} |
|
QStringList mimeTypes() const; |
|
QMimeData *mimeData (const QModelIndexList &indexes) const; |
|
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); |
|
bool removeRows(int row, int count, const QModelIndex &parent); |
|
|
|
QModelIndex indexForNode(UBDocumentTreeNode *pNode) const; |
|
QPersistentModelIndex persistentIndexForNode(UBDocumentTreeNode *pNode); |
|
// bool insertRow(int row, const QModelIndex &parent); |
|
|
|
QPersistentModelIndex copyIndexToNewParent(const QModelIndex &source, const QModelIndex &newParent, eCopyMode pMode = aReference); |
|
|
|
//N/C - NNE - 20140411 |
|
void copyIndexToNewParent(const QModelIndexList &list, const QModelIndex &newParent, eCopyMode pMode); |
|
|
|
void moveIndex(const QModelIndex &what, const QModelIndex &destination); |
|
UBDocumentTreeNode *currentNode() const {return mCurrentNode;} //work around for sorting model. |
|
void setCurrentNode(UBDocumentTreeNode *pNode) {mCurrentNode = pNode;} |
|
QModelIndex currentIndex() {return indexForNode(mCurrentNode);} //index representing a current document |
|
QModelIndex indexForProxy(UBDocumentProxy *pSearch) const; |
|
void setCurrentDocument(UBDocumentProxy *pDocument); |
|
void setRootNode(UBDocumentTreeNode *pRoot); |
|
UBDocumentTreeNode *rootNode() const {return mRootNode;} |
|
UBDocumentProxy *proxyForIndex(const QModelIndex &pIndex) const; |
|
QString virtualDirForIndex(const QModelIndex &pIndex) const; |
|
QString virtualPathForIndex(const QModelIndex &pIndex) const; |
|
QStringList nodeNameList(const QModelIndex &pIndex) const; |
|
bool newNodeAllowed(const QModelIndex &pSelectedIndex) const; |
|
QModelIndex goTo(const QString &dir); |
|
bool inTrash(const QModelIndex &index) const; |
|
bool inUntitledDocuments(const QModelIndex &index) const; |
|
bool isCatalog(const QModelIndex &index) const {return nodeFromIndex(index)->nodeType() == UBDocumentTreeNode::Catalog;} |
|
bool isDocument(const QModelIndex &index) const {return nodeFromIndex(index)->nodeType() == UBDocumentTreeNode::Document;} |
|
bool isToplevel(const QModelIndex &index) const {return nodeFromIndex(index) ? nodeFromIndex(index)->isTopLevel() : false;} |
|
bool isConstant(const QModelIndex &index) const {return isToplevel(index) || (index == mUntitledDocuments);} |
|
bool isOkToRename(const QModelIndex &index) const {return flags(index) & Qt::ItemIsEditable;} |
|
UBDocumentProxy *proxyData(const QModelIndex &index) const {return nodeFromIndex(index)->proxyData();} |
|
void addDocument(UBDocumentProxy *pProxyData, const QModelIndex &pParent = QModelIndex()); |
|
void addNewDocument(UBDocumentProxy *pProxyData, const QModelIndex &pParent = QModelIndex()); |
|
QModelIndex addCatalog(const QString &pName, const QModelIndex &pParent); |
|
QList<UBDocumentProxy*> newDocuments() {return mNewDocuments;} |
|
void markDocumentAsNew(UBDocumentProxy *pDoc) {if (indexForProxy(pDoc).isValid()) mNewDocuments << pDoc;} |
|
void setNewName(const QModelIndex &index, const QString &newName); |
|
QString adjustNameForParentIndex(const QString &pName, const QModelIndex &pIndex); |
|
|
|
QPersistentModelIndex myDocumentsIndex() const {return mMyDocuments;} |
|
QPersistentModelIndex trashIndex() const {return mTrash;} |
|
QPersistentModelIndex untitledDocumentsIndex() const {return mMyDocuments;} |
|
UBDocumentTreeNode *nodeFromIndex(const QModelIndex &pIndex) const; |
|
static bool nodeLessThan(const UBDocumentTreeNode *firstIndex, const UBDocumentTreeNode *secondIndex); |
|
void setHighLighted(const QModelIndex &newHighLighted) {mHighLighted = newHighLighted;} |
|
QModelIndex highLighted() {return mHighLighted;} |
|
|
|
//N/C - NNE - 20140407 |
|
bool ascendingOrder() const{ return mAscendingOrder; } |
|
|
|
QDateTime findNodeDate(UBDocumentTreeNode *node, QString type) const; |
|
bool inMyDocuments(const QModelIndex &index) const; |
|
void moveIndexes(const QModelIndexList &source, const QModelIndex &destination); |
|
//N/C - NNE - 20140407 : END |
|
bool isDescendantOf(const QModelIndex &pPossibleDescendant, const QModelIndex &pPossibleAncestor) const; |
|
|
|
signals: |
|
void indexChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex); |
|
void currentIndexMoved(const QModelIndex &newIndex, const QModelIndex &previous); /* Be aware that when you got the signal |
|
"previous" index would have allready been deleted. |
|
check it for "valid" first */ |
|
|
|
private: |
|
UBDocumentTreeNode *mRootNode; |
|
UBDocumentTreeNode *mCurrentNode; |
|
|
|
UBDocumentTreeNode *findProxy(UBDocumentProxy *pSearch, UBDocumentTreeNode *pParent) const; |
|
QModelIndex pIndexForNode(const QModelIndex &parent, UBDocumentTreeNode *pNode) const; |
|
QModelIndex addNode(UBDocumentTreeNode *pFreeNode, const QModelIndex &pParent, eAddItemMode pMode = aDetectPosition); |
|
int positionForParent(UBDocumentTreeNode *pFreeNode, UBDocumentTreeNode *pParentNode); |
|
void fixNodeName(const QModelIndex &source, const QModelIndex &dest); |
|
void updateIndexNameBindings(UBDocumentTreeNode *nd); |
|
QPersistentModelIndex mRoot; |
|
QPersistentModelIndex mMyDocuments; |
|
QPersistentModelIndex mTrash; |
|
QPersistentModelIndex mUntitledDocuments; |
|
QList<UBDocumentProxy*> mNewDocuments; |
|
QModelIndex mHighLighted; |
|
|
|
//N/C - NNE - 20140407 |
|
bool mAscendingOrder; |
|
|
|
QDateTime findCatalogUpdatedDate(UBDocumentTreeNode *node) const; |
|
QDateTime findCatalogCreationDate(UBDocumentTreeNode *node) const; |
|
//N/C - NNE - 20140407 : END |
|
}; |
|
|
|
class UBDocumentTreeMimeData : public QMimeData |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
QList<QModelIndex> indexes() const {return mIndexes;} |
|
void setIndexes (const QList<QModelIndex> &pIndexes) {mIndexes = pIndexes;} |
|
|
|
private: |
|
QList<QModelIndex> mIndexes; |
|
}; |
|
|
|
class UBDocumentTreeView : public QTreeView |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
UBDocumentTreeView (QWidget *parent = 0); |
|
|
|
//N/C - NNE - 20140404 |
|
QModelIndex mapIndexToSource(const QModelIndex &index); |
|
QModelIndexList mapIndexesToSource(const QModelIndexList &indexes); |
|
|
|
public slots: |
|
void setSelectedAndExpanded(const QModelIndex &pIndex, bool pExpand = true, bool pEdit = false); |
|
void onModelIndexChanged(const QModelIndex &pNewIndex, const QModelIndex &pOldIndex); |
|
void hSliderRangeChanged(int min, int max); |
|
|
|
protected: |
|
void dragEnterEvent(QDragEnterEvent *event); |
|
void dragLeaveEvent(QDragLeaveEvent *event); |
|
void dragMoveEvent(QDragMoveEvent *event); |
|
void dropEvent(QDropEvent *event); |
|
void paintEvent(QPaintEvent *event); |
|
|
|
|
|
UBDocumentTreeModel *fullModel() {return qobject_cast<UBDocumentTreeModel*>(model());} |
|
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); |
|
|
|
private: |
|
bool isAcceptable(const QModelIndex &dragIndex, const QModelIndex &atIndex); |
|
Qt::DropAction acceptableAction(const QModelIndex &dragIndex, const QModelIndex &atIndex); |
|
void updateIndexEnvirons(const QModelIndex &index); |
|
}; |
|
|
|
class UBDocumentTreeItemDelegate : public QStyledItemDelegate |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
UBDocumentTreeItemDelegate(QObject *parent = 0); |
|
|
|
private slots: |
|
void commitAndCloseEditor(); |
|
void processChangedText(const QString &str) const; |
|
bool validateString(const QString &str) const; |
|
|
|
protected: |
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; |
|
void setEditorData(QWidget *editor, const QModelIndex &index) const; |
|
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; |
|
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex &index) const; |
|
|
|
private: |
|
mutable QStringList mExistingFileNames; |
|
}; |
|
|
|
class UBDocumentController : public UBDocumentContainer |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
|
|
enum DeletionType { |
|
MoveToTrash = 0 |
|
, CompleteDelete |
|
, EmptyFolder |
|
, EmptyTrash |
|
, DeletePage |
|
, NoDeletion |
|
}; |
|
|
|
enum LastSelectedElementType |
|
{ |
|
None = 0, Folder, Document, Page |
|
}; |
|
|
|
enum SortOrder |
|
{ |
|
ASC = 0, |
|
DESC |
|
}; |
|
|
|
enum SortKind |
|
{ |
|
CreationDate, |
|
UpdateDate, |
|
Alphabetical |
|
}; |
|
|
|
UBDocumentController(UBMainWindow* mainWindow); |
|
virtual ~UBDocumentController(); |
|
|
|
void closing(); |
|
QWidget* controlView(); |
|
UBDocumentProxyTreeItem* findDocument(UBDocumentProxy* proxy); |
|
bool addFileToDocument(UBDocumentProxy* document); |
|
void deletePages(QList<QGraphicsItem*> itemsToDelete); |
|
int getSelectedItemIndex(); |
|
|
|
|
|
bool pageCanBeMovedUp(int page); |
|
bool pageCanBeMovedDown(int page); |
|
bool pageCanBeDuplicated(int page); |
|
bool pageCanBeDeleted(int page); |
|
QString documentTrashGroupName(){ return mDocumentTrashGroupName;} |
|
QString defaultDocumentGroupName(){ return mDefaultDocumentGroupName;} |
|
|
|
void setDocument(UBDocumentProxy *document, bool forceReload = false); |
|
QModelIndex firstSelectedTreeIndex(); |
|
UBDocumentProxy *firstSelectedTreeProxy(); |
|
inline DeletionType deletionTypeForSelection(LastSelectedElementType pTypeSelection |
|
, const QModelIndex &selectedIndex |
|
, UBDocumentTreeModel *docModel) const; |
|
bool firstAndOnlySceneSelected() const; |
|
QWidget *mainWidget() const {return mDocumentWidget;} |
|
|
|
//issue 1629 - NNE - 20131212 |
|
/** |
|
* Check if the current view will be deleted. If it' true, |
|
* this function assures a view will be always selected, even if |
|
* no view is availaible by creating a new one. |
|
* |
|
* \param index The index that will be deleted. |
|
* \param docModel The tree model which represents the organisation of the document hierarchy |
|
* |
|
* \return True if the index passed in argument was the current view, false otherwise. |
|
*/ |
|
void moveToTrash(QModelIndex &index, UBDocumentTreeModel* docModel); |
|
|
|
QModelIndex mapIndexToSource(const QModelIndex &index); |
|
QModelIndexList mapIndexesToSource(const QModelIndexList &indexes); |
|
|
|
void sortDocuments(int kind, int order); |
|
|
|
void moveIndexesToTrash(const QModelIndexList &list, UBDocumentTreeModel *docModel); |
|
QModelIndex findPreviousSiblingNotSelected(const QModelIndex &index, QItemSelectionModel *selectionModel); |
|
QModelIndex findNextSiblingNotSelected(const QModelIndex &index, QItemSelectionModel *selectionModel); |
|
bool parentIsSelected(const QModelIndex& child, QItemSelectionModel *selectionModel); |
|
|
|
signals: |
|
void exportDone(); |
|
|
|
public slots: |
|
void createNewDocument(); |
|
//issue 1629 - NNE - 20131105 |
|
void createNewDocumentInUntitledFolder(); |
|
|
|
void createNewDocumentGroup(); |
|
void deleteSelectedItem(); |
|
void deleteSingleItem(QModelIndex index, UBDocumentTreeModel *docModel); |
|
void deleteMultipleItems(QModelIndexList indexes, UBDocumentTreeModel *docModel); |
|
void emptyFolder(const QModelIndex &index, DeletionType pDeletionType = MoveToTrash); |
|
void deleteIndexAndAssociatedData(const QModelIndex &pIndex); |
|
void renameSelectedItem(); |
|
void openSelectedItem(); |
|
void duplicateSelectedItem(); |
|
void importFile(); |
|
void moveSceneToIndex(UBDocumentProxy* proxy, int source, int target); |
|
void selectDocument(UBDocumentProxy* proxy, bool setAsCurrentDocument = true, const bool onImport = false, const bool editMode = false); |
|
void show(); |
|
void hide(); |
|
void showMessage(const QString& message, bool showSpinningWheel = false); |
|
void hideMessage(); |
|
void toggleDocumentToolsPalette(); |
|
void cut(); |
|
void copy(); |
|
void paste(); |
|
void focusChanged(QWidget *old, QWidget *current); |
|
void updateActions(); |
|
void updateExportSubActions(const QModelIndex &selectedIndex); |
|
void currentIndexMoved(const QModelIndex &newIndex, const QModelIndex &PreviousIndex); |
|
|
|
//N/C - NNE - 20140403 |
|
void onSortKindChanged(int index); |
|
void onSortOrderChanged(bool order); |
|
void collapseAll(); |
|
void expandAll(); |
|
|
|
protected: |
|
virtual void setupViews(); |
|
virtual void setupToolbar(); |
|
void setupPalettes(); |
|
bool isOKToOpenDocument(UBDocumentProxy* proxy); |
|
UBDocumentProxy* selectedDocumentProxy(); |
|
QList<UBDocumentProxy*> selectedProxies(); |
|
QModelIndexList selectedTreeIndexes(); |
|
UBDocumentProxyTreeItem* selectedDocumentProxyTreeItem(); |
|
UBDocumentGroupTreeItem* selectedDocumentGroupTreeItem(); |
|
QStringList allGroupNames(); |
|
|
|
LastSelectedElementType mSelectionType; |
|
|
|
private: |
|
QWidget *mParentWidget; |
|
UBBoardController *mBoardController; |
|
Ui::documents* mDocumentUI; |
|
UBMainWindow* mMainWindow; |
|
QWidget *mDocumentWidget; |
|
QPointer<UBMessageWindow> mMessageWindow; |
|
QAction* mAddFolderOfImagesAction; |
|
QAction* mAddFileToDocumentAction; |
|
QAction* mAddImagesAction; |
|
bool mIsClosing; |
|
UBDocumentToolsPalette *mToolsPalette; |
|
bool mToolsPalettePositionned; |
|
UBDocumentGroupTreeItem* mTrashTi; |
|
|
|
void moveDocumentToTrash(UBDocumentGroupTreeItem* groupTi, UBDocumentProxyTreeItem *proxyTi); |
|
void moveFolderToTrash(UBDocumentGroupTreeItem* groupTi); |
|
QString mDocumentTrashGroupName; |
|
QString mDefaultDocumentGroupName; |
|
|
|
UBDocumentProxy *mCurrentTreeDocument; |
|
bool mCurrentIndexMoved; |
|
|
|
UBSortFilterProxyModel *mSortFilterProxyModel; |
|
|
|
public slots: |
|
void TreeViewSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous); |
|
void TreeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); |
|
|
|
private slots: |
|
void documentZoomSliderValueChanged (int value); |
|
void itemSelectionChanged(LastSelectedElementType newSelection); |
|
void exportDocument(); |
|
void exportDocumentSet(); |
|
|
|
void thumbnailViewResized(); |
|
void pageSelectionChanged(); |
|
|
|
void documentSceneChanged(UBDocumentProxy* proxy, int pSceneIndex); |
|
|
|
void thumbnailPageDoubleClicked(QGraphicsItem* item, int index); |
|
void pageClicked(QGraphicsItem* item, int index); |
|
void addToDocument(); |
|
|
|
void addFolderOfImages(); |
|
void addFileToDocument(); |
|
void addImages(); |
|
void refreshDocumentThumbnailsView(UBDocumentContainer* source); |
|
}; |
|
|
|
|
|
|
|
#endif /* UBDOCUMENTCONTROLLER_H_ */
|
|
|