UI scaling: fonts

This commit is contained in:
Jean-Francois Dockes 2022-04-19 18:23:51 +02:00
parent d08a59dd98
commit 8cec995573
16 changed files with 219 additions and 81 deletions

View File

@ -576,6 +576,7 @@ python/samples/recollqsd.py \
sampleconf/fields sampleconf/fragment-buttons.xml sampleconf/mimeconf \
sampleconf/mimemap sampleconf/mimeview sampleconf/macos/mimeview \
sampleconf/recoll.conf sampleconf/recoll.qss \
sampleconf/recoll-common.css sampleconf/recoll-common.qss \
sampleconf/recoll-dark.qss sampleconf/recoll-dark.css \
\
testmains/Makefile.am \
@ -660,17 +661,19 @@ defconfdir = $(pkgdatadir)/examples
defconf_DATA = \
desktop/recollindex.desktop \
index/rclmon.sh \
index/recollindex@.service \
index/recollindex.service \
sampleconf/fragment-buttons.xml \
index/recollindex@.service \
sampleconf/fields \
sampleconf/recoll.conf \
sampleconf/fragment-buttons.xml \
sampleconf/mimeconf \
sampleconf/recoll.qss \
sampleconf/recoll-dark.qss \
sampleconf/recoll-dark.css \
sampleconf/mimemap \
sampleconf/mimeview
sampleconf/mimeview \
sampleconf/recoll-common.css \
sampleconf/recoll-common.qss \
sampleconf/recoll-dark.css \
sampleconf/recoll-dark.qss \
sampleconf/recoll.conf \
sampleconf/recoll.qss
filterdir = $(pkgdatadir)/filters
dist_filter_DATA = \

View File

