diff --git a/src/dialog/vnewnotebookdialog.cpp b/src/dialog/vnewnotebookdialog.cpp index f19d8ca8..1f66a567 100644 --- a/src/dialog/vnewnotebookdialog.cpp +++ b/src/dialog/vnewnotebookdialog.cpp @@ -314,7 +314,7 @@ bool VNewNotebookDialog::autoComplete() // Get a folder name under vnoteFolder and set it as the name of the notebook. QString name = "vnotebook"; - name = VUtils::getFileNameWithSequence(vnoteFolder, name); + name = VUtils::getDirNameWithSequence(vnoteFolder, name); nameEdit->setText(name); ret = true; } else { diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index 4a22144a..4adbbb5f 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -377,31 +377,35 @@ int VUtils::showMessage(QMessageBox::Icon p_icon, const QString &p_title, const return msgBox.exec(); } -QString VUtils::generateCopiedFileName(const QString &p_dirPath, const QString &p_fileName) +QString VUtils::generateCopiedFileName(const QString &p_dirPath, + const QString &p_fileName, + bool p_completeBaseName) { - QString suffix; - QString base = p_fileName; - int dotIdx = p_fileName.lastIndexOf('.'); - if (dotIdx != -1) { - // .md - suffix = p_fileName.right(p_fileName.size() - dotIdx); - base = p_fileName.left(dotIdx); + QDir dir(p_dirPath); + if (!dir.exists() || !dir.exists(p_fileName)) { + return p_fileName; } - QDir dir(p_dirPath); - QString name = p_fileName; + QFileInfo fi(p_fileName); + QString baseName = p_completeBaseName ? fi.completeBaseName() : fi.baseName(); + QString suffix = p_completeBaseName ? fi.suffix() : fi.completeSuffix(); + int index = 0; - while (dir.exists(name)) { + QString fileName; + do { QString seq; if (index > 0) { - seq = QString::number(index); + seq = QString("%1").arg(QString::number(index), 3, '0'); } index++; - name = QString("%1_copy%2%3").arg(base).arg(seq).arg(suffix); - } + fileName = QString("%1_copy%2").arg(baseName).arg(seq); + if (!suffix.isEmpty()) { + fileName = fileName + "." + suffix; + } + } while (fileExists(dir, fileName, true)); - return name; + return fileName; } QString VUtils::generateCopiedDirName(const QString &p_parentDirPath, const QString &p_dirName) @@ -614,7 +618,8 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType, bool p_exp } QString VUtils::getFileNameWithSequence(const QString &p_directory, - const QString &p_baseFileName) + const QString &p_baseFileName, + bool p_completeBaseName) { QDir dir(p_directory); if (!dir.exists() || !dir.exists(p_baseFileName)) { @@ -623,8 +628,8 @@ QString VUtils::getFileNameWithSequence(const QString &p_directory, // Append a sequence. QFileInfo fi(p_baseFileName); - QString baseName = fi.baseName(); - QString suffix = fi.completeSuffix(); + QString baseName = p_completeBaseName ? fi.completeBaseName() : fi.baseName(); + QString suffix = p_completeBaseName ? fi.suffix() : fi.completeSuffix(); int seq = 1; QString fileName; do { @@ -637,6 +642,24 @@ QString VUtils::getFileNameWithSequence(const QString &p_directory, return fileName; } +QString VUtils::getDirNameWithSequence(const QString &p_directory, + const QString &p_baseDirName) +{ + QDir dir(p_directory); + if (!dir.exists() || !dir.exists(p_baseDirName)) { + return p_baseDirName; + } + + // Append a sequence. + int seq = 1; + QString fileName; + do { + fileName = QString("%1_%2").arg(p_baseDirName).arg(QString::number(seq++), 3, '0'); + } while (fileExists(dir, fileName, true)); + + return fileName; +} + QString VUtils::getRandomFileName(const QString &p_directory) { Q_ASSERT(!p_directory.isEmpty()); @@ -850,7 +873,8 @@ bool VUtils::deleteFile(const QString &p_recycleBinFolderPath, } QString destName = getFileNameWithSequence(binPath, - fileNameFromPath(p_path)); + fileNameFromPath(p_path), + true); qDebug() << "try to move" << p_path << "to" << binPath << "as" << destName; if (!binDir.rename(p_path, binDir.filePath(destName))) { diff --git a/src/utils/vutils.h b/src/utils/vutils.h index f3e75bb9..0bf4a87b 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -80,9 +80,19 @@ public: // Given the file name @p_fileName and directory path @p_dirPath, generate // a file name based on @p_fileName which does not exist in @p_dirPath. - static QString generateCopiedFileName(const QString &p_dirPath, const QString &p_fileName); + // @p_completeBaseName: use complete base name or complete suffix. For example, + // "abc.tar.gz", if @p_completeBaseName is true, the base name is "abc.tar", + // otherwise, it is "abc". + static QString generateCopiedFileName(const QString &p_dirPath, + const QString &p_fileName, + bool p_completeBaseName = true); + + // Given the directory name @p_dirName and directory path @p_parentDirPath, + // generate a directory name based on @p_dirName which does not exist in + // @p_parentDirPath. + static QString generateCopiedDirName(const QString &p_parentDirPath, + const QString &p_dirName); - static QString generateCopiedDirName(const QString &p_parentDirPath, const QString &p_dirName); static void processStyle(QString &style, const QVector > &varMap); // Return the last directory name of @p_path. @@ -148,8 +158,18 @@ public: // Get an available file name in @p_directory with base @p_baseFileName. // If there already exists a file named @p_baseFileName, try to add sequence // suffix to the name, such as _001. + // @p_completeBaseName: use complete base name or complete suffix. For example, + // "abc.tar.gz", if @p_completeBaseName is true, the base name is "abc.tar", + // otherwise, it is "abc". static QString getFileNameWithSequence(const QString &p_directory, - const QString &p_baseFileName); + const QString &p_baseFileName, + bool p_completeBaseName = true); + + // Get an available directory name in @p_directory with base @p_baseDirName. + // If there already exists a file named @p_baseFileName, try to add sequence + // suffix to the name, such as _001. + static QString getDirNameWithSequence(const QString &p_directory, + const QString &p_baseDirName); // Get an available random file name in @p_directory. static QString getRandomFileName(const QString &p_directory); diff --git a/src/vdirectorytree.cpp b/src/vdirectorytree.cpp index 68ff4f0f..41c78cf1 100644 --- a/src/vdirectorytree.cpp +++ b/src/vdirectorytree.cpp @@ -430,7 +430,7 @@ void VDirectoryTree::newSubDirectory() .arg(g_config->c_dataTextStyle) .arg(curDir->getName()); QString defaultName("new_folder"); - defaultName = VUtils::getFileNameWithSequence(curDir->fetchPath(), defaultName); + defaultName = VUtils::getDirNameWithSequence(curDir->fetchPath(), defaultName); VNewDirDialog dialog(tr("Create Folder"), info, defaultName, curDir, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); @@ -467,7 +467,7 @@ void VDirectoryTree::newRootDirectory() .arg(g_config->c_dataTextStyle) .arg(m_notebook->getName()); QString defaultName("new_folder"); - defaultName = VUtils::getFileNameWithSequence(rootDir->fetchPath(), defaultName); + 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(); diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index 5629ad37..500ee6b1 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -330,7 +330,9 @@ void VFileList::newFile() info = info + "
" + tr("Note with name ending with \"%1\" will be treated as Markdown type.") .arg(suffixStr); QString defaultName = QString("new_note.%1").arg(defaultSuf); - defaultName = VUtils::getFileNameWithSequence(m_directory->fetchPath(), defaultName); + defaultName = VUtils::getFileNameWithSequence(m_directory->fetchPath(), + defaultName, + true); VNewFileDialog dialog(tr("Create Note"), info, defaultName, m_directory, this); if (dialog.exec() == QDialog::Accepted) { VNoteFile *file = m_directory->createFile(dialog.getNameInput()); @@ -349,7 +351,7 @@ void VFileList::newFile() qWarning() << "fail to open newly-created note" << file->getName(); } else { Q_ASSERT(file->getContent().isEmpty()); - QString content = QString("# %1\n").arg(QFileInfo(file->getName()).baseName()); + QString content = QString("# %1\n").arg(QFileInfo(file->getName()).completeBaseName()); file->setContent(content); if (!file->save()) { qWarning() << "fail to write to newly-created note" << file->getName(); @@ -621,7 +623,7 @@ bool VFileList::importFiles(const QStringList &p_files, QString *p_errMsg) QString name = VUtils::fileNameFromPath(file); Q_ASSERT(!name.isEmpty()); - name = VUtils::getFileNameWithSequence(dirPath, name); + name = VUtils::getFileNameWithSequence(dirPath, name, true); QString targetFilePath = dir.filePath(name); bool ret = VUtils::copyFile(file, targetFilePath, false); if (!ret) { @@ -763,10 +765,14 @@ void VFileList::pasteFiles(VDirectory *p_destDir, } // Rename it to xxx_copy.md. - fileName = VUtils::generateCopiedFileName(file->fetchBasePath(), fileName); + fileName = VUtils::generateCopiedFileName(file->fetchBasePath(), + fileName, + true); } else { // Rename it to xxx_copy.md if needed. - fileName = VUtils::generateCopiedFileName(p_destDir->fetchPath(), fileName); + fileName = VUtils::generateCopiedFileName(p_destDir->fetchPath(), + fileName, + true); } QString msg; diff --git a/src/vnotefile.cpp b/src/vnotefile.cpp index 0cbb46f8..ea85a7fb 100644 --- a/src/vnotefile.cpp +++ b/src/vnotefile.cpp @@ -233,7 +233,9 @@ bool VNoteFile::addAttachment(const QString &p_file) QString folderPath = fetchAttachmentFolderPath(); QString name = VUtils::fileNameFromPath(p_file); Q_ASSERT(!name.isEmpty()); - name = VUtils::getFileNameWithSequence(folderPath, name); + // For attachments, we do not use complete base name. + // abc.tar.gz should be abc_001.tar.gz instead of abc.tar_001.gz. + name = VUtils::getFileNameWithSequence(folderPath, name, false); QString destPath = QDir(folderPath).filePath(name); if (!VUtils::copyFile(p_file, destPath, false)) { return false; @@ -543,7 +545,7 @@ bool VNoteFile::copyFile(VDirectory *p_destDir, if (!attaFolderPath.isEmpty()) { QDir dir(destFile->fetchBasePath()); QString folderPath = dir.filePath(destFile->getNotebook()->getAttachmentFolder()); - attaFolder = VUtils::getFileNameWithSequence(folderPath, attaFolder); + attaFolder = VUtils::getDirNameWithSequence(folderPath, attaFolder); folderPath = QDir(folderPath).filePath(attaFolder); // Copy attaFolderPath to folderPath.