tdf#119856 vcl: convert Qt5FilePicker and Qt5Menu to RunInMainThread

... and also convert KDE5FilePicker. And Qt5Frame.

The UNO methods in Qt5FilePicker/KDE5FilePicker have to ensure that the
thread actually owns SolarMutex, because if RunInMainThread() is
called without that it will deadlock.

Change-Id: Ie4d2f494ac81c799ec7c9a3acb3a9b0f77bb6361
Reviewed-on: https://gerrit.libreoffice.org/68357
Tested-by: Jenkins
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
diff --git a/vcl/inc/qt5/Qt5FilePicker.hxx b/vcl/inc/qt5/Qt5FilePicker.hxx
index 2f795a8..74d082a 100644
--- a/vcl/inc/qt5/Qt5FilePicker.hxx
+++ b/vcl/inc/qt5/Qt5FilePicker.hxx
@@ -158,121 +158,6 @@ protected:
    virtual void addCustomControl(sal_Int16 controlId);
    void setCustomControlWidgetLayout(QGridLayout* pLayout) { m_pLayout = pLayout; }

private Q_SLOTS:
    // XExecutableDialog functions
    /// @throws css::uno::RuntimeException
    void setTitleSlot(const OUString& rTitle) { return setTitle(rTitle); }
    /// @throws css::uno::RuntimeException
    sal_Int16 executeSlot() { return execute(); }

    // XFilePicker functions
    /// @throws css::uno::RuntimeException
    void setMultiSelectionModeSlot(bool bMode) { return setMultiSelectionMode(bMode); }
    /// @throws css::uno::RuntimeException
    void setDefaultNameSlot(const OUString& rName) { return setDefaultName(rName); }
    /// @throws css::uno::RuntimeException
    void setDisplayDirectorySlot(const OUString& rDirectory)
    {
        return setDisplayDirectory(rDirectory);
    }
    /// @throws css::uno::RuntimeException
    OUString getDisplayDirectorySlot() { return getDisplayDirectory(); }
    /// @throws css::uno::RuntimeException
    css::uno::Sequence<OUString> getFilesSlot() { return getFiles(); }

    // XFilterManager functions
    /// @throws css::lang::IllegalArgumentException
    /// @throws css::uno::RuntimeException
    void appendFilterSlot(const OUString& rTitle, const OUString& rFilter)
    {
        return appendFilter(rTitle, rFilter);
    }
    /// @throws css::lang::IllegalArgumentException
    /// @throws css::uno::RuntimeException
    void setCurrentFilterSlot(const OUString& rTitle) { return setCurrentFilter(rTitle); }
    /// @throws css::uno::RuntimeException
    OUString getCurrentFilterSlot() { return getCurrentFilter(); }

    // XFilterGroupManager functions
    /// @throws css::lang::IllegalArgumentException
    /// @throws css::uno::RuntimeException
    void appendFilterGroupSlot(const OUString& rGroupTitle,
                               const css::uno::Sequence<css::beans::StringPair>& rFilters)
    {
        return appendFilterGroup(rGroupTitle, rFilters);
    }

    // XFilePickerControlAccess functions
    /// @throws css::uno::RuntimeException
    void setValueSlot(sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any& rValue)
    {
        return setValue(nControlId, nControlAction, rValue);
    }
    /// @throws css::uno::RuntimeException
    css::uno::Any getValueSlot(sal_Int16 nControlId, sal_Int16 nControlAction)
    {
        return getValue(nControlId, nControlAction);
    }
    /// @throws css::uno::RuntimeException
    void enableControlSlot(sal_Int16 nControlId, bool bEnable)
    {
        return enableControl(nControlId, bEnable);
    }
    /// @throws css::uno::RuntimeException
    void setLabelSlot(sal_Int16 nControlId, const OUString& rLabel)
    {
        return setLabel(nControlId, rLabel);
    }
    /// @throws css::uno::RuntimeException
    OUString getLabelSlot(sal_Int16 nControlId) { return getLabel(nControlId); }

    // XFilePicker2 functions
    /// @throws css::uno::RuntimeException
    css::uno::Sequence<OUString> getSelectedFilesSlot() { return getSelectedFiles(); }

    // XInitialization
    /// @throws css::uno::Exception
    /// @throws css::uno::RuntimeException
    void initializeSlot(const css::uno::Sequence<css::uno::Any>& rArguments)
    {
        return initialize(rArguments);
    }

