From a87048cac296da444fa817cd8040f854aca910d8 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Mon, 3 Jul 2017 19:09:50 +0800 Subject: [PATCH] bug-fix: compare two paths with case convertion on Windows On Windows, case difference in file name is ignored. --- src/dialog/vdeletenotebookdialog.cpp | 19 ++++++++++--------- src/dialog/vdeletenotebookdialog.h | 6 ++++-- src/dialog/vnewnotebookdialog.cpp | 10 ++++++---- src/utils/vutils.cpp | 28 ++++++++++++++++++++++++++++ src/utils/vutils.h | 3 +++ src/vdirectory.cpp | 6 +++--- src/vdirectorytree.cpp | 2 +- src/vfile.cpp | 3 ++- src/vfilelist.cpp | 2 +- src/vmdedit.cpp | 4 ++-- src/vorphanfile.cpp | 3 ++- 11 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/dialog/vdeletenotebookdialog.cpp b/src/dialog/vdeletenotebookdialog.cpp index a8d1e753..808a1b9d 100644 --- a/src/dialog/vdeletenotebookdialog.cpp +++ b/src/dialog/vdeletenotebookdialog.cpp @@ -18,12 +18,13 @@ void VDeleteNotebookDialog::setupUI(const QString &p_title, const QString &p_nam m_warningLabel = new QLabel(); m_warningLabel->setWordWrap(true); - m_notDeleteCheck = new QCheckBox(tr("Do not delete files from disk."), this); - m_notDeleteCheck->setChecked(true); - m_notDeleteCheck->setToolTip(tr("When checked, VNote just removes the notebook instead of deleting files from disk")); - connect(m_notDeleteCheck, &QCheckBox::stateChanged, this, &VDeleteNotebookDialog::notDeleteCheckChanged); + m_deleteCheck = new QCheckBox(tr("Delete files from disk"), this); + m_deleteCheck->setChecked(false); + m_deleteCheck->setToolTip(tr("When checked, VNote will delete all the files within this notebook from disk")); + connect(m_deleteCheck, &QCheckBox::stateChanged, + this, &VDeleteNotebookDialog::deleteCheckChanged); - notDeleteCheckChanged(true); + deleteCheckChanged(false); // Ok is the default button. m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); @@ -49,7 +50,7 @@ void VDeleteNotebookDialog::setupUI(const QString &p_title, const QString &p_nam QVBoxLayout *infoLayout = new QVBoxLayout(); infoLayout->addWidget(infoLabel); - infoLayout->addWidget(m_notDeleteCheck); + infoLayout->addWidget(m_deleteCheck); infoLayout->addWidget(m_warningLabel); QHBoxLayout *topLayout = new QHBoxLayout(); @@ -67,7 +68,7 @@ void VDeleteNotebookDialog::setupUI(const QString &p_title, const QString &p_nam bool VDeleteNotebookDialog::getDeleteFiles() const { - return !m_notDeleteCheck->isChecked(); + return m_deleteCheck->isChecked(); } QPixmap VDeleteNotebookDialog::standardIcon(QMessageBox::Icon p_icon) @@ -104,9 +105,9 @@ QPixmap VDeleteNotebookDialog::standardIcon(QMessageBox::Icon p_icon) return QPixmap(); } -void VDeleteNotebookDialog::notDeleteCheckChanged(int p_state) +void VDeleteNotebookDialog::deleteCheckChanged(int p_state) { - if (p_state) { + if (!p_state) { m_warningLabel->setText(tr("VNote won't delete files in directory %2.") .arg(vconfig.c_dataTextStyle).arg(m_path)); } else { diff --git a/src/dialog/vdeletenotebookdialog.h b/src/dialog/vdeletenotebookdialog.h index 6c1706d1..34850689 100644 --- a/src/dialog/vdeletenotebookdialog.h +++ b/src/dialog/vdeletenotebookdialog.h @@ -16,10 +16,12 @@ class VDeleteNotebookDialog : public QDialog public: VDeleteNotebookDialog(const QString &p_title, const QString &p_name, const QString &p_path, QWidget *p_parent = 0); + + // Whether delete files from disk. bool getDeleteFiles() const; private slots: - void notDeleteCheckChanged(int p_state); + void deleteCheckChanged(int p_state); private: void setupUI(const QString &p_title, const QString &p_name); @@ -27,7 +29,7 @@ private: QString m_path; QLabel *m_warningLabel; - QCheckBox *m_notDeleteCheck; + QCheckBox *m_deleteCheck; QDialogButtonBox *m_btnBox; }; diff --git a/src/dialog/vnewnotebookdialog.cpp b/src/dialog/vnewnotebookdialog.cpp index 49602db9..f1721918 100644 --- a/src/dialog/vnewnotebookdialog.cpp +++ b/src/dialog/vnewnotebookdialog.cpp @@ -96,7 +96,9 @@ QString VNewNotebookDialog::getNameInput() const QString VNewNotebookDialog::getPathInput() const { - return QDir::cleanPath(pathEdit->text()); + // absoluteFilePath() to convert the drive to upper case. + // cleanPath() to remove duplicate separator, '.', and '..'. + return QDir::cleanPath(QFileInfo(pathEdit->text()).absoluteFilePath()); } QString VNewNotebookDialog::getImageFolder() const @@ -205,9 +207,8 @@ void VNewNotebookDialog::handleInputChanged() if (pathOk) { // Check if this path has been in VNote. int idx = -1; - path = QDir::cleanPath(path); for (idx = 0; idx < m_notebooks.size(); ++idx) { - if (QDir::cleanPath(m_notebooks[idx]->getPath()) == path) { + if (VUtils::equalPath(m_notebooks[idx]->getPath(), path)) { break; } } @@ -261,7 +262,8 @@ bool VNewNotebookDialog::autoComplete() QString vnoteFolder = vconfig.getVnoteNotebookFolderPath(); QString pathText = pathEdit->text(); - if (!pathText.isEmpty() && vnoteFolder != VUtils::basePathFromPath(pathText)) { + if (!pathText.isEmpty() + && !VUtils::equalPath(vnoteFolder, VUtils::basePathFromPath(pathText))) { return false; } diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index 9f741ace..e3a387f7 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -610,6 +610,13 @@ bool VUtils::checkPathLegal(const QString &p_path) } if (QFileInfo::exists(p_path)) { +#if defined(Q_OS_WIN) + // On Windows, "/" and ":" will also make exists() return true. + if (p_path.startsWith('/') || p_path == ":") { + return false; + } +#endif + return true; } @@ -626,6 +633,14 @@ bool VUtils::checkPathLegal(const QString &p_path) if (QFileInfo::exists(basePath)) { ret = true; + +#if defined(Q_OS_WIN) + // On Windows, "/" and ":" will also make exists() return true. + if (basePath.startsWith('/') || basePath == ":") { + ret = false; + } +#endif + break; } @@ -636,3 +651,16 @@ bool VUtils::checkPathLegal(const QString &p_path) delete validator; return ret; } + +bool VUtils::equalPath(const QString &p_patha, const QString &p_pathb) +{ + QString a = QDir::cleanPath(p_patha); + QString b = QDir::cleanPath(p_pathb); + +#if defined(Q_OS_WIN) + a = a.toLower(); + b = b.toLower(); +#endif + + return a == b; +} diff --git a/src/utils/vutils.h b/src/utils/vutils.h index ffed9a6c..bf6b3ef0 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -106,6 +106,9 @@ public: // Try to check if @p_path is legal. static bool checkPathLegal(const QString &p_path); + // Returns true if @p_patha and @p_pathb points to the same file/directory. + static bool equalPath(const QString &p_patha, const QString &p_pathb); + // Regular expression for image link. // ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" ) // Captured texts (need to be trimmed): diff --git a/src/vdirectory.cpp b/src/vdirectory.cpp index 2351b772..8d5660f5 100644 --- a/src/vdirectory.cpp +++ b/src/vdirectory.cpp @@ -484,7 +484,7 @@ VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName, { QString srcPath = QDir::cleanPath(p_srcFile->retrivePath()); QString destPath = QDir::cleanPath(QDir(p_destDir->retrivePath()).filePath(p_destName)); - if (srcPath == destPath) { + if (VUtils::equalPath(srcPath, destPath)) { return p_srcFile; } @@ -554,7 +554,7 @@ VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName, destImagePath = QDir(destImagePath).filePath(VUtils::fileNameFromPath(link.m_path)); // Copy or Cut the images accordingly. - if (destImagePath == link.m_path) { + if (VUtils::equalPath(destImagePath, link.m_path)) { ret = false; } else { ret = VUtils::copyFile(link.m_path, destImagePath, p_cut); @@ -607,7 +607,7 @@ VDirectory *VDirectory::copyDirectory(VDirectory *p_destDir, const QString &p_de { QString srcPath = QDir::cleanPath(p_srcDir->retrivePath()); QString destPath = QDir::cleanPath(QDir(p_destDir->retrivePath()).filePath(p_destName)); - if (srcPath == destPath) { + if (VUtils::equalPath(srcPath, destPath)) { return p_srcDir; } diff --git a/src/vdirectorytree.cpp b/src/vdirectorytree.cpp index b50e41a7..91a0eec7 100644 --- a/src/vdirectorytree.cpp +++ b/src/vdirectorytree.cpp @@ -619,7 +619,7 @@ bool VDirectoryTree::copyDirectory(VDirectory *p_destDir, const QString &p_destN 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) { + if (VUtils::equalPath(srcPath, destPath)) { return true; } diff --git a/src/vfile.cpp b/src/vfile.cpp index b51e49e6..e9dd3a5b 100644 --- a/src/vfile.cpp +++ b/src/vfile.cpp @@ -212,7 +212,8 @@ FileType VFile::getType() const bool VFile::isInternalImageFolder(const QString &p_path) const { - return VUtils::basePathFromPath(p_path) == getDirectory()->retrivePath(); + return VUtils::equalPath(VUtils::basePathFromPath(p_path), + getDirectory()->retrivePath()); } QUrl VFile::getBaseUrl() const diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index 44f0969c..7e706c27 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -485,7 +485,7 @@ bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VFile { QString srcPath = QDir::cleanPath(p_file->retrivePath()); QString destPath = QDir::cleanPath(QDir(p_destDir->retrivePath()).filePath(p_destName)); - if (srcPath == destPath) { + if (VUtils::equalPath(srcPath, destPath)) { return true; } diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp index 3a211d04..37d3aa49 100644 --- a/src/vmdedit.cpp +++ b/src/vmdedit.cpp @@ -221,7 +221,7 @@ void VMdEdit::clearUnusedImages() int j; for (j = 0; j < images.size(); ++j) { - if (link.m_path == images[j].m_path) { + if (VUtils::equalPath(link.m_path, images[j].m_path)) { break; } } @@ -246,7 +246,7 @@ void VMdEdit::clearUnusedImages() int j; for (j = 0; j < images.size(); ++j) { - if (link.m_path == images[j].m_path) { + if (VUtils::equalPath(link.m_path, images[j].m_path)) { break; } } diff --git a/src/vorphanfile.cpp b/src/vorphanfile.cpp index 444c34b6..5066031d 100644 --- a/src/vorphanfile.cpp +++ b/src/vorphanfile.cpp @@ -90,7 +90,8 @@ void VOrphanFile::setContent(const QString & /* p_content */) bool VOrphanFile::isInternalImageFolder(const QString &p_path) const { - return VUtils::basePathFromPath(p_path) == VUtils::basePathFromPath(m_path); + return VUtils::equalPath(VUtils::basePathFromPath(p_path), + VUtils::basePathFromPath(m_path)); } bool VOrphanFile::rename(const QString &p_name)