@ -19,6 +19,13 @@
#include <algorithm>
#include <cstdio>
// Programs built with gcc 4.8.4 (e.g.: Ubuntu Trusty), crash at startup while initializing stdc++
// regular expression objects (and also crash if we make them non-static).
#if defined(__clang__) || defined(_WIN32) || __GNUC__ > 4
#define USE_REGEX
#include <regex>
#endif
#include "recoll.h"
#include "log.h"
#include "smallut.h"
@ -31,6 +38,7 @@
#include <QSettings>
#include <QStringList>
#ifdef BUILDING_RECOLLGUI
#include <QWidget>
#include <QFont>
#endif
@ -289,6 +297,7 @@ void rwSettings(bool writing)
SETTING_RW(prefs.showTrayIcon, "/Recoll/prefs/showTrayIcon", Bool, false);
SETTING_RW(prefs.closeToTray, "/Recoll/prefs/closeToTray", Bool, false);
SETTING_RW(prefs.trayMessages, "/Recoll/prefs/trayMessages", Bool, false);
SETTING_RW(prefs.wholeuiscale, "/Recoll/ui/wholeuiscale", Double, 1.0);
/*INSERTHERE*/
// See qxtconfirmationmessage. Needs to be -1 for the dialog to show.
@ -415,6 +424,83 @@ void rwSettings(bool writing)
havereadsettings = true;
}
#ifdef USE_REGEX
/* font-size: 10pt; */
static const std::string fntsz_exp(
R"((\s*font-size\s*:\s*)([0-9]+)(p[tx]\s*;\s*))"
);
static std::regex fntsz_regex(fntsz_exp);
#endif // USE_REGEX
std::string PrefsPack::scaleFonts(const std::string& style, float multiplier)
{
//cerr << "scale_fonts: multiplier: " << multiplier << "\n";
std::vector<std::string> lines;
stringToTokens(style, lines, "\n");
#ifdef USE_REGEX
for (unsigned int ln = 0; ln < lines.size(); ln++) {
const string& line = lines[ln];
std::smatch m;
//std::cerr << "LINE: " << line << "\n";
if (regex_match(line, m, fntsz_regex) && m.size() == 4) {
//std::cerr << "Got match (sz " << m.size() << ") for " << line << "\n";
int fs = atoi(m[2].str().c_str());
int nfs = round(fs * multiplier);
char buf[20];
snprintf(buf, 20, "%d", nfs);
lines[ln] = m[1].str() + buf + m[3].str();
//std::cerr << "New line: [" << lines[ln] << "]\n";
}
}
#endif
string nstyle = string();
for (auto& ln : lines) {
nstyle += ln + "\n";
}
return nstyle;
}
int PrefsPack::fontsize()
{
// While building the kio, we don't really care about QT Gui
// defaults and referencing QFont introduces a useless dependency
#ifdef BUILDING_RECOLLGUI
int fs;
if (prefs.reslistfontsize > 0) {
fs = prefs.reslistfontsize;
} else {
fs = QWidget().font().pixelSize();
}
fs = round(fs * prefs.wholeuiscale);
return fs;
#else
return 12;
#endif
}
std::string PrefsPack::htmlHeaderContents()
{
auto comfn = path_cat(path_cat(theconfig->getDatadir(), "examples"), "recoll-common.css");
std::string comcss;
file_to_string(comfn, comcss);
std::ostringstream oss;
oss << comcss << "\n";
oss << "<style type=\"text/css\">\nhtml,body,form, fieldset,table,tr,td,img,select,input {\n";
#ifdef SETFONT_WITH_HEADSTYLE
if (!prefs.reslistfontfamily.isEmpty()) {
oss << "font-family: \"" << qs2utf8s(prefs.reslistfontfamily) << "\";\n";
}
oss << "font-size: " << round(prefs.reslistfontsize * 1.2) << "px;\n";
#endif
oss << "color: " << qs2utf8s(prefs.fontcolor) << ";\n";
oss << "}\n</style>\n";
oss << qs2utf8s(prefs.darkreslistheadertext) << qs2utf8s(prefs.reslistheadertext);
auto css = PrefsPack::scaleFonts(oss.str(), prefs.wholeuiscale);
return css;
}
void PrefsPack::setupDarkCSS()
{
if (!darkMode) {
@ -424,8 +510,7 @@ void PrefsPack::setupDarkCSS()
if (nullptr == theconfig) {
return;
}
string fn = path_cat(
path_cat(theconfig->getDatadir(), "examples"), "recoll-dark.css");
string fn = path_cat(path_cat(theconfig->getDatadir(), "examples"), "recoll-dark.css");
string data;
string reason;
if (!file_to_string(fn, data, &reason)) {

View File

@ -161,6 +161,7 @@ public:
bool showTrayIcon{false};
bool closeToTray{false};
bool trayMessages{false};
double wholeuiscale{1.0};
/*INSERTHERE*/
// See widgets/qxtconfirmationmessage.
@ -176,12 +177,20 @@ public:
std::string stemlang();
void setupDarkCSS();
// HTML Header contents for both the result list, the snippets window and others
std::string htmlHeaderContents();
// MIME types for which we prefer to use stored text from preview
// rather than extracting the possibly nicer HTML because the
// extractor is very slow. This is compiled in and there is no UI
// for now.
std::set<std::string> preferStoredTextMimes{"application/x-hwp"};
// Scale font-sizes inside css or qss input and return changed sheet. The font-size statements
// need to be on their own line.
static std::string scaleFonts(const std::string& style, float multiplier);
int fontsize();
};
/** Global preferences record */

View File

@ -161,17 +161,19 @@ static void recollCleanup()
LOGDEB2("recollCleanup: done\n" );
}
void applyStyleSheet(const QString& ssfname)
void applyStyleSheet(const QString& qssfn)
{
const std::string cfname = qs2path(ssfname);
LOGDEB0("Applying style sheet: [" << cfname << "]\n");
if (!cfname.empty()) {
string stylesheet;
file_to_string(cfname, stylesheet);
qApp->setStyleSheet(QString::fromUtf8(stylesheet.c_str()));
} else {
qApp->setStyleSheet(QString());
auto comfn = path_cat(path_cat(theconfig->getDatadir(), "examples"), "recoll-common.qss");
std::string qss;
file_to_string(comfn, qss);
if (!qssfn.isEmpty()) {
LOGDEB0("Using custom style sheet: [" << qs2path(qssfn) << "]\n");
string customqss;
file_to_string(qs2path(qssfn), customqss);
qss += customqss;
}
qss = prefs.scaleFonts(qss, prefs.wholeuiscale);
qApp->setStyleSheet(u8s2qs(qss));
}
extern void qInitImages_recoll();
@ -370,9 +372,8 @@ int main(int argc, char **argv)
rwSettings(false);
// fprintf(stderr, "Settings done\n");
if (!prefs.qssFile.isEmpty()) {
applyStyleSheet(prefs.qssFile);
}
applyStyleSheet(prefs.qssFile);
QIcon icon;
icon.addFile(QString::fromUtf8(":/images/recoll.png"));
app.setWindowIcon(icon);

View File

@ -125,10 +125,13 @@ void Preview::init()
}
if (prefs.reslistfontfamily != "") {
m_font = QFont(prefs.reslistfontfamily, prefs.reslistfontsize);
m_font = QFont(prefs.reslistfontfamily);
} else {
m_font = QFont();
m_font.setPointSize(prefs.reslistfontsize);
}
if (prefs.reslistfontsize || prefs.wholeuiscale) {
int fs = prefs.reslistfontsize ? prefs.reslistfontsize : m_font.pixelSize();
m_font.setPixelSize(round(fs * prefs.wholeuiscale));
}
(void)new HelpClient(this);

View File

@ -334,7 +334,8 @@ void RclMain::showExtIdxDialog()
void RclMain::showAboutDialog()
{
QString vstring = QString("<html><head>") + prefs.darkreslistheadertext + "</head><body>" +
QString vstring = QString("<html><head>") + u8s2qs(prefs.htmlHeaderContents()) +
"</head><body>" +
u8s2qs(Rcl::version_string()) +
"<br><a href='https://www.recoll.org'>www.recoll.org</a>" +
"<br><a href='https://www.xapian.org'>www.xapian.org</a>";

View File

@ -5,6 +5,11 @@ VPATH = @srcdir@
DEFINES += BUILDING_RECOLL
DEFINES += BUILDING_RECOLLGUI
# Decide if we set font family and style with a css section in the html <head> or with qwebsettings
# setfont... calls. We used to do it with websettings because it gave a faster redisplay, and the
# css has a tendancy to not find some system fonts. We currently do it with css anyway.
DEFINES += SETFONT_WITH_HEADSTYLE=1
@QMAKE_ENABLE_WEBKIT@ QT += webkit
@QMAKE_ENABLE_WEBKIT@ DEFINES += USING_WEBKIT

View File

@ -121,13 +121,6 @@ bool RclWebPage::acceptNavigationRequest(const QUrl& url,
#endif // WEBENGINE
// Decide if we set font family and style with a css section in the
// html <head> or with qwebsettings setfont... calls. We currently do
// it with websettings because this gives an instant redisplay, and
// the css has a tendancy to not find some system fonts. Otoh,
// SetFontSize() needs a strange offset of 3, not needed with css.
#undef SETFONT_WITH_HEADSTYLE
class QtGuiResListPager : public ResListPager {
public:
QtGuiResListPager(ResList *p, int ps, bool alwayssnip)
@ -230,26 +223,7 @@ string QtGuiResListPager::prevUrl()
string QtGuiResListPager::headerContent()
{
string out;
out = "<style type=\"text/css\">\nbody,table,select,input {\n";
#ifdef SETFONT_WITH_HEADSTYLE
char ftsz[30];
sprintf(ftsz, "%d", prefs.reslistfontsize);
out += string("font-family: \"") + qs2utf8s(prefs.reslistfontfamily)
+ "\";\n";
out += string("font-size: ") + ftsz + "pt;\n";
#endif
out += string("color: ") + qs2utf8s(prefs.fontcolor) + ";\n";
out += string("}\n</style>\n");
#if defined(USING_WEBENGINE)
out += "<script type=\"text/javascript\">\n";
out += locdetailscript;
out += "</script>\n";
#endif
out += qs2utf8s(prefs.darkreslistheadertext);
out += qs2utf8s(prefs.reslistheadertext);
return out;
return prefs.htmlHeaderContents();
}
void QtGuiResListPager::suggest(const vector<string>uterms,

View File

@ -69,7 +69,6 @@ static const int TEXTINCELLVTRANS = -4;
// Adjust font size from prefs, display is slightly different here
static const int fsadjustdetail = 1;
static const int fsadjusttable = 1;
static PlainToRichQtReslist g_hiliter;
@ -93,6 +92,8 @@ public:
virtual string absSep() override {
return (const char *)(prefs.abssep.toUtf8());}
virtual string headerContent() override {
// Note: the detail area is a qtextbrowser which gets confused by the general Html
// header. So we manage it differently from the snippets or main result list.
return qs2utf8s(prefs.darkreslistheadertext) + qs2utf8s(prefs.reslistheadertext);
}
private:
@ -155,11 +156,7 @@ void ResTableDetailArea::createPopupMenu(const QPoint& pos)
void ResTableDetailArea::setFont()
{
int fs = prefs.reslistfontsize;
// fs shows slightly bigger in qtextbrowser? adjust.
if (prefs.reslistfontsize > fsadjustdetail) {
fs -= fsadjustdetail;
}
int fs = prefs.fontsize() - fsadjustdetail;
if (prefs.reslistfontfamily != "") {
QFont nfont(prefs.reslistfontfamily, fs);
QTextBrowser::setFont(nfont);
@ -392,15 +389,12 @@ QVariant RecollModel::data(const QModelIndex& index, int role) const
// The font is actually set in the custom delegate, but we need
// this to adjust the row height (there is probably a better way
// to do it in the delegate?)
if (role == Qt::FontRole && prefs.reslistfontsize > 0) {
if (m_reslfntszforcached != prefs.reslistfontsize) {
m_reslfntszforcached = prefs.reslistfontsize;
if (role == Qt::FontRole && (prefs.reslistfontsize > 0 || prefs.wholeuiscale != 1.0)) {
if (m_reslfntszforcached != prefs.fontsize() - fsadjustdetail) {
m_reslfntszforcached = prefs.fontsize() - fsadjustdetail;
m_table->setDefRowHeight();
m_cachedfont = m_table->font();
int fs = prefs.reslistfontsize <= fsadjusttable ?
prefs.reslistfontsize: prefs.reslistfontsize - fsadjusttable;
if (fs > 0)
m_cachedfont.setPointSize(fs);
m_cachedfont.setPixelSize(m_reslfntszforcached);
}
return m_cachedfont;
}
@ -542,9 +536,8 @@ public:
QString seltextcolor =
opt.palette.color(QPalette::HighlightedText).name();
QString fstyle;
if (prefs.reslistfontsize > 0) {
int fs = prefs.reslistfontsize <= fsadjusttable ?
prefs.reslistfontsize : prefs.reslistfontsize - fsadjusttable;
if (prefs.reslistfontsize > 0 || prefs.wholeuiscale != 1.0) {
int fs = prefs.fontsize() - fsadjustdetail;
fstyle = QString("font-size: %1pt").arg(fs);
}
QString ntxt("<div style='");
@ -581,8 +574,7 @@ void ResTable::setDefRowHeight()
// header->setSectionResizeMode(QHeaderView::ResizeToContents);
// Compute ourselves instead, for one row.
QFont font = tableView->font();
int fs = prefs.reslistfontsize <= fsadjusttable ?
prefs.reslistfontsize : prefs.reslistfontsize - fsadjusttable;
int fs = prefs.fontsize() - fsadjustdetail;
if (fs > 0)
font.setPointSize(fs);
QFontMetrics fm(font);

View File

@ -215,7 +215,7 @@ protected:
private:
void init(QStringList fields);
RecollModel *m_model{nullptr};
ResTablePager *m_pager{nullptr};
ResTableDetailArea *m_detail{nullptr};

View File

@ -53,6 +53,7 @@
#include "rclhelp.h"
#include "plaintorich.h"
#include "scbase.h"
#include "readfile.h"
using namespace std;
@ -105,13 +106,13 @@ void SnippetsW::init()
connect(browser, SIGNAL(linkClicked(const QUrl &)), this, SLOT(onLinkClicked(const QUrl &)));
browser->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
browser->page()->currentFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
#ifndef SETFONT_WITH_HEADSTYLE
QWEBSETTINGS *ws = browser->page()->settings();
if (prefs.reslistfontfamily != "") {
ws->setFontFamily(QWEBSETTINGS::StandardFont, prefs.reslistfontfamily);
ws->setFontSize(QWEBSETTINGS::DefaultFontSize, prefs.reslistfontsize);
}
if (!prefs.snipCssFile.isEmpty())
ws->setUserStyleSheetUrl(QUrl::fromLocalFile(prefs.snipCssFile));
#endif
browserw->setContextMenuPolicy(Qt::CustomContextMenu);
connect(browserw, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(createPopupMenu(const QPoint&)));
@ -119,11 +120,13 @@ void SnippetsW::init()
browserw = new QWebEngineView(this);
verticalLayout->insertWidget(0, browserw);
browser->setPage(new SnipWebPage(this));
#ifndef SETFONT_WITH_HEADSTYLE
QWEBSETTINGS *ws = browser->page()->settings();
if (prefs.reslistfontfamily != "") {
ws->setFontFamily(QWEBSETTINGS::StandardFont, prefs.reslistfontfamily);
ws->setFontSize(QWEBSETTINGS::DefaultFontSize, prefs.reslistfontsize);
}
#endif
// Stylesheet TBD
browserw->setContextMenuPolicy(Qt::CustomContextMenu);
connect(browserw, SIGNAL(customContextMenuRequested(const QPoint&)),
@ -222,16 +225,15 @@ void SnippetsW::onSetDoc(Rcl::Doc doc, std::shared_ptr<DocSequence> source)
HighlightData hdata;
source->getTerms(hdata);
std::string snipcss;
if (!prefs.snipCssFile.isEmpty()) {
file_to_string(qs2path(prefs.snipCssFile), snipcss);
}
ostringstream oss;
oss << "<html><head>"
"<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
oss << "<style type=\"text/css\">\nbody,table,select,input {\n";
oss << "color: " + qs2utf8s(prefs.fontcolor) + ";\n";
oss << "}\n</style>\n";
oss << qs2utf8s(prefs.darkreslistheadertext) << qs2utf8s(prefs.reslistheadertext);
oss << "</head><body><table class=\"snippets\">";
oss << "<html><head>\n"
"<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n";
oss << prefs.htmlHeaderContents() << snipcss;
oss << "\n</head>\n<body>\n<table class=\"snippets\">";
g_hiliter.set_inputhtml(false);
bool nomatch = true;

View File

@ -544,6 +544,52 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" stretch="0,0,1">
<item>
<widget class="QLabel" name="wuiscaleLBL">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Zoom factor for the user interface. Useful if the default is not right for your screen resolution.</string>
</property>
<property name="text">
<string>Display scale (default 1.0):</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="wholeuiscaleSB">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="wholeuiscaleHSPC">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>

View File

@ -163,6 +163,7 @@ void UIPrefsDialog::setFromPrefs()
trayMessagesCB->setEnabled(showTrayIconCB->checkState());
closeToTrayCB->setChecked(prefs.closeToTray);
trayMessagesCB->setChecked(prefs.trayMessages);
wholeuiscaleSB->setValue(prefs.wholeuiscale);
/*INSERTHERE_LOAD*/
// See qxtconfirmationmessage. Needs to be -1 for the dialog to show.
@ -439,6 +440,7 @@ void UIPrefsDialog::accept()
m_mainWindow->enableTrayIcon(prefs.showTrayIcon);
prefs.closeToTray = closeToTrayCB->isChecked();
prefs.trayMessages = trayMessagesCB->isChecked();
prefs.wholeuiscale = wholeuiscaleSB->value();
/*INSERTHERE_ACCEPT*/
// -1 is the qxtconf... predefined value to show the dialog

View File

@ -0,0 +1,6 @@
<style>
/* Default font size for the HTML widgets */
html, body, form, fieldset, table, tr, td, img {
font-size: 12px;
}
</style>

View File

@ -0,0 +1,8 @@
/*
* This is always applied to the recoll GUI, and can be extended or overridden by the style sheet
* set in the preferences. The font size is edited before applying when recoll is scaled.
*/
QWidget {
font-size: 12px;
}

View File

@ -180,6 +180,7 @@ copyrecoll()
chkcp $RCL/windows/mimeview $DESTDIR/Share/examples/windows
chkcp $RCL/sampleconf/recoll.conf $DESTDIR/Share/examples
chkcp $RCL/sampleconf/recoll.qss $DESTDIR/Share/examples
chkcp $RCL/sampleconf/recoll-common.qss $DESTDIR/Share/examples
chkcp $RCL/sampleconf/recoll-dark.qss $DESTDIR/Share/examples
chkcp $RCL/sampleconf/recoll-dark.css $DESTDIR/Share/examples