diff options
-rw-r--r-- | vcl/inc/qt5/Qt5FilePicker.hxx | 21 | ||||
-rw-r--r-- | vcl/qt5/Qt5FilePicker.cxx | 89 |
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"; |