summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2024-11-06 22:42:40 +0100
committerMichael Weghorn <m.weghorn@posteo.de>2024-11-07 09:53:56 +0100
commita3400e0471e99a3f3cfa750d0a5cf61a9c3ee0cc (patch)
treed4d1430dd997a6dfa9813a624237f2bf14ab3a30
parent6e2dd3bed69355c028c2378bce81b98f390b50b2 (diff)
tdf#130857 qt weld: Implement simple drawing in QtInstanceDrawingArea
Implement simple drawing in QtInstanceDrawingArea by handling the QEvent::Resize and QEvent::Paint events for the QLabel widget. While the QLabel does not emit any signals when these events occur, it's possible to handle them by setting an event filter using QObject::installEventFilter [1]. Install QtInstanceDrawingArea as an event filter for its label, and implement handling of the Resize and Paint event in QtInstanceDrawingArea::eventFilter: On the QEvent::Resize event, adjust the output size of the output device and call the `weld::Widget::m_aSizeAllocateHdl` handler. (See also GtkInstanceDrawingArea::signal_size_allocate and SalInstanceDrawingArea::ResizeHdl to see what the gtk3 and VCL implementations do.) On the QEvent::Paint event, trigger drawing on the output device via the weld::DrawingArea::m_aDrawHdl handler, and get a QPixmap for what's painted on the output device and set that QPixmap for the label if it has changed. With this in place, the GtkDrawingArea in the "Help" -> "Show Tip of the Day" dialog displays the image as expected, and gets updated when moving to the next tip, once support for that dialog has been declared, which will be done in an upcoming commit. For more complex cases, a more performant solution might become necessary and can be investigated once support for these is implemented. For the "Tip of the Day" dialog, the `aRect` passed in QtInstanceDrawingArea::handlePaintEvent is irrelevant as CuiGraphicPreviewWindow::Paint doesn't make use of the passed rectangle. (This might also have to be reconsidered/adjusted in case a dialog actually making use of the rectangle doesn't work as expected.) [1] https://doc.qt.io/qt-6/qobject.html#installEventFilter Change-Id: I651e00043fac04a4c77aae921e6397e8d97cc69c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176173 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
-rw-r--r--include/vcl/qt/QtUtils.hxx6
-rw-r--r--vcl/inc/qt5/QtInstanceDrawingArea.hxx6
-rw-r--r--vcl/qt5/QtInstanceDrawingArea.cxx50
3 files changed, 62 insertions, 0 deletions
diff --git a/include/vcl/qt/QtUtils.hxx b/include/vcl/qt/QtUtils.hxx
index 368424a8cbe7..87f21d96315c 100644
--- a/include/vcl/qt/QtUtils.hxx
+++ b/include/vcl/qt/QtUtils.hxx
@@ -21,6 +21,7 @@
#include <rtl/ustring.hxx>
#include <vcl/filter/PngImageWriter.hxx>
#include <vcl/image.hxx>
+#include <vcl/outdev.hxx>
#include <QtCore/QString>
#include <QtGui/QPixmap>
@@ -53,6 +54,11 @@ inline QPixmap toQPixmap(const css::uno::Reference<css::graphic::XGraphic>& rIma
return toQPixmap(aImage);
}
+inline QPixmap toQPixmap(const OutputDevice& rDevice)
+{
+ return toQPixmap(Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel())));
+}
+
inline QPixmap loadQPixmapIcon(const OUString& rIconName)
{
BitmapEx aIcon(rIconName);
diff --git a/vcl/inc/qt5/QtInstanceDrawingArea.hxx b/vcl/inc/qt5/QtInstanceDrawingArea.hxx
index 757174330c13..e730464ee83e 100644
--- a/vcl/inc/qt5/QtInstanceDrawingArea.hxx
+++ b/vcl/inc/qt5/QtInstanceDrawingArea.hxx
@@ -45,6 +45,12 @@ public:
virtual a11yrelationset get_accessible_relation_set() override;
virtual AbsoluteScreenPixelPoint get_accessible_location_on_screen() override;
+ virtual bool eventFilter(QObject* pObject, QEvent* pEvent) override;
+
+private:
+ void handlePaintEvent();
+ void handleResizeEvent();
+
private:
virtual void click(const Point&) override;
};
diff --git a/vcl/qt5/QtInstanceDrawingArea.cxx b/vcl/qt5/QtInstanceDrawingArea.cxx
index 0ae6baa2b087..3046c890022d 100644
--- a/vcl/qt5/QtInstanceDrawingArea.cxx
+++ b/vcl/qt5/QtInstanceDrawingArea.cxx
@@ -10,12 +10,17 @@
#include <QtInstanceDrawingArea.hxx>
#include <QtInstanceDrawingArea.moc>
+#include <vcl/qt/QtUtils.hxx>
+
QtInstanceDrawingArea::QtInstanceDrawingArea(QLabel* pLabel)
: QtInstanceWidget(pLabel)
, m_pLabel(pLabel)
, m_xDevice(DeviceFormat::WITHOUT_ALPHA)
{
assert(m_pLabel);
+
+ // install event filter, so eventFilter() can handle widget events
+ m_pLabel->installEventFilter(this);
}
void QtInstanceDrawingArea::queue_draw()
@@ -74,4 +79,49 @@ AbsoluteScreenPixelPoint QtInstanceDrawingArea::get_accessible_location_on_scree
void QtInstanceDrawingArea::click(const Point&) { assert(false && "Not implemented yet"); }
+bool QtInstanceDrawingArea::eventFilter(QObject* pObject, QEvent* pEvent)
+{
+ if (pObject != m_pLabel)
+ return false;
+
+ SolarMutexGuard g;
+ assert(GetQtInstance().IsMainThread());
+
+ switch (pEvent->type())
+ {
+ case QEvent::Paint:
+ handlePaintEvent();
+ return false;
+ case QEvent::Resize:
+ handleResizeEvent();
+ return false;
+ default:
+ return false;
+ }
+}
+
+void QtInstanceDrawingArea::handlePaintEvent()
+{
+ tools::Rectangle aRect(0, 0, m_pLabel->width(), m_pLabel->height());
+ aRect = m_xDevice->PixelToLogic(aRect);
+ m_xDevice->Erase(aRect);
+ m_aDrawHdl.Call(std::pair<vcl::RenderContext&, const tools::Rectangle&>(*m_xDevice, aRect));
+ QPixmap aPixmap = toQPixmap(*m_xDevice);
+
+ // set new pixmap if it changed
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (aPixmap.toImage() != m_pLabel->pixmap().toImage())
+#else
+ if (aPixmap.toImage() != m_pLabel->pixmap(Qt::ReturnByValue).toImage())
+#endif
+ m_pLabel->setPixmap(aPixmap);
+}
+
+void QtInstanceDrawingArea::handleResizeEvent()
+{
+ const Size aSize = toSize(m_pLabel->size());
+ m_xDevice->SetOutputSizePixel(aSize);
+ m_aSizeAllocateHdl.Call(aSize);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */