Skip to content

Commit 8f7666d

Browse files
authored
Fix #14983 (GUI: exclude file with relative path) (#8804)
1 parent 9699b99 commit 8f7666d

6 files changed

Lines changed: 83 additions & 7 deletions

File tree

gui/manualtest/projectfiledialog.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44
Some manual testing in the project file dialog interface
55

66

7+
## Test: Relative paths
8+
9+
Ticket: #14983
10+
11+
1. Configure files/paths in project folder:
12+
* import a projectfile
13+
* add include paths in project folder
14+
* exclude file/folder
15+
16+
2. Save project
17+
18+
EXPECTED: Relative paths should be used in the XML
19+
20+
721
## Test: Platform file pic8.xml
822

923
Ticket: #14489

gui/projectfile.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,15 @@ QStringList ProjectFile::getSearchPaths(const QString& projectPath, const QStrin
11931193
return ret;
11941194
}
11951195

1196+
QString ProjectFile::getRelativePath(const QString &absolutePath) const
1197+
{
1198+
const QDir dir(QFileInfo(mFilename).absolutePath());
1199+
const QString relativePath(dir.relativeFilePath(absolutePath));
1200+
if (relativePath.startsWith("../../..") || absolutePath.length() < relativePath.length())
1201+
return absolutePath;
1202+
return relativePath;
1203+
}
1204+
11961205
QStringList ProjectFile::getSearchPaths(const QString& dir) const {
11971206
const QFileInfo inf(mFilename);
11981207
const QString applicationFilePath = QCoreApplication::applicationFilePath();

gui/projectfile.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,14 @@ class ProjectFile : public QObject {
447447

448448
static QStringList getSearchPaths(const QString& projectPath, const QString& appPath, const QString& datadir, const QString& dir);
449449

450+
/**
451+
* @brief Convert an absolute path to a path relative to this project's directory.
452+
* If the relative path would need to walk up more than 2 parent folders
453+
* (i.e. "../../...") the absolute path is returned unchanged instead.
454+
* @param absolutePath Absolute path to convert.
455+
*/
456+
QString getRelativePath(const QString &absolutePath) const;
457+
450458
/** Set user includes in settings if non-empty */
451459
void setSettingsUserIncludes(Settings &settings) const;
452460

gui/projectfiledialog.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -571,10 +571,7 @@ QString ProjectFileDialog::getExistingDirectory(const QString &caption, bool tra
571571

572572
// Check if the path is relative to project file's path and if so
573573
// make it a relative path instead of absolute path.
574-
const QDir dir(projectPath);
575-
const QString relpath(dir.relativeFilePath(selectedDir));
576-
if (!relpath.startsWith("../.."))
577-
selectedDir = relpath;
574+
selectedDir = mProjectFile->getRelativePath(selectedDir);
578575

579576
// Trailing slash..
580577
if (trailingSlash && !selectedDir.endsWith('/'))
@@ -631,7 +628,7 @@ void ProjectFileDialog::browseImportProject()
631628
dir.canonicalPath(),
632629
toFilterString(filters));
633630
if (!fileName.isEmpty()) {
634-
mUI->mEditImportProject->setText(dir.relativeFilePath(fileName));
631+
mUI->mEditImportProject->setText(mProjectFile->getRelativePath(fileName));
635632
updatePathsAndDefines();
636633
setProjectConfigurations(getProjectConfigs(fileName));
637634
for (int row = 0; row < mUI->mListVsConfigs->count(); ++row) {
@@ -652,7 +649,7 @@ void ProjectFileDialog::browseUserInclude()
652649
dir.canonicalPath(),
653650
toFilterString(filters));
654651
if (!fileName.isEmpty()) {
655-
mUI->mEditUserInclude->setText(dir.relativeFilePath(fileName));
652+
mUI->mEditUserInclude->setText(mProjectFile->getRelativePath(fileName));
656653
}
657654
}
658655

@@ -891,7 +888,9 @@ void ProjectFileDialog::addExcludeFile()
891888
QMap<QString,QString> filters;
892889
filters[tr("Source files")] = "*.c *.cpp";
893890
filters[tr("All files")] = "*.*";
894-
addExcludePath(QFileDialog::getOpenFileName(this, tr("Exclude file"), dir.canonicalPath(), toFilterString(filters)));
891+
QString fileName = QFileDialog::getOpenFileName(this, tr("Exclude file"), dir.canonicalPath(), toFilterString(filters));
892+
if (!fileName.isEmpty())
893+
addExcludePath(mProjectFile->getRelativePath(fileName));
895894
}
896895

897896
void ProjectFileDialog::editExcludePath()

gui/test/projectfile/testprojectfile.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,45 @@ void TestProjectFile::emptyUserInclude() const
214214
QCOMPARE(settings.userIncludes.size(), 0);
215215
}
216216

217+
// Absolute path is made relative when it does not require walking up more than 3 parent folders
218+
void TestProjectFile::getRelativePathRelative() const
219+
{
220+
ProjectFile projectFile;
221+
projectFile.setFilename("/some/path/sub/123.cppcheck");
222+
QCOMPARE(projectFile.getRelativePath("/some/path/externals/foo.cpp"), QString("../externals/foo.cpp"));
223+
}
224+
225+
// Absolute path is made relative even when it requires walking up 2 parent folders
226+
void TestProjectFile::getRelativePathTwoUp() const
227+
{
228+
ProjectFile projectFile;
229+
projectFile.setFilename("/some/path/sub/123.cppcheck");
230+
QCOMPARE(projectFile.getRelativePath("/some/externals/foo.cpp"), QString("../../externals/foo.cpp"));
231+
}
232+
233+
// Absolute path is kept as-is when making it relative would require walking up more than 3 parent folders
234+
void TestProjectFile::getRelativePathTooFarUp() const
235+
{
236+
ProjectFile projectFile;
237+
projectFile.setFilename("/some/path/sub/123.cppcheck");
238+
QCOMPARE(projectFile.getRelativePath("/other/deep/foo.cpp"), QString("/other/deep/foo.cpp"));
239+
}
240+
241+
// Absolute path in a subfolder of the project path is made relative without walking up at all
242+
void TestProjectFile::getRelativePathSubfolder() const
243+
{
244+
ProjectFile projectFile;
245+
projectFile.setFilename("/some/path/sub/123.cppcheck");
246+
QCOMPARE(projectFile.getRelativePath("/some/path/sub/src/file1.c"), QString("src/file1.c"));
247+
}
248+
249+
// Absolute path is kept as-is when it is shorter than the relative path, even if it does not require walking up 3 or more parent folders
250+
void TestProjectFile::getRelativePathAbsoluteShorter() const
251+
{
252+
ProjectFile projectFile;
253+
projectFile.setFilename("/ab/path/sub/123.cppcheck");
254+
QCOMPARE(projectFile.getRelativePath("/ab/foo.cpp"), QString("/ab/foo.cpp"));
255+
}
256+
217257
QTEST_MAIN(TestProjectFile)
218258

gui/test/projectfile/testprojectfile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,10 @@ private slots:
3838
void getCheckingSuppressionsStar() const;
3939

4040
void emptyUserInclude() const;
41+
42+
void getRelativePathRelative() const;
43+
void getRelativePathTwoUp() const;
44+
void getRelativePathTooFarUp() const;
45+
void getRelativePathSubfolder() const;
46+
void getRelativePathAbsoluteShorter() const;
4147
};

0 commit comments

Comments
 (0)