File indexing completed on 2024-12-22 04:40:13
0001 /* 0002 SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar> 0003 SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "commondefs.h" 0009 0010 #include <cstdlib> 0011 #include <climits> 0012 0013 #include <QStringBuilder> 0014 #include <QDir> 0015 #include <QFileInfo> 0016 0017 #include <QDebug> 0018 #include <QStandardPaths> 0019 0020 #include <kio_version.h> 0021 #include <kio/statjob.h> 0022 0023 #ifndef Q_OS_WIN 0024 #include <unistd.h> 0025 #endif 0026 0027 /** 0028 * String 0029 */ 0030 0031 QString 0032 String::title(const QString &text) 0033 { 0034 QString auxText = text.toLower(); 0035 for(const QChar sep: QStringLiteral(" -_([:,;./\\\t\n\"")) { 0036 QStringList auxWordsList; 0037 for(const QString &word: auxText.split(sep)) { 0038 if(!word.isEmpty()) 0039 auxWordsList << (word.at(0).toUpper() + word.mid(1)); 0040 else 0041 auxWordsList << QString(); 0042 } 0043 auxText = auxWordsList.join(sep); 0044 } 0045 return auxText; 0046 } 0047 0048 QString 0049 String::capitalize(const QString &text) 0050 { 0051 return text.isEmpty() ? QString() : text.at(0).toUpper() + text.mid(1).toLower(); 0052 } 0053 0054 QString 0055 String::sentence(const QString &text) 0056 { 0057 return text.isEmpty() ? QString() : text.at(0).toUpper() + text.mid(1).toLower(); 0058 } 0059 0060 int 0061 String::rfindFunctionStart(const QString &text) 0062 { 0063 qsizetype pos[5] = { 0064 text.lastIndexOf(QLatin1String("capitalize{")), 0065 text.lastIndexOf(QLatin1String("titlecase{")), 0066 text.lastIndexOf(QLatin1String("uppercase{")), 0067 text.lastIndexOf(QLatin1String("lowercase{")), 0068 text.lastIndexOf(QLatin1String("ascii{")), 0069 }; 0070 0071 return qMax(qMax(qMax(qMax(pos[0], pos[1]), pos[2]), pos[3]), pos[4]); 0072 } 0073 0074 int 0075 String::rfindFunctionEnd(const QString &text, int startPos) 0076 { 0077 int pos = startPos, len = text.length(); 0078 while(pos < len) { 0079 // next is safe because idx will always be greater than 0 0080 if(text[pos] == '}' && text[pos - 1] != '\\') 0081 return pos; 0082 pos++; 0083 } 0084 return -1; 0085 } 0086 0087 /** 0088 * System: 0089 */ 0090 0091 bool 0092 System::recursiveMakeDir(const QString &path, QStringList *createdDirsList) 0093 { 0094 if(createdDirsList) 0095 createdDirsList->clear(); 0096 0097 QDir parcialPath(QStringLiteral("/")); 0098 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 0099 QStringList tokens = path.split(QChar('/'), QString::SkipEmptyParts); 0100 #else 0101 QStringList tokens = path.split(QChar('/'), Qt::SkipEmptyParts); 0102 #endif 0103 0104 for(QStringList::ConstIterator it = tokens.constBegin(), end = tokens.constEnd(); it != end; ++it) { 0105 parcialPath.setPath(parcialPath.path() + '/' + *it); 0106 if(!QFileInfo::exists(parcialPath.path())) { 0107 if(!QDir().mkdir(parcialPath.path())) 0108 return false; 0109 if(createdDirsList) 0110 createdDirsList->prepend(parcialPath.path()); 0111 } 0112 } 0113 0114 return true; 0115 } 0116 0117 bool 0118 System::copy(const QString &srcPath, const QString &dstPath) 0119 { 0120 if(QFile::exists(dstPath)) 0121 if(!System::remove(dstPath)) 0122 return false; 0123 0124 return QFile::copy(srcPath, dstPath); 0125 } 0126 0127 bool 0128 System::move(const QString &srcPath, const QString &dstPath) 0129 { 0130 if(!System::copy(srcPath, dstPath)) { 0131 qDebug() << "move: error copying" << srcPath << "to" << dstPath; 0132 0133 return false; 0134 } 0135 0136 if(!QFile::remove(srcPath)) { 0137 qDebug() << "move: error removing" << srcPath; 0138 0139 return false; 0140 } 0141 0142 return true; 0143 } 0144 0145 bool 0146 System::remove(const QString &path) 0147 { 0148 return QFile::remove(path); 0149 } 0150 0151 bool 0152 System::isReadable(const QString &path) 0153 { 0154 QFileInfo fileInfo(path); 0155 return fileInfo.isFile() && fileInfo.isReadable(); 0156 } 0157 0158 bool 0159 System::isWritable(const QString &path) 0160 { 0161 QFileInfo fileInfo(path); 0162 return fileInfo.isFile() && fileInfo.isWritable(); 0163 } 0164 0165 QString 0166 System::homeDir() 0167 { 0168 return QDir::homePath(); 0169 } 0170 0171 QString 0172 System::tempDir() 0173 { 0174 QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); 0175 while(tempDir.endsWith(QDir::separator())) 0176 tempDir.chop(1); 0177 return tempDir; 0178 } 0179 0180 QUrl 0181 System::newUrl(const QUrl &baseUrl, const QString &fileName, const QString &extension, int retries) 0182 { 0183 if(retries < 0) 0184 retries = INT_MAX; 0185 0186 QString newFileName(fileName); 0187 QString newFileNameBuilder(fileName + QStringLiteral("-%1")); 0188 if(!extension.isEmpty()) { 0189 newFileName += '.' + extension; 0190 newFileNameBuilder += '.' + extension; 0191 } 0192 0193 QString newFileDir = baseUrl.path(); 0194 if(!newFileDir.endsWith(QDir::separator())) 0195 newFileDir += QDir::separator(); 0196 0197 int i = 2; 0198 retries += i; 0199 0200 if(baseUrl.isLocalFile()) { 0201 QFileInfo dirInfo(newFileDir); 0202 if(dirInfo.isDir() && dirInfo.isWritable()) { 0203 QString newFilePath = newFileDir + newFileName; 0204 while(i < retries && QFile::exists(newFilePath)) 0205 newFilePath = newFileDir + newFileNameBuilder.arg(i++); 0206 if(i < retries) 0207 return QUrl::fromLocalFile(newFilePath); 0208 } 0209 } else { 0210 QUrl newUrl = baseUrl; 0211 newUrl.setPath(newFileDir + newFileName); 0212 for(;;) { 0213 #if KIO_VERSION < QT_VERSION_CHECK(5, 69, 0) 0214 KIO::Job *job = KIO::stat(newUrl, KIO::StatJob::DestinationSide, 2); 0215 #else 0216 KIO::Job *job = KIO::statDetails(newUrl, KIO::StatJob::DestinationSide, KIO::StatDefaultDetails, KIO::HideProgressInfo); 0217 #endif 0218 if(!job->exec()) 0219 return newUrl; 0220 if(i >= retries) 0221 break; 0222 newUrl.setPath(newFileDir + newFileNameBuilder.arg(i++)); 0223 } 0224 } 0225 0226 // could not return a writable url in baseUrl so we return one in the temp dir 0227 newFileDir = tempDir() + QDir::separator(); 0228 0229 i = 2; 0230 QString newFilePath = newFileDir + newFileName; 0231 while(QFile::exists(newFilePath)) 0232 newFilePath = newFileDir + newFileNameBuilder.arg(i++); 0233 0234 return QUrl::fromLocalFile(newFilePath); 0235 } 0236 0237 /*static*/ QUrl 0238 System::urlFromPath(const QString &path) 0239 { 0240 const QFileInfo file(path); 0241 const QUrl url(path); 0242 if(file.exists() || url.isRelative()) 0243 return QUrl::fromLocalFile(file.absoluteFilePath()); 0244 return url; 0245 } 0246 0247 0248 /*static*/ bool 0249 System::urlIsInside(const QUrl &url, const QString &path) 0250 { 0251 if(!url.scheme().isEmpty() && url.scheme() != QLatin1String("file")) 0252 return false; 0253 QString urlPath = url.toLocalFile(); 0254 return urlPath.startsWith(path); 0255 } 0256 0257 /*static*/ bool 0258 System::urlIsInside(const QUrl &url, QStringList &path) 0259 { 0260 for(QStringList::const_iterator i = path.constBegin(), end = path.constEnd(); i != end; i++) { 0261 if(urlIsInside(url, *i)) 0262 return true; 0263 } 0264 return false; 0265 }