mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	Drag and drop
This commit is contained in:
		| @@ -271,7 +271,10 @@ bool MainWindow::canPerformOperation(Operation operation) const | |||||||
|             return isSelected; |             return isSelected; | ||||||
|  |  | ||||||
|         case Operation::Paste: |         case Operation::Paste: | ||||||
|             return !QApplication::clipboard()->text().isEmpty(); |         { | ||||||
|  |             const QMimeData* mimeData = QApplication::clipboard()->mimeData(); | ||||||
|  |             return mimeData && mimeData->hasFormat(PageItemModel::getMimeDataType()); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         case Operation::RotateLeft: |         case Operation::RotateLeft: | ||||||
|         case Operation::RotateRight: |         case Operation::RotateRight: | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ | |||||||
|        <bool>true</bool> |        <bool>true</bool> | ||||||
|       </property> |       </property> | ||||||
|       <property name="dragDropMode"> |       <property name="dragDropMode"> | ||||||
|        <enum>QAbstractItemView::InternalMove</enum> |        <enum>QAbstractItemView::DragDrop</enum> | ||||||
|       </property> |       </property> | ||||||
|       <property name="defaultDropAction"> |       <property name="defaultDropAction"> | ||||||
|        <enum>Qt::MoveAction</enum> |        <enum>Qt::MoveAction</enum> | ||||||
| @@ -167,7 +167,7 @@ | |||||||
|     <string>Remove Selection</string> |     <string>Remove Selection</string> | ||||||
|    </property> |    </property> | ||||||
|    <property name="shortcut"> |    <property name="shortcut"> | ||||||
|     <string>Ctrl+R</string> |     <string>Del</string> | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|   <action name="actionRestoreRemovedItems"> |   <action name="actionRestoreRemovedItems"> | ||||||
|   | |||||||
| @@ -375,5 +375,177 @@ std::set<int> PageGroupItem::getDocumentIndices() const | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | QStringList PageItemModel::mimeTypes() const | ||||||
|  | { | ||||||
|  |     return { getMimeDataType() }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QMimeData* PageItemModel::mimeData(const QModelIndexList& indexes) const | ||||||
|  | { | ||||||
|  |     if (indexes.isEmpty()) | ||||||
|  |     { | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     QMimeData* mimeData = new QMimeData; | ||||||
|  |  | ||||||
|  |     QByteArray serializedData; | ||||||
|  |     { | ||||||
|  |         QDataStream stream(&serializedData, QIODevice::WriteOnly); | ||||||
|  |         for (const QModelIndex& index : indexes) | ||||||
|  |         { | ||||||
|  |             stream << index.row(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     mimeData->setData(getMimeDataType(), serializedData); | ||||||
|  |     return mimeData; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool PageItemModel::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const | ||||||
|  | { | ||||||
|  |     Q_UNUSED(row); | ||||||
|  |     Q_UNUSED(column); | ||||||
|  |     Q_UNUSED(parent); | ||||||
|  |  | ||||||
|  |     switch (action) | ||||||
|  |     { | ||||||
|  |         case Qt::CopyAction: | ||||||
|  |         case Qt::MoveAction: | ||||||
|  |         case Qt::IgnoreAction: | ||||||
|  |             break; | ||||||
|  |  | ||||||
|  |         case Qt::LinkAction: | ||||||
|  |         case Qt::TargetMoveAction: | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         default: | ||||||
|  |             Q_ASSERT(false); | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return data && data->hasFormat(getMimeDataType()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool PageItemModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) | ||||||
|  | { | ||||||
|  |     if (action == Qt::IgnoreAction) | ||||||
|  |     { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!data->hasFormat(getMimeDataType())) | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (column > 0) | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     int insertRow = rowCount(QModelIndex()); | ||||||
|  |     if (row > -1) | ||||||
|  |     { | ||||||
|  |         insertRow = row; | ||||||
|  |     } | ||||||
|  |     else if (parent.isValid()) | ||||||
|  |     { | ||||||
|  |         insertRow = parent.row(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::vector<int> rows; | ||||||
|  |  | ||||||
|  |     QByteArray serializedData = data->data(getMimeDataType()); | ||||||
|  |     QDataStream stream(&serializedData, QIODevice::ReadOnly); | ||||||
|  |     while (!stream.atEnd()) | ||||||
|  |     { | ||||||
|  |         int row = -1; | ||||||
|  |         stream >> row; | ||||||
|  |         rows.push_back(row); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     qSort(rows); | ||||||
|  |  | ||||||
|  |     // Sanity checks on rows | ||||||
|  |     if (rows.empty()) | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     if (rows.front() < 0 || rows.back() >= rowCount(QModelIndex())) | ||||||
|  |     { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::vector<PageGroupItem> newItems = m_pageGroupItems; | ||||||
|  |     std::vector<PageGroupItem> workItems; | ||||||
|  |  | ||||||
|  |     // When moving, update insert row | ||||||
|  |     if (action == Qt::MoveAction) | ||||||
|  |     { | ||||||
|  |         const int originalInsertRow = insertRow; | ||||||
|  |         if (rows.front() < originalInsertRow) | ||||||
|  |         { | ||||||
|  |             ++insertRow; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (int currentRow : rows) | ||||||
|  |         { | ||||||
|  |             if (currentRow < originalInsertRow) | ||||||
|  |             { | ||||||
|  |                 --insertRow; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     workItems.reserve(rows.size()); | ||||||
|  |     for (int currentRow : rows) | ||||||
|  |     { | ||||||
|  |         workItems.push_back(m_pageGroupItems[currentRow]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // When move, delete old page items | ||||||
|  |     if (action == Qt::MoveAction) | ||||||
|  |     { | ||||||
|  |         for (auto it = rows.rbegin(); it != rows.rend(); ++it) | ||||||
|  |         { | ||||||
|  |             newItems.erase(std::next(newItems.begin(), *it)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Insert work items at a given position | ||||||
|  |     newItems.insert(std::next(newItems.begin(), insertRow), workItems.begin(), workItems.end()); | ||||||
|  |  | ||||||
|  |     if (newItems != m_pageGroupItems) | ||||||
|  |     { | ||||||
|  |         beginResetModel(); | ||||||
|  |         m_pageGroupItems = std::move(newItems); | ||||||
|  |         endResetModel(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Qt::DropActions PageItemModel::supportedDropActions() const | ||||||
|  | { | ||||||
|  |     return Qt::CopyAction | Qt::MoveAction; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Qt::DropActions PageItemModel::supportedDragActions() const | ||||||
|  | { | ||||||
|  |     return Qt::CopyAction | Qt::MoveAction; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Qt::ItemFlags PageItemModel::flags(const QModelIndex& index) const | ||||||
|  | { | ||||||
|  |     Qt::ItemFlags flags = BaseClass::flags(index); | ||||||
|  |  | ||||||
|  |     if (index.isValid()) | ||||||
|  |     { | ||||||
|  |         flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return flags; | ||||||
|  | } | ||||||
|  |  | ||||||
| }   // namespace pdfdocpage | }   // namespace pdfdocpage | ||||||
|   | |||||||
| @@ -60,6 +60,9 @@ class PageItemModel : public QAbstractItemModel | |||||||
| { | { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     using BaseClass = QAbstractItemModel; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     explicit PageItemModel(QObject* parent); |     explicit PageItemModel(QObject* parent); | ||||||
|  |  | ||||||
| @@ -69,6 +72,13 @@ public: | |||||||
|     virtual int rowCount(const QModelIndex& parent) const override; |     virtual int rowCount(const QModelIndex& parent) const override; | ||||||
|     virtual int columnCount(const QModelIndex& parent) const override; |     virtual int columnCount(const QModelIndex& parent) const override; | ||||||
|     virtual QVariant data(const QModelIndex& index, int role) const override; |     virtual QVariant data(const QModelIndex& index, int role) const override; | ||||||
|  |     virtual QStringList mimeTypes() const override; | ||||||
|  |     virtual QMimeData* mimeData(const QModelIndexList& indexes) const override; | ||||||
|  |     virtual bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override; | ||||||
|  |     virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; | ||||||
|  |     virtual Qt::DropActions supportedDropActions() const override; | ||||||
|  |     virtual Qt::DropActions supportedDragActions() const override; | ||||||
|  |     virtual Qt::ItemFlags flags(const QModelIndex& index) const override; | ||||||
|  |  | ||||||
|     /// Adds document to the model, inserts one single page group containing |     /// Adds document to the model, inserts one single page group containing | ||||||
|     /// the whole document. Returns index of a newly added document. If document |     /// the whole document. Returns index of a newly added document. If document | ||||||
| @@ -102,6 +112,8 @@ public: | |||||||
|     void group(const QModelIndexList& list); |     void group(const QModelIndexList& list); | ||||||
|     void ungroup(const QModelIndexList& list); |     void ungroup(const QModelIndexList& list); | ||||||
|  |  | ||||||
|  |     static QString getMimeDataType() { return QLatin1String("application/pagemodel.PDF4QtDocPageOrganizer"); } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     void createDocumentGroup(int index); |     void createDocumentGroup(int index); | ||||||
|     QString getGroupNameFromDocument(int index) const; |     QString getGroupNameFromDocument(int index) const; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user