mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
support copy and paste directory
Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
parent
787d54c808
commit
02d5300821
@ -202,6 +202,54 @@ bool VUtils::copyFile(const QString &p_srcFilePath, const QString &p_destFilePat
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy @p_srcDirPath to be @p_destDirPath.
|
||||
bool VUtils::copyDirectory(const QString &p_srcDirPath, const QString &p_destDirPath, bool p_isCut)
|
||||
{
|
||||
QString srcPath = QDir::cleanPath(p_srcDirPath);
|
||||
QString destPath = QDir::cleanPath(p_destDirPath);
|
||||
if (srcPath == destPath) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make a directory
|
||||
QDir parentDir(VUtils::basePathFromPath(p_destDirPath));
|
||||
QString dirName = VUtils::fileNameFromPath(p_destDirPath);
|
||||
if (!parentDir.mkdir(dirName)) {
|
||||
qWarning() << QString("failed to create target directory %1: already exists").arg(p_destDirPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle sub-dirs recursively and copy files.
|
||||
QDir srcDir(p_srcDirPath);
|
||||
QDir destDir(p_destDirPath);
|
||||
Q_ASSERT(srcDir.exists() && destDir.exists());
|
||||
QFileInfoList nodes = srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::Hidden
|
||||
| QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
||||
for (int i = 0; i < nodes.size(); ++i) {
|
||||
const QFileInfo &fileInfo = nodes.at(i);
|
||||
QString name = fileInfo.fileName();
|
||||
if (fileInfo.isDir()) {
|
||||
if (!copyDirectory(srcDir.filePath(name), destDir.filePath(name), p_isCut)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(fileInfo.isFile());
|
||||
if (!copyFile(srcDir.filePath(name), destDir.filePath(name), p_isCut)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the src dir if p_isCut
|
||||
if (p_isCut) {
|
||||
if (!srcDir.removeRecursively()) {
|
||||
qWarning() << "failed to remove directory" << p_srcDirPath;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int VUtils::showMessage(QMessageBox::Icon p_icon, const QString &p_title, const QString &p_text, const QString &p_infoText,
|
||||
QMessageBox::StandardButtons p_buttons, QMessageBox::StandardButton p_defaultBtn, QWidget *p_parent)
|
||||
{
|
||||
@ -236,3 +284,21 @@ QString VUtils::generateCopiedFileName(const QString &p_dirPath, const QString &
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
QString VUtils::generateCopiedDirName(const QString &p_parentDirPath, const QString &p_dirName)
|
||||
{
|
||||
QDir dir(p_parentDirPath);
|
||||
QString name = p_dirName;
|
||||
QString dirPath = dir.filePath(name);
|
||||
int index = 0;
|
||||
while (QDir(dirPath).exists()) {
|
||||
QString seq;
|
||||
if (index > 0) {
|
||||
seq = QString::number(index);
|
||||
}
|
||||
index++;
|
||||
name = QString("%1_copy%2").arg(p_dirName).arg(seq);
|
||||
dirPath = dir.filePath(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
static QString generateImageFileName(const QString &path, const QString &title,
|
||||
const QString &format = "png");
|
||||
static QString generateCopiedFileName(const QString &p_dirPath, const QString &p_fileName);
|
||||
static QString generateCopiedDirName(const QString &p_parentDirPath, const QString &p_dirName);
|
||||
static void processStyle(QString &style, const QVector<QPair<QString, QString> > &varMap);
|
||||
static bool isMarkdown(const QString &fileName);
|
||||
static inline QString directoryNameFromPath(const QString& path);
|
||||
@ -30,6 +31,7 @@ public:
|
||||
static void makeDirectory(const QString &path);
|
||||
static ClipboardOpType opTypeInClipboard();
|
||||
static bool copyFile(const QString &p_srcFilePath, const QString &p_destFilePath, bool p_isCut);
|
||||
static bool copyDirectory(const QString &p_srcDirPath, const QString &p_destDirPath, bool p_isCut);
|
||||
static int showMessage(QMessageBox::Icon p_icon, const QString &p_title, const QString &p_text,
|
||||
const QString &p_infoText, QMessageBox::StandardButtons p_buttons,
|
||||
QMessageBox::StandardButton p_defaultBtn, QWidget *p_parent);
|
||||
|
@ -126,15 +126,7 @@ VDirectory *VDirectory::createSubDirectory(const QString &p_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Update parent's config file to include this new directory
|
||||
QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
|
||||
Q_ASSERT(!dirJson.isEmpty());
|
||||
QJsonObject itemJson;
|
||||
itemJson["name"] = p_name;
|
||||
QJsonArray subDirArray = dirJson["sub_directories"].toArray();
|
||||
subDirArray.append(itemJson);
|
||||
dirJson["sub_directories"] = subDirArray;
|
||||
if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
|
||||
if (!createSubDirectoryInConfig(p_name)) {
|
||||
VConfigManager::deleteDirectoryConfig(QDir(path).filePath(p_name));
|
||||
dir.rmdir(p_name);
|
||||
return NULL;
|
||||
@ -145,6 +137,26 @@ VDirectory *VDirectory::createSubDirectory(const QString &p_name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool VDirectory::createSubDirectoryInConfig(const QString &p_name, int p_index)
|
||||
{
|
||||
QString path = retrivePath();
|
||||
QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
|
||||
Q_ASSERT(!dirJson.isEmpty());
|
||||
QJsonObject itemJson;
|
||||
itemJson["name"] = p_name;
|
||||
QJsonArray subDirArray = dirJson["sub_directories"].toArray();
|
||||
if (p_index == -1) {
|
||||
subDirArray.append(itemJson);
|
||||
} else {
|
||||
subDirArray.insert(p_index, itemJson);
|
||||
}
|
||||
dirJson["sub_directories"] = subDirArray;
|
||||
if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VDirectory *VDirectory::findSubDirectory(const QString &p_name)
|
||||
{
|
||||
if (!m_opened && !open()) {
|
||||
@ -171,6 +183,22 @@ VFile *VDirectory::findFile(const QString &p_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool VDirectory::containsFile(const VFile *p_file) const
|
||||
{
|
||||
if (!p_file) {
|
||||
return false;
|
||||
}
|
||||
QObject *paDir = p_file->parent();
|
||||
while (paDir) {
|
||||
if (paDir == this) {
|
||||
return true;
|
||||
} else {
|
||||
paDir = paDir->parent();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VFile *VDirectory::createFile(const QString &p_name)
|
||||
{
|
||||
Q_ASSERT(!p_name.isEmpty());
|
||||
@ -254,24 +282,77 @@ VFile *VDirectory::addFile(const QString &p_name, int p_index)
|
||||
return file;
|
||||
}
|
||||
|
||||
void VDirectory::deleteSubDirectory(VDirectory *p_subDir)
|
||||
VDirectory *VDirectory::addSubDirectory(VDirectory *p_dir, int p_index)
|
||||
{
|
||||
if (!open()) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
if (!createSubDirectoryInConfig(p_dir->getName(), p_index)) {
|
||||
return NULL;
|
||||
}
|
||||
if (p_index == -1) {
|
||||
m_subDirs.append(p_dir);
|
||||
} else {
|
||||
m_subDirs.insert(p_index, p_dir);
|
||||
}
|
||||
p_dir->setParent(this);
|
||||
return p_dir;
|
||||
}
|
||||
|
||||
VDirectory *VDirectory::addSubDirectory(const QString &p_name, int p_index)
|
||||
{
|
||||
if (!open()) {
|
||||
return NULL;
|
||||
}
|
||||
if (!createSubDirectoryInConfig(p_name, p_index)) {
|
||||
return NULL;
|
||||
}
|
||||
VDirectory *dir = new VDirectory(m_notebook, p_name, this);
|
||||
if (!dir) {
|
||||
return NULL;
|
||||
}
|
||||
if (p_index == -1) {
|
||||
m_subDirs.append(dir);
|
||||
} else {
|
||||
m_subDirs.insert(p_index, dir);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
void VDirectory::deleteSubDirectory(VDirectory *p_subDir)
|
||||
{
|
||||
QString dirPath = p_subDir->retrivePath();
|
||||
|
||||
removeSubDirectory(p_subDir);
|
||||
|
||||
// Delete the entire directory
|
||||
p_subDir->close();
|
||||
QDir dir(dirPath);
|
||||
if (!dir.removeRecursively()) {
|
||||
qWarning() << "failed to remove" << dirPath << "recursively";
|
||||
} else {
|
||||
qDebug() << "deleted" << dirPath;
|
||||
}
|
||||
delete p_subDir;
|
||||
}
|
||||
|
||||
int VDirectory::removeSubDirectory(VDirectory *p_dir)
|
||||
{
|
||||
Q_ASSERT(m_opened);
|
||||
Q_ASSERT(p_dir);
|
||||
|
||||
QString path = retrivePath();
|
||||
|
||||
int index;
|
||||
for (index = 0; index < m_subDirs.size(); ++index) {
|
||||
if (m_subDirs[index] == p_subDir) {
|
||||
if (m_subDirs[index] == p_dir) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == m_subDirs.size()) {
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(index != m_subDirs.size());
|
||||
m_subDirs.remove(index);
|
||||
QString name = p_subDir->getName();
|
||||
|
||||
QString name = p_dir->getName();
|
||||
// Update config to exclude this directory
|
||||
QJsonObject dirJson = VConfigManager::readDirectoryConfig(path);
|
||||
QJsonArray subDirArray = dirJson["sub_directories"].toArray();
|
||||
@ -281,6 +362,7 @@ void VDirectory::deleteSubDirectory(VDirectory *p_subDir)
|
||||
if (ele["name"].toString() == name) {
|
||||
subDirArray.removeAt(i);
|
||||
deleted = true;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -289,17 +371,7 @@ void VDirectory::deleteSubDirectory(VDirectory *p_subDir)
|
||||
if (!VConfigManager::writeDirectoryConfig(path, dirJson)) {
|
||||
qWarning() << "failed to update configuration in" << path;
|
||||
}
|
||||
|
||||
// Delete the entire directory
|
||||
p_subDir->close();
|
||||
delete p_subDir;
|
||||
QString dirName = QDir(path).filePath(name);
|
||||
QDir dir(dirName);
|
||||
if (!dir.removeRecursively()) {
|
||||
qWarning() << "failed to delete" << dirName << "recursively";
|
||||
} else {
|
||||
qDebug() << "deleted" << dirName;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// After calling this, p_file->parent() remain the same.
|
||||
@ -466,3 +538,37 @@ VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName,
|
||||
|
||||
return destFile;
|
||||
}
|
||||
|
||||
// Copy @p_srcDir to be a sub-directory of @p_destDir with name @p_destName.
|
||||
VDirectory *VDirectory::copyDirectory(VDirectory *p_destDir, const QString &p_destName,
|
||||
VDirectory *p_srcDir, bool p_cut)
|
||||
{
|
||||
QString srcPath = QDir::cleanPath(p_srcDir->retrivePath());
|
||||
QString destPath = QDir::cleanPath(QDir(p_destDir->retrivePath()).filePath(p_destName));
|
||||
if (srcPath == destPath) {
|
||||
return p_srcDir;
|
||||
}
|
||||
VDirectory *srcParentDir = p_srcDir->getParentDirectory();
|
||||
|
||||
// Copy the directory
|
||||
if (!VUtils::copyDirectory(srcPath, destPath, p_cut)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Handle VDirectory
|
||||
int index = -1;
|
||||
VDirectory *destDir = NULL;
|
||||
if (p_cut) {
|
||||
// Remove the directory from config
|
||||
index = srcParentDir->removeSubDirectory(p_srcDir);
|
||||
p_srcDir->setName(p_destName);
|
||||
if (srcParentDir != p_destDir) {
|
||||
index = -1;
|
||||
}
|
||||
// Add the directory to new dir's config
|
||||
destDir = p_destDir->addSubDirectory(p_srcDir, index);
|
||||
} else {
|
||||
destDir = p_destDir->addSubDirectory(p_destName, -1);
|
||||
}
|
||||
return destDir;
|
||||
}
|
||||
|
@ -20,34 +20,41 @@ public:
|
||||
void close();
|
||||
VDirectory *createSubDirectory(const QString &p_name);
|
||||
VDirectory *findSubDirectory(const QString &p_name);
|
||||
// Returns the VFile with the name @p_name.
|
||||
VFile *findFile(const QString &p_name);
|
||||
// If current dir or its sub-dir contains @p_file.
|
||||
bool containsFile(const VFile *p_file) const;
|
||||
VFile *createFile(const QString &p_name);
|
||||
void deleteSubDirectory(VDirectory *p_subDir);
|
||||
// Remove the file in the config and m_files without deleting it in the disk.
|
||||
int removeFile(VFile *p_file);
|
||||
// Remove the directory in the config and m_subDirs without deleting it in the disk.
|
||||
int removeSubDirectory(VDirectory *p_dir);
|
||||
// Add the file in the config and m_files. If @p_index is -1, add it at the end.
|
||||
// Return the VFile if succeed.
|
||||
VFile *addFile(VFile *p_file, int p_index);
|
||||
VFile *addFile(const QString &p_name, int p_index);
|
||||
VDirectory *addSubDirectory(VDirectory *p_dir, int p_index);
|
||||
VDirectory *addSubDirectory(const QString &p_name, int p_index);
|
||||
void deleteFile(VFile *p_file);
|
||||
bool rename(const QString &p_name);
|
||||
|
||||
inline const QVector<VDirectory *> &getSubDirs() const;
|
||||
inline const QString &getName() const;
|
||||
inline bool isOpened() const;
|
||||
inline VDirectory *getParentDirectory();
|
||||
inline const QVector<VFile *> &getFiles() const;
|
||||
inline QString retrivePath() const;
|
||||
inline QString retriveRelativePath() const;
|
||||
inline QString retriveNotebook() const;
|
||||
|
||||
// Copy @p_srcFile to @p_destDir, setting new name to @p_destName.
|
||||
// @p_cut: copy or cut. Returns the dest VFile.
|
||||
static VFile *copyFile(VDirectory *p_destDir, const QString &p_destName,
|
||||
VFile *p_srcFile, bool p_cut);
|
||||
signals:
|
||||
static VDirectory *copyDirectory(VDirectory *p_destDir, const QString &p_destName,
|
||||
VDirectory *p_srcDir, bool p_cut);
|
||||
|
||||
public slots:
|
||||
inline const QVector<VDirectory *> &getSubDirs() const;
|
||||
inline const QString &getName() const;
|
||||
inline void setName(const QString &p_name);
|
||||
inline bool isOpened() const;
|
||||
inline VDirectory *getParentDirectory();
|
||||
inline const VDirectory *getParentDirectory() const;
|
||||
inline const QVector<VFile *> &getFiles() const;
|
||||
inline QString retrivePath() const;
|
||||
inline QString retriveRelativePath() const;
|
||||
inline QString getNotebook() const;
|
||||
|
||||
private:
|
||||
// Get the path of @p_dir recursively
|
||||
@ -56,6 +63,7 @@ private:
|
||||
QString retriveRelativePath(const VDirectory *p_dir) const;
|
||||
QJsonObject createDirectoryJson() const;
|
||||
bool createFileInConfig(const QString &p_name, int p_index = -1);
|
||||
bool createSubDirectoryInConfig(const QString &p_name, int p_index = -1);
|
||||
|
||||
QPointer<VNotebook> m_notebook;
|
||||
QString m_name;
|
||||
@ -76,6 +84,11 @@ inline const QString &VDirectory::getName() const
|
||||
return m_name;
|
||||
}
|
||||
|
||||
inline void VDirectory::setName(const QString &p_name)
|
||||
{
|
||||
m_name = p_name;
|
||||
}
|
||||
|
||||
inline bool VDirectory::isOpened() const
|
||||
{
|
||||
return m_opened;
|
||||
@ -86,12 +99,17 @@ inline VDirectory *VDirectory::getParentDirectory()
|
||||
return (VDirectory *)this->parent();
|
||||
}
|
||||
|
||||
inline const VDirectory *VDirectory::getParentDirectory() const
|
||||
{
|
||||
return (const VDirectory *)this->parent();
|
||||
}
|
||||
|
||||
inline const QVector<VFile *> &VDirectory::getFiles() const
|
||||
{
|
||||
return m_files;
|
||||
}
|
||||
|
||||
inline QString VDirectory::retriveNotebook() const
|
||||
inline QString VDirectory::getNotebook() const
|
||||
{
|
||||
return m_notebook->getName();
|
||||
}
|
||||
|
@ -47,6 +47,24 @@ void VDirectoryTree::initActions()
|
||||
dirInfoAct->setStatusTip(tr("View and edit current directory's information"));
|
||||
connect(dirInfoAct, &QAction::triggered,
|
||||
this, &VDirectoryTree::editDirectoryInfo);
|
||||
|
||||
copyAct = new QAction(QIcon(":/resources/icons/copy.svg"),
|
||||
tr("&Copy"), this);
|
||||
copyAct->setStatusTip(tr("Copy selected directories"));
|
||||
connect(copyAct, &QAction::triggered,
|
||||
this, &VDirectoryTree::copySelectedDirectories);
|
||||
|
||||
cutAct = new QAction(QIcon(":/resources/icons/cut.svg"),
|
||||
tr("&Cut"), this);
|
||||
cutAct->setStatusTip(tr("Cut selected directories"));
|
||||
connect(cutAct, &QAction::triggered,
|
||||
this, &VDirectoryTree::cutSelectedDirectories);
|
||||
|
||||
pasteAct = new QAction(QIcon(":/resources/icons/paste.svg"),
|
||||
tr("&Paste"), this);
|
||||
pasteAct->setStatusTip(tr("Paste directories"));
|
||||
connect(pasteAct, &QAction::triggered,
|
||||
this, &VDirectoryTree::pasteDirectoriesInCurDir);
|
||||
}
|
||||
|
||||
void VDirectoryTree::setNotebook(VNotebook *p_notebook)
|
||||
@ -145,26 +163,38 @@ void VDirectoryTree::updateChildren(QTreeWidgetItem *p_item)
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QTreeWidgetItem *> VDirectoryTree::updateItemChildrenAdded(QTreeWidgetItem *p_item)
|
||||
void VDirectoryTree::updateItemChildren(QTreeWidgetItem *p_item)
|
||||
{
|
||||
QVector<QTreeWidgetItem *> ret;
|
||||
QPointer<VDirectory> parentDir;
|
||||
if (p_item) {
|
||||
parentDir = getVDirectory(p_item);
|
||||
} else {
|
||||
parentDir = m_notebook->getRootDir();
|
||||
}
|
||||
const QVector<VDirectory *> &subDirs = parentDir->getSubDirs();
|
||||
for (int i = 0; i < subDirs.size(); ++i) {
|
||||
int nrChild;
|
||||
if (p_item) {
|
||||
nrChild = p_item->childCount();
|
||||
const QVector<VDirectory *> &dirs = parentDir->getSubDirs();
|
||||
|
||||
QHash<VDirectory *, QTreeWidgetItem *> itemDirMap;
|
||||
int nrChild = p_item ? p_item->childCount() : topLevelItemCount();
|
||||
for (int i = 0; i < nrChild; ++i) {
|
||||
QTreeWidgetItem *item = p_item ? p_item->child(i) : topLevelItem(i);
|
||||
itemDirMap.insert(getVDirectory(item), item);
|
||||
}
|
||||
|
||||
for (int i = 0; i < dirs.size(); ++i) {
|
||||
VDirectory *dir = dirs[i];
|
||||
QTreeWidgetItem *item = itemDirMap.value(dir, NULL);
|
||||
if (item) {
|
||||
if (p_item) {
|
||||
p_item->removeChild(item);
|
||||
p_item->insertChild(i, item);
|
||||
} else {
|
||||
int topIdx = indexOfTopLevelItem(item);
|
||||
takeTopLevelItem(topIdx);
|
||||
insertTopLevelItem(i, item);
|
||||
}
|
||||
itemDirMap.remove(dir);
|
||||
} else {
|
||||
nrChild = this->topLevelItemCount();
|
||||
}
|
||||
VDirectory *dir = subDirs[i];
|
||||
QTreeWidgetItem *item;
|
||||
if (i >= nrChild) {
|
||||
// Insert a new item
|
||||
if (p_item) {
|
||||
item = new QTreeWidgetItem(p_item);
|
||||
} else {
|
||||
@ -172,37 +202,30 @@ QVector<QTreeWidgetItem *> VDirectoryTree::updateItemChildrenAdded(QTreeWidgetIt
|
||||
}
|
||||
fillTreeItem(*item, dir->getName(), dir, QIcon(":/resources/icons/dir_item.svg"));
|
||||
updateDirectoryTreeOne(item, 1);
|
||||
ret.append(item);
|
||||
} else {
|
||||
VDirectory *itemDir;
|
||||
if (p_item) {
|
||||
itemDir = getVDirectory(p_item->child(i));
|
||||
} else {
|
||||
itemDir = getVDirectory(topLevelItem(i));
|
||||
}
|
||||
if (itemDir != dir) {
|
||||
item = new QTreeWidgetItem();
|
||||
if (p_item) {
|
||||
p_item->insertChild(i, item);
|
||||
} else {
|
||||
this->insertTopLevelItem(i, item);
|
||||
}
|
||||
fillTreeItem(*item, dir->getName(), dir, QIcon(":/resources/icons/dir_item.svg"));
|
||||
updateDirectoryTreeOne(item, 1);
|
||||
ret.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << ret.size() << "items added";
|
||||
return ret;
|
||||
|
||||
// Delete items without corresponding VDirectory
|
||||
for (auto iter = itemDirMap.begin(); iter != itemDirMap.end(); ++iter) {
|
||||
QTreeWidgetItem *item = iter.value();
|
||||
if (p_item) {
|
||||
p_item->removeChild(item);
|
||||
} else {
|
||||
int topIdx = indexOfTopLevelItem(item);
|
||||
takeTopLevelItem(topIdx);
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void VDirectoryTree::contextMenuRequested(QPoint pos)
|
||||
{
|
||||
QTreeWidgetItem *item = itemAt(pos);
|
||||
|
||||
if (!m_notebook) {
|
||||
return;
|
||||
}
|
||||
QTreeWidgetItem *item = itemAt(pos);
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
if (!item) {
|
||||
@ -219,8 +242,24 @@ void VDirectoryTree::contextMenuRequested(QPoint pos)
|
||||
menu.addAction(newSubDirAct);
|
||||
}
|
||||
menu.addAction(deleteDirAct);
|
||||
menu.addSeparator();
|
||||
menu.addAction(copyAct);
|
||||
menu.addAction(cutAct);
|
||||
}
|
||||
|
||||
if (VUtils::opTypeInClipboard() == ClipboardOpType::CopyDir
|
||||
&& !m_copiedDirs.isEmpty()) {
|
||||
if (!item) {
|
||||
menu.addSeparator();
|
||||
}
|
||||
menu.addAction(pasteAct);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
menu.addSeparator();
|
||||
menu.addAction(dirInfoAct);
|
||||
}
|
||||
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
@ -255,9 +294,7 @@ void VDirectoryTree::newSubDirectory()
|
||||
QMessageBox::Ok, QMessageBox::Ok, this);
|
||||
return;
|
||||
}
|
||||
QVector<QTreeWidgetItem *> items = updateItemChildrenAdded(curItem);
|
||||
Q_ASSERT(items.size() == 1);
|
||||
setCurrentItem(items[0]);
|
||||
updateItemChildren(curItem);
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
@ -288,9 +325,7 @@ void VDirectoryTree::newRootDirectory()
|
||||
QMessageBox::Ok, QMessageBox::Ok, this);
|
||||
return;
|
||||
}
|
||||
QVector<QTreeWidgetItem *> items = updateItemChildrenAdded(NULL);
|
||||
Q_ASSERT(items.size() == 1);
|
||||
setCurrentItem(items[0]);
|
||||
updateItemChildren(NULL);
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
@ -356,7 +391,172 @@ void VDirectoryTree::editDirectoryInfo()
|
||||
return;
|
||||
}
|
||||
curItem->setText(0, name);
|
||||
emit directoryUpdated(curDir);
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void VDirectoryTree::copySelectedDirectories(bool p_cut)
|
||||
{
|
||||
QList<QTreeWidgetItem *> items = selectedItems();
|
||||
if (items.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
QJsonArray dirs;
|
||||
m_copiedDirs.clear();
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
VDirectory *dir = getVDirectory(items[i]);
|
||||
QJsonObject dirJson;
|
||||
dirJson["notebook"] = dir->getNotebook();
|
||||
dirJson["path"] = dir->retrivePath();
|
||||
dirs.append(dirJson);
|
||||
|
||||
m_copiedDirs.append(dir);
|
||||
}
|
||||
|
||||
copyDirectoryInfoToClipboard(dirs, p_cut);
|
||||
}
|
||||
|
||||
void VDirectoryTree::copyDirectoryInfoToClipboard(const QJsonArray &p_dirs, bool p_cut)
|
||||
{
|
||||
QJsonObject clip;
|
||||
clip["operation"] = (int)ClipboardOpType::CopyDir;
|
||||
clip["is_cut"] = p_cut;
|
||||
clip["sources"] = p_dirs;
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(QJsonDocument(clip).toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void VDirectoryTree::cutSelectedDirectories()
|
||||
{
|
||||
copySelectedDirectories(true);
|
||||
}
|
||||
|
||||
void VDirectoryTree::pasteDirectoriesInCurDir()
|
||||
{
|
||||
QTreeWidgetItem *item = currentItem();
|
||||
VDirectory *destDir = m_notebook->getRootDir();
|
||||
if (item) {
|
||||
destDir = getVDirectory(item);
|
||||
}
|
||||
pasteDirectories(destDir);
|
||||
}
|
||||
|
||||
void VDirectoryTree::pasteDirectories(VDirectory *p_destDir)
|
||||
{
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
QString text = clipboard->text();
|
||||
QJsonObject clip = QJsonDocument::fromJson(text.toLocal8Bit()).object();
|
||||
Q_ASSERT(!clip.isEmpty() && clip["operation"] == (int)ClipboardOpType::CopyDir);
|
||||
bool isCut = clip["is_cut"].toBool();
|
||||
|
||||
int nrPasted = 0;
|
||||
for (int i = 0; i < m_copiedDirs.size(); ++i) {
|
||||
QPointer<VDirectory> srcDir = m_copiedDirs[i];
|
||||
if (!srcDir) {
|
||||
continue;
|
||||
}
|
||||
QString dirName = srcDir->getName();
|
||||
VDirectory *srcParentDir = srcDir->getParentDirectory();
|
||||
if (srcParentDir == p_destDir && !isCut) {
|
||||
// Copy and paste in the same directory.
|
||||
// Rename it to xx_copy
|
||||
dirName = VUtils::generateCopiedDirName(srcParentDir->retrivePath(), dirName);
|
||||
}
|
||||
if (copyDirectory(p_destDir, dirName, srcDir, isCut)) {
|
||||
nrPasted++;
|
||||
}
|
||||
}
|
||||
qDebug() << "pasted" << nrPasted << "files successfully";
|
||||
clipboard->clear();
|
||||
m_copiedDirs.clear();
|
||||
}
|
||||
|
||||
void VDirectoryTree::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QTreeWidgetItem *item = itemAt(event->pos());
|
||||
if (!item) {
|
||||
setCurrentItem(NULL);
|
||||
}
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
bool VDirectoryTree::copyDirectory(VDirectory *p_destDir, const QString &p_destName,
|
||||
VDirectory *p_srcDir, bool p_cut)
|
||||
{
|
||||
qDebug() << "copy" << p_srcDir->getName() << "to" << p_destDir->getName()
|
||||
<< "as" << p_destName;
|
||||
QString srcName = p_srcDir->getName();
|
||||
QString srcPath = QDir::cleanPath(p_srcDir->retrivePath());
|
||||
QString destPath = QDir::cleanPath(QDir(p_destDir->retrivePath()).filePath(p_destName));
|
||||
if (srcPath == destPath) {
|
||||
return true;
|
||||
}
|
||||
|
||||
VDirectory *srcParentDir = p_srcDir->getParentDirectory();
|
||||
VDirectory *destDir = VDirectory::copyDirectory(p_destDir, p_destName, p_srcDir, p_cut);
|
||||
|
||||
if (destDir) {
|
||||
// Update QTreeWidget
|
||||
bool isWidget;
|
||||
QTreeWidgetItem *destItem = findVDirectory(p_destDir, isWidget);
|
||||
if (destItem || isWidget) {
|
||||
updateItemChildren(destItem);
|
||||
}
|
||||
|
||||
if (p_cut) {
|
||||
QTreeWidgetItem *srcItem = findVDirectory(srcParentDir, isWidget);
|
||||
if (srcItem || isWidget) {
|
||||
updateItemChildren(srcItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast this update
|
||||
emit directoryUpdated(destDir);
|
||||
} else {
|
||||
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
|
||||
QString("Failed to copy directory %1.").arg(srcName),
|
||||
QString("Please check if there alread exists a directory with the same name"),
|
||||
QMessageBox::Ok, QMessageBox::Ok, this);
|
||||
}
|
||||
|
||||
return destDir;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *VDirectoryTree::findVDirectory(const VDirectory *p_dir, bool &p_widget)
|
||||
{
|
||||
p_widget = false;
|
||||
if (!p_dir) {
|
||||
return NULL;
|
||||
} else if (p_dir->getNotebook() != m_notebook->getName()) {
|
||||
return NULL;
|
||||
} else if (p_dir == m_notebook->getRootDir()) {
|
||||
p_widget = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isWidget;
|
||||
QTreeWidgetItem *pItem = findVDirectory(p_dir->getParentDirectory(), isWidget);
|
||||
if (pItem) {
|
||||
// Iterate all its children to find the match.
|
||||
int nrChild = pItem->childCount();
|
||||
for (int i = 0; i < nrChild; ++i) {
|
||||
QTreeWidgetItem *item = pItem->child(i);
|
||||
if (getVDirectory(item) == p_dir) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
} else if (isWidget) {
|
||||
// Iterate all the top-level items.
|
||||
int nrChild = topLevelItemCount();
|
||||
for (int i = 0; i < nrChild; ++i) {
|
||||
QTreeWidgetItem *item = topLevelItem(i);
|
||||
if (getVDirectory(item) == p_dir) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ public:
|
||||
|
||||
signals:
|
||||
void currentDirectoryChanged(VDirectory *p_directory);
|
||||
void directoryRenamed(const QString ¬ebook, const QString &oldRelativePath,
|
||||
const QString &newRelativePath);
|
||||
void directoryUpdated(const VDirectory *p_directory);
|
||||
|
||||
public slots:
|
||||
void setNotebook(VNotebook *p_notebook);
|
||||
@ -33,19 +32,32 @@ private slots:
|
||||
void contextMenuRequested(QPoint pos);
|
||||
void newSubDirectory();
|
||||
void currentDirectoryItemChanged(QTreeWidgetItem *currentItem);
|
||||
void copySelectedDirectories(bool p_cut = false);
|
||||
void cutSelectedDirectories();
|
||||
void pasteDirectoriesInCurDir();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
void updateDirectoryTreeOne(QTreeWidgetItem *p_parent, int depth);
|
||||
void fillTreeItem(QTreeWidgetItem &p_item, const QString &p_name,
|
||||
VDirectory *p_directory, const QIcon &p_icon);
|
||||
void initActions();
|
||||
// New directories added to @p_item. Update @p_item's children items.
|
||||
// If @p_item is NULL, then top level items added.
|
||||
QVector<QTreeWidgetItem *> updateItemChildrenAdded(QTreeWidgetItem *p_item);
|
||||
// Update @p_item's direct children only: deleted, added, renamed.
|
||||
void updateItemChildren(QTreeWidgetItem *p_item);
|
||||
// Find the corresponding item of @p_dir;
|
||||
// Return's NULL if no item is found and it is the root directory if @p_widget is true.
|
||||
QTreeWidgetItem *findVDirectory(const VDirectory *p_dir, bool &p_widget);
|
||||
inline QPointer<VDirectory> getVDirectory(QTreeWidgetItem *p_item);
|
||||
void copyDirectoryInfoToClipboard(const QJsonArray &p_dirs, bool p_cut);
|
||||
void pasteDirectories(VDirectory *p_destDir);
|
||||
bool copyDirectory(VDirectory *p_destDir, const QString &p_destName,
|
||||
VDirectory *p_srcDir, bool p_cut);
|
||||
|
||||
VNote *vnote;
|
||||
QPointer<VNotebook> m_notebook;
|
||||
QVector<QPointer<VDirectory> > m_copiedDirs;
|
||||
|
||||
// Actions
|
||||
QAction *newRootDirAct;
|
||||
@ -53,6 +65,9 @@ private:
|
||||
QAction *newSubDirAct;
|
||||
QAction *deleteDirAct;
|
||||
QAction *dirInfoAct;
|
||||
QAction *copyAct;
|
||||
QAction *cutAct;
|
||||
QAction *pasteAct;
|
||||
};
|
||||
|
||||
inline QPointer<VDirectory> VDirectoryTree::getVDirectory(QTreeWidgetItem *p_item)
|
||||
|
@ -313,3 +313,11 @@ void VEditArea::handleFileUpdated(const VFile *p_file)
|
||||
getWindow(i)->updateFileInfo(p_file);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditArea::handleDirectoryUpdated(const VDirectory *p_dir)
|
||||
{
|
||||
int nrWin = splitter->count();
|
||||
for (int i = 0; i < nrWin; ++i) {
|
||||
getWindow(i)->updateDirectoryInfo(p_dir);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
class VNote;
|
||||
class VFile;
|
||||
class VDirectory;
|
||||
|
||||
class VEditArea : public QWidget
|
||||
{
|
||||
@ -42,6 +43,7 @@ public slots:
|
||||
void saveAndReadFile();
|
||||
void handleOutlineItemActivated(const VAnchor &anchor);
|
||||
void handleFileUpdated(const VFile *p_file);
|
||||
void handleDirectoryUpdated(const VDirectory *p_dir);
|
||||
|
||||
private slots:
|
||||
void handleSplitWindowRequest(VEditWindow *curWindow);
|
||||
|
@ -258,7 +258,9 @@ void VEditWindow::noticeTabStatus(int p_index)
|
||||
bool editMode = editor->getIsEditMode();
|
||||
|
||||
// Update tab text
|
||||
tabBar()->setTabText(p_index, generateTabText(file->getName(), file->isModified()));
|
||||
QTabBar *tabs = tabBar();
|
||||
tabs->setTabText(p_index, generateTabText(file->getName(), file->isModified()));
|
||||
tabs->setTabToolTip(p_index, generateTooltip(file));
|
||||
emit tabStatusChanged(file, editMode);
|
||||
}
|
||||
|
||||
@ -431,3 +433,19 @@ void VEditWindow::updateFileInfo(const VFile *p_file)
|
||||
noticeStatus(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditWindow::updateDirectoryInfo(const VDirectory *p_dir)
|
||||
{
|
||||
if (!p_dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nrTab = tabBar()->count();
|
||||
for (int i = 0; i < nrTab; ++i) {
|
||||
VEditTab *editor = getTab(i);
|
||||
QPointer<VFile> file = editor->getFile();
|
||||
if (p_dir->containsFile(file)) {
|
||||
noticeStatus(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
void focusWindow();
|
||||
void scrollCurTab(const VAnchor &p_anchor);
|
||||
void updateFileInfo(const VFile *p_file);
|
||||
void updateDirectoryInfo(const VDirectory *p_dir);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||
@ -96,7 +97,7 @@ inline QString VEditWindow::generateTooltip(const VFile *p_file) const
|
||||
return "";
|
||||
}
|
||||
// [Notebook]path
|
||||
return QString("[%1] %2").arg(p_file->retriveNotebook()).arg(p_file->retrivePath());
|
||||
return QString("[%1] %2").arg(p_file->getNotebook()).arg(p_file->retrivePath());
|
||||
}
|
||||
|
||||
inline QString VEditWindow::generateTabText(const QString &p_name, bool p_modified) const
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
inline DocType getDocType() const;
|
||||
inline QString &getContent();
|
||||
inline void setContent(const QString &p_content);
|
||||
inline QString retriveNotebook() const;
|
||||
inline QString getNotebook() const;
|
||||
inline QString retrivePath() const;
|
||||
inline QString retriveRelativePath() const;
|
||||
inline QString retriveBasePath() const;
|
||||
@ -80,9 +80,9 @@ inline QString &VFile::getContent()
|
||||
return m_content;
|
||||
}
|
||||
|
||||
inline QString VFile::retriveNotebook() const
|
||||
inline QString VFile::getNotebook() const
|
||||
{
|
||||
return getDirectory()->retriveNotebook();
|
||||
return getDirectory()->getNotebook();
|
||||
}
|
||||
|
||||
inline QString VFile::retrivePath() const
|
||||
|
@ -266,7 +266,8 @@ void VFileList::contextMenuRequested(QPoint pos)
|
||||
menu.addAction(cutAct);
|
||||
}
|
||||
|
||||
if (VUtils::opTypeInClipboard() == ClipboardOpType::CopyFile) {
|
||||
if (VUtils::opTypeInClipboard() == ClipboardOpType::CopyFile
|
||||
&& !m_copiedFiles.isEmpty()) {
|
||||
if (!item) {
|
||||
menu.addSeparator();
|
||||
}
|
||||
@ -343,7 +344,7 @@ void VFileList::copySelectedFiles(bool p_isCut)
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
VFile *file = getVFile(items[i]);
|
||||
QJsonObject fileJson;
|
||||
fileJson["notebook"] = file->retriveNotebook();
|
||||
fileJson["notebook"] = file->getNotebook();
|
||||
fileJson["path"] = file->retrivePath();
|
||||
files.append(fileJson);
|
||||
|
||||
|
@ -57,6 +57,11 @@ void VMainWindow::setupUI()
|
||||
|
||||
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
|
||||
fileList, &VFileList::setDirectory);
|
||||
connect(directoryTree, &VDirectoryTree::directoryUpdated,
|
||||
editArea, &VEditArea::handleDirectoryUpdated);
|
||||
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
|
||||
this, &VMainWindow::handleCurrentDirectoryChanged);
|
||||
|
||||
connect(fileList, &VFileList::fileClicked,
|
||||
editArea, &VEditArea::openFile);
|
||||
connect(fileList, &VFileList::fileCreated,
|
||||
@ -695,7 +700,7 @@ void VMainWindow::handleCurTabStatusChanged(const VFile *p_file, bool p_editMode
|
||||
|
||||
QString title;
|
||||
if (p_file) {
|
||||
title = QString("[%1] %2").arg(p_file->retriveNotebook()).arg(p_file->retrivePath());
|
||||
title = QString("[%1] %2").arg(p_file->getNotebook()).arg(p_file->retrivePath());
|
||||
if (p_file->isModified()) {
|
||||
title.append('*');
|
||||
}
|
||||
@ -796,3 +801,8 @@ const QVector<QPair<QString, QString> >& VMainWindow::getPalette() const
|
||||
{
|
||||
return vnote->getPallete();
|
||||
}
|
||||
|
||||
void VMainWindow::handleCurrentDirectoryChanged(const VDirectory *p_dir)
|
||||
{
|
||||
newNoteAct->setEnabled(p_dir);
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ private slots:
|
||||
void changePanelView(QAction *action);
|
||||
void curEditFileInfo();
|
||||
void deleteCurNote();
|
||||
void handleCurrentDirectoryChanged(const VDirectory *p_dir);
|
||||
|
||||
signals:
|
||||
void curNotebookChanged(VNotebook *p_notebook);
|
||||
|
@ -121,7 +121,7 @@ void VNote::removeNotebook(int idx)
|
||||
|
||||
// Close all the directory and files
|
||||
notebookPathHash.remove(name);
|
||||
nb->close(true);
|
||||
nb->close();
|
||||
delete nb;
|
||||
qDebug() << "notebook" << name << "deleted";
|
||||
|
||||
|
@ -33,7 +33,7 @@ void VNotebook::setPath(const QString &path)
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
void VNotebook::close(bool p_forced)
|
||||
void VNotebook::close()
|
||||
{
|
||||
m_rootDir->close();
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ public:
|
||||
// Open the root directory to load contents
|
||||
bool open();
|
||||
// Close all the directory and files of this notebook.
|
||||
// If @p_forced, unsaved files will also be closed without a confirm.
|
||||
void close(bool p_forced);
|
||||
// Please make sure all files belonging to this notebook have been closed in the tab.
|
||||
void close();
|
||||
|
||||
QString getName() const;
|
||||
QString getPath() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user