[multimedia/kdenlive/release/26.08] src: Resolve video import and profile loading failures on paths with diacritical marks

Jean-Baptiste Mardelle <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit a248b44adcfaac52ff967a9e509532a1111419de by Jean-Baptiste Mardelle, on behalf of Jaimukund Bhan.
Committed on 23/07/2026 at 07:37.
Pushed by mardelle into branch 'release/26.08'.

Resolve video import and profile loading failures on paths with diacritical marks

When Kdenlive is run from a standalone folder located in a directory path containing diacritical marks or non-ASCII characters, it fails to import video files and displays a "Cannot open file" error in the GUI. This MR fixes the issue by resolving startup and library search paths to their ASCII-only Windows 8.3 short paths before configuring the runtime environment.

* **Windows Short Path Helper**: Implemented a `getShortPath()` helper function on Windows to convert long paths containing spaces or non-ASCII characters to their 8.3 short path representation.
* **Environment PATH**: Updated the `PATH` environment variable setup in `main.cpp` using the short path.
* **MLT Path Configuration**: Relocated `locateMeltAndProfilesPath` earlier during MLT initialization in `MltConnection` and exported `MLT_PROFILES_PATH` and `MLT_DATA` environment variables using the Windows short paths.

BUG: 513899

M  +16   -2    src/main.cpp
M  +33   -2    src/mltconnection.cpp

https://invent.kde.org/multimedia/kdenlive/-/commit/a248b44adcfaac52ff967a9e509532a1111419de

diff --git a/src/main.cpp b/src/main.cpp
index 9a155d6811..83df480af5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -60,11 +60,24 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 #include <QUrl> //new
 
 #ifdef Q_OS_WIN
+#include <windows.h>
 extern "C" {
 // Inform the driver we could make use of the discrete gpu
 // __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
 // __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
 }
+static QString getShortPath(const QString &longPath)
+{
+    std::wstring longPathStd = QDir::toNativeSeparators(longPath).toStdWString();
+    DWORD size = GetShortPathNameW(longPathStd.c_str(), nullptr, 0);
+    if (size > 0) {
+        std::vector<wchar_t> buffer(size);
+        if (GetShortPathNameW(longPathStd.c_str(), buffer.data(), size) > 0) {
+            return QString::fromWCharArray(buffer.data());
+        }
+    }
+    return longPath;
+}
 #endif
 
 static LinuxPackageType getPackageType()
@@ -514,8 +527,9 @@ int main(int argc, char *argv[])
     }
 
 #ifdef Q_OS_WIN
-    QString path = qApp->applicationDirPath() + QLatin1Char(';') + qgetenv("PATH");
-    qputenv("PATH", path.toUtf8().constData());
+#include <stdlib.h>
+    QString path = getShortPath(qApp->applicationDirPath()) + QLatin1Char(';') + qEnvironmentVariable("PATH");
+    _wputenv_s(L"PATH", path.toStdWString().c_str());
 #endif
 
     if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) {
diff --git a/src/mltconnection.cpp b/src/mltconnection.cpp
index 7f2d839e6c..739ec34999 100644
--- a/src/mltconnection.cpp
+++ b/src/mltconnection.cpp
@@ -12,7 +12,10 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 #include <KLocalizedString>
 #include <KUrlRequester>
 #include <KUrlRequesterDialog>
+#include <QDir>
 #include <QDirIterator>
+#include <QFile>
+#include <QTextStream>
 #include <QtConcurrent/QtConcurrentRun>
 
 #include <clocale>
@@ -49,6 +52,22 @@ static void mlt_log_handler(void *service, int mlt_level, const char *format, va
     qDebug() << "MLT:" << message;
 }
 
+#ifdef Q_OS_WIN
+#include <windows.h>
+static QString getShortPath(const QString &longPath)
+{
+    std::wstring longPathStd = QDir::toNativeSeparators(longPath).toStdWString();
+    DWORD size = GetShortPathNameW(longPathStd.c_str(), nullptr, 0);
+    if (size > 0) {
+        std::vector<wchar_t> buffer(size);
+        if (GetShortPathNameW(longPathStd.c_str(), buffer.data(), size) > 0) {
+            return QString::fromWCharArray(buffer.data());
+        }
+    }
+    return longPath;
+}
+#endif
+
 std::unique_ptr<MltConnection> MltConnection::m_self;
 MltConnection::MltConnection(const QString &mltPath)
 {
@@ -59,6 +78,20 @@ MltConnection::MltConnection(const QString &mltPath)
         qputenv("MLT_AVFORMAT_HWACCEL", KdenliveSettings::hwDecoding().toUtf8());
     }
 
+    locateMeltAndProfilesPath(mltPath);
+
+#ifdef Q_OS_WIN
+    {
+        QString profilesDir = KdenliveSettings::mltpath();
+        if (QFile::exists(profilesDir)) {
+            QString shortProfilePath = getShortPath(profilesDir);
+            QString shortMltDataPath = getShortPath(QDir(profilesDir).absoluteFilePath(QStringLiteral("..")));
+            _wputenv_s(L"MLT_PROFILES_PATH", shortProfilePath.toStdWString().c_str());
+            _wputenv_s(L"MLT_DATA", shortMltDataPath.toStdWString().c_str());
+        }
+    }
+#endif
+
     // After initialising the MLT factory, set the locale back from user default to C
     // to ensure numbers are always serialised with . as decimal point.
     m_repository = std::unique_ptr<Mlt::Repository>(Mlt::Factory::init());
@@ -69,8 +102,6 @@ MltConnection::MltConnection(const QString &mltPath)
     std::setlocale(MLT_LC_CATEGORY, nullptr);
 #endif
 
-    locateMeltAndProfilesPath(mltPath);
-
     // Retrieve the list of available producers.
     QScopedPointer<Mlt::Properties> producers(m_repository->producers());
     QStringList producersList;
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.