[LyX/master] HiDPI support for search indicators (#12162)

Juergen Spitzmueller spitz at lyx.org
Sun Feb 28 11:31:40 UTC 2021


commit 557382520246c80bff226e6f7e6fcbd45941c14c
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Sun Feb 28 12:35:29 2021 +0100

    HiDPI support for search indicators (#12162)
    
    Requires Qt5
---
 src/frontends/qt/FancyLineEdit.cpp |   25 ++++++--
 src/frontends/qt/GuiSearch.cpp     |  124 ++++++++++++++++++++++++++++++------
 2 files changed, 125 insertions(+), 24 deletions(-)

diff --git a/src/frontends/qt/FancyLineEdit.cpp b/src/frontends/qt/FancyLineEdit.cpp
index c3b597c..b9874d2 100644
--- a/src/frontends/qt/FancyLineEdit.cpp
+++ b/src/frontends/qt/FancyLineEdit.cpp
@@ -33,6 +33,9 @@
 #include <QPainter>
 #include <QStyle>
 #include <QPaintEvent>
+#if QT_VERSION >= 0x050000
+#include <QWindow>
+#endif
 
 enum { margin = 6 };
 
@@ -194,8 +197,13 @@ void FancyLineEdit::updateMargins()
 	Side realLeft = (leftToRight ? Left : Right);
 	Side realRight = (leftToRight ? Right : Left);
 
-	int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
-	int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
+	qreal dpr = 1.0;
+#if QT_VERSION >= 0x050000
+	// Consider device/pixel ratio (HiDPI)
+	dpr = devicePixelRatio();
+#endif
+	int leftMargin = (m_d->m_iconbutton[realLeft]->pixmap().width() / dpr ) + 8;
+	int rightMargin = (m_d->m_iconbutton[realRight]->pixmap().width() / dpr) + 8;
 	// Note KDE does not reserve space for the highlight color
 	if (style()->inherits("OxygenStyle")) {
 		leftMargin = qMax(24, leftMargin);
@@ -334,14 +342,21 @@ IconButton::IconButton(QWidget *parent)
 
 void IconButton::paintEvent(QPaintEvent *)
 {
-	QPainter painter(this);
-	QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
+	qreal dpr = 1.0;
+#if QT_VERSION >= 0x050000
+	// Consider device/pixel ratio (HiDPI)
+	QWindow * window = this->window()->windowHandle();
+	dpr = window->devicePixelRatio();
+#endif
+	QRect pixmapRect(QPoint(), m_pixmap.size() / dpr);
 	pixmapRect.moveCenter(rect().center());
+	QPixmap pm = m_pixmap;
 
+	QPainter painter(this);
 	if (m_autoHide)
 		painter.setOpacity(m_iconOpacity);
 
-	painter.drawPixmap(pixmapRect, m_pixmap);
+	painter.drawPixmap(pixmapRect, pm);
 }
 
 
diff --git a/src/frontends/qt/GuiSearch.cpp b/src/frontends/qt/GuiSearch.cpp
index e938d0c..169c7aa 100644
--- a/src/frontends/qt/GuiSearch.cpp
+++ b/src/frontends/qt/GuiSearch.cpp
@@ -27,8 +27,11 @@
 #include "GuiKeySymbol.h"
 #include "GuiView.h"
 
+#include "qt_helpers.h"
+#include "support/filetools.h"
 #include "support/debug.h"
 #include "support/gettext.h"
+#include "support/FileName.h"
 #include "frontends/alert.h"
 #include "frontends/Clipboard.h"
 
@@ -38,8 +41,12 @@
 #include <QSettings>
 #include <QShowEvent>
 #include "QSizePolicy"
+#if QT_VERSION >= 0x050000
+#include <QSvgRenderer>
+#endif
 
 using namespace std;
+using namespace lyx::support;
 
 using lyx::KeySymbol;
 
@@ -221,13 +228,24 @@ void GuiSearchWidget::handleIndicators()
 		if (wrapCB->isChecked())
 			++pms;
 
+		bool const dark_mode = guiApp && guiApp->isInDarkMode();
+		qreal dpr = 1.0;
+#if QT_VERSION >= 0x050000
+		// Consider device/pixel ratio (HiDPI)
+		if (guiApp && guiApp->currentView())
+			dpr = guiApp->currentView()->devicePixelRatio();
+#endif
+		QString imagedir = "images/";
 		QPixmap bpixmap = getPixmap("images/", "search-options", "svgz,png");
+		QPixmap pm = bpixmap;
 
 		if (pms > 0) {
 			int const gap = 3;
-			QPixmap tpixmap(pms * (bpixmap.width() + gap), bpixmap.height());
-			tpixmap.fill(Qt::transparent);
-			QPainter painter(&tpixmap);
+			QPixmap scaled_pm = QPixmap(bpixmap.size() * dpr);
+			pm = QPixmap(pms * scaled_pm.width() + ((pms - 1) * gap),
+				     scaled_pm.height());
+			pm.fill(Qt::transparent);
+			QPainter painter(&pm);
 			int x = 0;
 			
 			tip = qt_("Active options:");
@@ -235,50 +253,118 @@ void GuiSearchWidget::handleIndicators()
 			if (caseCB->isChecked()) {
 				tip += "<li>" + qt_("Case sensitive search");
 				QPixmap spixmap = getPixmap("images/", "search-case-sensitive", "svgz,png");
+#if QT_VERSION < 0x050000
 				painter.drawPixmap(x, 0, spixmap);
-				x += spixmap.width() + gap;
+#else
+				// With Qt5, we render SVG directly for HiDPI scalability
+				FileName fname = imageLibFileSearch(imagedir, "search-case-sensitive", "svgz,png");
+				QString fpath = toqstr(fname.absFileName());
+				if (!fpath.isEmpty()) {
+					QSvgRenderer svgRenderer(fpath);
+					if (svgRenderer.isValid())
+						svgRenderer.render(&painter, QRectF(0, 0, spixmap.width() * dpr,
+										    spixmap.height() * dpr));
+				}
+#endif
+				x += (spixmap.width() * dpr) + gap;
 			}
 			if (wordsCB->isChecked()) {
 				tip += "<li>" + qt_("Whole words only");
 				QPixmap spixmap = getPixmap("images/", "search-whole-words", "svgz,png");
+#if QT_VERSION < 0x050000
 				painter.drawPixmap(x, 0, spixmap);
-				x += spixmap.width() + gap;
+#else
+				FileName fname = imageLibFileSearch(imagedir, "search-whole-words", "svgz,png");
+				QString fpath = toqstr(fname.absFileName());
+				if (!fpath.isEmpty()) {
+					QSvgRenderer svgRenderer(fpath);
+					if (svgRenderer.isValid())
+						svgRenderer.render(&painter, QRectF(x, 0, spixmap.width() * dpr,
+										    spixmap.height() * dpr));
+				}
+#endif
+				x += (spixmap.width() * dpr) + gap;
 			}
 			if (selectionCB->isChecked()) {
 				tip += "<li>" + qt_("Search only in selection");
 				QPixmap spixmap = getPixmap("images/", "search-selection", "svgz,png");
+#if QT_VERSION < 0x050000
 				painter.drawPixmap(x, 0, spixmap);
-				x += spixmap.width() + gap;
+#else
+				FileName fname = imageLibFileSearch(imagedir, "search-selection", "svgz,png");
+				QString fpath = toqstr(fname.absFileName());
+				if (!fpath.isEmpty()) {
+					QSvgRenderer svgRenderer(fpath);
+					if (svgRenderer.isValid())
+						svgRenderer.render(&painter, QRectF(x, 0, spixmap.width() * dpr,
+										    spixmap.height() * dpr));
+				}
+#endif
+				x += (spixmap.width() * dpr) + gap;
 			}
 			if (instantSearchCB->isChecked()) {
 				tip += "<li>" + qt_("Search as you type");
 				QPixmap spixmap = getPixmap("images/", "search-instant", "svgz,png");
+#if QT_VERSION < 0x050000
 				painter.drawPixmap(x, 0, spixmap);
-				x += spixmap.width() + gap;
+#else
+				FileName fname = imageLibFileSearch(imagedir, "search-instant", "svgz,png");
+				QString fpath = toqstr(fname.absFileName());
+				if (!fpath.isEmpty()) {
+					QSvgRenderer svgRenderer(fpath);
+					if (svgRenderer.isValid())
+						svgRenderer.render(&painter, QRectF(x, 0, spixmap.width() * dpr,
+										    spixmap.height() * dpr));
+				}
+#endif
+				x += (spixmap.width() * dpr) + gap;
 			}
 			if (wrapCB->isChecked()) {
 				tip += "<li>" + qt_("Wrap search");
 				QPixmap spixmap = getPixmap("images/", "search-wrap", "svgz,png");
+#if QT_VERSION < 0x050000
 				painter.drawPixmap(x, 0, spixmap);
-				x += spixmap.width() + gap;
+#else
+				FileName fname = imageLibFileSearch(imagedir, "search-wrap", "svgz,png");
+				QString fpath = toqstr(fname.absFileName());
+				if (!fpath.isEmpty()) {
+					QSvgRenderer svgRenderer(fpath);
+					if (svgRenderer.isValid())
+						svgRenderer.render(&painter, QRectF(x, 0, spixmap.width() * dpr,
+										    spixmap.height() * dpr));
+				}
+#endif
+				x += (spixmap.width() * dpr) + gap;
 			}
 			tip += "</ul>";
+#if QT_VERSION >= 0x050000
+			pm.setDevicePixelRatio(dpr);
+#endif
 			painter.end();
-			if (guiApp && guiApp->isInDarkMode()) {
-				QImage img = tpixmap.toImage();
-				img.invertPixels();
-				tpixmap.convertFromImage(img);
-			}
-			findLE_->setButtonPixmap(FancyLineEdit::Right, tpixmap);
 		} else {
 			tip = qt_("Click here to change search options");
-			if (guiApp && guiApp->isInDarkMode()) {
-				QImage img = bpixmap.toImage();
-				img.invertPixels();
-				bpixmap.convertFromImage(img);
+#if QT_VERSION >= 0x050000
+			// With Qt5, we render SVG directly for HiDPI scalability
+			FileName fname = imageLibFileSearch(imagedir, "search-options", "svgz,png");
+			QString fpath = toqstr(fname.absFileName());
+			if (!fpath.isEmpty()) {
+				QSvgRenderer svgRenderer(fpath);
+				if (svgRenderer.isValid()) {
+					pm = QPixmap(bpixmap.size() * dpr);
+					pm.fill(Qt::transparent);
+					QPainter painter(&pm);
+					svgRenderer.render(&painter);
+					pm.setDevicePixelRatio(dpr);
+				}
 			}
-			findLE_->setButtonPixmap(FancyLineEdit::Right, bpixmap);
+#endif
+		}
+		if (dark_mode) {
+			QImage img = pm.toImage();
+			img.invertPixels();
+			pm.convertFromImage(img);
 		}
+		findLE_->setButtonPixmap(FancyLineEdit::Right, pm);
 	}
 	findLE_->setButtonToolTip(FancyLineEdit::Right, tip);
 }


More information about the lyx-cvs mailing list