Q_SIGNALS:
    // XExecutableDialog functions
    void setTitleSignal(const OUString& rTitle);
    sal_Int16 executeSignal();

    // XFilePicker functions
    void setMultiSelectionModeSignal(bool bMode);
    void setDefaultNameSignal(const OUString& rName);
    void setDisplayDirectorySignal(const OUString& rDirectory);
    OUString getDisplayDirectorySignal();
    css::uno::Sequence<OUString> getFilesSignal();

    // XFilterManager functions
    void appendFilterSignal(const OUString& rTitle, const OUString& rFilter);
    void setCurrentFilterSignal(const OUString& rTitle);
    OUString getCurrentFilterSignal();

    // XFilterGroupManager functions
    void appendFilterGroupSignal(const OUString& rGroupTitle,
                                 const css::uno::Sequence<css::beans::StringPair>& rFilters);

    // XFilePickerControlAccess functions
    void setValueSignal(sal_Int16 nControlId, sal_Int16 nControlAction,
                        const css::uno::Any& rValue);
    css::uno::Any getValueSignal(sal_Int16 nControlId, sal_Int16 nControlAction);
    void enableControlSignal(sal_Int16 nControlId, bool bEnable);
    void setLabelSignal(sal_Int16 nControlId, const OUString& rLabel);
    OUString getLabelSignal(sal_Int16 nControlId);

    // XFilePicker2 functions
    css::uno::Sequence<OUString> getSelectedFilesSignal();

    // XInitialization
    void initializeSignal(const css::uno::Sequence<css::uno::Any>& rArguments);

private:
    Qt5FilePicker(const Qt5FilePicker&) = delete;
    Qt5FilePicker& operator=(const Qt5FilePicker&) = delete;
diff --git a/vcl/inc/qt5/Qt5Frame.hxx b/vcl/inc/qt5/Qt5Frame.hxx
index 274a6ca..1309c17 100644
--- a/vcl/inc/qt5/Qt5Frame.hxx
+++ b/vcl/inc/qt5/Qt5Frame.hxx
@@ -107,11 +107,10 @@ class VCLPLUG_QT5_PUBLIC Qt5Frame : public QObject, public SalFrame
    void TriggerPaintEvent();
    void TriggerPaintEvent(QRect aRect);

private Q_SLOTS:
private:
    void setVisible(bool);

Q_SIGNALS:
    void setVisibleSignal(bool);
    void tooltipRequest(const OUString& rTooltip);

