Browse Source

bug-fix: use completeBaseName() when adding sequence to file name

- When adding attachments, if the name conflicts, we add sequence after
the base name. "abc.tar.gz" to "abc_001.tar.gz".
- When handling notes and folders, if the name conflicts, we add
sequence after the complete base name. "abc.5.9.1.md" to
"abc.5.9.1_001.md".
Le Tan 8 years ago
parent
commit
893c0b2823
6 changed files with 84 additions and 32 deletions
  1. 1 1
      src/dialog/vnewnotebookdialog.cpp
  2. 43 19
      src/utils/vutils.cpp
  3. 23 3
      src/utils/vutils.h
  4. 2 2
      src/vdirectorytree.cpp
  5. 11 5
      src/vfilelist.cpp
  6. 4 2
      src/vnotefile.cpp

+ 1 - 1
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 {

+ 43 - 19
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))) {

+ 23 - 3
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<QPair<QString, QString> > &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);

+ 2 - 2
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();

+ 11 - 5
src/vfilelist.cpp

@@ -330,7 +330,9 @@ void VFileList::newFile()
     info = info + "<br>" + 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;

+ 4 - 2
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.