tdf#130857 qt weld: Support asnyc running of msg dialogs
Implement methods required to run a welded Qt message dialog asynchronously: `QtInstanceMessageDialog::runAsync` and `QtInstanceMessageDialog::response`. Run the dialog asynchronously using `QDialog::open` and connect to the `QDialog::finished` signal to be notified when the dialog gets closed. Similar to how the gtk-based implementation, use local variables for the `std::shared_ptr`s and reset the members right away, not only at the end of the slot, since resetting the relevant one set in the corresponding `runAsync` overload will result in the object getting deallocated, thus the members can no longer be accessed safely. Take the solar mutex before calling the callback function as that seems to be expected (e.g. otherwise triggers an assert for the below example where the callback functions modifies VCL widgets). With this in place, running welded Qt message dialogs asynchronously works instead of not showing up at all, e.g. 1) start Writer with qt6 VCL plugin and without `SAL_VCL_QT_NO_WELDED_WIDGETS` set 2) open "File" -> "Properties" -> "Security" 3) click the "Protect..." button 4) enter 2 different passwords and press "OK" button Change-Id: Ic1b1bfc7d89c1be8a9f9dee59bc86cf3da37a280 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162948 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
This commit is contained in:
parent
0a83e6dfaf
commit
a54abf77c4
4 changed files with 83 additions and 1 deletions
|
@ -14,6 +14,7 @@ $(call gb_CustomTarget_get_target,vcl/qt5) : \
|
|||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtFilePicker.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtFrame.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtInstance.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtInstanceMessageDialog.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtMainWindow.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtMenu.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt5)/QtObject.moc \
|
||||
|
|
|
@ -14,6 +14,7 @@ $(call gb_CustomTarget_get_target,vcl/qt6) : \
|
|||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtFilePicker.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtFrame.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtInstance.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtInstanceMessageDialog.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtMainWindow.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtMenu.moc \
|
||||
$(call gb_CustomTarget_get_workdir,vcl/qt6)/QtObject.moc \
|
||||
|
|
|
@ -12,11 +12,20 @@
|
|||
#include "QtInstanceDialog.hxx"
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
class QtInstanceMessageDialog : public QtInstanceDialog, public virtual weld::MessageDialog
|
||||
class QtInstanceMessageDialog : public QObject,
|
||||
public QtInstanceDialog,
|
||||
public virtual weld::MessageDialog
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
private:
|
||||
QMessageBox* m_pMessageDialog;
|
||||
|
||||
// the DialogController/Dialog/function passed to the runAsync variants
|
||||
std::shared_ptr<weld::DialogController> m_xRunAsyncDialogController;
|
||||
std::shared_ptr<weld::Dialog> m_xRunAsyncDialog;
|
||||
std::function<void(sal_Int32)> m_aRunAsyncFunc;
|
||||
|
||||
public:
|
||||
QtInstanceMessageDialog(QMessageBox* pMessageDialog);
|
||||
|
||||
|
@ -35,6 +44,14 @@ public:
|
|||
const OUString& rHelpId = {}) override;
|
||||
virtual void set_default_response(int nResponse) override;
|
||||
virtual int run() override;
|
||||
virtual bool runAsync(std::shared_ptr<weld::DialogController> const& rxOwner,
|
||||
const std::function<void(sal_Int32)>& func) override;
|
||||
virtual bool runAsync(std::shared_ptr<Dialog> const& rxSelf,
|
||||
const std::function<void(sal_Int32)>& func) override;
|
||||
virtual void response(int nResponse) override;
|
||||
|
||||
private slots:
|
||||
void dialogFinished(int nResult);
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <QtInstanceMessageDialog.hxx>
|
||||
#include <QtInstanceMessageDialog.moc>
|
||||
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
|
@ -20,7 +21,9 @@ const char* const PROPERTY_VCL_RESPONSE_CODE = "response-code";
|
|||
QtInstanceMessageDialog::QtInstanceMessageDialog(QMessageBox* pMessageDialog)
|
||||
: QtInstanceDialog(pMessageDialog)
|
||||
, m_pMessageDialog(pMessageDialog)
|
||||
, m_aRunAsyncFunc(nullptr)
|
||||
{
|
||||
assert(m_pMessageDialog);
|
||||
}
|
||||
|
||||
void QtInstanceMessageDialog::set_primary_text(const rtl::OUString& rText)
|
||||
|
@ -81,4 +84,64 @@ int QtInstanceMessageDialog::run()
|
|||
return pClickedButton->property(PROPERTY_VCL_RESPONSE_CODE).toInt();
|
||||
}
|
||||
|
||||
bool QtInstanceMessageDialog::runAsync(const std::shared_ptr<weld::DialogController>& rxOwner,
|
||||
const std::function<void(sal_Int32)>& func)
|
||||
{
|
||||
assert(m_pMessageDialog);
|
||||
|
||||
m_xRunAsyncDialogController = rxOwner;
|
||||
m_aRunAsyncFunc = func;
|
||||
connect(m_pMessageDialog, &QDialog::finished, this, &QtInstanceMessageDialog::dialogFinished);
|
||||
m_pMessageDialog->open();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtInstanceMessageDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf,
|
||||
const std::function<void(sal_Int32)>& func)
|
||||
{
|
||||
assert(m_pMessageDialog);
|
||||
assert(rxSelf.get() == this);
|
||||
|
||||
m_xRunAsyncDialog = rxSelf;
|
||||
m_aRunAsyncFunc = func;
|
||||
connect(m_pMessageDialog, &QDialog::finished, this, &QtInstanceMessageDialog::dialogFinished);
|
||||
m_pMessageDialog->open();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtInstanceMessageDialog::response(int nResponse)
|
||||
{
|
||||
assert(m_pMessageDialog);
|
||||
m_pMessageDialog->done(nResponse);
|
||||
}
|
||||
|
||||
void QtInstanceMessageDialog::dialogFinished(int nResult)
|
||||
{
|
||||
assert(m_aRunAsyncFunc);
|
||||
|
||||
disconnect(m_pMessageDialog, &QDialog::finished, this,
|
||||
&QtInstanceMessageDialog::dialogFinished);
|
||||
|
||||
// use local variables for these, as members might have got de-allocated by the time they're reset
|
||||
std::shared_ptr<weld::Dialog> xRunAsyncDialog = m_xRunAsyncDialog;
|
||||
std::shared_ptr<weld::DialogController> xRunAsyncDialogController = m_xRunAsyncDialogController;
|
||||
std::function<void(sal_Int32)> aFunc = m_aRunAsyncFunc;
|
||||
m_aRunAsyncFunc = nullptr;
|
||||
m_xRunAsyncDialogController.reset();
|
||||
m_xRunAsyncDialog.reset();
|
||||
|
||||
// if a button was clicked, use its response code, otherwise the passed one
|
||||
int nRet = nResult;
|
||||
if (QAbstractButton* pClickedButton = m_pMessageDialog->clickedButton())
|
||||
nRet = pClickedButton->property(PROPERTY_VCL_RESPONSE_CODE).toInt();
|
||||
|
||||
SolarMutexGuard g;
|
||||
aFunc(nRet);
|
||||
|
||||
xRunAsyncDialogController.reset();
|
||||
xRunAsyncDialog.reset();
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
Loading…
Reference in a new issue