public:
diff --git a/vcl/qt5/Qt5FilePicker.cxx b/vcl/qt5/Qt5FilePicker.cxx
index 282723f..084aa76 100644
--- a/vcl/qt5/Qt5FilePicker.cxx
+++ b/vcl/qt5/Qt5FilePicker.cxx
@@ -101,62 +101,6 @@ Qt5FilePicker::Qt5FilePicker(QFileDialog::FileMode eMode, bool bShowFileExtensio

    setMultiSelectionMode(false);

    // XExecutableDialog functions
    connect(this, SIGNAL(setTitleSignal(const OUString&)), this,
            SLOT(setTitleSlot(const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(executeSignal()), this, SLOT(executeSlot()), Qt::BlockingQueuedConnection);

    // XFilePicker functions
    connect(this, SIGNAL(setMultiSelectionModeSignal(bool)), this,
            SLOT(setMultiSelectionModeSlot(bool)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(setDefaultNameSignal(const OUString&)), this,
            SLOT(setDefaultNameSlot(const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(setDisplayDirectorySignal(const OUString&)), this,
            SLOT(setDisplayDirectorySlot(const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(getDisplayDirectorySignal()), this, SLOT(getDisplayDirectorySlot()),
            Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(getFilesSignal()), this, SLOT(getFilesSlot()),
            Qt::BlockingQueuedConnection);

    // XFilterManager functions
    connect(this, SIGNAL(appendFilterSignal(const OUString&, const OUString&)), this,
            SLOT(appendFilterSlot(const OUString&, const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(setCurrentFilterSignal(const OUString&)), this,
            SLOT(setCurrentFilterSlot(const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(getCurrentFilterSignal()), this, SLOT(getCurrentFilterSlot()),
            Qt::BlockingQueuedConnection);

    // XFilterGroupManager functions
    connect(this,
            SIGNAL(appendFilterGroupSignal(const OUString&,
                                           const css::uno::Sequence<css::beans::StringPair>&)),
            this,
            SLOT(appendFilterGroupSlot(const OUString&,
                                       const css::uno::Sequence<css::beans::StringPair>&)),
            Qt::BlockingQueuedConnection);

    // XFilePickerControlAccess functions
    connect(this, SIGNAL(setValueSignal(sal_Int16, sal_Int16, const css::uno::Any&)), this,
            SLOT(setValueSlot(sal_Int16, sal_Int16, const css::uno::Any&)),
            Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(getValueSignal(sal_Int16, sal_Int16)), this,
            SLOT(getValueSlot(sal_Int16, sal_Int16)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(enableControlSignal(sal_Int16, bool)), this,
            SLOT(enableControlSlot(sal_Int16, bool)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(setLabelSignal(sal_Int16, const OUString&)), this,
            SLOT(setLabelSlot(sal_Int16, const OUString&)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(getLabelSignal(sal_Int16)), this, SLOT(getLabelSlot(sal_Int16)),
            Qt::BlockingQueuedConnection);

    // XFilePicker2 functions
    connect(this, SIGNAL(getSelectedFilesSignal()), this, SLOT(getSelectedFilesSlot()),
            Qt::BlockingQueuedConnection);

    // XInitialization
    connect(this, SIGNAL(initializeSignal(const css::uno::Sequence<css::uno::Any>&)), this,
            SLOT(initializeSlot(const css::uno::Sequence<css::uno::Any>&)),
            Qt::BlockingQueuedConnection);

    // XFilePickerListener notifications
    connect(m_pFileDialog.get(), SIGNAL(filterSelected(const QString&)), this,
            SLOT(filterSelected(const QString&)));
@@ -170,6 +114,7 @@ Qt5FilePicker::Qt5FilePicker(QFileDialog::FileMode eMode, bool bShowFileExtensio

Qt5FilePicker::~Qt5FilePicker()
{
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this]() {
@@ -194,21 +139,23 @@ void SAL_CALL Qt5FilePicker::removeFilePickerListener(const uno::Reference<XFile

void SAL_CALL Qt5FilePicker::setTitle(const OUString& title)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setTitleSignal(title);
    }

    m_pFileDialog->setWindowTitle(toQString(title));
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread(
        [this, &title]() { m_pFileDialog->setWindowTitle(toQString(title)); });
}

sal_Int16 SAL_CALL Qt5FilePicker::execute()
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT executeSignal();
        sal_uInt16 ret;
        pSalInst->RunInMainThread([&ret, this]() { ret = execute(); });
        return ret;
    }

    vcl::Window* pWindow = ::Application::GetActiveTopWindow();
@@ -247,58 +194,50 @@ sal_Int16 SAL_CALL Qt5FilePicker::execute()

void SAL_CALL Qt5FilePicker::setMultiSelectionMode(sal_Bool multiSelect)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setMultiSelectionModeSignal(multiSelect);
    }
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, multiSelect]() {
        if (m_bIsFolderPicker || m_pFileDialog->acceptMode() == QFileDialog::AcceptSave)
            return;

    if (m_bIsFolderPicker || m_pFileDialog->acceptMode() == QFileDialog::AcceptSave)
        return;

    m_pFileDialog->setFileMode(multiSelect ? QFileDialog::ExistingFiles
                                           : QFileDialog::ExistingFile);
        m_pFileDialog->setFileMode(multiSelect ? QFileDialog::ExistingFiles
                                               : QFileDialog::ExistingFile);
    });
}

void SAL_CALL Qt5FilePicker::setDefaultName(const OUString& name)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setDefaultNameSignal(name);
    }
    m_pFileDialog->selectFile(toQString(name));
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, &name]() { m_pFileDialog->selectFile(toQString(name)); });
}

void SAL_CALL Qt5FilePicker::setDisplayDirectory(const OUString& dir)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setDisplayDirectorySignal(dir);
    }

    QString qDir(toQString(dir));
    m_pFileDialog->setDirectoryUrl(QUrl(qDir));
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, &dir]() {
        QString qDir(toQString(dir));
        m_pFileDialog->setDirectoryUrl(QUrl(qDir));
    });
}

OUString SAL_CALL Qt5FilePicker::getDisplayDirectory()
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getDisplayDirectorySignal();
    }
    return toOUString(m_pFileDialog->directoryUrl().toString());
    SolarMutexGuard g;
    OUString ret;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread(
        [&ret, this]() { ret = toOUString(m_pFileDialog->directoryUrl().toString()); });
    return ret;
}

uno::Sequence<OUString> SAL_CALL Qt5FilePicker::getFiles()
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getFilesSignal();
    }
    uno::Sequence<OUString> seq = getSelectedFiles();
    if (seq.getLength() > 1)
        seq.realloc(1);
