diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -71,6 +71,7 @@ io/kprocess.cpp io/kbackup.cpp io/kurlmimedata.cpp + io/kfileutils.cpp jobs/kcompositejob.cpp jobs/kjob.cpp jobs/kjobtrackerinterface.cpp @@ -161,6 +162,7 @@ KBackup KUrlMimeData KFileSystemType + KFileUtils RELATIVE io REQUIRED_HEADERS KCoreAddons_HEADERS ) diff --git a/src/lib/io/kfileutils.h b/src/lib/io/kfileutils.h new file mode 100644 --- /dev/null +++ b/src/lib/io/kfileutils.h @@ -0,0 +1,43 @@ +/* This file is part of the KDE libraries + Copyright (C) 2019 Nicolas Fella + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KFILEUTILS_H +#define KFILEUTILS_H + +#include "kcoreaddons_export.h" + +#include +#include + +/** + * @short A namespace for KFileUtils globals + * + */ +namespace KFileUtils +{ + +/** + * Given a directory path and a filename (which usually exists already), + * this function returns a suggested name for a file that doesn't exist + * in that directory. The existence is only checked for local urls though. + * The suggested file name is of the form "foo 1", "foo 2" etc. + * @since 5.61 + */ +KCOREADDONS_EXPORT QString suggestName(const QUrl &baseURL, const QString &oldName); + +} +#endif diff --git a/src/lib/io/kfileutils.cpp b/src/lib/io/kfileutils.cpp new file mode 100644 --- /dev/null +++ b/src/lib/io/kfileutils.cpp @@ -0,0 +1,75 @@ +/* This file is part of the KDE libraries + Copyright (C) 2019 Nicolas Fella + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kfileutils.h" + +#include +#include + +QString KFileUtils::suggestName(const QUrl &baseURL, const QString &oldName) +{ + QString basename; + + // Extract the original file extension from the filename + QMimeDatabase db; + QString nameSuffix = db.suffixForFileName(oldName); + + if (oldName.lastIndexOf(QLatin1Char('.')) == 0) { + basename = QStringLiteral("."); + nameSuffix = oldName; + } else if (nameSuffix.isEmpty()) { + const int lastDot = oldName.lastIndexOf(QLatin1Char('.')); + if (lastDot == -1) { + basename = oldName; + } else { + basename = oldName.left(lastDot); + nameSuffix = oldName.mid(lastDot); + } + } else { + nameSuffix.prepend(QLatin1Char('.')); + basename = oldName.left(oldName.length() - nameSuffix.length()); + } + + // check if (number) exists from the end of the oldName and increment that number + QRegExp numSearch(QStringLiteral("\\(\\d+\\)")); + int start = numSearch.lastIndexIn(oldName); + if (start != -1) { + QString numAsStr = numSearch.cap(0); + QString number = QString::number(numAsStr.midRef(1, numAsStr.size() - 2).toInt() + 1); + basename = basename.leftRef(start) + QLatin1Char('(') + number + QLatin1Char(')'); + } else { + // number does not exist, so just append " (1)" to filename + basename += QLatin1String(" (1)"); + } + const QString suggestedName = basename + nameSuffix; + + // Check if suggested name already exists + bool exists = false; + + // TODO: network transparency. However, using NetAccess from a modal dialog + // could be a problem, no? (given that it uses a modal widget itself....) + if (baseURL.isLocalFile()) { + exists = QFileInfo::exists(baseURL.toLocalFile() + QLatin1Char('/') + suggestedName); + } + + if (!exists) { + return suggestedName; + } else { // already exists -> recurse + return suggestName(baseURL, suggestedName); + } +}