From 880d16e8f4b3e77886cf7d52bc85c17a9d6bf4ae Mon Sep 17 00:00:00 2001 From: Le Tan Date: Wed, 28 Dec 2016 19:02:27 +0800 Subject: [PATCH] support reordering notes in file list panel Signed-off-by: Le Tan --- src/vdirectory.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++ src/vdirectory.h | 2 ++ src/vfilelist.cpp | 32 ++++++++++++++++++++++++-- src/vfilelist.h | 9 +++++--- 4 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/vdirectory.cpp b/src/vdirectory.cpp index daa9abf5..8b4b6af9 100644 --- a/src/vdirectory.cpp +++ b/src/vdirectory.cpp @@ -582,3 +582,59 @@ void VDirectory::setExpanded(bool p_expanded) m_expanded = p_expanded; } +void VDirectory::reorderFiles(int p_first, int p_last, int p_destStart) +{ + Q_ASSERT(m_opened); + Q_ASSERT(p_first <= p_last); + Q_ASSERT(p_last < m_files.size()); + Q_ASSERT(p_destStart < p_first || p_destStart > p_last); + Q_ASSERT(p_destStart >= 0 && p_destStart <= m_files.size()); + + if (!reorderFilesInConfig(p_first, p_last, p_destStart)) { + qWarning() << "failed to reorder files in config" << p_first << p_last << p_destStart; + return; + } + + // Reorder m_files. + if (p_destStart > p_last) { + int to = p_destStart - 1; + for (int i = p_first; i <= p_last; ++i) { + // Move p_first to p_destStart every time. + m_files.move(p_first, to); + } + } else { + int to = p_destStart; + for (int i = p_first; i <= p_last; ++i) { + m_files.move(i, to++); + } + } +} + +bool VDirectory::reorderFilesInConfig(int p_first, int p_last, int p_destStart) +{ + QString path = retrivePath(); + QJsonObject dirJson = VConfigManager::readDirectoryConfig(path); + Q_ASSERT(!dirJson.isEmpty()); + QJsonArray fileArray = dirJson["files"].toArray(); + Q_ASSERT(fileArray.size() == m_files.size()); + + if (p_destStart > p_last) { + int to = p_destStart - 1; + for (int i = p_first; i <= p_last; ++i) { + // Move p_first to p_destStart every time. + QJsonValue ele = fileArray.takeAt(p_first); + fileArray.insert(to, ele); + } + } else { + int to = p_destStart; + for (int i = p_first; i <= p_last; ++i) { + QJsonValue ele = fileArray.takeAt(i); + fileArray.insert(to++, ele); + } + } + dirJson["files"] = fileArray; + if (!VConfigManager::writeDirectoryConfig(path, dirJson)) { + return false; + } + return true; +} diff --git a/src/vdirectory.h b/src/vdirectory.h index cd65599f..a6ccb220 100644 --- a/src/vdirectory.h +++ b/src/vdirectory.h @@ -59,6 +59,8 @@ public: inline QString getNotebookName() const; inline bool isExpanded() const; void setExpanded(bool p_expanded); + void reorderFiles(int p_first, int p_last, int p_destStart); + bool reorderFilesInConfig(int p_first, int p_last, int p_destStart); static QJsonObject createDirectoryJson(); diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index d451b554..f959cc50 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -21,6 +21,7 @@ void VFileList::setupUI() fileList = new QListWidget(this); fileList->setContextMenuPolicy(Qt::CustomContextMenu); fileList->setSelectionMode(QAbstractItemView::ExtendedSelection); + fileList->setDragDropMode(QAbstractItemView::InternalMove); fileList->setObjectName("FileList"); QVBoxLayout *mainLayout = new QVBoxLayout; @@ -31,6 +32,8 @@ void VFileList::setupUI() this, &VFileList::contextMenuRequested); connect(fileList, &QListWidget::itemClicked, this, &VFileList::handleItemClicked); + connect(fileList->model(), &QAbstractItemModel::rowsMoved, + this, &VFileList::handleRowsMoved); setLayout(mainLayout); } @@ -140,8 +143,9 @@ QListWidgetItem* VFileList::insertFileListItem(VFile *file, bool atFront) { Q_ASSERT(file); QListWidgetItem *item = new QListWidgetItem(file->getName()); - item->setData(Qt::UserRole, QVariant::fromValue(file)); - + unsigned long long ptr = (long long)file; + item->setData(Qt::UserRole, ptr); + Q_ASSERT(sizeof(file) <= sizeof(ptr)); if (atFront) { fileList->insertItem(0, item); } else { @@ -469,3 +473,27 @@ bool VFileList::locateFile(const VFile *p_file) } return false; } + +void VFileList::handleRowsMoved(const QModelIndex &p_parent, int p_start, int p_end, const QModelIndex &p_destination, int p_row) +{ + if (p_parent == p_destination) { + // Items[p_start, p_end] are moved to p_row. + m_directory->reorderFiles(p_start, p_end, p_row); + Q_ASSERT(identicalListWithDirectory()); + } +} + +bool VFileList::identicalListWithDirectory() const +{ + const QVector files = m_directory->getFiles(); + int nrItems = fileList->count(); + if (nrItems != files.size()) { + return false; + } + for (int i = 0; i < nrItems; ++i) { + if (getVFile(fileList->item(i)) != files.at(i)) { + return false; + } + } + return true; +} diff --git a/src/vfilelist.h b/src/vfilelist.h index 30309345..add35837 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -44,6 +44,7 @@ private slots: void cutSelectedFiles(); void pasteFilesInCurDir(); void deleteFile(); + void handleRowsMoved(const QModelIndex &p_parent, int p_start, int p_end, const QModelIndex &p_destination, int p_row); public slots: void setDirectory(VDirectory *p_directory); @@ -64,7 +65,9 @@ private: bool copyFile(VDirectory *p_destDir, const QString &p_destName, VFile *p_file, bool p_cut); // New items have been added to direcotry. Update file list accordingly. QVector updateFileListAdded(); - inline QPointer getVFile(QListWidgetItem *p_item); + inline QPointer getVFile(QListWidgetItem *p_item) const; + // Check if the list items match exactly the contents of the directory. + bool identicalListWithDirectory() const; VEditArea *editArea; QListWidget *fileList; @@ -85,10 +88,10 @@ inline void VFileList::setEditArea(VEditArea *editArea) this->editArea = editArea; } -inline QPointer VFileList::getVFile(QListWidgetItem *p_item) +inline QPointer VFileList::getVFile(QListWidgetItem *p_item) const { Q_ASSERT(p_item); - return p_item->data(Qt::UserRole).value(); + return (VFile *)p_item->data(Qt::UserRole).toULongLong(); } inline const VDirectory *VFileList::currentDirectory() const