@@ -307,12 +246,12 @@ uno::Sequence<OUString> SAL_CALL Qt5FilePicker::getFiles()

uno::Sequence<OUString> SAL_CALL Qt5FilePicker::getSelectedFiles()
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getSelectedFilesSignal();
    }
    QList<QUrl> urls = m_pFileDialog->selectedUrls();
    SolarMutexGuard g;
    QList<QUrl> urls;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([&urls, this]() { urls = m_pFileDialog->selectedUrls(); });

    uno::Sequence<OUString> seq(urls.size());

    size_t i = 0;
@@ -324,10 +263,13 @@ uno::Sequence<OUString> SAL_CALL Qt5FilePicker::getSelectedFiles()

void SAL_CALL Qt5FilePicker::appendFilter(const OUString& title, const OUString& filter)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT appendFilterSignal(title, filter);
        pSalInst->RunInMainThread([this, &title, &filter]() { appendFilter(title, filter); });
        return;
    }

    // '/' need to be escaped else they are assumed to be mime types
@@ -357,24 +299,24 @@ void SAL_CALL Qt5FilePicker::appendFilter(const OUString& title, const OUString&

void SAL_CALL Qt5FilePicker::setCurrentFilter(const OUString& title)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setCurrentFilterSignal(title);
    }

    m_aCurrentFilter = m_aTitleToFilterMap.value(toQString(title).replace("/", "\\/"));
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, &title]() {
        m_aCurrentFilter = m_aTitleToFilterMap.value(toQString(title).replace("/", "\\/"));
    });
}

OUString SAL_CALL Qt5FilePicker::getCurrentFilter()
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getCurrentFilterSignal();
    }
    SolarMutexGuard g;
    QString filter;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([&filter, this]() {
        filter = m_aTitleToFilterMap.key(m_pFileDialog->selectedNameFilter());
    });

    QString filter = m_aTitleToFilterMap.key(m_pFileDialog->selectedNameFilter());
    if (filter.isEmpty())
        filter = "ODF Text Document (.odt)";
    return toOUString(filter);
@@ -383,10 +325,14 @@ OUString SAL_CALL Qt5FilePicker::getCurrentFilter()
void SAL_CALL Qt5FilePicker::appendFilterGroup(const OUString& rGroupTitle,
                                               const uno::Sequence<beans::StringPair>& filters)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT appendFilterGroupSignal(rGroupTitle, filters);
        pSalInst->RunInMainThread(
            [this, &rGroupTitle, &filters]() { appendFilterGroup(rGroupTitle, filters); });
        return;
    }

    const sal_uInt16 length = filters.getLength();
@@ -476,10 +422,15 @@ void Qt5FilePicker::handleSetListValue(QComboBox* pWidget, sal_Int16 nControlAct
void SAL_CALL Qt5FilePicker::setValue(sal_Int16 controlId, sal_Int16 nControlAction,
                                      const uno::Any& value)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setValueSignal(controlId, nControlAction, value);
        pSalInst->RunInMainThread([this, controlId, nControlAction, &value]() {
            setValue(controlId, nControlAction, value);
        });
        return;
    }

    if (m_aCustomWidgetsMap.contains(controlId))
