[multimedia/haruna] src/playlist: m3uparser: MetaData: replace path with url

George Florea Bănuș <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 2e90a4bd1e94ed00670c3b3227516cb430f1c177 by George Florea Bănuș.
Committed on 18/07/2026 at 22:18.
Pushed by georgefb into branch 'master'.

m3uparser: MetaData: replace path with url

add stringToUrl function that turns a string (line in playlist) into a proper QUrl

BUG: 523205

M  +28   -8    src/playlist/m3uparser.cpp
M  +9    -3    src/playlist/m3uparser.h
M  +1    -1    src/playlist/playlistmodel.cpp

https://invent.kde.org/multimedia/haruna/-/commit/2e90a4bd1e94ed00670c3b3227516cb430f1c177

diff --git a/src/playlist/m3uparser.cpp b/src/playlist/m3uparser.cpp
index 93109862..099fa840 100644
--- a/src/playlist/m3uparser.cpp
+++ b/src/playlist/m3uparser.cpp
@@ -33,14 +33,15 @@ void M3uParser::read(const std::filesystem::path &path)
     auto firstLine = in.readLine();
     if (firstLine.startsWith(u"#EXTM3U")) {
         while (!in.atEnd()) {
-            parseExtendedLine(in.readLine());
+            parseExtendedLine(in.readLine(), QString::fromStdString(path));
         }
     } else {
-        parseStandardLine(firstLine);
+        parseStandardLine(firstLine, QString::fromStdString(path));
         while (!in.atEnd()) {
-            parseStandardLine(in.readLine());
+            parseStandardLine(in.readLine(), QString::fromStdString(path));
         }
     }
+    file.close();
 }
 
 void M3uParser::write(const PlaylistFilterProxyModel *playlistModel, const std::filesystem::path &savePath)
@@ -78,28 +79,28 @@ void M3uParser::write(const PlaylistFilterProxyModel *playlistModel, const std::
     m3uFile.close();
 }
 
-void M3uParser::parseStandardLine(const QString &line)
+void M3uParser::parseStandardLine(const QString &line, const QString &playlistPath)
 {
     if (line.isEmpty() || line.startsWith(u"#")) {
         return;
     }
 
-    metadata.path = line;
+    metadata.url = stringToUrl(line, playlistPath);
     m_data.append(metadata);
 }
 
-void M3uParser::parseExtendedLine(const QString &line)
+void M3uParser::parseExtendedLine(const QString &line, const QString &playlistPath)
 {
     if (line.isEmpty()) {
         return;
     }
 
     if (!line.startsWith(u"#")) {
-        metadata.path = line;
+        metadata.url = stringToUrl(line, playlistPath);
         m_data.append(std::move(metadata));
         metadata.duration.reset();
         metadata.title.reset();
-        metadata.path.clear();
+        metadata.url.clear();
         return;
     }
 
@@ -130,6 +131,25 @@ void M3uParser::parseExtendedLine(const QString &line)
     }
 }
 
+QUrl M3uParser::stringToUrl(const QString &urlString, const QString &parentPath)
+{
+    const QString decoded = QUrl::fromPercentEncoding(urlString.toUtf8());
+
+    const QUrl url(decoded);
+    if (url.isValid() && !url.scheme().isEmpty()) {
+        return url;
+    }
+
+    std::filesystem::path path(decoded.toStdString());
+    std::filesystem::path playlistParentPath(parentPath.toStdString());
+
+    if (path.is_relative()) {
+        path = playlistParentPath.parent_path() / path;
+    }
+
+    return QUrl::fromLocalFile(QString::fromStdString(path));
+}
+
 QList<MetaData> M3uParser::data() const
 {
     return m_data;
diff --git a/src/playlist/m3uparser.h b/src/playlist/m3uparser.h
index 240ddfb6..e4264220 100644
--- a/src/playlist/m3uparser.h
+++ b/src/playlist/m3uparser.h
@@ -15,7 +15,7 @@
 #include "playlistfilterproxymodel.h"
 
 struct MetaData {
-    QString path;
+    QUrl url;
     std::optional<double> duration;
     std::optional<QString> title;
 };
@@ -30,8 +30,14 @@ public:
     QList<MetaData> data() const;
 
 private:
-    void parseStandardLine(const QString &line);
-    void parseExtendedLine(const QString &line);
+    void parseStandardLine(const QString &line, const QString &playlistPath);
+    void parseExtendedLine(const QString &line, const QString &playlistPath);
+    /**
+     * If urlString is a valid URL with a scheme, it is returned as-is.
+     * Otherwise, it is treated as a local file path.
+     * Relative paths are appended to parentPath.
+     */
+    QUrl stringToUrl(const QString &urlString, const QString &parentPath);
 
     MetaData metadata;
     QList<MetaData> m_data;
diff --git a/src/playlist/playlistmodel.cpp b/src/playlist/playlistmodel.cpp
index 281b6eff..36ac0c57 100644
--- a/src/playlist/playlistmodel.cpp
+++ b/src/playlist/playlistmodel.cpp
@@ -411,7 +411,7 @@ void PlaylistModel::addM3uItems(const QUrl &url, Behavior behavior)
     const auto data = parser.data();
     for (const auto &metadata : data) {
         const auto row = m_playlist.size();
-        auto url = QUrl::fromUserInput(metadata.path, QFileInfo(m_playlistPath).absolutePath());
+        auto url = metadata.url;
         PlaylistItem item;
         if (url.isLocalFile()) {
             auto _item = localFileToPlaylistItem(QFileInfo(url.toLocalFile()));
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.