From c0f1600fbb4f4d0c51c69fe662d816592a42a00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 1 Feb 2015 22:56:54 +0100 Subject: [PATCH] added drag&drop to GridView --- YACReaderLibrary/db/comic_model.cpp | 11 +++ YACReaderLibrary/db/comic_model.h | 1 + YACReaderLibrary/grid_comics_view.cpp | 44 +++++++++- YACReaderLibrary/grid_comics_view.h | 7 ++ YACReaderLibrary/qml/GridComicsView.qml | 109 +++++++++++++++++++++--- 5 files changed, 161 insertions(+), 11 deletions(-) diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index 222e2fc6..922360b6 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -50,6 +50,7 @@ bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, i //TODO: optimize this method bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { + QAbstractItemModel::dropMimeData(data,action,row,column,parent); QLOG_INFO() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<"<< parent << row << "," << column; @@ -117,6 +118,8 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int QLOG_INFO() << newSorting; + if(!beginMoveRows(parent,currentIndexes.first(),currentIndexes.last(),parent,row)) + return false; _data = resortedData; @@ -141,6 +144,9 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int } QSqlDatabase::removeDatabase(_databasePath); + + endMoveRows(); + emit resortedIndexes(newSorting); int destSelectedIndex = row<0?_data.length():row; @@ -152,6 +158,11 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int return true; } +bool ComicModel::canBeResorted() +{ + return enableResorting; +} + QMimeData *ComicModel::mimeData(const QModelIndexList &indexes) const { //custom model data diff --git a/YACReaderLibrary/db/comic_model.h b/YACReaderLibrary/db/comic_model.h index 8ec5271b..bd48038b 100644 --- a/YACReaderLibrary/db/comic_model.h +++ b/YACReaderLibrary/db/comic_model.h @@ -36,6 +36,7 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const; bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + bool canBeResorted(); QMimeData * mimeData(const QModelIndexList &indexes) const; QStringList mimeTypes() const; diff --git a/YACReaderLibrary/grid_comics_view.cpp b/YACReaderLibrary/grid_comics_view.cpp index fa7440e7..f4f5f637 100644 --- a/YACReaderLibrary/grid_comics_view.cpp +++ b/YACReaderLibrary/grid_comics_view.cpp @@ -3,6 +3,9 @@ #include #include +#include "yacreader_global.h" +#include "comic.h" +#include "comic_files_manager.h" #include "QsLog.h" GridComicsView::GridComicsView(QWidget *parent) : @@ -64,6 +67,8 @@ void GridComicsView::setModel(ComicModel *model) ctxt->setContextProperty("comicsSelectionHelper", this); ctxt->setContextProperty("comicRatingHelper", this); ctxt->setContextProperty("dummyValue", true); + ctxt->setContextProperty("dragManager", this); + ctxt->setContextProperty("dropManager", this); if(model->rowCount()>0) setCurrentIndex(model->index(0,0)); @@ -202,7 +207,44 @@ void GridComicsView::startDrag() drag->setMimeData(model->mimeData(_selectionModel->selectedRows())); drag->setPixmap(QPixmap(":/images/openInYACReader.png")); //TODO add better image - Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); + /*Qt::DropAction dropAction =*/ drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); +} + +bool GridComicsView::canDropUrls(const QList &urls, Qt::DropAction action) +{ + if(action == Qt::CopyAction) + { + QString currentPath; + foreach (QUrl url, urls) + { + //comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping) + currentPath = url.toLocalFile(); + if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir()) + return true; + } + } + return false; +} + +bool GridComicsView::canDropFormats(const QString &formats) +{ + return (formats.contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat) && model->canBeResorted()); +} + +void GridComicsView::droppedFiles(const QList &urls, Qt::DropAction action) +{ + bool validAction = action == Qt::CopyAction; //TODO add move + + if(validAction) + { + QList > droppedFiles = ComicFilesManager::getDroppedFiles(urls); + emit copyComicsToCurrentFolder(droppedFiles); + } +} + +void GridComicsView::droppedComicsForResortingAt(const QString &data, int index) +{ + model->dropMimeData(model->mimeData(_selectionModel->selectedRows()), Qt::MoveAction, index, 0, QModelIndex()); } //helper diff --git a/YACReaderLibrary/grid_comics_view.h b/YACReaderLibrary/grid_comics_view.h index 6aa41938..77d3c343 100644 --- a/YACReaderLibrary/grid_comics_view.h +++ b/YACReaderLibrary/grid_comics_view.h @@ -54,7 +54,14 @@ public slots: //rating void rate(int index, int rating); + //dragManager void startDrag(); + //dropManager + bool canDropUrls(const QList & urls, Qt::DropAction action); + bool canDropFormats(const QString &formats); + void droppedFiles(const QList & urls, Qt::DropAction action); + void droppedComicsForResortingAt(const QString & data, int index); + protected slots: void requestedContextMenu(const QPoint & point); diff --git a/YACReaderLibrary/qml/GridComicsView.qml b/YACReaderLibrary/qml/GridComicsView.qml index 74e9176d..2c317116 100644 --- a/YACReaderLibrary/qml/GridComicsView.qml +++ b/YACReaderLibrary/qml/GridComicsView.qml @@ -42,7 +42,7 @@ Rectangle { Drag.onActiveChanged: { if(!dragging) { - comicsSelectionHelper.startDrag(); + dragManager.startDrag(); dragging = true; }else dragging = false; @@ -76,9 +76,9 @@ Rectangle { } onPressed: { - //grid.currentIndex = index - //comicsSelection.setCurrentIndex(index,0x0002) - var ci = grid.currentIndex; + + var ci = grid.currentIndex; //save current index + /*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) { if(!comicsSelectionHelper.isSelectedIndex(index)) @@ -99,10 +99,10 @@ Rectangle { mouse.accepted = true; - if(mouse.button == Qt.RightButton) + if(mouse.button == Qt.RightButton) // context menu is requested { - if(!comicsSelectionHelper.isSelectedIndex(index)) + if(!comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be { comicsSelectionHelper.setCurrentIndex(index) grid.currentIndex = index; @@ -111,8 +111,9 @@ Rectangle { var coordinates = main.mapFromItem(realCell,mouseX,mouseY) contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y)); - } else + } else //left button { + if(mouse.modifiers & Qt.ControlModifier) { if(comicsSelectionHelper.isSelectedIndex(index)) @@ -121,7 +122,7 @@ Rectangle { { comicsSelectionHelper.deselectIndex(index); if(grid.currentIndex === index) - grid.currentIndex = comicsSelectionHelper.lastSelectedIndex(); + grid.currentIndex = comicsSelectionHelper.lastSelectedIndex(); } } else @@ -130,16 +131,30 @@ Rectangle { grid.currentIndex = index; } } + + if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) //just left button click + { + if(comicsSelectionHelper.isSelectedIndex(index)) //the context menu is requested outside the current selection, the selection will be + { + + } + else + { + comicsSelectionHelper.setCurrentIndex(index) + } + + grid.currentIndex = index; + } } } onReleased: { - if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) + /*if(mouse.button != Qt.RightButton && !(mouse.modifiers & Qt.ControlModifier || mouse.modifiers & Qt.ShiftModifier)) { comicsSelectionHelper.setCurrentIndex(index) grid.currentIndex = index; - } + }*/ } } @@ -255,6 +270,56 @@ Rectangle { anchors.fill: parent anchors.margins: 0 + //QTBUG-39453 + //Another fu%$ยท#& bug in Qt + //https://bugreports.qt.io/browse/QTBUG-39453 + //To solve this I am going to accept any input drag, drops will be filtered in "onDropped" + DropArea { + anchors.fill: parent + + /* + onEntered: { + console.log("onEntered"); + if(drag.hasUrls) + { + console.log("HAS URLS -> ", drag.urls); + if(dropManager.canDropUrls(drag.urls, drag.action)) + { + drag.accepted = true; + console.log("canDropUrls"); + }else + drag.accepted = false; + } + else if (dropManager.canDropFormats(drag.formats)) { + drag.accepted = true; + console.log("canDropFormats"); + } else + drag.accepted = false; + }*/ + + + onDropped: { + if(drop.hasUrls && dropManager.canDropUrls(drop.urls, drop.action)) + { + dropManager.droppedFiles(drop.urls, drop.action); + } + else{ + if (dropManager.canDropFormats(drop.formats)) + { + var destItem = grid.itemAt(drop.x,drop.y + grid.contentY); + var destLocalX = grid.mapToItem(destItem,drop.x,drop.y + grid.contentY).x + var realIndex = grid.indexAt(drop.x,drop.y + grid.contentY); + + if(realIndex === -1) + realIndex = grid.count - 1; + + var destIndex = destLocalX < (grid.cellWidth / 2) ? realIndex : realIndex + 1; + dropManager.droppedComicsForResortingAt(drop.getDataAsString(), destIndex); + } + } + } + + } GridView { id:grid @@ -274,6 +339,30 @@ Rectangle { currentIndex: 0 cacheBuffer: 0 + move: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + remove: Transition { + ParallelAnimation { + NumberAnimation { property: "opacity"; to: 0; duration: 250 } + + } + } + + removeDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } + + + + displaced: Transition { + NumberAnimation { properties: "x,y"; duration: 250 } + } function numCellsPerRow() { return Math.floor(width / 185);