@@ -501,10 +452,16 @@ void SAL_CALL Qt5FilePicker::setValue(sal_Int16 controlId, sal_Int16 nControlAct

uno::Any SAL_CALL Qt5FilePicker::getValue(sal_Int16 controlId, sal_Int16 nControlAction)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getValueSignal(controlId, nControlAction);
        uno::Any ret;
        pSalInst->RunInMainThread([&ret, this, controlId, nControlAction]() {
            ret = getValue(controlId, nControlAction);
        });
        return ret;
    }

    uno::Any res(false);
@@ -529,24 +486,26 @@ uno::Any SAL_CALL Qt5FilePicker::getValue(sal_Int16 controlId, sal_Int16 nContro

void SAL_CALL Qt5FilePicker::enableControl(sal_Int16 controlId, sal_Bool enable)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT enableControlSignal(controlId, enable);
    }

    if (m_aCustomWidgetsMap.contains(controlId))
        m_aCustomWidgetsMap.value(controlId)->setEnabled(enable);
    else
        SAL_WARN("vcl.qt5", "enable unknown control " << controlId);
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, controlId, enable]() {
        if (m_aCustomWidgetsMap.contains(controlId))
            m_aCustomWidgetsMap.value(controlId)->setEnabled(enable);
        else
            SAL_WARN("vcl.qt5", "enable unknown control " << controlId);
    });
}

void SAL_CALL Qt5FilePicker::setLabel(sal_Int16 controlId, const OUString& label)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setLabelSignal(controlId, label);
        pSalInst->RunInMainThread([this, controlId, label]() { setLabel(controlId, label); });
        return;
    }

    if (m_aCustomWidgetsMap.contains(controlId))
@@ -561,10 +520,14 @@ void SAL_CALL Qt5FilePicker::setLabel(sal_Int16 controlId, const OUString& label

OUString SAL_CALL Qt5FilePicker::getLabel(sal_Int16 controlId)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getLabelSignal(controlId);
        OUString ret;
        pSalInst->RunInMainThread([&ret, this, controlId]() { ret = getLabel(controlId); });
        return ret;
    }

    QString label;
@@ -696,16 +659,6 @@ void Qt5FilePicker::addCustomControl(sal_Int16 controlId)

void SAL_CALL Qt5FilePicker::initialize(const uno::Sequence<uno::Any>& args)
{
    if (qApp->thread() != QThread::currentThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT initializeSignal(args);
    }

    m_aNamedFilterList.clear();
    m_aTitleToFilterMap.clear();
    m_aCurrentFilter.clear();

    // parameter checking
    uno::Any arg;
    if (args.getLength() == 0)
@@ -722,6 +675,19 @@ void SAL_CALL Qt5FilePicker::initialize(const uno::Sequence<uno::Any>& args)
                                             static_cast<XFilePicker2*>(this), 1);
    }

    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        pSalInst->RunInMainThread([this, args]() { initialize(args); });
        return;
    }

    m_aNamedFilterList.clear();
    m_aTitleToFilterMap.clear();
    m_aCurrentFilter.clear();

    sal_Int16 templateId = -1;
    arg >>= templateId;

diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index eb2314d..e8fb145 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -128,7 +128,6 @@ Qt5Frame::Qt5Frame(Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo)
    else
        m_pQWidget = new Qt5Widget(*this, aWinFlags);

    connect(this, SIGNAL(setVisibleSignal(bool)), SLOT(setVisible(bool)));
    connect(this, &Qt5Frame::tooltipRequest, static_cast<Qt5Widget*>(m_pQWidget),
            &Qt5Widget::showTooltip);

@@ -358,7 +357,9 @@ void Qt5Frame::Show(bool bVisible, bool /*bNoActivate*/)
    if (m_bDefaultSize)
        SetDefaultSize();

    Q_EMIT setVisibleSignal(bVisible);
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    pSalInst->RunInMainThread([this, bVisible]() { setVisible(bVisible); });
}

