mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
FileList: support drag&drop to copy/move files
This commit is contained in:
parent
d1e7926630
commit
ba75c94f40
@ -148,7 +148,8 @@ SOURCES += main.cpp\
|
||||
peghighlighterresult.cpp \
|
||||
vtexteditcompleter.cpp \
|
||||
utils/vkeyboardlayoutmanager.cpp \
|
||||
dialog/vkeyboardlayoutmappingdialog.cpp
|
||||
dialog/vkeyboardlayoutmappingdialog.cpp \
|
||||
vfilelistwidget.cpp
|
||||
|
||||
HEADERS += vmainwindow.h \
|
||||
vdirectorytree.h \
|
||||
@ -289,7 +290,8 @@ HEADERS += vmainwindow.h \
|
||||
vtexteditcompleter.h \
|
||||
vtextdocumentlayoutdata.h \
|
||||
utils/vkeyboardlayoutmanager.h \
|
||||
dialog/vkeyboardlayoutmappingdialog.h
|
||||
dialog/vkeyboardlayoutmappingdialog.h \
|
||||
vfilelistwidget.h
|
||||
|
||||
RESOURCES += \
|
||||
vnote.qrc \
|
||||
|
@ -25,6 +25,7 @@ namespace ClipboardConfig
|
||||
static const QString c_isCut = "is_cut";
|
||||
static const QString c_files = "files";
|
||||
static const QString c_dirs = "dirs";
|
||||
static const QString c_format = "text/json";
|
||||
}
|
||||
|
||||
enum class OpenFileMode {Read = 0, Edit, Invalid };
|
||||
|
@ -30,6 +30,9 @@ VDirectoryTree::VDirectoryTree(QWidget *parent)
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setFitContent(true);
|
||||
|
||||
viewport()->setAcceptDrops(true);
|
||||
setDropIndicatorShown(true);
|
||||
|
||||
initShortcuts();
|
||||
|
||||
connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)),
|
||||
@ -1229,3 +1232,69 @@ void VDirectoryTree::pinDirectoryToHistory()
|
||||
g_mainWin->getHistoryList()->pinFolder(getVDirectory(curItem)->fetchPath());
|
||||
g_mainWin->showStatusMessage(tr("1 folder pinned to History"));
|
||||
}
|
||||
|
||||
Qt::DropActions VDirectoryTree::supportedDropActions() const
|
||||
{
|
||||
return Qt::CopyAction | Qt::MoveAction;
|
||||
}
|
||||
|
||||
bool VDirectoryTree::dropMimeData(QTreeWidgetItem *p_parent,
|
||||
int p_index,
|
||||
const QMimeData *p_data,
|
||||
Qt::DropAction p_action)
|
||||
{
|
||||
Q_UNUSED(p_index);
|
||||
|
||||
if (p_data->hasFormat(ClipboardConfig::c_format)) {
|
||||
VDirectory *dir = getVDirectory(p_parent);
|
||||
if (!dir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray ba = p_data->data(ClipboardConfig::c_format);
|
||||
QJsonObject obj = QJsonDocument::fromJson(ba).object();
|
||||
if (obj.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj[ClipboardConfig::c_type] != (int)ClipboardOpType::CopyFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonArray files = obj[ClipboardConfig::c_files].toArray();
|
||||
if (files.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<QString> filesToPaste;
|
||||
for (auto const & file : files) {
|
||||
filesToPaste.append(file.toString());
|
||||
}
|
||||
|
||||
qDebug() << "paste files from dropped mime data" << dir->getName() << filesToPaste;
|
||||
g_mainWin->getFileList()->pasteFiles(dir, filesToPaste, p_action == Qt::MoveAction);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VDirectoryTree::dropEvent(QDropEvent *p_event)
|
||||
{
|
||||
// Distinguish copy and cut.
|
||||
int modifiers = p_event->keyboardModifiers();
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
p_event->setDropAction(Qt::CopyAction);
|
||||
} else {
|
||||
// Cut.
|
||||
// Will pass to dropMimeData().
|
||||
p_event->setDropAction(Qt::MoveAction);
|
||||
}
|
||||
|
||||
QTreeWidget::dropEvent(p_event);
|
||||
}
|
||||
|
||||
QStringList VDirectoryTree::mimeTypes() const
|
||||
{
|
||||
return QStringList(ClipboardConfig::c_format);
|
||||
}
|
||||
|
@ -101,6 +101,19 @@ protected:
|
||||
|
||||
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
QStringList mimeTypes() const Q_DECL_OVERRIDE;
|
||||
|
||||
Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
|
||||
|
||||
// Will be called inside dropEvent().
|
||||
bool dropMimeData(QTreeWidgetItem *p_parent,
|
||||
int p_index,
|
||||
const QMimeData *p_data,
|
||||
Qt::DropAction p_action) Q_DECL_OVERRIDE;
|
||||
|
||||
// Drop the data.
|
||||
void dropEvent(QDropEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
// Build the subtree of @p_parent recursively to the depth @p_depth.
|
||||
// @p_depth: negative - infinite levels.
|
||||
|
@ -83,12 +83,14 @@ void VFileList::setupUI()
|
||||
|
||||
titleLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
fileList = new VListWidget(this);
|
||||
fileList = new VFileListWidget(this);
|
||||
fileList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
fileList->setObjectName("FileList");
|
||||
fileList->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
fileList->setMouseTracking(true);
|
||||
fileList->setMimeDataGetter([this](const QString &p_format,
|
||||
const QList<QListWidgetItem *> &p_items) {
|
||||
return getMimeData(p_format, p_items);
|
||||
});
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(titleLayout);
|
||||
@ -1502,3 +1504,22 @@ void VFileList::selectFiles(const QVector<VNoteFile *> &p_files)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray VFileList::getMimeData(const QString &p_format,
|
||||
const QList<QListWidgetItem *> &p_items) const
|
||||
{
|
||||
Q_UNUSED(p_format);
|
||||
Q_ASSERT(p_format ==ClipboardConfig::c_format);
|
||||
|
||||
QJsonArray files;
|
||||
for (int i = 0; i < p_items.size(); ++i) {
|
||||
VNoteFile *file = getVFile(p_items[i]);
|
||||
files.append(file->fetchPath());
|
||||
}
|
||||
|
||||
QJsonObject obj;
|
||||
obj[ClipboardConfig::c_type] = (int)ClipboardOpType::CopyFile;
|
||||
obj[ClipboardConfig::c_files] = files;
|
||||
|
||||
return QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
@ -13,10 +13,9 @@
|
||||
#include "vdirectory.h"
|
||||
#include "vnotefile.h"
|
||||
#include "vnavigationmode.h"
|
||||
#include "vlistwidget.h"
|
||||
#include "vfilelistwidget.h"
|
||||
|
||||
class VNote;
|
||||
class QListWidget;
|
||||
class QPushButton;
|
||||
class VEditArea;
|
||||
class QFocusEvent;
|
||||
@ -50,6 +49,11 @@ public:
|
||||
|
||||
QWidget *getContentWidget() const;
|
||||
|
||||
// Paste files given path by @p_files to destination directory @p_destDir.
|
||||
void pasteFiles(VDirectory *p_destDir,
|
||||
const QVector<QString> &p_files,
|
||||
bool p_isCut);
|
||||
|
||||
// Implementations for VNavigationMode.
|
||||
void showNavigation() Q_DECL_OVERRIDE;
|
||||
bool handleKeyNavigation(int p_key, bool &p_succeed) Q_DECL_OVERRIDE;
|
||||
@ -155,11 +159,6 @@ private:
|
||||
// Return the corresponding QListWidgetItem of @p_file.
|
||||
QListWidgetItem *findItem(const VNoteFile *p_file);
|
||||
|
||||
// Paste files given path by @p_files to destination directory @p_destDir.
|
||||
void pasteFiles(VDirectory *p_destDir,
|
||||
const QVector<QString> &p_files,
|
||||
bool p_isCut);
|
||||
|
||||
inline QPointer<VNoteFile> getVFile(QListWidgetItem *p_item) const;
|
||||
|
||||
// Fill the info of @p_item according to @p_file.
|
||||
@ -190,9 +189,11 @@ private:
|
||||
|
||||
void selectFiles(const QVector<VNoteFile *> &p_files);
|
||||
|
||||
QByteArray getMimeData(const QString &p_format, const QList<QListWidgetItem *> &p_items) const;
|
||||
|
||||
VEditArea *editArea;
|
||||
|
||||
VListWidget *fileList;
|
||||
VFileListWidget *fileList;
|
||||
|
||||
QLabel *m_numLabel;
|
||||
|
||||
|
44
src/vfilelistwidget.cpp
Normal file
44
src/vfilelistwidget.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "vfilelistwidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QMimeData>
|
||||
|
||||
#include "vconstants.h"
|
||||
|
||||
VFileListWidget::VFileListWidget(QWidget *p_parent)
|
||||
: VListWidget(p_parent)
|
||||
{
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setDragEnabled(true);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
QStringList VFileListWidget::mimeTypes() const
|
||||
{
|
||||
return QStringList(ClipboardConfig::c_format);
|
||||
}
|
||||
|
||||
QMimeData *VFileListWidget::mimeData(const QList<QListWidgetItem *> p_items) const
|
||||
{
|
||||
const QString format(ClipboardConfig::c_format);
|
||||
QStringList types = mimeTypes();
|
||||
if (!types.contains(format) || p_items.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (m_mimeDataGetter) {
|
||||
QMimeData *data = new QMimeData();
|
||||
data->setData(format, m_mimeDataGetter(format, p_items));
|
||||
return data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VFileListWidget::setMimeDataGetter(const MimeDataGetterFunc &p_getter)
|
||||
{
|
||||
m_mimeDataGetter = p_getter;
|
||||
}
|
28
src/vfilelistwidget.h
Normal file
28
src/vfilelistwidget.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef VFILELISTWIDGET_H
|
||||
#define VFILELISTWIDGET_H
|
||||
|
||||
#include "vlistwidget.h"
|
||||
|
||||
#include <functional>
|
||||
#include <QList>
|
||||
|
||||
typedef std::function<QByteArray(const QString &, const QList<QListWidgetItem *> &)> MimeDataGetterFunc;
|
||||
|
||||
class VFileListWidget : public VListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VFileListWidget(QWidget *p_parent = nullptr);
|
||||
|
||||
void setMimeDataGetter(const MimeDataGetterFunc &p_getter);
|
||||
|
||||
protected:
|
||||
QStringList mimeTypes() const Q_DECL_OVERRIDE;
|
||||
|
||||
QMimeData *mimeData(const QList<QListWidgetItem *> p_items) const Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
MimeDataGetterFunc m_mimeDataGetter;
|
||||
};
|
||||
|
||||
#endif // VFILELISTWIDGET_H
|
Loading…
x
Reference in New Issue
Block a user