File indexing completed on 2024-04-28 05:27:05

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             line = match.capturedView(1).toUInt();
0069             column = match.capturedView(2).toUInt();
0070         }
0071 
0072         /**
0073          * construct url:
0074          *   - make relative paths absolute using the current working directory
0075          *   - do not prefer local file, to be able to open things like foo.com in browser
0076          */
0077         url = QUrl::fromUserInput(pathOrUrl2, QDir::currentPath(), QUrl::DefaultResolution);
0078 
0079         /**
0080          * in some cases, this will fail, e.g. if you have line/column specs like test.c:10:1
0081          * => fallback: assume a local file and just convert it to an url
0082          */
0083         if (!url.isValid()) {
0084             /**
0085              * create absolute file path, we will e.g. pass this over dbus to other processes
0086              */
0087             url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(pathOrUrl2));
0088         }
0089     }
0090 
0091     bool atStart() const
0092     {
0093         return (line == 0 || line == 1) && (column == 0 || column == 1);
0094     }
0095 
0096     /**
0097      * url computed out of the passed path or URL
0098      */
0099     QUrl url;
0100 
0101     /**
0102      * initial cursor position, if any found inside the path as line/column specification at the end
0103      */
0104     unsigned line, column;
0105 };
0106 
0107 #endif // URLINFO_H