void Qt5Frame::SetMinClientSize(long nWidth, long nHeight)
diff --git a/vcl/qt5/Qt5Menu.cxx b/vcl/qt5/Qt5Menu.cxx
index 49de2c0..4fdebe0 100644
--- a/vcl/qt5/Qt5Menu.cxx
+++ b/vcl/qt5/Qt5Menu.cxx
@@ -12,6 +12,7 @@
#include <Qt5Bitmap.hxx>
#include <Qt5Menu.hxx>
#include <Qt5Menu.moc>
#include <Qt5Instance.hxx>

#include <QtWidgets/QtWidgets>

@@ -390,10 +391,12 @@ void Qt5Menu::SetSubMenu(SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned 

void Qt5Menu::SetFrame(const SalFrame* pFrame)
{
    if (qApp->thread() != QThread::currentThread())
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT setFrameSignal(pFrame);
        pSalInst->RunInMainThread([this, pFrame]() { SetFrame(pFrame); });
        return;
    }

    SolarMutexGuard aGuard;
diff --git a/vcl/unx/kde5/KDE5FilePicker.hxx b/vcl/unx/kde5/KDE5FilePicker.hxx
index fb73fbe..dc3f5c0 100644
--- a/vcl/unx/kde5/KDE5FilePicker.hxx
+++ b/vcl/unx/kde5/KDE5FilePicker.hxx
@@ -92,9 +92,6 @@ private:

protected:
    bool eventFilter(QObject* watched, QEvent* event) override;

Q_SIGNALS:
    sal_Int16 executeSignal();
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDE5FilePicker2.cxx b/vcl/unx/kde5/KDE5FilePicker2.cxx
index 403c522..3563692 100644
--- a/vcl/unx/kde5/KDE5FilePicker2.cxx
+++ b/vcl/unx/kde5/KDE5FilePicker2.cxx
@@ -36,6 +36,7 @@

#include <unx/geninst.h>
#include <qt5/Qt5Tools.hxx>
#include <qt5/Qt5Instance.hxx>

#include <QtCore/QDebug>
#include <QtCore/QThread>
@@ -107,19 +108,20 @@ KDE5FilePicker::KDE5FilePicker(QFileDialog::FileMode eMode)
        QStringLiteral("smb"),
    });

    connect(this, &KDE5FilePicker::executeSignal, this, &KDE5FilePicker::execute,
            Qt::BlockingQueuedConnection);

    // used to set the custom controls
    qApp->installEventFilter(this);
}

sal_Int16 SAL_CALL KDE5FilePicker::execute()
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        //SolarMutexReleaser aReleaser;
        return Q_EMIT executeSignal();
        sal_Int16 ret;
        pSalInst->RunInMainThread([&ret, this] { ret = execute(); });
        return ret;
    }

    if (!m_aNamedFilterList.isEmpty())
@@ -145,10 +147,16 @@ void SAL_CALL KDE5FilePicker::setValue(sal_Int16 controlId, sal_Int16 nControlAc

uno::Any SAL_CALL KDE5FilePicker::getValue(sal_Int16 controlId, sal_Int16 nControlAction)
{
    if (qApp->thread() != QThread::currentThread())
    SolarMutexGuard g;
    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
    if (!pSalInst->IsMainThread())
    {
        SolarMutexReleaser aReleaser;
        return Q_EMIT getValueSignal(controlId, nControlAction);
        uno::Any ret;
        pSalInst->RunInMainThread([&ret, this, controlId, nControlAction]() {
            ret = getValue(controlId, nControlAction);
        });
        return ret;
    }

    if (CHECKBOX_AUTOEXTENSION == controlId)
diff --git a/vcl/unx/kde5/KDE5SalInstance.cxx b/vcl/unx/kde5/KDE5SalInstance.cxx
index 6350d10..0847e99 100644
--- a/vcl/unx/kde5/KDE5SalInstance.cxx
+++ b/vcl/unx/kde5/KDE5SalInstance.cxx
@@ -61,6 +61,7 @@ KDE5SalInstance::createFilePicker(const uno::Reference<uno::XComponentContext>& 
{
    if (!IsMainThread())
    {
        SolarMutexGuard g;
        uno::Reference<ui::dialogs::XFilePicker2> xRet;
        RunInMainThread(
            std::function([&xRet, this, xMSF]() { xRet = this->createFilePicker(xMSF); }));