diff --git a/src/resources/icons/copy.svg b/src/resources/icons/copy.svg
new file mode 100644
index 00000000..75b8c0ba
--- /dev/null
+++ b/src/resources/icons/copy.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/src/resources/icons/cut.svg b/src/resources/icons/cut.svg
new file mode 100644
index 00000000..264e7c2b
--- /dev/null
+++ b/src/resources/icons/cut.svg
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/src/resources/icons/paste.svg b/src/resources/icons/paste.svg
new file mode 100644
index 00000000..84bb8e29
--- /dev/null
+++ b/src/resources/icons/paste.svg
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/src/src.pro b/src/src.pro
index b2f3c755..a03493c6 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -42,7 +42,8 @@ SOURCES += main.cpp\
veditwindow.cpp \
vedittab.cpp \
voutline.cpp \
- vtoc.cpp
+ vtoc.cpp \
+ vfilelocation.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@@ -73,7 +74,8 @@ HEADERS += vmainwindow.h \
veditwindow.h \
vedittab.h \
voutline.h \
- vtoc.h
+ vtoc.h \
+ vfilelocation.h
RESOURCES += \
vnote.qrc
diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp
index 2b4b8307..3c1051e3 100644
--- a/src/utils/vutils.cpp
+++ b/src/utils/vutils.cpp
@@ -4,6 +4,11 @@
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
VUtils::VUtils()
{
@@ -159,3 +164,42 @@ void VUtils::makeDirectory(const QString &path)
qDebug() << "mkdir" << path;
}
}
+
+ClipboardOpType VUtils::opTypeInClipboard()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ const QMimeData *mimeData = clipboard->mimeData();
+
+ if (mimeData->hasText()) {
+ QString text = mimeData->text();
+ QJsonObject clip = QJsonDocument::fromJson(text.toLocal8Bit()).object();
+ if (clip.contains("operation")) {
+ return (ClipboardOpType)clip["operation"].toInt();
+ }
+ }
+ return ClipboardOpType::Invalid;
+}
+
+bool VUtils::copyFile(const QString &p_srcFilePath, const QString &p_destFilePath, bool p_isCut)
+{
+ QString srcPath = QDir::cleanPath(p_srcFilePath);
+ QString destPath = QDir::cleanPath(p_destFilePath);
+
+ if (srcPath == destPath) {
+ return true;
+ }
+
+ if (p_isCut) {
+ QFile file(srcPath);
+ if (!file.rename(destPath)) {
+ qWarning() << "error: fail to copy file" << srcPath << destPath;
+ return false;
+ }
+ } else {
+ if (!QFile::copy(srcPath, destPath)) {
+ qWarning() << "error: fail to copy file" << srcPath << destPath;
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/utils/vutils.h b/src/utils/vutils.h
index 0fe70145..7e5ad932 100644
--- a/src/utils/vutils.h
+++ b/src/utils/vutils.h
@@ -6,6 +6,7 @@
#include
#include
#include "vconfigmanager.h"
+#include "vconstants.h"
class VUtils
{
@@ -25,6 +26,8 @@ public:
static QString basePathFromPath(const QString &path);
static QVector imagesFromMarkdownFile(const QString &filePath);
static void makeDirectory(const QString &path);
+ static ClipboardOpType opTypeInClipboard();
+ static bool copyFile(const QString &p_srcFilePath, const QString &p_destFilePath, bool p_isCut);
private:
static inline void addQssVarToMap(QVector > &map,
const QString &key, const QString &value);
diff --git a/src/vconstants.h b/src/vconstants.h
index cdd19d40..eadcd9e2 100644
--- a/src/vconstants.h
+++ b/src/vconstants.h
@@ -2,5 +2,6 @@
#define VCONSTANTS_H
enum class DocType { Html, Markdown };
+enum class ClipboardOpType { Invalid, CopyFile, CopyDir };
#endif
diff --git a/src/veditarea.cpp b/src/veditarea.cpp
index 9290963c..efa3b2df 100644
--- a/src/veditarea.cpp
+++ b/src/veditarea.cpp
@@ -242,13 +242,14 @@ void VEditArea::handleDirectoryRenamed(const QString ¬ebook, const QString &o
updateWindowStatus();
}
-void VEditArea::handleFileRenamed(const QString ¬ebook,
- const QString &oldRelativePath, const QString &newRelativePath)
+void VEditArea::handleFileRenamed(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath)
{
+ qDebug() << "fileRenamed" << p_srcNotebook << p_srcRelativePath << p_destNotebook << p_destRelativePath;
int nrWin = splitter->count();
for (int i = 0; i < nrWin; ++i) {
VEditWindow *win = getWindow(i);
- win->handleFileRenamed(notebook, oldRelativePath, newRelativePath);
+ win->handleFileRenamed(p_srcNotebook, p_srcRelativePath, p_destNotebook, p_destRelativePath);
}
updateWindowStatus();
}
diff --git a/src/veditarea.h b/src/veditarea.h
index 26a8b1ba..73db00a5 100644
--- a/src/veditarea.h
+++ b/src/veditarea.h
@@ -44,8 +44,8 @@ public slots:
void handleOutlineItemActivated(const VAnchor &anchor);
void handleDirectoryRenamed(const QString ¬ebook,
const QString &oldRelativePath, const QString &newRelativePath);
- void handleFileRenamed(const QString ¬ebook,
- const QString &oldRelativePath, const QString &newRelativePath);
+ void handleFileRenamed(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath);
private slots:
void handleSplitWindowRequest(VEditWindow *curWindow);
diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp
index 1c4143a8..a4b9c82c 100644
--- a/src/veditwindow.cpp
+++ b/src/veditwindow.cpp
@@ -280,23 +280,23 @@ void VEditWindow::handleDirectoryRenamed(const QString ¬ebook, const QString
updateTabListMenu();
}
-void VEditWindow::handleFileRenamed(const QString ¬ebook, const QString &oldRelativePath,
- const QString &newRelativePath)
+void VEditWindow::handleFileRenamed(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath)
{
QTabBar *tabs = tabBar();
int nrTabs = tabs->count();
for (int i = 0; i < nrTabs; ++i) {
QJsonObject tabJson = tabs->tabData(i).toJsonObject();
- if (tabJson["notebook"].toString() == notebook) {
+ if (tabJson["notebook"].toString() == p_srcNotebook) {
QString relativePath = tabJson["relative_path"].toString();
- if (relativePath == oldRelativePath) {
+ if (relativePath == p_srcRelativePath) {
VEditTab *tab = getTab(i);
- relativePath = newRelativePath;
- tabJson["relative_path"] = relativePath;
+ tabJson["notebook"] = p_destNotebook;
+ tabJson["relative_path"] = p_destRelativePath;
tabs->setTabData(i, tabJson);
tabs->setTabToolTip(i, generateTooltip(tabJson));
- tabs->setTabText(i, generateTabText(VUtils::fileNameFromPath(relativePath), tab->isModified()));
- QString path = QDir::cleanPath(QDir(vnote->getNotebookPath(notebook)).filePath(relativePath));
+ tabs->setTabText(i, generateTabText(VUtils::fileNameFromPath(p_destRelativePath), tab->isModified()));
+ QString path = QDir::cleanPath(QDir(vnote->getNotebookPath(p_destNotebook)).filePath(p_destRelativePath));
tab->updatePath(path);
}
}
diff --git a/src/veditwindow.h b/src/veditwindow.h
index 9ea74f56..63042556 100644
--- a/src/veditwindow.h
+++ b/src/veditwindow.h
@@ -39,8 +39,8 @@ public:
void scrollCurTab(const VAnchor &anchor);
void handleDirectoryRenamed(const QString ¬ebook,
const QString &oldRelativePath, const QString &newRelativePath);
- void handleFileRenamed(const QString ¬ebook,
- const QString &oldRelativePath, const QString &newRelativePath);
+ void handleFileRenamed(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath);
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp
index da152638..e548ed74 100644
--- a/src/vfilelist.cpp
+++ b/src/vfilelist.cpp
@@ -51,6 +51,24 @@ void VFileList::initActions()
fileInfoAct->setStatusTip(tr("View and edit current note's information"));
connect(fileInfoAct, &QAction::triggered,
this, &VFileList::curFileInfo);
+
+ copyAct = new QAction(QIcon(":/resources/icons/copy.svg"),
+ tr("&Copy"), this);
+ copyAct->setStatusTip(tr("Copy selected notes"));
+ connect(copyAct, &QAction::triggered,
+ this, &VFileList::copySelectedFiles);
+
+ cutAct = new QAction(QIcon(":/resources/icons/cut.svg"),
+ tr("&Cut"), this);
+ cutAct->setStatusTip(tr("Cut selected notes"));
+ connect(cutAct, &QAction::triggered,
+ this, &VFileList::cutSelectedFiles);
+
+ pasteAct = new QAction(QIcon(":/resources/icons/paste.svg"),
+ tr("&Paste"), this);
+ pasteAct->setStatusTip(tr("Paste notes"));
+ connect(pasteAct, &QAction::triggered,
+ this, &VFileList::pasteFilesInCurDir);
}
void VFileList::setDirectory(QJsonObject dirJson)
@@ -88,6 +106,7 @@ void VFileList::updateFileList()
{
QString path = QDir(rootPath).filePath(relativePath);
+ fileList->clear();
if (!QDir(path).exists()) {
qDebug() << "invalid notebook directory:" << path;
QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), tr("Invalid notebook directory."),
@@ -144,7 +163,8 @@ void VFileList::fileInfo(const QString &p_notebook, const QString &p_relativePat
defaultName = name;
continue;
}
- renameFile(p_notebook, p_relativePath, name);
+ copyFile(p_notebook, p_relativePath, p_notebook,
+ QDir(VUtils::basePathFromPath(p_relativePath)).filePath(name), true);
}
break;
} while (true);
@@ -252,8 +272,13 @@ void VFileList::contextMenuRequested(QPoint pos)
if (item) {
menu.addAction(deleteFileAct);
menu.addAction(fileInfoAct);
+ menu.addAction(copyAct);
+ menu.addAction(cutAct);
}
+ if (VUtils::opTypeInClipboard() == ClipboardOpType::CopyFile) {
+ menu.addAction(pasteAct);
+ }
menu.exec(fileList->mapToGlobal(pos));
}
@@ -306,52 +331,20 @@ QListWidgetItem* VFileList::createFileAndUpdateList(const QString &name)
file.close();
qDebug() << "create file:" << filePath;
- // Update current directory's config file to include this new file
- QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
- Q_ASSERT(!dirJson.isEmpty());
- QJsonObject fileJson;
- fileJson["name"] = name;
- QJsonArray fileArray = dirJson["files"].toArray();
- fileArray.push_front(fileJson);
- dirJson["files"] = fileArray;
- if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
- qWarning() << "error: fail to update directory's configuration file to add a new file"
- << name;
+ if (!addFileInConfig(filePath, 0)) {
file.remove();
return NULL;
}
- return insertFileListItem(fileJson, true);
+ return insertFileListItem(readFileInConfig(filePath), true);
}
void VFileList::deleteFileAndUpdateList(const QString &p_notebook,
const QString &p_relativePath)
{
- QString path = QDir(vnote->getNotebookPath(p_notebook)).filePath(VUtils::basePathFromPath(p_relativePath));
- QString fileName = VUtils::fileNameFromPath(p_relativePath);
- QString filePath = QDir(path).filePath(fileName);
+ QString filePath = QDir(vnote->getNotebookPath(p_notebook)).filePath(p_relativePath);
- // Update current directory's config file to exclude this file
- QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
- Q_ASSERT(!dirJson.isEmpty());
- QJsonArray fileArray = dirJson["files"].toArray();
- bool deleted = false;
- for (int i = 0; i < fileArray.size(); ++i) {
- QJsonObject ele = fileArray[i].toObject();
- if (ele["name"].toString() == fileName) {
- fileArray.removeAt(i);
- deleted = true;
- break;
- }
- }
- if (!deleted) {
- qWarning() << "error: fail to find" << fileName << "to delete";
- return;
- }
- dirJson["files"] = fileArray;
- if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
- qWarning() << "error: fail to update directory's configuration file to delete"
- << fileName;
+ if (!removeFileInConfig(filePath)) {
return;
}
@@ -446,86 +439,6 @@ void VFileList::handleDirectoryRenamed(const QString ¬ebook,
}
}
-// @p_relativePath contains the flie name
-void VFileList::renameFile(const QString &p_notebook,
- const QString &p_relativePath, const QString &p_newName)
-{
- QString name = VUtils::fileNameFromPath(p_relativePath);
-
- // If change the file type, we need to convert it
- DocType docType = VUtils::isMarkdown(name) ? DocType::Markdown : DocType::Html;
- DocType newDocType = VUtils::isMarkdown(p_newName) ? DocType::Markdown : DocType::Html;
- if (docType != newDocType) {
- if (editArea->isFileOpened(p_notebook, p_relativePath)) {
- QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Rename will change the note type"),
- QMessageBox::Ok | QMessageBox::Cancel, this);
- msgBox.setDefaultButton(QMessageBox::Ok);
- msgBox.setInformativeText(QString("You should close the note %1 before continue").arg(name));
- if (QMessageBox::Ok == msgBox.exec()) {
- QJsonObject curItemJson;
- curItemJson["notebook"] = p_notebook;
- curItemJson["relative_path"] = p_relativePath;
- curItemJson["is_forced"] = false;
- if (!editArea->closeFile(curItemJson)) {
- return;
- }
- } else {
- return;
- }
- }
- convertFileType(p_notebook, p_relativePath, docType, newDocType);
- }
-
- QString path = QDir(vnote->getNotebookPath(p_notebook)).filePath(VUtils::basePathFromPath(p_relativePath));
- QFile file(QDir(path).filePath(name));
- QString newFilePath(QDir(path).filePath(p_newName));
- Q_ASSERT(file.exists());
- if (!file.rename(newFilePath)) {
- qWarning() << "error: fail to rename file" << name << "under" << path;
- QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Could not rename note \"%1\" under \"%2\".")
- .arg(name).arg(path), QMessageBox::Ok, this);
- msgBox.setInformativeText(QString("Please check if there already exists a file named \"%1\".").arg(p_newName));
- msgBox.exec();
- return;
- }
-
- // Update directory's config file
- QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
- Q_ASSERT(!dirJson.isEmpty());
- QJsonArray fileArray = dirJson["files"].toArray();
- int index = 0;
- for (index = 0; index < fileArray.size(); ++index) {
- QJsonObject tmp = fileArray[index].toObject();
- if (tmp["name"].toString() == name) {
- tmp["name"] = p_newName;
- fileArray[index] = tmp;
- break;
- }
- }
- Q_ASSERT(index != fileArray.size());
- dirJson["files"] = fileArray;
- if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
- qWarning() << "error: fail to rename file"
- << name << "to" << p_newName;
- file.rename(name);
- return;
- }
-
- // Update item
- QListWidgetItem *item = findItem(p_notebook, p_relativePath);
- if (item) {
- QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject();
- itemJson["name"] = p_newName;
- item->setData(Qt::UserRole, itemJson);
- item->setText(p_newName);
- }
-
- QString oldPath = QDir::cleanPath(p_relativePath);
- QString newPath = QDir::cleanPath(QDir(VUtils::basePathFromPath(p_relativePath)).filePath(p_newName));
- qDebug() << "file renamed" << oldPath << "to" << newPath;
- emit fileRenamed(p_notebook, oldPath, newPath);
-}
-
void VFileList::convertFileType(const QString ¬ebook, const QString &fileRelativePath,
DocType oldType, DocType newType)
{
@@ -559,3 +472,258 @@ void VFileList::deleteLocalImages(const QString &filePath)
}
qDebug() << "delete" << deleted << "images for" << filePath;
}
+
+void VFileList::copySelectedFiles(bool p_isCut)
+{
+ QList items = fileList->selectedItems();
+ if (items.isEmpty()) {
+ return;
+ }
+ QJsonArray files;
+ QDir dir(relativePath);
+ for (int i = 0; i < items.size(); ++i) {
+ QJsonObject itemJson = items[i]->data(Qt::UserRole).toJsonObject();
+ QString itemName = itemJson["name"].toString();
+ QJsonObject fileJson;
+ fileJson["notebook"] = notebook;
+ fileJson["relative_path"] = dir.filePath(itemName);
+ files.append(fileJson);
+ }
+
+ copyFileInfoToClipboard(files, p_isCut);
+}
+
+void VFileList::cutSelectedFiles()
+{
+ copySelectedFiles(true);
+}
+
+void VFileList::copyFileInfoToClipboard(const QJsonArray &p_files, bool p_isCut)
+{
+ QJsonObject clip;
+ clip["operation"] = (int)ClipboardOpType::CopyFile;
+ clip["is_cut"] = p_isCut;
+ clip["sources"] = p_files;
+
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(QJsonDocument(clip).toJson(QJsonDocument::Compact));
+}
+
+void VFileList::pasteFilesInCurDir()
+{
+ pasteFiles(notebook, relativePath);
+}
+
+void VFileList::pasteFiles(const QString &p_notebook, const QString &p_dirRelativePath)
+{
+ qDebug() << "paste files to" << p_notebook << p_dirRelativePath;
+ QClipboard *clipboard = QApplication::clipboard();
+ QString text = clipboard->text();
+ QJsonObject clip = QJsonDocument::fromJson(text.toLocal8Bit()).object();
+ Q_ASSERT(!clip.isEmpty() && clip["operation"] == (int)ClipboardOpType::CopyFile);
+
+ bool isCut = clip["is_cut"].toBool();
+ QJsonArray sources = clip["sources"].toArray();
+
+ int nrFiles = sources.size();
+ QDir destDir(p_dirRelativePath);
+ int nrPasted = 0;
+ for (int i = 0; i < nrFiles; ++i) {
+ QJsonObject file = sources[i].toObject();
+ QString srcNotebook = file["notebook"].toString();
+ QString srcRelativePath = file["relative_path"].toString();
+ bool ret = copyFile(srcNotebook, srcRelativePath, p_notebook,
+ destDir.filePath(VUtils::fileNameFromPath(srcRelativePath)), isCut);
+ if (ret) {
+ nrPasted++;
+ }
+ }
+ qDebug() << "pasted" << nrPasted << "files sucessfully";
+ clipboard->clear();
+}
+
+bool VFileList::copyFile(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath,
+ bool p_isCut)
+{
+ QString srcPath = QDir(vnote->getNotebookPath(p_srcNotebook)).filePath(p_srcRelativePath);
+ srcPath = QDir::cleanPath(srcPath);
+ QString destPath = QDir(vnote->getNotebookPath(p_destNotebook)).filePath(p_destRelativePath);
+ destPath = QDir::cleanPath(destPath);
+ if (srcPath == destPath) {
+ return true;
+ }
+
+ // If change the file type, we need to convert it
+ bool needConversion = false;
+ DocType docType = VUtils::isMarkdown(srcPath) ? DocType::Markdown : DocType::Html;
+ DocType newDocType = VUtils::isMarkdown(destPath) ? DocType::Markdown : DocType::Html;
+ if (docType != newDocType) {
+ if (editArea->isFileOpened(p_srcNotebook, p_srcRelativePath)) {
+ QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Rename will change the note type"),
+ QMessageBox::Ok | QMessageBox::Cancel, this);
+ msgBox.setDefaultButton(QMessageBox::Ok);
+ msgBox.setInformativeText(QString("You should close the note %1 before continue")
+ .arg(VUtils::fileNameFromPath(p_srcRelativePath)));
+ if (QMessageBox::Ok == msgBox.exec()) {
+ QJsonObject curItemJson;
+ curItemJson["notebook"] = p_srcNotebook;
+ curItemJson["relative_path"] = p_srcRelativePath;
+ curItemJson["is_forced"] = false;
+ if (!editArea->closeFile(curItemJson)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ // Convert it later
+ needConversion = true;
+ }
+
+ QVector images;
+ if (docType == DocType::Markdown) {
+ images = VUtils::imagesFromMarkdownFile(srcPath);
+ }
+
+ // Copy the file
+ if (!VUtils::copyFile(srcPath, destPath, p_isCut)) {
+ QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Fail to copy %1 from %2.")
+ .arg(p_srcRelativePath).arg(p_srcNotebook), QMessageBox::Ok, this);
+ msgBox.setInformativeText(QString("Please check if there already exists a file with the same name"));
+ msgBox.exec();
+ return false;
+ }
+
+ if (needConversion) {
+ convertFileType(p_destNotebook, p_destRelativePath, docType, newDocType);
+ }
+
+ // We need to copy images when it is still markdown
+ if (!images.isEmpty()) {
+ if (newDocType == DocType::Markdown) {
+ QString dirPath = QDir(VUtils::basePathFromPath(destPath)).filePath("images");
+ VUtils::makeDirectory(dirPath);
+ int nrPasted = 0;
+ for (int i = 0; i < images.size(); ++i) {
+ if (!QFile(images[i]).exists()) {
+ continue;
+ }
+
+ QString destImagePath = QDir(dirPath).filePath(VUtils::fileNameFromPath(images[i]));
+ if (VUtils::copyFile(images[i], destImagePath, p_isCut)) {
+ nrPasted++;
+ } else {
+ QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Fail to copy image %1.")
+ .arg(images[i]), QMessageBox::Ok, this);
+ msgBox.setInformativeText(QString("Please check if there already exists a file with the same name and manually copy it"));
+ msgBox.exec();
+ }
+ }
+ qDebug() << "pasted" << nrPasted << "images sucessfully";
+ } else {
+ // Delete the images
+ for (int i = 0; i < images.size(); ++i) {
+ QFile file(images[i]);
+ file.remove();
+ }
+ }
+ }
+
+ int idx = -1;
+ if (p_isCut) {
+ // Remove src in the config
+ idx = removeFileInConfig(srcPath);
+ if (VUtils::basePathFromPath(srcPath) != VUtils::basePathFromPath(destPath)) {
+ idx = -1;
+ }
+ }
+
+ // Add dest in the config
+ addFileInConfig(destPath, idx);
+
+ updateFileList();
+
+ if (p_isCut) {
+ emit fileRenamed(p_srcNotebook, p_srcRelativePath,
+ p_destNotebook, p_destRelativePath);
+ }
+ return true;
+}
+
+int VFileList::removeFileInConfig(const QString &p_filePath)
+{
+ QString dirPath = VUtils::basePathFromPath(p_filePath);
+ QString fileName = VUtils::fileNameFromPath(p_filePath);
+ // Update current directory's config file to exclude this file
+ QJsonObject dirJson = VConfigManager::readDirectoryConfig(dirPath);
+ Q_ASSERT(!dirJson.isEmpty());
+ QJsonArray fileArray = dirJson["files"].toArray();
+ bool deleted = false;
+ int idx = -1;
+ for (int i = 0; i < fileArray.size(); ++i) {
+ QJsonObject ele = fileArray[i].toObject();
+ if (ele["name"].toString() == fileName) {
+ fileArray.removeAt(i);
+ deleted = true;
+ idx = i;
+ break;
+ }
+ }
+ if (!deleted) {
+ qWarning() << "error: fail to find" << fileName << "to delete";
+ return idx;
+ }
+ dirJson["files"] = fileArray;
+ if (!VConfigManager::writeDirectoryConfig(dirPath, dirJson)) {
+ qWarning() << "error: fail to update directory's configuration file to delete"
+ << fileName;
+ return idx;
+ }
+ return idx;
+}
+
+// @index = -1, add it to the end of the list
+bool VFileList::addFileInConfig(const QString &p_filePath, int p_index)
+{
+ QString dirPath = VUtils::basePathFromPath(p_filePath);
+ QString fileName = VUtils::fileNameFromPath(p_filePath);
+
+ // Update current directory's config file to include this file
+ QJsonObject dirJson = VConfigManager::readDirectoryConfig(dirPath);
+ Q_ASSERT(!dirJson.isEmpty());
+ QJsonObject fileJson;
+ fileJson["name"] = fileName;
+ QJsonArray fileArray = dirJson["files"].toArray();
+ if (p_index == -1) {
+ p_index = fileArray.size();
+ }
+ fileArray.insert(p_index, fileJson);
+ dirJson["files"] = fileArray;
+ if (!VConfigManager::writeDirectoryConfig(dirPath, dirJson)) {
+ qWarning() << "error: fail to update directory's configuration file to add a new file"
+ << fileName;
+ return false;
+ }
+
+ return true;
+}
+
+QJsonObject VFileList::readFileInConfig(const QString &p_filePath)
+{
+ QString dirPath = VUtils::basePathFromPath(p_filePath);
+ QString fileName = VUtils::fileNameFromPath(p_filePath);
+
+ QJsonObject dirJson = VConfigManager::readDirectoryConfig(dirPath);
+ Q_ASSERT(!dirJson.isEmpty());
+
+ qDebug() << "config" << p_filePath;
+ QJsonArray fileArray = dirJson["files"].toArray();
+ for (int i = 0; i < fileArray.size(); ++i) {
+ QJsonObject ele = fileArray[i].toObject();
+ if (ele["name"].toString() == fileName) {
+ return ele;
+ }
+ }
+ return QJsonObject();
+}
diff --git a/src/vfilelist.h b/src/vfilelist.h
index 8215e61e..efb5a604 100644
--- a/src/vfilelist.h
+++ b/src/vfilelist.h
@@ -29,8 +29,8 @@ signals:
void fileClicked(QJsonObject fileJson);
void fileDeleted(QJsonObject fileJson);
void fileCreated(QJsonObject fileJson);
- void fileRenamed(const QString ¬ebook, const QString &oldPath,
- const QString &newPath);
+ void fileRenamed(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath);
void directoryChanged(const QString ¬ebook, const QString &relativePath);
private slots:
@@ -38,6 +38,9 @@ private slots:
void handleItemClicked(QListWidgetItem *currentItem);
void curFileInfo();
void deleteCurFile();
+ void copySelectedFiles(bool p_isCut = false);
+ void cutSelectedFiles();
+ void pasteFilesInCurDir();
public slots:
void setDirectory(QJsonObject dirJson);
@@ -58,12 +61,18 @@ private:
void deleteFileAndUpdateList(const QString &p_notebook,
const QString &p_relativePath);
void clearDirectoryInfo();
- void renameFile(const QString &p_notebook,
- const QString &p_relativePath, const QString &p_newName);
void convertFileType(const QString ¬ebook, const QString &fileRelativePath,
DocType oldType, DocType newType);
QListWidgetItem *findItem(const QString &p_notebook, const QString &p_relativePath);
void deleteLocalImages(const QString &filePath);
+ void copyFileInfoToClipboard(const QJsonArray &p_files, bool p_isCut);
+ void pasteFiles(const QString &p_notebook, const QString &p_dirRelativePath);
+ bool copyFile(const QString &p_srcNotebook, const QString &p_srcRelativePath,
+ const QString &p_destNotebook, const QString &p_destRelativePath,
+ bool p_isCut);
+ int removeFileInConfig(const QString &p_filePath);
+ bool addFileInConfig(const QString &p_filePath, int p_index);
+ QJsonObject readFileInConfig(const QString &p_filePath);
VNote *vnote;
QString notebook;
@@ -80,6 +89,9 @@ private:
QAction *newFileAct;
QAction *deleteFileAct;
QAction *fileInfoAct;
+ QAction *copyAct;
+ QAction *cutAct;
+ QAction *pasteAct;
};
inline void VFileList::setEditArea(VEditArea *editArea)
diff --git a/src/vfilelocation.cpp b/src/vfilelocation.cpp
new file mode 100644
index 00000000..7361f269
--- /dev/null
+++ b/src/vfilelocation.cpp
@@ -0,0 +1,10 @@
+#include "vfilelocation.h"
+
+VFileLocation::VFileLocation()
+{
+}
+
+VFileLocation::VFileLocation(const QString &p_notebook, const QString &p_relativePath)
+ : m_notebook(p_notebook), m_relativePath(p_relativePath)
+{
+}
diff --git a/src/vfilelocation.h b/src/vfilelocation.h
new file mode 100644
index 00000000..b11a8bc0
--- /dev/null
+++ b/src/vfilelocation.h
@@ -0,0 +1,15 @@
+#ifndef VFILELOCATION_H
+#define VFILELOCATION_H
+
+#include
+
+class VFileLocation
+{
+public:
+ VFileLocation();
+ VFileLocation(const QString &p_notebook, const QString &p_relativePath);
+ QString m_notebook;
+ QString m_relativePath;
+};
+
+#endif // VFILELOCATION_H
diff --git a/src/vnote.qrc b/src/vnote.qrc
index 3d8babd5..24e857b4 100644
--- a/src/vnote.qrc
+++ b/src/vnote.qrc
@@ -64,5 +64,8 @@
resources/vnote.qss
resources/icons/note_info_tb.svg
resources/icons/delete_note_tb.svg
+ resources/icons/copy.svg
+ resources/icons/cut.svg
+ resources/icons/paste.svg