summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-06-19 15:03:04 +0200
committerStephan Bergmann <sbergman@redhat.com>2019-06-19 18:18:22 +0200
commite2589f4584efcf0306ab69f7223abdd7469e3604 (patch)
tree047501260836e3f146d2641e9fe765ccae261757 /vcl
parent1982ac9d8e474e3d1aaf62418f6620a0984406d9 (diff)
tdf#125971: map file URLs from QFileDialog to LO internal format
jmux' suggestion at <https://bugs.documentfoundation.org/show_bug.cgi?id=125971#c7> turns out to be the correct fix after all; explained in a lengthy comment why that seemingly wrong call of translateToInternal happens to do the right thing. (Much of this patch is about passing the XComponentContext down to where it is now needed in Qt5FilePicker::getSelectedFiles.) Change-Id: I235554f8494cd3094a011d5a903059326db499fc Reviewed-on: https://gerrit.libreoffice.org/74359 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/qt5/Qt5FilePicker.hxx5
-rw-r--r--vcl/inc/qt5/Qt5Instance.hxx4
-rw-r--r--vcl/qt5/Qt5FilePicker.cxx27
-rw-r--r--vcl/qt5/Qt5Instance.cxx16
-rw-r--r--vcl/unx/kde5/KDE5FilePicker.hxx3
-rw-r--r--vcl/unx/kde5/KDE5FilePicker2.cxx5
-rw-r--r--vcl/unx/kde5/KDE5SalInstance.cxx10
-rw-r--r--vcl/unx/kde5/KDE5SalInstance.hxx3
8 files changed, 54 insertions, 19 deletions
diff --git a/vcl/inc/qt5/Qt5FilePicker.hxx b/vcl/inc/qt5/Qt5FilePicker.hxx
index 74d082a83aa0..d4e74b92ba15 100644
--- a/vcl/inc/qt5/Qt5FilePicker.hxx
+++ b/vcl/inc/qt5/Qt5FilePicker.hxx
@@ -58,6 +58,8 @@ class VCLPLUG_QT5_PUBLIC Qt5FilePicker : public QObject, public Qt5FilePicker_Ba
Q_OBJECT
private:
+ css::uno::Reference<css::uno::XComponentContext> m_context;
+
// whether to show (i.e. not remove) the file extension in the filter title,
// e.g. whether to use "ODF Text Document (*.odt)" or just
// "ODF Text Document" as filter title
@@ -88,7 +90,8 @@ protected:
public:
// use non-native file dialog by default; there's no easy way to add custom widgets
// in a generic way in the native one
- explicit Qt5FilePicker(QFileDialog::FileMode, bool bShowFileExtensionInFilterTitle = false,
+ explicit Qt5FilePicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode, bool bShowFileExtensionInFilterTitle = false,
bool bUseNativeDialog = false);
virtual ~Qt5FilePicker() override;
diff --git a/vcl/inc/qt5/Qt5Instance.hxx b/vcl/inc/qt5/Qt5Instance.hxx
index 2411cdb7f52c..881ac17803d4 100644
--- a/vcl/inc/qt5/Qt5Instance.hxx
+++ b/vcl/inc/qt5/Qt5Instance.hxx
@@ -78,7 +78,9 @@ Q_SIGNALS:
void deleteObjectLaterSignal(QObject* pObject);
protected:
- virtual Qt5FilePicker* createPicker(QFileDialog::FileMode);
+ virtual Qt5FilePicker*
+ createPicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode);
public:
explicit Qt5Instance(std::unique_ptr<QApplication>& pQApp, bool bUseCairo = false);
diff --git a/vcl/qt5/Qt5FilePicker.cxx b/vcl/qt5/Qt5FilePicker.cxx
index 084aa7622a0a..63b3ff79a2bc 100644
--- a/vcl/qt5/Qt5FilePicker.cxx
+++ b/vcl/qt5/Qt5FilePicker.cxx
@@ -33,6 +33,7 @@
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
#include <cppuhelper/interfacecontainer.h>
#include <cppuhelper/supportsservice.hxx>
#include <sal/log.hxx>
@@ -77,9 +78,11 @@ uno::Sequence<OUString> FilePicker_getSupportedServiceNames()
}
}
-Qt5FilePicker::Qt5FilePicker(QFileDialog::FileMode eMode, bool bShowFileExtensionInFilterTitle,
+Qt5FilePicker::Qt5FilePicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode eMode, bool bShowFileExtensionInFilterTitle,
bool bUseNativeDialog)
: Qt5FilePicker_Base(m_aHelperMutex)
+ , m_context(context)
, m_bShowFileExtensionInFilterTitle(bShowFileExtensionInFilterTitle)
, m_pFileDialog(new QFileDialog(nullptr, {}, QDir::homePath()))
, m_bIsFolderPicker(eMode == QFileDialog::Directory)
@@ -254,9 +257,29 @@ uno::Sequence<OUString> SAL_CALL Qt5FilePicker::getSelectedFiles()
uno::Sequence<OUString> seq(urls.size());
+ auto const trans = css::uri::ExternalUriReferenceTranslator::create(m_context);
size_t i = 0;
for (const QUrl& aURL : urls)
- seq[i++] = toOUString(aURL.toString());
+ {
+ // Unlike LO, QFileDialog (<https://doc.qt.io/qt-5/qfiledialog.html>) apparently always
+ // treats file-system pathnames as UTF-8--encoded, regardless of LANG/LC_CTYPE locale
+ // setting. And pathnames containing byte sequences that are not valid UTF-8 are apparently
+ // filtered out and not even displayed by QFileDialog, so aURL will always have a "payload"
+ // that matches the pathname's byte sequence. So the pathname's byte sequence (which
+ // happens to also be aURL's payload) in the LANG/LC_CTYPE encoding needs to be converted
+ // into LO's internal UTF-8 file URL encoding via
+ // XExternalUriReferenceTranslator::translateToInternal (which looks somewhat paradoxical as
+ // aURL.toEncoded() nominally already has a UTF-8 payload):
+ auto const extUrl = toOUString(aURL.toEncoded());
+ auto intUrl = trans->translateToInternal(extUrl);
+ if (intUrl.isEmpty())
+ {
+ // If translation failed, fall back to original URL:
+ SAL_WARN("vcl.qt5", "cannot convert <" << extUrl << "> from locale encoding to UTF-8");
+ intUrl = extUrl;
+ }
+ seq[i++] = intUrl;
+ }
return seq;
}
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index dc3df6446a67..d657ab729801 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -403,32 +403,34 @@ void Qt5Instance::ProcessEvent(SalUserEvent aEvent)
aEvent.m_pFrame->CallCallback(aEvent.m_nEvent, aEvent.m_pData);
}
-Qt5FilePicker* Qt5Instance::createPicker(QFileDialog::FileMode eMode)
+Qt5FilePicker*
+Qt5Instance::createPicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode eMode)
{
if (!IsMainThread())
{
SolarMutexGuard g;
Qt5FilePicker* pPicker;
- RunInMainThread(std::function([&, this]() { pPicker = createPicker(eMode); }));
+ RunInMainThread(std::function([&, this]() { pPicker = createPicker(context, eMode); }));
assert(pPicker);
return pPicker;
}
- return new Qt5FilePicker(eMode);
+ return new Qt5FilePicker(context, eMode);
}
css::uno::Reference<css::ui::dialogs::XFilePicker2>
-Qt5Instance::createFilePicker(const css::uno::Reference<css::uno::XComponentContext>&)
+Qt5Instance::createFilePicker(const css::uno::Reference<css::uno::XComponentContext>& context)
{
return css::uno::Reference<css::ui::dialogs::XFilePicker2>(
- createPicker(QFileDialog::ExistingFile));
+ createPicker(context, QFileDialog::ExistingFile));
}
css::uno::Reference<css::ui::dialogs::XFolderPicker2>
-Qt5Instance::createFolderPicker(const css::uno::Reference<css::uno::XComponentContext>&)
+Qt5Instance::createFolderPicker(const css::uno::Reference<css::uno::XComponentContext>& context)
{
return css::uno::Reference<css::ui::dialogs::XFolderPicker2>(
- createPicker(QFileDialog::Directory));
+ createPicker(context, QFileDialog::Directory));
}
css::uno::Reference<css::uno::XInterface>
diff --git a/vcl/unx/kde5/KDE5FilePicker.hxx b/vcl/unx/kde5/KDE5FilePicker.hxx
index 32cbd4c92e7d..786a99b00777 100644
--- a/vcl/unx/kde5/KDE5FilePicker.hxx
+++ b/vcl/unx/kde5/KDE5FilePicker.hxx
@@ -34,7 +34,8 @@ protected:
bool allowRemoteUrls;
public:
- explicit KDE5FilePicker(QFileDialog::FileMode);
+ explicit KDE5FilePicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode);
// XExecutableDialog functions
virtual sal_Int16 SAL_CALL execute() override;
diff --git a/vcl/unx/kde5/KDE5FilePicker2.cxx b/vcl/unx/kde5/KDE5FilePicker2.cxx
index ac99b5d21066..cb778e2fd0f7 100644
--- a/vcl/unx/kde5/KDE5FilePicker2.cxx
+++ b/vcl/unx/kde5/KDE5FilePicker2.cxx
@@ -49,9 +49,10 @@ uno::Sequence<OUString> FilePicker_getSupportedServiceNames()
// KDE5FilePicker
-KDE5FilePicker::KDE5FilePicker(QFileDialog::FileMode eMode)
+KDE5FilePicker::KDE5FilePicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode eMode)
// Native kde5 filepicker does not add file extension automatically
- : Qt5FilePicker(eMode, true, true)
+ : Qt5FilePicker(context, eMode, true, true)
, _layout(new QGridLayout(m_pExtraControls))
, allowRemoteUrls(false)
{
diff --git a/vcl/unx/kde5/KDE5SalInstance.cxx b/vcl/unx/kde5/KDE5SalInstance.cxx
index 3a227fc7b2b6..0143212249ed 100644
--- a/vcl/unx/kde5/KDE5SalInstance.cxx
+++ b/vcl/unx/kde5/KDE5SalInstance.cxx
@@ -50,13 +50,15 @@ SalFrame* KDE5SalInstance::CreateFrame(SalFrame* pParent, SalFrameStyleFlags nSt
return pRet;
}
-Qt5FilePicker* KDE5SalInstance::createPicker(QFileDialog::FileMode eMode)
+Qt5FilePicker*
+KDE5SalInstance::createPicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode eMode)
{
if (!IsMainThread())
{
SolarMutexGuard g;
Qt5FilePicker* pPicker;
- RunInMainThread(std::function([&, this]() { pPicker = createPicker(eMode); }));
+ RunInMainThread(std::function([&, this]() { pPicker = createPicker(context, eMode); }));
assert(pPicker);
return pPicker;
}
@@ -65,8 +67,8 @@ Qt5FilePicker* KDE5SalInstance::createPicker(QFileDialog::FileMode eMode)
// being used in the native file picker, which is only the case for KDE Plasma.
// Therefore, return the plain qt5 one in order to not lose custom controls.
if (Application::GetDesktopEnvironment() == "KDE5")
- return new KDE5FilePicker(eMode);
- return Qt5Instance::createPicker(eMode);
+ return new KDE5FilePicker(context, eMode);
+ return Qt5Instance::createPicker(context, eMode);
}
extern "C" {
diff --git a/vcl/unx/kde5/KDE5SalInstance.hxx b/vcl/unx/kde5/KDE5SalInstance.hxx
index 53993a5ecc34..a7c633f150e1 100644
--- a/vcl/unx/kde5/KDE5SalInstance.hxx
+++ b/vcl/unx/kde5/KDE5SalInstance.hxx
@@ -23,7 +23,8 @@
class KDE5SalInstance final : public Qt5Instance
{
- Qt5FilePicker* createPicker(QFileDialog::FileMode) override;
+ Qt5FilePicker* createPicker(css::uno::Reference<css::uno::XComponentContext> const& context,
+ QFileDialog::FileMode) override;
SalFrame* CreateFrame(SalFrame* pParent, SalFrameStyleFlags nStyle) override;
bool hasNativeFileSelection() const override { return true; }