mirror of
https://github.com/YACReader/yacreader
synced 2025-06-04 01:28:55 -04:00
added drag&drop to GridView
This commit is contained in:
parent
b3ce0f7ab0
commit
c0f1600fbb
@ -50,6 +50,7 @@ bool ComicModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, i
|
|||||||
//TODO: optimize this method
|
//TODO: optimize this method
|
||||||
bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
QAbstractItemModel::dropMimeData(data,action,row,column,parent);
|
QAbstractItemModel::dropMimeData(data,action,row,column,parent);
|
||||||
QLOG_INFO() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<"<< parent << row << "," << column;
|
QLOG_INFO() << ">>>>>>>>>>>>>>dropMimeData ComicModel<<<<<<<<<<<<<<<<<"<< parent << row << "," << column;
|
||||||
|
|
||||||
@ -117,6 +118,8 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
|
|||||||
|
|
||||||
QLOG_INFO() << newSorting;
|
QLOG_INFO() << newSorting;
|
||||||
|
|
||||||
|
if(!beginMoveRows(parent,currentIndexes.first(),currentIndexes.last(),parent,row))
|
||||||
|
return false;
|
||||||
_data = resortedData;
|
_data = resortedData;
|
||||||
|
|
||||||
|
|
||||||
@ -141,6 +144,9 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSqlDatabase::removeDatabase(_databasePath);
|
QSqlDatabase::removeDatabase(_databasePath);
|
||||||
|
|
||||||
|
endMoveRows();
|
||||||
|
|
||||||
emit resortedIndexes(newSorting);
|
emit resortedIndexes(newSorting);
|
||||||
int destSelectedIndex = row<0?_data.length():row;
|
int destSelectedIndex = row<0?_data.length():row;
|
||||||
|
|
||||||
@ -152,6 +158,11 @@ bool ComicModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComicModel::canBeResorted()
|
||||||
|
{
|
||||||
|
return enableResorting;
|
||||||
|
}
|
||||||
|
|
||||||
QMimeData *ComicModel::mimeData(const QModelIndexList &indexes) const
|
QMimeData *ComicModel::mimeData(const QModelIndexList &indexes) const
|
||||||
{
|
{
|
||||||
//custom model data
|
//custom model data
|
||||||
|
@ -36,6 +36,7 @@ public:
|
|||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 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 dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||||
|
bool canBeResorted();
|
||||||
QMimeData * mimeData(const QModelIndexList &indexes) const;
|
QMimeData * mimeData(const QModelIndexList &indexes) const;
|
||||||
QStringList mimeTypes() const;
|
QStringList mimeTypes() const;
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include <QtQuick>
|
#include <QtQuick>
|
||||||
|
|
||||||
|
#include "yacreader_global.h"
|
||||||
|
#include "comic.h"
|
||||||
|
#include "comic_files_manager.h"
|
||||||
#include "QsLog.h"
|
#include "QsLog.h"
|
||||||
|
|
||||||
GridComicsView::GridComicsView(QWidget *parent) :
|
GridComicsView::GridComicsView(QWidget *parent) :
|
||||||
@ -64,6 +67,8 @@ void GridComicsView::setModel(ComicModel *model)
|
|||||||
ctxt->setContextProperty("comicsSelectionHelper", this);
|
ctxt->setContextProperty("comicsSelectionHelper", this);
|
||||||
ctxt->setContextProperty("comicRatingHelper", this);
|
ctxt->setContextProperty("comicRatingHelper", this);
|
||||||
ctxt->setContextProperty("dummyValue", true);
|
ctxt->setContextProperty("dummyValue", true);
|
||||||
|
ctxt->setContextProperty("dragManager", this);
|
||||||
|
ctxt->setContextProperty("dropManager", this);
|
||||||
|
|
||||||
if(model->rowCount()>0)
|
if(model->rowCount()>0)
|
||||||
setCurrentIndex(model->index(0,0));
|
setCurrentIndex(model->index(0,0));
|
||||||
@ -202,7 +207,44 @@ void GridComicsView::startDrag()
|
|||||||
drag->setMimeData(model->mimeData(_selectionModel->selectedRows()));
|
drag->setMimeData(model->mimeData(_selectionModel->selectedRows()));
|
||||||
drag->setPixmap(QPixmap(":/images/openInYACReader.png")); //TODO add better image
|
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<QUrl> &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<QUrl> &urls, Qt::DropAction action)
|
||||||
|
{
|
||||||
|
bool validAction = action == Qt::CopyAction; //TODO add move
|
||||||
|
|
||||||
|
if(validAction)
|
||||||
|
{
|
||||||
|
QList<QPair<QString, QString> > 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
|
//helper
|
||||||
|
@ -54,7 +54,14 @@ public slots:
|
|||||||
//rating
|
//rating
|
||||||
void rate(int index, int rating);
|
void rate(int index, int rating);
|
||||||
|
|
||||||
|
//dragManager
|
||||||
void startDrag();
|
void startDrag();
|
||||||
|
//dropManager
|
||||||
|
bool canDropUrls(const QList<QUrl> & urls, Qt::DropAction action);
|
||||||
|
bool canDropFormats(const QString &formats);
|
||||||
|
void droppedFiles(const QList<QUrl> & urls, Qt::DropAction action);
|
||||||
|
void droppedComicsForResortingAt(const QString & data, int index);
|
||||||
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void requestedContextMenu(const QPoint & point);
|
void requestedContextMenu(const QPoint & point);
|
||||||
|
@ -42,7 +42,7 @@ Rectangle {
|
|||||||
Drag.onActiveChanged: {
|
Drag.onActiveChanged: {
|
||||||
if(!dragging)
|
if(!dragging)
|
||||||
{
|
{
|
||||||
comicsSelectionHelper.startDrag();
|
dragManager.startDrag();
|
||||||
dragging = true;
|
dragging = true;
|
||||||
}else
|
}else
|
||||||
dragging = false;
|
dragging = false;
|
||||||
@ -76,9 +76,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
//grid.currentIndex = index
|
|
||||||
//comicsSelection.setCurrentIndex(index,0x0002)
|
var ci = grid.currentIndex; //save current index
|
||||||
var ci = grid.currentIndex;
|
|
||||||
/*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))
|
||||||
{
|
{
|
||||||
if(!comicsSelectionHelper.isSelectedIndex(index))
|
if(!comicsSelectionHelper.isSelectedIndex(index))
|
||||||
@ -99,10 +99,10 @@ Rectangle {
|
|||||||
|
|
||||||
mouse.accepted = true;
|
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)
|
comicsSelectionHelper.setCurrentIndex(index)
|
||||||
grid.currentIndex = index;
|
grid.currentIndex = index;
|
||||||
@ -111,8 +111,9 @@ Rectangle {
|
|||||||
var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
|
var coordinates = main.mapFromItem(realCell,mouseX,mouseY)
|
||||||
contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y));
|
contextMenuHelper.requestedContextMenu(Qt.point(coordinates.x,coordinates.y));
|
||||||
|
|
||||||
} else
|
} else //left button
|
||||||
{
|
{
|
||||||
|
|
||||||
if(mouse.modifiers & Qt.ControlModifier)
|
if(mouse.modifiers & Qt.ControlModifier)
|
||||||
{
|
{
|
||||||
if(comicsSelectionHelper.isSelectedIndex(index))
|
if(comicsSelectionHelper.isSelectedIndex(index))
|
||||||
@ -121,7 +122,7 @@ Rectangle {
|
|||||||
{
|
{
|
||||||
comicsSelectionHelper.deselectIndex(index);
|
comicsSelectionHelper.deselectIndex(index);
|
||||||
if(grid.currentIndex === index)
|
if(grid.currentIndex === index)
|
||||||
grid.currentIndex = comicsSelectionHelper.lastSelectedIndex();
|
grid.currentIndex = comicsSelectionHelper.lastSelectedIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -130,16 +131,30 @@ Rectangle {
|
|||||||
grid.currentIndex = index;
|
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: {
|
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)
|
comicsSelectionHelper.setCurrentIndex(index)
|
||||||
grid.currentIndex = index;
|
grid.currentIndex = index;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -255,6 +270,56 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 0
|
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 {
|
GridView {
|
||||||
id:grid
|
id:grid
|
||||||
@ -274,6 +339,30 @@ Rectangle {
|
|||||||
currentIndex: 0
|
currentIndex: 0
|
||||||
cacheBuffer: 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() {
|
function numCellsPerRow() {
|
||||||
return Math.floor(width / 185);
|
return Math.floor(width / 185);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user