From 557382520246c80bff226e6f7e6fcbd45941c14c Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Sun, 28 Feb 2021 12:35:29 +0100 Subject: [PATCH] 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 c3b597c9e1..b9874d2e89 100644 --- a/src/frontends/qt/FancyLineEdit.cpp +++ b/src/frontends/qt/FancyLineEdit.cpp @@ -33,6 +33,9 @@ #include #include #include +#if QT_VERSION >= 0x050000 +#include +#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 e938d0c50b..169c7aa8b6 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 #include #include "QSizePolicy" +#if QT_VERSION >= 0x050000 +#include +#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 += "
  • " + 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 += "
  • " + 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 += "
  • " + 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 += "
  • " + 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 += "
  • " + 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 += ""; +#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); } -- 2.39.5