void VDirectoryTree::handleItemCollapsed(QTreeWidgetItem *p_item) { if (p_item) { VDirectory *dir = getVDirectory(p_item); dir->setExpanded(false); } }
bool VNoteFile::deleteFile(VNoteFile *p_file, QString *p_errMsg) { Q_ASSERT(!p_file->isOpened()); bool ret = true; QString name = p_file->getName(); QString path = p_file->fetchPath(); if (!p_file->deleteFile(p_errMsg)) { qWarning() << "fail to delete file" << name << path; ret = false; } VDirectory *dir = p_file->getDirectory(); Q_ASSERT(dir); if (!dir->removeFile(p_file)) { qWarning() << "fail to remove file from directory" << name << path; VUtils::addErrMsg(p_errMsg, tr("Fail to remove the note from the folder configuration.")); ret = false; } delete p_file; return ret; }
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::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::handleItemExpanded(QTreeWidgetItem *p_item) { if (p_item) { buildChildren(p_item); VDirectory *dir = getVDirectory(p_item); dir->setExpanded(true); } }
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 VListFolderUE::processCommand(int p_id, const QString &p_cmd) { Q_UNUSED(p_id); init(); QString folderPath = m_folderPath; if (folderPath.isEmpty()) { VDirectory *dir = g_mainWin->getDirectoryTree()->currentDirectory(); folderPath = dir->fetchPath(); } listFolder(folderPath, p_cmd); m_listWidget->updateGeometry(); emit widgetUpdated(); emit stateUpdated(State::Success); }
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)); } }
void VDirectoryTree::newSubDirectory() { if (!m_notebook) { return; } QTreeWidgetItem *curItem = currentItem(); if (!curItem) { return; } VDirectory *curDir = getVDirectory(curItem); 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(curItem); locateDirectory(subDir); } }
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); } }
bool VNoteFile::rename(const QString &p_name) { if (m_name == p_name) { return true; } QString oldName = m_name; VDirectory *dir = getDirectory(); Q_ASSERT(dir); // Rename it in disk. QDir diskDir(dir->fetchPath()); if (!diskDir.rename(m_name, p_name)) { qWarning() << "fail to rename file" << m_name << "to" << p_name << "in disk"; return false; } m_name = p_name; // Update parent directory's config file. if (!dir->updateFileConfig(this)) { m_name = oldName; diskDir.rename(p_name, m_name); return false; } // Can't not change doc type. Q_ASSERT(m_docType == DocType::Unknown || m_docType == VUtils::docTypeFromName(m_name)); m_docType = VUtils::docTypeFromName(m_name); qDebug() << "file renamed from" << oldName << "to" << m_name; return true; }
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::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); } }
bool VListFolderUE::listFolder(const QString &p_path, const QString &p_cmd) { VDirectory *dir = g_vnote->getInternalDirectory(p_path); if (!dir) { // See if it is a notebook. VNotebook *nb = g_vnote->getNotebook(p_path); if (!nb) { return false; } dir = nb->getRootDir(); } m_panel->clearTitle(); m_listWidget->clearAll(); m_data.clear(); m_currentFolderPath = dir->fetchPath(); m_panel->setTitle(m_currentFolderPath); if (!dir->open()) { return true; } if (p_cmd.isEmpty()) { // List the content. for (auto const & it : dir->getSubDirs()) { QSharedPointer<VSearchResultItem> item(new VSearchResultItem(VSearchResultItem::Folder, VSearchResultItem::LineNumber, it->getName(), it->fetchPath())); addResultItem(item); } for (auto const & file : dir->getFiles()) { QSharedPointer<VSearchResultItem> item(new VSearchResultItem(VSearchResultItem::Note, VSearchResultItem::LineNumber, file->getName(), file->fetchPath())); addResultItem(item); } } else { // Search the content. VSearchConfig config(VSearchConfig::CurrentFolder, VSearchConfig::Name, VSearchConfig::Note | VSearchConfig::Folder, VSearchConfig::Internal, VSearchConfig::NoneOption, p_cmd, QString()); for (auto const & it : dir->getSubDirs()) { QString name = it->getName(); if (!config.m_token.matched(name)) { continue; } QSharedPointer<VSearchResultItem> item(new VSearchResultItem(VSearchResultItem::Folder, VSearchResultItem::LineNumber, name, it->fetchPath())); addResultItem(item); } for (auto const & file : dir->getFiles()) { QString name = file->getName(); if (!config.m_token.matched(name)) { continue; } QSharedPointer<VSearchResultItem> item(new VSearchResultItem(VSearchResultItem::Note, VSearchResultItem::LineNumber, name, file->fetchPath())); addResultItem(item); } } return true; }
bool VNoteFile::copyFile(VDirectory *p_destDir, const QString &p_destName, VNoteFile *p_file, bool p_isCut, VNoteFile **p_targetFile, QString *p_errMsg) { bool ret = true; *p_targetFile = NULL; int nrImageCopied = 0; bool attachmentFolderCopied = false; QString srcPath = QDir::cleanPath(p_file->fetchPath()); QString destPath = QDir::cleanPath(QDir(p_destDir->fetchPath()).filePath(p_destName)); if (VUtils::equalPath(srcPath, destPath)) { *p_targetFile = p_file; return false; } if (!p_destDir->isOpened()) { VUtils::addErrMsg(p_errMsg, tr("Fail to open target folder.")); return false; } QString opStr = p_isCut ? tr("cut") : tr("copy"); VDirectory *srcDir = p_file->getDirectory(); DocType docType = p_file->getDocType(); Q_ASSERT(srcDir->isOpened()); Q_ASSERT(docType == VUtils::docTypeFromName(p_destName)); // Images to be copied. QVector<ImageLink> images; if (docType == DocType::Markdown) { images = VUtils::fetchImagesFromMarkdownFile(p_file, ImageLink::LocalRelativeInternal); } // Attachments to be copied. QString attaFolder = p_file->getAttachmentFolder(); QString attaFolderPath; if (!attaFolder.isEmpty()) { attaFolderPath = p_file->fetchAttachmentFolderPath(); } // Copy the note file. if (!VUtils::copyFile(srcPath, destPath, p_isCut)) { VUtils::addErrMsg(p_errMsg, tr("Fail to %1 the note file.").arg(opStr)); qWarning() << "fail to" << opStr << "the note file" << srcPath << "to" << destPath; return false; } // Add file to VDirectory. VNoteFile *destFile = NULL; if (p_isCut) { srcDir->removeFile(p_file); p_file->setName(p_destName); if (p_destDir->addFile(p_file, -1)) { destFile = p_file; } else { destFile = NULL; } } else { destFile = p_destDir->addFile(p_destName, -1); } if (!destFile) { VUtils::addErrMsg(p_errMsg, tr("Fail to add the note to target folder's configuration.")); return false; } // Copy images. if (!copyInternalImages(images, destFile->fetchBasePath(), p_isCut, &nrImageCopied, p_errMsg)) { ret = false; } // Copy attachment folder. if (!attaFolderPath.isEmpty()) { QDir dir(destFile->fetchBasePath()); QString folderPath = dir.filePath(destFile->getNotebook()->getAttachmentFolder()); attaFolder = VUtils::getDirNameWithSequence(folderPath, attaFolder); folderPath = QDir(folderPath).filePath(attaFolder); // Copy attaFolderPath to folderPath. if (!VUtils::copyDirectory(attaFolderPath, folderPath, p_isCut)) { VUtils::addErrMsg(p_errMsg, tr("Fail to %1 attachments folder %2 to %3. " "Please manually maintain it.") .arg(opStr).arg(attaFolderPath).arg(folderPath)); QVector<VAttachment> emptyAttas; destFile->setAttachments(emptyAttas); ret = false; } else { attachmentFolderCopied = true; destFile->setAttachmentFolder(attaFolder); if (!p_isCut) { destFile->setAttachments(p_file->getAttachments()); } } if (!p_destDir->updateFileConfig(destFile)) { VUtils::addErrMsg(p_errMsg, tr("Fail to update configuration of note %1.") .arg(destFile->fetchPath())); ret = false; } } qDebug() << "copyFile:" << p_file << "to" << destFile << "copied_images:" << nrImageCopied << "copied_attachments:" << attachmentFolderCopied; *p_targetFile = destFile; return ret; }
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(); }
void VSearcher::startSearch() { if (m_inSearch) { return; } m_searchBtn->setEnabled(false); setProgressVisible(true); m_results->clearResults(); m_askedToStop = false; m_inSearch = true; m_consoleEdit->clear(); appendLogLine(tr("Search started.")); updateItemToComboBox(m_keywordCB); updateItemToComboBox(m_filePatternCB); m_search.clear(); QSharedPointer<VSearchConfig> config(new VSearchConfig(m_searchScopeCB->currentData().toInt(), m_searchObjectCB->currentData().toInt(), m_searchTargetCB->currentData().toInt(), m_searchEngineCB->currentData().toInt(), getSearchOption(), m_keywordCB->currentText(), m_filePatternCB->currentText())); m_search.setConfig(config); g_config->setSearchOptions(config->toConfig()); QSharedPointer<VSearchResult> result; switch (config->m_scope) { case VSearchConfig::CurrentNote: { QVector<VFile *> files; files.append(g_mainWin->getCurrentFile()); if (files[0]) { QString msg(tr("Search current note %1.").arg(files[0]->getName())); appendLogLine(msg); showMessage(msg); } result = m_search.search(files); break; } case VSearchConfig::OpenedNotes: { QVector<VEditTabInfo> tabs = g_mainWin->getEditArea()->getAllTabsInfo(); QVector<VFile *> files; files.reserve(tabs.size()); for (auto const & ta : tabs) { files.append(ta.m_editTab->getFile()); } result = m_search.search(files); break; } case VSearchConfig::CurrentFolder: { VDirectory *dir = g_mainWin->getDirectoryTree()->currentDirectory(); if (dir) { QString msg(tr("Search current folder %1.").arg(dir->getName())); appendLogLine(msg); showMessage(msg); } result = m_search.search(dir); break; } case VSearchConfig::CurrentNotebook: { QVector<VNotebook *> notebooks; notebooks.append(g_mainWin->getNotebookSelector()->currentNotebook()); if (notebooks[0]) { QString msg(tr("Search current notebook %1.").arg(notebooks[0]->getName())); appendLogLine(msg); showMessage(msg); } result = m_search.search(notebooks); break; } case VSearchConfig::AllNotebooks: { const QVector<VNotebook *> ¬ebooks = g_vnote->getNotebooks(); result = m_search.search(notebooks); break; } case VSearchConfig::ExplorerDirectory: { QString rootDirectory = g_mainWin->getExplorer()->getRootDirectory(); if (!rootDirectory.isEmpty()) { QString msg(tr("Search Explorer directory %1.").arg(rootDirectory)); appendLogLine(msg); showMessage(msg); } result = m_search.search(rootDirectory); break; } default: break; } handleSearchFinished(result); }
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); } }