pathutils.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "pathutils.h"
  2. #include <QDebug>
  3. #include <QFileInfo>
  4. #include <QRegularExpression>
  5. #include <QImageReader>
  6. #include <QValidator>
  7. #include <QRegularExpressionValidator>
  8. using namespace vnotex;
  9. const QString PathUtils::c_fileNameRegularExpression = QString("\\A(?:[^\\\\/:\\*\\?\"<>\\|\\s]| )+\\z");
  10. QString PathUtils::parentDirPath(const QString &p_path)
  11. {
  12. if (p_path.isEmpty()) {
  13. return p_path;
  14. }
  15. QFileInfo info(p_path);
  16. Q_ASSERT(info.isAbsolute());
  17. return cleanPath(info.absolutePath());
  18. }
  19. QString PathUtils::dirOrParentDirPath(const QString &p_path)
  20. {
  21. if (p_path.isEmpty()) {
  22. return p_path;
  23. }
  24. QFileInfo info(p_path);
  25. if (info.isDir()) {
  26. return p_path;
  27. } else {
  28. return info.absolutePath();
  29. }
  30. }
  31. bool PathUtils::isEmptyDir(const QString &p_path)
  32. {
  33. QFileInfo fi(p_path);
  34. if (!fi.exists()) {
  35. return true;
  36. }
  37. return fi.isDir() && QDir(p_path).isEmpty();
  38. }
  39. QString PathUtils::concatenateFilePath(const QString &p_dirPath, const QString &p_name)
  40. {
  41. QString dirPath = cleanPath(p_dirPath);
  42. if (p_name.isEmpty()) {
  43. return dirPath;
  44. }
  45. if (dirPath.isEmpty()) {
  46. return p_name;
  47. }
  48. return dirPath + "/" + p_name;
  49. }
  50. QString PathUtils::dirName(const QString &p_path)
  51. {
  52. Q_ASSERT(!QFileInfo::exists(p_path) || QFileInfo(p_path).isDir());
  53. return QDir(p_path).dirName();
  54. }
  55. QString PathUtils::fileName(const QString &p_path)
  56. {
  57. QFileInfo fi(p_path);
  58. return fi.fileName();
  59. }
  60. QString PathUtils::fileNameCheap(const QString &p_path)
  61. {
  62. int idx = p_path.lastIndexOf(QRegularExpression("[\\\\/]"));
  63. if (idx == -1) {
  64. return p_path;
  65. }
  66. return p_path.mid(idx + 1);
  67. }
  68. QString PathUtils::normalizePath(const QString &p_path)
  69. {
  70. Q_ASSERT(isLocalFile(p_path));
  71. auto absPath = QDir::cleanPath(QDir(p_path).absolutePath());
  72. #if defined(Q_OS_WIN)
  73. return absPath.toLower();
  74. #else
  75. return absPath;
  76. #endif
  77. }
  78. bool PathUtils::areSamePaths(const QString &p_a, const QString &p_b)
  79. {
  80. return normalizePath(p_a) == normalizePath(p_b);
  81. }
  82. bool PathUtils::pathContains(const QString &p_dir, const QString &p_path)
  83. {
  84. auto rel = relativePath(p_dir, p_path);
  85. if (rel.startsWith(QStringLiteral("../")) || rel == QStringLiteral("..")) {
  86. return false;
  87. }
  88. if (QFileInfo(rel).isAbsolute()) {
  89. return false;
  90. }
  91. return true;
  92. }
  93. bool PathUtils::isLegalFileName(const QString &p_name)
  94. {
  95. QRegularExpression nameRe(c_fileNameRegularExpression);
  96. auto match = nameRe.match(p_name);
  97. return match.hasMatch();
  98. }
  99. bool PathUtils::isLegalPath(const QString &p_path)
  100. {
  101. // Ensure each part of the @p_path is a valid file name until we come to
  102. // an existing parent directory.
  103. if (p_path.isEmpty()) {
  104. return false;
  105. }
  106. if (QFileInfo::exists(p_path)) {
  107. #if defined(Q_OS_WIN)
  108. // On Windows, "/" and ":" will also make exists() return true.
  109. if (p_path.startsWith('/') || p_path == ":") {
  110. return false;
  111. }
  112. #endif
  113. return true;
  114. }
  115. bool ret = false;
  116. int pos = -1;
  117. QString basePath = parentDirPath(p_path);
  118. QString name = dirName(p_path);
  119. QScopedPointer<QValidator> validator(new QRegularExpressionValidator(QRegularExpression(c_fileNameRegularExpression)));
  120. while (!name.isEmpty()) {
  121. QValidator::State validFile = validator->validate(name, pos);
  122. if (validFile != QValidator::Acceptable) {
  123. break;
  124. }
  125. if (QFileInfo::exists(basePath)) {
  126. ret = true;
  127. #if defined(Q_OS_WIN)
  128. // On Windows, "/" and ":" will also make exists() return true.
  129. if (basePath.startsWith('/') || basePath == ":") {
  130. ret = false;
  131. }
  132. #endif
  133. break;
  134. }
  135. basePath = parentDirPath(basePath);
  136. name = dirName(basePath);
  137. }
  138. return ret;
  139. }
  140. QString PathUtils::relativePath(const QString &p_dir, const QString &p_path)
  141. {
  142. QDir dir(p_dir);
  143. return cleanPath(dir.relativeFilePath(p_path));
  144. }
  145. QUrl PathUtils::pathToUrl(const QString &p_path)
  146. {
  147. // Need to judge the path: Url, local file, resource file.
  148. QUrl url;
  149. QFileInfo pathInfo(p_path);
  150. if (pathInfo.exists()) {
  151. if (pathInfo.isNativePath()) {
  152. // Local file.
  153. url = QUrl::fromLocalFile(p_path);
  154. } else {
  155. // Resource file.
  156. url = QUrl(QStringLiteral("qrc") + p_path);
  157. }
  158. } else {
  159. // Url.
  160. url = QUrl(p_path);
  161. }
  162. return url;
  163. }
  164. QString PathUtils::urlToPath(const QUrl &p_url)
  165. {
  166. if (p_url.isLocalFile()) {
  167. return p_url.toLocalFile();
  168. } else {
  169. return p_url.toString();
  170. }
  171. }
  172. QString PathUtils::encodeSpacesInPath(const QString &p_path)
  173. {
  174. QString tmp(p_path);
  175. tmp.replace(QLatin1Char(' '), QStringLiteral("%20"));
  176. return tmp;
  177. }
  178. void PathUtils::prependDotIfRelative(QString &p_path)
  179. {
  180. if (QDir::isRelativePath(p_path)
  181. && !p_path.startsWith(QStringLiteral("."))) {
  182. p_path.prepend(QStringLiteral("./"));
  183. }
  184. }
  185. QString PathUtils::removeUrlParameters(const QString &p_url)
  186. {
  187. int idx = p_url.indexOf(QLatin1Char('?'));
  188. if (idx > -1) {
  189. return p_url.left(idx);
  190. }
  191. return p_url;
  192. }
  193. bool PathUtils::isImageUrl(const QString &p_url)
  194. {
  195. QFileInfo info(removeUrlParameters(p_url));
  196. return QImageReader::supportedImageFormats().contains(info.suffix().toLower().toLatin1());
  197. }
  198. bool PathUtils::isDir(const QString &p_path)
  199. {
  200. return QFileInfo(p_path).isDir();
  201. }
  202. bool PathUtils::isLocalFile(const QString &p_path)
  203. {
  204. if (p_path.isEmpty()) {
  205. return false;
  206. }
  207. QRegularExpression regExp("^(?:ftp|http|https)://");
  208. if (regExp.match(p_path).hasMatch()) {
  209. return false;
  210. }
  211. return true;
  212. }