File indexing completed on 2024-04-28 16:44:28

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2015 Milian Wolff <mail@milianw.de>
0003 
0004    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #ifndef URLINFO_H
0008 #define URLINFO_H
0009 
0010 #include <QDir>
0011 #include <QRegularExpression>
0012 #include <QString>
0013 #include <QUrl>
0014 
0015 /**
0016  * Represents a file to be opened, consisting of its URL and the cursor to jump to.
0017  */
0018 class UrlInfo
0019 {
0020 public:
0021     /**
0022      * Parses an argument and determines its line number and column and full path
0023      * @param pathOrUrl path passed on e.g. command line to parse into an URL or just an URL
0024      */
0025     UrlInfo(const QString &pathOrUrl)
0026         : line(0)
0027         , column(0)
0028     {
0029         /**
0030          * first try: just check if the path is an existing file
0031          */
0032         if (QFile::exists(pathOrUrl)) {
0033             /**
0034              * create absolute file path, we will e.g. pass this over dbus to other processes
0035              * and then we are done, no cursor can be detected here!
0036              */
0037             url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(pathOrUrl));
0038             return;
0039         }
0040 
0041         /**
0042          * if the path starts with http:// or any other scheme, except file://
0043          * we also don't want to do anything with URL
0044          */
0045         if (!QUrl::fromUserInput(pathOrUrl).isLocalFile()) {
0046             url = QUrl::fromUserInput(pathOrUrl, QDir::currentPath(), QUrl::DefaultResolution);
0047             // relative paths are not isLocalFile(), but not valid too, so we don't want them
0048             if (url.isValid()) {
0049                 return;
0050             }
0051         }
0052 
0053         /**
0054          * ok, the path as is, is no existing file, now, cut away :xx:yy stuff as cursor
0055          * this will make test:50 to test with line 50
0056          */
0057         QString pathOrUrl2 = pathOrUrl;
0058         const auto match = QRegularExpression(QStringLiteral(":(\\d+)(?::(\\d+))?:?$")).match(pathOrUrl2);
0059         if (match.isValid()) {
0060             /**
0061              * cut away the line/column specification from the path
0062              */
0063             pathOrUrl2.chop(match.capturedLength());
0064 
0065             /**
0066              * set right cursor position
0067              */
0068 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0069             line = match.capturedRef(1).toUInt();
0070             column = match.capturedRef(2).toUInt();
0071 #else
0072             line = match.capturedView(1).toUInt();
0073             column = match.capturedView(2).toUInt();
0074 #endif
0075         }
0076 
0077         /**
0078          * construct url:
0079          *   - make relative paths absolute using the current working directory
0080          *   - do not prefer local file, to be able to open things like foo.com in browser
0081          */
0082         url = QUrl::fromUserInput(pathOrUrl2, QDir::currentPath(), QUrl::DefaultResolution);
0083 
0084         /**
0085          * in some cases, this will fail, e.g. if you have line/column specs like test.c:10:1
0086          * => fallback: assume a local file and just convert it to an url
0087          */
0088         if (!url.isValid()) {
0089             /**
0090              * create absolute file path, we will e.g. pass this over dbus to other processes
0091              */
0092             url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(pathOrUrl2));
0093         }
0094     }
0095 
0096     bool atStart() const
0097     {
0098         return (line == 0 || line == 1) && (column == 0 || column == 1);
0099     }
0100 
0101     /**
0102      * url computed out of the passed path or URL
0103      */
0104     QUrl url;
0105 
0106     /**
0107      * initial cursor position, if any found inside the path as line/column specification at the end
0108      */
0109     unsigned line, column;
0110 };
0111 
0112 #endif // URLINFO_H