support copy and paste directory

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-12-01 21:15:21 +08:00
parent 787d54c808
commit 02d5300821
17 changed files with 545 additions and 97 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -18,8 +18,7 @@ public:
signals:
void currentDirectoryChanged(VDirectory *p_directory);
void directoryRenamed(const QString &notebook, 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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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";

View File

@ -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();
}

View File

@ -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;