summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2019-06-05 14:04:24 +0200
committerJan-Marek Glogowski <glogow@fbihome.de>2019-12-09 17:17:56 +0100
commite756a570cc18427a4ad61af15c42e3d8d54beb13 (patch)
tree49e3294a22dc67a6410d7c5dd051ce27f9a64bd2 /vcl
parent34d5b03d8f323e6af33e2358b898a5843596f4ea (diff)
tdf#129071 Qt5 set file picker parent widget
If the XInitialization::initialize has a parent option, use that system window ID to find the parent Qt5Frame and set this as the parent of the file picker. This way the file picker doesn't show up as a separate window in the KDE task bar and get the proper icon. Just setting it transient to the parent is not enough. This also includes the terminate listener handling, so an open file picker won't prevent LO to shut down gracefully (which is handled independent from the document modified state). Change-Id: I62aef532e739e7fea9fe8a4b4e6c0e205faae1d9 Reviewed-on: https://gerrit.libreoffice.org/74544 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de> (cherry picked from commit d79a41a02cd46c50cab08ba1a5d5b213b6843251) Reviewed-on: https://gerrit.libreoffice.org/84756
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/qt5/Qt5FilePicker.hxx21
-rw-r--r--vcl/qt5/Qt5FilePicker.cxx89
2 files changed, 82 insertions, 28 deletions
diff --git a/vcl/inc/qt5/Qt5FilePicker.hxx b/vcl/inc/qt5/Qt5FilePicker.hxx
index f88395c6acce..5fef2aaeae43 100644
--- a/vcl/inc/qt5/Qt5FilePicker.hxx
+++ b/vcl/inc/qt5/Qt5FilePicker.hxx
@@ -23,8 +23,9 @@
#include <cppuhelper/compbase.hxx>
-#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
@@ -33,8 +34,6 @@
#include <osl/conditn.hxx>
#include <osl/mutex.hxx>
-#include <rtl/ustrbuf.hxx>
-
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -48,9 +47,10 @@ class QGridLayout;
class QLabel;
class QWidget;
-typedef ::cppu::WeakComponentImplHelper<
- css::ui::dialogs::XFilePicker3, css::ui::dialogs::XFilePickerControlAccess,
- css::ui::dialogs::XFolderPicker2, css::lang::XInitialization, css::lang::XServiceInfo>
+typedef ::cppu::WeakComponentImplHelper<css::frame::XTerminateListener, css::lang::XInitialization,
+ css::lang::XServiceInfo, css::ui::dialogs::XFilePicker3,
+ css::ui::dialogs::XFilePickerControlAccess,
+ css::ui::dialogs::XFolderPicker2>
Qt5FilePicker_Base;
class VCLPLUG_QT5_PUBLIC Qt5FilePicker : public QObject, public Qt5FilePicker_Base
@@ -75,6 +75,8 @@ private:
const bool m_bIsFolderPicker;
+ QWidget* m_pParentWidget;
+
protected:
std::unique_ptr<QFileDialog> m_pFileDialog; ///< the file picker dialog
QWidget* m_pExtraControls; ///< widget to contain extra custom controls
@@ -132,8 +134,7 @@ public:
virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
// XEventListener
- /// @throws css::uno::RuntimeException
- virtual void disposing(const css::lang::EventObject& rEvent);
+ void SAL_CALL disposing(const css::lang::EventObject& rEvent) override;
using cppu::WeakComponentImplHelperBase::disposing;
// XServiceInfo
@@ -145,6 +146,10 @@ public:
virtual OUString SAL_CALL getDirectory() override;
virtual void SAL_CALL setDescription(const OUString& rDescription) override;
+ // XTerminateListener
+ void SAL_CALL queryTermination(const css::lang::EventObject& aEvent) override;
+ void SAL_CALL notifyTermination(const css::lang::EventObject& aEvent) override;
+
protected:
virtual void addCustomControl(sal_Int16 controlId);
void setCustomControlWidgetLayout(QGridLayout* pLayout) { m_pLayout = pLayout; }
diff --git a/vcl/qt5/Qt5FilePicker.cxx b/vcl/qt5/Qt5FilePicker.cxx
index 10c25052fd8a..d37c28b33c11 100644
--- a/vcl/qt5/Qt5FilePicker.cxx
+++ b/vcl/qt5/Qt5FilePicker.cxx
@@ -25,8 +25,15 @@
#include <Qt5Widget.hxx>
#include <Qt5Instance.hxx>
+#include <com/sun/star/awt/SystemDependentXWindow.hpp>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/TerminationVetoException.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/ControlActions.hpp>
@@ -36,6 +43,7 @@
#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
#include <cppuhelper/interfacecontainer.h>
#include <cppuhelper/supportsservice.hxx>
+#include <rtl/process.h>
#include <sal/log.hxx>
#include <QtCore/QDebug>
@@ -80,6 +88,7 @@ Qt5FilePicker::Qt5FilePicker(css::uno::Reference<css::uno::XComponentContext> co
: Qt5FilePicker_Base(m_aHelperMutex)
, m_context(context)
, m_bIsFolderPicker(eMode == QFileDialog::Directory)
+ , m_pParentWidget(nullptr)
, m_pFileDialog(new QFileDialog(nullptr, {}, QDir::homePath()))
, m_pExtraControls(new QWidget())
{
@@ -155,17 +164,16 @@ sal_Int16 SAL_CALL Qt5FilePicker::execute()
return ret;
}
- vcl::Window* pWindow = ::Application::GetActiveTopWindow();
- QWidget* pTransientParent = nullptr;
- QWindow* pTransientWindow = nullptr;
- if (pWindow)
+ QWidget* pTransientParent = m_pParentWidget;
+ if (!pTransientParent)
{
- Qt5Frame* pFrame = dynamic_cast<Qt5Frame*>(pWindow->ImplGetFrame());
- assert(pFrame);
- if (pFrame)
+ vcl::Window* pWindow = ::Application::GetActiveTopWindow();
+ if (pWindow)
{
- pTransientParent = pFrame->GetQWidget();
- pTransientWindow = pTransientParent->window()->windowHandle();
+ Qt5Frame* pFrame = dynamic_cast<Qt5Frame*>(pWindow->ImplGetFrame());
+ assert(pFrame);
+ if (pFrame)
+ pTransientParent = pFrame->asChild();
}
}
@@ -174,16 +182,19 @@ sal_Int16 SAL_CALL Qt5FilePicker::execute()
if (!m_aCurrentFilter.isEmpty())
m_pFileDialog->selectNameFilter(m_aCurrentFilter);
- if (pTransientParent)
- {
- m_pFileDialog->show();
- m_pFileDialog->window()->windowHandle()->setTransientParent(pTransientWindow);
- m_pFileDialog->setFocusProxy(pTransientParent);
- }
-
updateAutomaticFileExtension();
+ uno::Reference<css::frame::XDesktop> xDesktop(css::frame::Desktop::create(m_context),
+ UNO_QUERY_THROW);
+
+ // will hide the window, so do before show
+ m_pFileDialog->setParent(pTransientParent, m_pFileDialog->windowFlags());
+ m_pFileDialog->show();
+ xDesktop->addTerminateListener(this);
int result = m_pFileDialog->exec();
+ xDesktop->removeTerminateListener(this);
+ m_pFileDialog->setParent(nullptr, m_pFileDialog->windowFlags());
+
if (QFileDialog::Rejected == result)
return ExecutableDialogResults::CANCEL;
return ExecutableDialogResults::OK;
@@ -679,9 +690,7 @@ void SAL_CALL Qt5FilePicker::initialize(const uno::Sequence<uno::Any>& args)
// parameter checking
uno::Any arg;
if (args.getLength() == 0)
- {
throw lang::IllegalArgumentException("no arguments", static_cast<XFilePicker2*>(this), 1);
- }
arg = args[0];
@@ -805,11 +814,40 @@ void SAL_CALL Qt5FilePicker::initialize(const uno::Sequence<uno::Any>& args)
m_pFileDialog->setAcceptMode(acceptMode);
m_pFileDialog->setWindowTitle(getResString(resId));
+
+ css::uno::Reference<css::awt::XWindow> xParentWindow;
+ if (args.getLength() > 1)
+ args[1] >>= xParentWindow;
+ if (xParentWindow.is())
+ {
+ css::uno::Reference<css::awt::XSystemDependentWindowPeer> xSysWinPeer(xParentWindow,
+ css::uno::UNO_QUERY);
+ if (xSysWinPeer.is())
+ {
+ // the sal_*Int8 handling is strange, but it's public API - no way around
+ css::uno::Sequence<sal_Int8> aProcessIdent(16);
+ rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
+ uno::Any aAny = xSysWinPeer->getWindowHandle(
+ aProcessIdent, css::lang::SystemDependent::SYSTEM_XWINDOW);
+ css::awt::SystemDependentXWindow xSysWin;
+ aAny >>= xSysWin;
+
+ const auto& pFrames = pSalInst->getFrames();
+ const long aWindowHandle = xSysWin.WindowHandle;
+ const auto it = std::find_if(pFrames.begin(), pFrames.end(),
+ [&aWindowHandle](auto pFrame) -> bool {
+ const SystemEnvData* pData = pFrame->GetSystemData();
+ return pData && long(pData->aWindow) == aWindowHandle;
+ });
+ if (it != pFrames.end())
+ m_pParentWidget = static_cast<Qt5Frame*>(*it)->asChild();
+ }
+ }
}
-void SAL_CALL Qt5FilePicker::cancel() {}
+void SAL_CALL Qt5FilePicker::cancel() { m_pFileDialog->reject(); }
-void Qt5FilePicker::disposing(const lang::EventObject& rEvent)
+void SAL_CALL Qt5FilePicker::disposing(const lang::EventObject& rEvent)
{
uno::Reference<XFilePickerListener> xFilePickerListener(rEvent.Source, uno::UNO_QUERY);
@@ -819,6 +857,17 @@ void Qt5FilePicker::disposing(const lang::EventObject& rEvent)
}
}
+void SAL_CALL Qt5FilePicker::queryTermination(const css::lang::EventObject&)
+{
+ throw css::frame::TerminationVetoException();
+}
+
+void SAL_CALL Qt5FilePicker::notifyTermination(const css::lang::EventObject&)
+{
+ SolarMutexGuard aGuard;
+ m_pFileDialog->reject();
+}
+
OUString SAL_CALL Qt5FilePicker::getImplementationName()
{
return "com.sun.star.ui.dialogs.Qt5FilePicker";