| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325 |
- #include <QtWidgets>
- #include "vdirectorytree.h"
- #include "dialog/vnewdirdialog.h"
- #include "vconfigmanager.h"
- #include "dialog/vdirinfodialog.h"
- #include "vnote.h"
- #include "vdirectory.h"
- #include "utils/vutils.h"
- #include "veditarea.h"
- #include "vconfigmanager.h"
- #include "vmainwindow.h"
- #include "dialog/vsortdialog.h"
- #include "utils/vimnavigationforwidget.h"
- #include "utils/viconutils.h"
- #include "vfilelist.h"
- #include "vhistorylist.h"
- extern VMainWindow *g_mainWin;
- extern VConfigManager *g_config;
- extern VNote *g_vnote;
- VDirectoryTree::VDirectoryTree(QWidget *parent)
- : VTreeWidget(parent),
- VNavigationMode(),
- m_editArea(NULL)
- {
- setColumnCount(1);
- setHeaderHidden(true);
- setContextMenuPolicy(Qt::CustomContextMenu);
- setFitContent(true);
- viewport()->setAcceptDrops(true);
- setDropIndicatorShown(true);
- initShortcuts();
- connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)),
- this, SLOT(handleItemExpanded(QTreeWidgetItem*)));
- connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)),
- this, SLOT(handleItemCollapsed(QTreeWidgetItem*)));
- connect(this, SIGNAL(customContextMenuRequested(QPoint)),
- this, SLOT(contextMenuRequested(QPoint)));
- connect(this, &VDirectoryTree::currentItemChanged,
- this, &VDirectoryTree::currentDirectoryItemChanged);
- }
- void VDirectoryTree::initShortcuts()
- {
- QShortcut *infoShortcut = new QShortcut(QKeySequence(Shortcut::c_info), this);
- infoShortcut->setContext(Qt::WidgetWithChildrenShortcut);
- connect(infoShortcut, &QShortcut::activated,
- this, [this](){
- editDirectoryInfo();
- });
- QShortcut *copyShortcut = new QShortcut(QKeySequence(Shortcut::c_copy), this);
- copyShortcut->setContext(Qt::WidgetWithChildrenShortcut);
- connect(copyShortcut, &QShortcut::activated,
- this, [this](){
- copySelectedDirectories();
- });
- QShortcut *cutShortcut = new QShortcut(QKeySequence(Shortcut::c_cut), this);
- cutShortcut->setContext(Qt::WidgetWithChildrenShortcut);
- connect(cutShortcut, &QShortcut::activated,
- this, [this](){
- cutSelectedDirectories();
- });
- QShortcut *pasteShortcut = new QShortcut(QKeySequence(Shortcut::c_paste), this);
- pasteShortcut->setContext(Qt::WidgetWithChildrenShortcut);
- connect(pasteShortcut, &QShortcut::activated,
- this, [this](){
- pasteDirectoriesFromClipboard();
- });
- QKeySequence seq = QKeySequence(g_config->getShortcutKeySequence("NewSubfolder"));
- if (!seq.isEmpty()) {
- QShortcut *newSubDirShortcut = new QShortcut(seq, this);
- newSubDirShortcut->setContext(Qt::ApplicationShortcut);
- connect(newSubDirShortcut, &QShortcut::activated,
- this, [this](){
- newSubDirectory();
- });
- }
- }
- void VDirectoryTree::setNotebook(VNotebook *p_notebook)
- {
- if (m_notebook == p_notebook) {
- return;
- }
- clear();
- m_notebook = p_notebook;
- if (!m_notebook) {
- return;
- }
- if (!m_notebook->open()) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to open notebook <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(m_notebook->getName()),
- tr("Please check if the notebook's root folder <span style=\"%1\">%2</span> exists.")
- .arg(g_config->c_dataTextStyle)
- .arg(m_notebook->getPath()),
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return;
- }
- updateDirectoryTree();
- }
- void VDirectoryTree::fillTreeItem(QTreeWidgetItem *p_item, VDirectory *p_directory)
- {
- static QIcon itemIcon = VIconUtils::treeViewIcon(":/resources/icons/dir_item.svg");
- int col = 0;
- QString name = p_directory->getName();
- p_item->setText(col, name);
- p_item->setToolTip(col, name);
- p_item->setData(col, Qt::UserRole, QVariant::fromValue(p_directory));
- p_item->setIcon(col, itemIcon);
- }
- void VDirectoryTree::updateDirectoryTree()
- {
- clear();
- VDirectory *rootDir = m_notebook->getRootDir();
- const QVector<VDirectory *> &subDirs = rootDir->getSubDirs();
- for (int i = 0; i < subDirs.size(); ++i) {
- VDirectory *dir = subDirs[i];
- QTreeWidgetItem *item = new QTreeWidgetItem(this);
- fillTreeItem(item, dir);
- buildSubTree(item, 1);
- }
- if (!restoreCurrentItem() && topLevelItemCount() > 0) {
- setCurrentItem(topLevelItem(0));
- }
- resizeColumnToContents(0);
- }
- bool VDirectoryTree::restoreCurrentItem()
- {
- auto it = m_notebookCurrentDirMap.find(m_notebook);
- if (it != m_notebookCurrentDirMap.end()) {
- QTreeWidgetItem *item = findVDirectory(it.value());
- if (item) {
- setCurrentItem(item);
- return true;
- }
- }
- return false;
- }
- void VDirectoryTree::buildSubTree(QTreeWidgetItem *p_parent, int p_depth)
- {
- if (p_depth == 0) {
- return;
- }
- Q_ASSERT(p_parent);
- VDirectory *dir = getVDirectory(p_parent);
- if (!dir->open()) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to open folder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(dir->getName()),
- tr("Please check if directory <span style=\"%1\">%2</span> exists.")
- .arg(g_config->c_dataTextStyle)
- .arg(dir->fetchPath()),
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return;
- }
- if (p_parent->childCount() > 0) {
- // This directory has been built before. Try its children directly.
- int cnt = p_parent->childCount();
- for (int i = 0; i < cnt; ++i) {
- buildSubTree(p_parent->child(i), p_depth -1);
- }
- } else {
- const QVector<VDirectory *> &subDirs = dir->getSubDirs();
- for (int i = 0; i < subDirs.size(); ++i) {
- VDirectory *subDir = subDirs[i];
- QTreeWidgetItem *item = new QTreeWidgetItem(p_parent);
- fillTreeItem(item, subDir);
- buildSubTree(item, p_depth - 1);
- }
- }
- if (dir->isExpanded()) {
- expandItem(p_parent);
- }
- }
- void VDirectoryTree::handleItemCollapsed(QTreeWidgetItem *p_item)
- {
- if (p_item) {
- VDirectory *dir = getVDirectory(p_item);
- dir->setExpanded(false);
- }
- }
- void VDirectoryTree::handleItemExpanded(QTreeWidgetItem *p_item)
- {
- if (p_item) {
- buildChildren(p_item);
- VDirectory *dir = getVDirectory(p_item);
- dir->setExpanded(true);
- }
- }
- void VDirectoryTree::buildChildren(QTreeWidgetItem *p_item)
- {
- Q_ASSERT(p_item);
- int nrChild = p_item->childCount();
- if (nrChild == 0) {
- return;
- }
- for (int i = 0; i < nrChild; ++i) {
- QTreeWidgetItem *childItem = p_item->child(i);
- if (childItem->childCount() > 0) {
- continue;
- }
- buildSubTree(childItem, 1);
- }
- }
- void VDirectoryTree::updateItemDirectChildren(QTreeWidgetItem *p_item)
- {
- QPointer<VDirectory> parentDir;
- if (p_item) {
- parentDir = getVDirectory(p_item);
- } else {
- parentDir = m_notebook->getRootDir();
- }
- 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 {
- // Insert a new item
- if (p_item) {
- item = new QTreeWidgetItem(p_item);
- } else {
- item = new QTreeWidgetItem(this);
- }
- fillTreeItem(item, dir);
- buildSubTree(item, 1);
- }
- expandSubTree(item);
- }
- // 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;
- }
- QMenu menu(this);
- menu.setToolTipsVisible(true);
- QAction *newRootDirAct = new QAction(VIconUtils::menuIcon(":/resources/icons/create_rootdir.svg"),
- tr("New &Root Folder"),
- &menu);
- newRootDirAct->setToolTip(tr("Create a root folder in current notebook"));
- connect(newRootDirAct, &QAction::triggered,
- this, &VDirectoryTree::newRootDirectory);
- QAction *sortAct = new QAction(VIconUtils::menuIcon(":/resources/icons/sort.svg"),
- tr("&Sort"),
- &menu);
- sortAct->setToolTip(tr("Sort folders in this folder/notebook manually"));
- connect(sortAct, SIGNAL(triggered(bool)),
- this, SLOT(sortItems()));
- if (!item) {
- // Context menu on the free space of the QTreeWidget
- menu.addAction(newRootDirAct);
- if (topLevelItemCount() > 1) {
- menu.addAction(sortAct);
- }
- } else {
- // Context menu on a QTreeWidgetItem
- QAction *newNoteAct = new QAction(VIconUtils::menuIcon(":/resources/icons/create_note_tb.svg"),
- tr("New &Note"),
- &menu);
- VUtils::fixTextWithShortcut(newNoteAct, "NewNote");
- newNoteAct->setToolTip(tr("Create a note in selected folder"));
- connect(newNoteAct, &QAction::triggered,
- this, []() {
- g_mainWin->getFileList()->newFile();
- });
- menu.addAction(newNoteAct);
- QAction *newSiblingFolder = new QAction(tr("New Si&bling Folder"), &menu);
- newSiblingFolder->setToolTip(tr("Create a folder in the same parent folder"));
- connect(newSiblingFolder, &QAction::triggered,
- this, [this]() {
- auto item = currentItem();
- if (item) {
- newDirectory(item->parent());
- }
- });
- QAction *newSubDirAct = new QAction(VIconUtils::menuIcon(":/resources/icons/create_subdir.svg"),
- tr("New Sub&folder"),
- &menu);
- newSubDirAct->setToolTip(tr("Create a subfolder"));
- VUtils::fixTextWithShortcut(newSubDirAct, "NewSubfolder");
- connect(newSubDirAct, &QAction::triggered,
- this, &VDirectoryTree::newSubDirectory);
- if (item->parent()) {
- // Low-level item
- menu.addAction(newSiblingFolder);
- menu.addAction(newSubDirAct);
- if (item->parent()->childCount() > 1) {
- menu.addAction(sortAct);
- }
- } else {
- // Top-level item
- menu.addAction(newRootDirAct);
- menu.addAction(newSubDirAct);
- if (topLevelItemCount() > 1) {
- menu.addAction(sortAct);
- }
- }
- menu.addSeparator();
- QAction *deleteDirAct = new QAction(VIconUtils::menuDangerIcon(":/resources/icons/delete_dir.svg"),
- tr("&Delete"),
- &menu);
- deleteDirAct->setToolTip(tr("Delete selected folder"));
- connect(deleteDirAct, &QAction::triggered,
- this, &VDirectoryTree::deleteSelectedDirectory);
- menu.addAction(deleteDirAct);
- QAction *copyAct = new QAction(VIconUtils::menuIcon(":/resources/icons/copy.svg"),
- tr("&Copy\t%1").arg(VUtils::getShortcutText(Shortcut::c_copy)),
- &menu);
- copyAct->setToolTip(tr("Copy selected folders"));
- connect(copyAct, &QAction::triggered,
- this, &VDirectoryTree::copySelectedDirectories);
- menu.addAction(copyAct);
- QAction *cutAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cut.svg"),
- tr("C&ut\t%1").arg(VUtils::getShortcutText(Shortcut::c_cut)),
- &menu);
- cutAct->setToolTip(tr("Cut selected folders"));
- connect(cutAct, &QAction::triggered,
- this, &VDirectoryTree::cutSelectedDirectories);
- menu.addAction(cutAct);
- }
- if (pasteAvailable()) {
- if (!item) {
- menu.addSeparator();
- }
- QAction *pasteAct = new QAction(VIconUtils::menuIcon(":/resources/icons/paste.svg"),
- tr("&Paste\t%1").arg(VUtils::getShortcutText(Shortcut::c_paste)),
- &menu);
- pasteAct->setToolTip(tr("Paste folders in this folder"));
- connect(pasteAct, &QAction::triggered,
- this, &VDirectoryTree::pasteDirectoriesFromClipboard);
- menu.addAction(pasteAct);
- }
- menu.addSeparator();
- QAction *reloadAct = new QAction(tr("Reload From Disk"), &menu);
- reloadAct->setToolTip(tr("Reload the content of this folder (or notebook) from disk"));
- connect(reloadAct, &QAction::triggered,
- this, &VDirectoryTree::reloadFromDisk);
- menu.addAction(reloadAct);
- if (item) {
- QAction *openLocationAct = new QAction(VIconUtils::menuIcon(":/resources/icons/open_location.svg"),
- tr("Open Folder &Location"),
- &menu);
- openLocationAct->setToolTip(tr("Explore this folder in operating system"));
- connect(openLocationAct, &QAction::triggered,
- this, &VDirectoryTree::openDirectoryLocation);
- menu.addAction(openLocationAct);
- QAction *pinToHistoryAct = new QAction(VIconUtils::menuIcon(":/resources/icons/pin.svg"),
- tr("Pin To History"),
- &menu);
- pinToHistoryAct->setToolTip(tr("Pin selected folder to History"));
- connect(pinToHistoryAct, &QAction::triggered,
- this, &VDirectoryTree::pinDirectoryToHistory);
- menu.addAction(pinToHistoryAct);
- QAction *dirInfoAct = new QAction(VIconUtils::menuIcon(":/resources/icons/dir_info.svg"),
- tr("&Info (Rename)\t%1").arg(VUtils::getShortcutText(Shortcut::c_info)),
- &menu);
- dirInfoAct->setToolTip(tr("View and edit current folder's information"));
- connect(dirInfoAct, &QAction::triggered,
- this, &VDirectoryTree::editDirectoryInfo);
- menu.addAction(dirInfoAct);
- }
- menu.exec(mapToGlobal(pos));
- }
- void VDirectoryTree::newSubDirectory()
- {
- if (!m_notebook) {
- return;
- }
- newDirectory(currentItem());
- }
- void VDirectoryTree::newDirectory(QTreeWidgetItem *p_parentItem)
- {
- if (!p_parentItem) {
- return;
- }
- VDirectory *curDir = getVDirectory(p_parentItem);
- QString info = tr("Create a subfolder in <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(curDir->getName());
- QString defaultName("new_folder");
- defaultName = VUtils::getDirNameWithSequence(curDir->fetchPath(), defaultName);
- VNewDirDialog dialog(tr("Create Folder"), info, defaultName, curDir, this);
- if (dialog.exec() == QDialog::Accepted) {
- QString name = dialog.getNameInput();
- QString msg;
- VDirectory *subDir = curDir->createSubDirectory(name, &msg);
- if (!subDir) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to create subfolder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(name),
- msg,
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return;
- }
- updateItemDirectChildren(p_parentItem);
- locateDirectory(subDir);
- }
- }
- void VDirectoryTree::newRootDirectory()
- {
- if (!m_notebook) {
- return;
- }
- VDirectory *rootDir = m_notebook->getRootDir();
- QString info = tr("Create a root folder in notebook <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(m_notebook->getName());
- QString defaultName("new_folder");
- defaultName = VUtils::getDirNameWithSequence(rootDir->fetchPath(), defaultName);
- VNewDirDialog dialog(tr("Create Root Folder"), info, defaultName, rootDir, this);
- if (dialog.exec() == QDialog::Accepted) {
- QString name = dialog.getNameInput();
- QString msg;
- VDirectory *dir = rootDir->createSubDirectory(name, &msg);
- if (!dir) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to create root folder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(name),
- msg,
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return;
- }
- updateItemDirectChildren(NULL);
- locateDirectory(dir);
- }
- }
- void VDirectoryTree::deleteSelectedDirectory()
- {
- Q_ASSERT(selectedItems().size() <= 1);
- QTreeWidgetItem *curItem = currentItem();
- if (!curItem) {
- return;
- }
- VDirectory *curDir = getVDirectory(curItem);
- int ret = VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Are you sure to delete folder <span style=\"%1\">%2</span>?")
- .arg(g_config->c_dataTextStyle)
- .arg(curDir->getName()),
- tr("<span style=\"%1\">WARNING</span>: "
- "VNote will delete the whole directory "
- "<span style=\"%2\">%3</span>."
- "Deleted files could be found in the recycle bin "
- "of this folder.<br>"
- "The operation is IRREVERSIBLE!")
- .arg(g_config->c_warningTextStyle)
- .arg(g_config->c_dataTextStyle)
- .arg(curDir->fetchPath()),
- QMessageBox::Ok | QMessageBox::Cancel,
- QMessageBox::Ok,
- this,
- MessageBoxType::Danger);
- if (ret == QMessageBox::Ok) {
- int nrDeleted = 1;
- m_editArea->closeFile(curDir, true);
- // Remove the item from the tree.
- delete curItem;
- QString msg;
- QString dirName = curDir->getName();
- QString dirPath = curDir->fetchPath();
- if (!VDirectory::deleteDirectory(curDir, false, &msg)) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to delete folder <span style=\"%1\">%2</span>.<br>"
- "Please check <span style=\"%1\">%3</span> and manually delete it.")
- .arg(g_config->c_dataTextStyle)
- .arg(dirName)
- .arg(dirPath),
- msg,
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- } else {
- g_mainWin->showStatusMessage(tr("%1 %2 deleted")
- .arg(nrDeleted)
- .arg(nrDeleted > 1 ? tr("folders") : tr("folder")));
- }
- }
- }
- void VDirectoryTree::currentDirectoryItemChanged(QTreeWidgetItem *currentItem)
- {
- if (!currentItem) {
- emit currentDirectoryChanged(NULL);
- return;
- }
- QPointer<VDirectory> dir = getVDirectory(currentItem);
- m_notebookCurrentDirMap[m_notebook] = dir;
- emit currentDirectoryChanged(dir);
- }
- void VDirectoryTree::editDirectoryInfo()
- {
- QTreeWidgetItem *curItem = currentItem();
- if (!curItem) {
- return;
- }
- VDirectory *curDir = getVDirectory(curItem);
- QString curName = curDir->getName();
- VDirInfoDialog dialog(tr("Folder Information"),
- "",
- curDir,
- curDir->getParentDirectory(),
- this);
- if (dialog.exec() == QDialog::Accepted) {
- QString name = dialog.getNameInput();
- if (name == curName) {
- return;
- }
- if (!curDir->rename(name)) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to rename folder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(curName),
- "",
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return;
- }
- fillTreeItem(curItem, curDir);
- emit directoryUpdated(curDir, UpdateAction::InfoChanged);
- }
- }
- void VDirectoryTree::openDirectoryLocation() const
- {
- QTreeWidgetItem *curItem = currentItem();
- V_ASSERT(curItem);
- QUrl url = QUrl::fromLocalFile(getVDirectory(curItem)->fetchPath());
- QDesktopServices::openUrl(url);
- }
- void VDirectoryTree::reloadFromDisk()
- {
- if (!m_notebook) {
- return;
- }
- QString msg;
- QString info;
- VDirectory *curDir = NULL;
- QTreeWidgetItem *curItem = currentItem();
- if (curItem) {
- // Reload current directory.
- curDir = getVDirectory(curItem);
- info = tr("Are you sure to reload folder <span style=\"%1\">%2</span>?")
- .arg(g_config->c_dataTextStyle).arg(curDir->getName());
- msg = tr("Folder %1 reloaded from disk").arg(curDir->getName());
- } else {
- // Reload notebook.
- info = tr("Are you sure to reload notebook <span style=\"%1\">%2</span>?")
- .arg(g_config->c_dataTextStyle).arg(m_notebook->getName());
- msg = tr("Notebook %1 reloaded from disk").arg(m_notebook->getName());
- }
- if (g_config->getConfirmReloadFolder()) {
- int ret = VUtils::showMessage(QMessageBox::Information, tr("Information"),
- info,
- tr("VNote will close all the related notes before reload."),
- QMessageBox::Ok | QMessageBox::YesToAll | QMessageBox::Cancel,
- QMessageBox::Ok,
- this);
- switch (ret) {
- case QMessageBox::YesToAll:
- g_config->setConfirmReloadFolder(false);
- // Fall through.
- case QMessageBox::Ok:
- break;
- case QMessageBox::Cancel:
- return;
- default:
- return;
- }
- }
- m_notebookCurrentDirMap.remove(m_notebook);
- if (curItem) {
- if (!m_editArea->closeFile(curDir, false)) {
- return;
- }
- setCurrentItem(NULL);
- curItem->setExpanded(false);
- curDir->setExpanded(false);
- curDir->close();
- // Remove all its children.
- QList<QTreeWidgetItem *> children = curItem->takeChildren();
- for (int i = 0; i < children.size(); ++i) {
- delete children[i];
- }
- buildSubTree(curItem, 1);
- setCurrentItem(curItem);
- } else {
- if (!m_editArea->closeFile(m_notebook, false)) {
- return;
- }
- m_notebook->close();
- if (!m_notebook->open()) {
- VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
- tr("Fail to open notebook <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle).arg(m_notebook->getName()),
- tr("Please check if path <span style=\"%1\">%2</span> exists.")
- .arg(g_config->c_dataTextStyle).arg(m_notebook->getPath()),
- QMessageBox::Ok, QMessageBox::Ok, this);
- clear();
- return;
- }
- updateDirectoryTree();
- }
- if (!msg.isEmpty()) {
- g_mainWin->showStatusMessage(msg);
- }
- }
- void VDirectoryTree::copySelectedDirectories(bool p_isCut)
- {
- QList<QTreeWidgetItem *> items = selectedItems();
- if (items.isEmpty()) {
- return;
- }
- QJsonArray dirs;
- for (int i = 0; i < items.size(); ++i) {
- VDirectory *dir = getVDirectory(items[i]);
- dirs.append(dir->fetchPath());
- }
- QJsonObject clip;
- clip[ClipboardConfig::c_magic] = getNewMagic();
- clip[ClipboardConfig::c_type] = (int)ClipboardOpType::CopyDir;
- clip[ClipboardConfig::c_isCut] = p_isCut;
- clip[ClipboardConfig::c_dirs] = dirs;
- QClipboard *clipboard = QApplication::clipboard();
- clipboard->setText(QJsonDocument(clip).toJson(QJsonDocument::Compact));
- qDebug() << "copied directories info" << clipboard->text();
- int cnt = dirs.size();
- g_mainWin->showStatusMessage(tr("%1 %2 %3")
- .arg(cnt)
- .arg(cnt > 1 ? tr("folders") : tr("folder"))
- .arg(p_isCut ? tr("cut") : tr("copied")));
- }
- void VDirectoryTree::cutSelectedDirectories()
- {
- copySelectedDirectories(true);
- }
- void VDirectoryTree::pasteDirectoriesFromClipboard()
- {
- if (!pasteAvailable()) {
- return;
- }
- QJsonObject obj = VUtils::clipboardToJson();
- QJsonArray dirs = obj[ClipboardConfig::c_dirs].toArray();
- bool isCut = obj[ClipboardConfig::c_isCut].toBool();
- QVector<QString> dirsToPaste(dirs.size());
- for (int i = 0; i < dirs.size(); ++i) {
- dirsToPaste[i] = dirs[i].toString();
- }
- VDirectory *destDir;
- QTreeWidgetItem *item = currentItem();
- if (item) {
- destDir = getVDirectory(item);
- } else {
- destDir = m_notebook->getRootDir();
- }
- pasteDirectories(destDir, dirsToPaste, isCut);
- QClipboard *clipboard = QApplication::clipboard();
- clipboard->clear();
- }
- void VDirectoryTree::pasteDirectories(VDirectory *p_destDir,
- const QVector<QString> &p_dirs,
- bool p_isCut)
- {
- if (!p_destDir || p_dirs.isEmpty()) {
- return;
- }
- int nrPasted = 0;
- for (int i = 0; i < p_dirs.size(); ++i) {
- VDirectory *dir = g_vnote->getInternalDirectory(p_dirs[i]);
- if (!dir) {
- qWarning() << "Copied dir is not an internal folder" << p_dirs[i];
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to paste folder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(p_dirs[i]),
- tr("VNote could not find this folder in any notebook."),
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- continue;
- }
- if (dir == p_destDir) {
- continue;
- }
- QString dirName = dir->getName();
- VDirectory *paDir = dir->getParentDirectory();
- if (paDir == p_destDir) {
- if (p_isCut) {
- continue;
- }
- // Copy and paste in the same folder.
- // Rename it to xxx_copy.
- dirName = VUtils::generateCopiedDirName(paDir->fetchPath(), dirName);
- } else {
- // Rename it to xxx_copy if needed.
- dirName = VUtils::generateCopiedDirName(p_destDir->fetchPath(), dirName);
- }
- QString msg;
- VDirectory *destDir = NULL;
- bool ret = VDirectory::copyDirectory(p_destDir,
- dirName,
- dir,
- p_isCut,
- &destDir,
- &msg);
- if (!ret) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to copy folder <span style=\"%1\">%2</span>.")
- .arg(g_config->c_dataTextStyle)
- .arg(p_dirs[i]),
- msg,
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- }
- if (destDir) {
- ++nrPasted;
- // Update QTreeWidget.
- bool isWidget;
- QTreeWidgetItem *destItem = findVDirectory(p_destDir, &isWidget);
- if (destItem || isWidget) {
- updateItemDirectChildren(destItem);
- }
- if (p_isCut) {
- QTreeWidgetItem *srcItem = findVDirectory(paDir, &isWidget);
- if (srcItem || isWidget) {
- updateItemDirectChildren(srcItem);
- }
- }
- // Broadcast this update
- emit directoryUpdated(destDir, p_isCut ? UpdateAction::Moved : UpdateAction::InfoChanged);
- }
- }
- qDebug() << "pasted" << nrPasted << "directories";
- if (nrPasted > 0) {
- g_mainWin->showStatusMessage(tr("%1 %2 pasted")
- .arg(nrPasted)
- .arg(nrPasted > 1 ? tr("folders") : tr("folder")));
- }
- getNewMagic();
- }
- bool VDirectoryTree::pasteAvailable() const
- {
- QJsonObject obj = VUtils::clipboardToJson();
- if (obj.isEmpty()) {
- return false;
- }
- if (!obj.contains(ClipboardConfig::c_type)) {
- return false;
- }
- ClipboardOpType type = (ClipboardOpType)obj[ClipboardConfig::c_type].toInt();
- if (type != ClipboardOpType::CopyDir) {
- return false;
- }
- if (!obj.contains(ClipboardConfig::c_magic)
- || !obj.contains(ClipboardConfig::c_isCut)
- || !obj.contains(ClipboardConfig::c_dirs)) {
- return false;
- }
- int magic = obj[ClipboardConfig::c_magic].toInt();
- if (!checkMagic(magic)) {
- return false;
- }
- QJsonArray dirs = obj[ClipboardConfig::c_dirs].toArray();
- return !dirs.isEmpty();
- }
- void VDirectoryTree::mousePressEvent(QMouseEvent *event)
- {
- QTreeWidgetItem *item = itemAt(event->pos());
- if (!item) {
- setCurrentItem(NULL);
- }
- VTreeWidget::mousePressEvent(event);
- }
- void VDirectoryTree::keyPressEvent(QKeyEvent *event)
- {
- int key = event->key();
- int modifiers = event->modifiers();
- switch (key) {
- case Qt::Key_Return:
- {
- QTreeWidgetItem *item = currentItem();
- if (item) {
- item->setExpanded(!item->isExpanded());
- }
- break;
- }
- case Qt::Key_Asterisk:
- {
- if (modifiers == Qt::ShiftModifier) {
- // *, by default will expand current item recursively.
- // We build the tree recursively before the expanding.
- QTreeWidgetItem *item = currentItem();
- if (item) {
- buildSubTree(item, -1);
- }
- }
- break;
- }
- default:
- break;
- }
- VTreeWidget::keyPressEvent(event);
- }
- QTreeWidgetItem *VDirectoryTree::findVDirectory(const VDirectory *p_dir, bool *p_widget)
- {
- if (p_widget) {
- *p_widget = false;
- }
- if (!p_dir) {
- return NULL;
- } else if (p_dir->getNotebookName() != m_notebook->getName()) {
- return NULL;
- } else if (p_dir == m_notebook->getRootDir()) {
- if (p_widget) {
- *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;
- }
- bool VDirectoryTree::locateDirectory(const VDirectory *p_directory)
- {
- if (p_directory) {
- if (p_directory->getNotebook() != m_notebook) {
- return false;
- }
- QTreeWidgetItem *item = expandToVDirectory(p_directory);
- if (item) {
- setCurrentItem(item);
- }
- return item;
- }
- return false;
- }
- QTreeWidgetItem *VDirectoryTree::expandToVDirectory(const VDirectory *p_directory)
- {
- if (!p_directory
- || p_directory->getNotebook() != m_notebook
- || p_directory == m_notebook->getRootDir()) {
- return NULL;
- }
- if (p_directory->getParentDirectory() == m_notebook->getRootDir()) {
- // Top-level items.
- int nrChild = topLevelItemCount();
- for (int i = 0; i < nrChild; ++i) {
- QTreeWidgetItem *item = topLevelItem(i);
- if (getVDirectory(item) == p_directory) {
- return item;
- }
- }
- } else {
- QTreeWidgetItem *pItem = expandToVDirectory(p_directory->getParentDirectory());
- if (!pItem) {
- return NULL;
- }
- int nrChild = pItem->childCount();
- if (nrChild == 0) {
- buildSubTree(pItem, 1);
- }
- nrChild = pItem->childCount();
- for (int i = 0; i < nrChild; ++i) {
- QTreeWidgetItem *item = pItem->child(i);
- if (getVDirectory(item) == p_directory) {
- return item;
- }
- }
- }
- return NULL;
- }
- void VDirectoryTree::expandSubTree(QTreeWidgetItem *p_item)
- {
- if (!p_item) {
- return;
- }
- VDirectory *dir = getVDirectory(p_item);
- int nrChild = p_item->childCount();
- for (int i = 0; i < nrChild; ++i) {
- expandSubTree(p_item->child(i));
- }
- if (dir->isExpanded()) {
- Q_ASSERT(nrChild > 0);
- expandItem(p_item);
- }
- }
- void VDirectoryTree::showNavigation()
- {
- VNavigationMode::showNavigation(this);
- }
- bool VDirectoryTree::handleKeyNavigation(int p_key, bool &p_succeed)
- {
- return VNavigationMode::handleKeyNavigation(this,
- p_key,
- p_succeed);
- }
- int VDirectoryTree::getNewMagic()
- {
- m_magicForClipboard = (int)QDateTime::currentDateTime().toTime_t();
- m_magicForClipboard |= qrand();
- return m_magicForClipboard;
- }
- bool VDirectoryTree::checkMagic(int p_magic) const
- {
- return m_magicForClipboard == p_magic;
- }
- void VDirectoryTree::sortItems()
- {
- if (!m_notebook) {
- return;
- }
- QTreeWidgetItem *item = currentItem();
- if (item && item->parent()) {
- sortItems(getVDirectory(item->parent()));
- } else {
- sortItems(m_notebook->getRootDir());
- }
- if (item) {
- setCurrentItem(item);
- }
- }
- void VDirectoryTree::sortItems(VDirectory *p_dir)
- {
- if (!p_dir) {
- return;
- }
- const QVector<VDirectory *> &dirs = p_dir->getSubDirs();
- if (dirs.size() < 2) {
- return;
- }
- bool isNotebook = p_dir->parent() == NULL;
- VSortDialog dialog(tr("Sort Folders"),
- tr("Sort folders in %1 <span style=\"%2\">%3</span> "
- "in the configuration file.")
- .arg(isNotebook ? tr("notebook") : tr("folder"))
- .arg(g_config->c_dataTextStyle)
- .arg(isNotebook ? p_dir->getNotebook()->getName() : p_dir->getName()),
- this);
- QTreeWidget *tree = dialog.getTreeWidget();
- tree->clear();
- tree->setColumnCount(2);
- QStringList headers;
- headers << tr("Name") << tr("Created Time");
- tree->setHeaderLabels(headers);
- for (int i = 0; i < dirs.size(); ++i) {
- const VDirectory *dir = dirs[i];
- Q_ASSERT(dir->isOpened());
- QString createdTime = VUtils::displayDateTime(dir->getCreatedTimeUtc().toLocalTime(), true);
- QStringList cols;
- cols << dir->getName() << createdTime;
- QTreeWidgetItem *item = new QTreeWidgetItem(tree, cols);
- item->setData(0, Qt::UserRole, i);
- }
- dialog.treeUpdated();
- if (dialog.exec()) {
- QVector<QVariant> data = dialog.getSortedData();
- Q_ASSERT(data.size() == dirs.size());
- QVector<int> sortedIdx(data.size(), -1);
- for (int i = 0; i < data.size(); ++i) {
- sortedIdx[i] = data[i].toInt();
- }
- qDebug() << "sort dirs" << sortedIdx;
- if (!p_dir->sortSubDirectories(sortedIdx)) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Fail to sort folders in %1 <span style=\"%2\">%3</span>.")
- .arg(isNotebook ? tr("notebook") : tr("folder"))
- .arg(g_config->c_dataTextStyle)
- .arg(isNotebook ? p_dir->getNotebook()->getName() : p_dir->getName()),
- "",
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- }
- updateItemDirectChildren(findVDirectory(p_dir));
- }
- }
- VDirectory *VDirectoryTree::currentDirectory() const
- {
- QTreeWidgetItem *item = currentItem();
- if (item) {
- return getVDirectory(item);
- }
- return NULL;
- }
- void VDirectoryTree::pinDirectoryToHistory()
- {
- QTreeWidgetItem *curItem = currentItem();
- V_ASSERT(curItem);
- g_mainWin->getHistoryList()->pinFolder(getVDirectory(curItem)->fetchPath());
- g_mainWin->showStatusMessage(tr("1 folder pinned to History"));
- }
- Qt::DropActions VDirectoryTree::supportedDropActions() const
- {
- return Qt::CopyAction | Qt::MoveAction;
- }
- bool VDirectoryTree::dropMimeData(QTreeWidgetItem *p_parent,
- int p_index,
- const QMimeData *p_data,
- Qt::DropAction p_action)
- {
- Q_UNUSED(p_index);
- if (!p_parent) {
- VUtils::showMessage(QMessageBox::Warning,
- tr("Warning"),
- tr("Please drop it on a folder item."),
- "",
- QMessageBox::Ok,
- QMessageBox::Ok,
- this);
- return false;
- }
- if (p_data->hasFormat(ClipboardConfig::c_format)) {
- VDirectory *dir = getVDirectory(p_parent);
- if (!dir) {
- return false;
- }
- QByteArray ba = p_data->data(ClipboardConfig::c_format);
- QJsonObject obj = QJsonDocument::fromJson(ba).object();
- if (obj.isEmpty()) {
- return false;
- }
- if (obj[ClipboardConfig::c_type] != (int)ClipboardOpType::CopyFile) {
- return false;
- }
- QJsonArray files = obj[ClipboardConfig::c_files].toArray();
- if (files.isEmpty()) {
- return false;
- }
- QVector<QString> filesToPaste;
- for (auto const & file : files) {
- filesToPaste.append(file.toString());
- }
- qDebug() << "paste files from dropped mime data" << dir->getName() << filesToPaste;
- g_mainWin->getFileList()->pasteFiles(dir, filesToPaste, p_action == Qt::MoveAction);
- return true;
- }
- return false;
- }
- void VDirectoryTree::dropEvent(QDropEvent *p_event)
- {
- // Distinguish copy and cut.
- int modifiers = p_event->keyboardModifiers();
- if (modifiers & Qt::ControlModifier) {
- p_event->setDropAction(Qt::CopyAction);
- } else {
- // Cut.
- // Will pass to dropMimeData().
- p_event->setDropAction(Qt::MoveAction);
- }
- QTreeWidget::dropEvent(p_event);
- }
- QStringList VDirectoryTree::mimeTypes() const
- {
- return QStringList(ClipboardConfig::c_format);
- }
|