diff --git a/lib/RELEASE-NOTES b/lib/RELEASE-NOTES index 9b939b736d..cc5a3e19fc 100644 --- a/lib/RELEASE-NOTES +++ b/lib/RELEASE-NOTES @@ -53,6 +53,9 @@ * Edit > Paste operation now preserves newlines in text by default. +* Dark mode on Windows is possible now by choosing "fusion" user interface style + in the user interface preferences dialog, your system style has to be set to dark. + !!Documents compilation process and images conversion diff --git a/lib/configure.py b/lib/configure.py index e5f71f7a2a..5d0806e267 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -2004,7 +2004,7 @@ if __name__ == '__main__': lyx_check_config = True lyx_kpsewhich = True outfile = 'lyxrc.defaults' - lyxrc_fileformat = 37 + lyxrc_fileformat = 38 rc_entries = '' lyx_keep_temps = False version_suffix = '' diff --git a/lib/doc/UserGuide.lyx b/lib/doc/UserGuide.lyx index 1239e73704..a4a53cff67 100644 --- a/lib/doc/UserGuide.lyx +++ b/lib/doc/UserGuide.lyx @@ -1,5 +1,5 @@ #LyX 2.4 created this file. For more info see https://www.lyx.org/ -\lyxformat 618 +\lyxformat 620 \begin_document \begin_header \save_transient_properties true @@ -167,6 +167,7 @@ logicalmkup \author 5863208 "ab" \author 5863344 "Enrico Forestieri" \author 244031559 "Yuriy" +\author 258250489 "eugen" \author 274215730 "scott" \author 630872221 "Jean-Pierre Chrétien" jeanpierre.chretien@free.fr \author 1064312605 "Udi Fogiel" @@ -58115,6 +58116,33 @@ literal "false" \end_inset . +\change_inserted 258250489 1697053558 + +\end_layout + +\begin_layout Standard + +\change_inserted 258250489 1697054388 + +\family sans +User +\begin_inset space ~ +\end_inset + +interface +\begin_inset space ~ +\end_inset + +style +\family default + allows you to change the look and feel of \SpecialChar LyX +'s user interface control elements. + There may be different choices available on different operating systems. + On certain operating systems some styles may support dark mode while others don't. + In order to use dark mode in \SpecialChar LyX + you may first need to enable it in your system's settings. +\change_unchanged + \end_layout \begin_layout Subsubsection diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py index a5a3a7dbf1..69b97fd30e 100644 --- a/lib/scripts/prefs2prefs_prefs.py +++ b/lib/scripts/prefs2prefs_prefs.py @@ -168,6 +168,10 @@ # Add \screen_width # Add \screen_limit +# Incremented to format 38, by ec +# Add option to configure ui style +# No conversion necessary. + # NOTE: The format should also be updated in LYXRC.cpp and # in configure.py (search for lyxrc_fileformat). @@ -555,5 +559,6 @@ conversions = [ [ 34, [rename_cyrillic_kmap_files]], [ 35, [add_dark_color]], [ 36, [add_spellcheck_default]], - [ 37, [remove_fullscreen_widthlimit]] + [ 37, [remove_fullscreen_widthlimit]], + [ 38, []] ] diff --git a/src/LyX.cpp b/src/LyX.cpp index 04c1dd4f25..d077771b8d 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -997,6 +997,7 @@ bool LyX::init() // This one is edited through the preferences dialog. if (!readRcFile("preferences", true)) return false; + pimpl_->application_->applyPrefs(); // The language may have been set to someting useful through prefs setLocale(); diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index fa50d4a51d..73aec189f3 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -60,7 +60,7 @@ namespace { // The format should also be updated in configure.py, and conversion code // should be added to prefs2prefs_prefs.py. -static unsigned int const LYXRC_FILEFORMAT = 37; // chillenb: screen_width and screen_limit +static unsigned int const LYXRC_FILEFORMAT = 38; // chillenb: screen_width and screen_limit // when adding something to this array keep it sorted! LexerKeyword lyxrcTags[] = { { "\\accept_compound", LyXRC::RC_ACCEPT_COMPOUND }, @@ -197,6 +197,7 @@ LexerKeyword lyxrcTags[] = { { "\\texinputs_prefix", LyXRC::RC_TEXINPUTS_PREFIX }, { "\\thesaurusdir_path", LyXRC::RC_THESAURUSDIRPATH }, { "\\ui_file", LyXRC::RC_UIFILE }, + { "\\ui_style", LyXRC::RC_UI_STYLE }, { "\\use_converter_cache", LyXRC::RC_USE_CONVERTER_CACHE }, { "\\use_converter_needauth", LyXRC::RC_USE_CONVERTER_NEEDAUTH }, { "\\use_converter_needauth_forbidden", LyXRC::RC_USE_CONVERTER_NEEDAUTH_FORBIDDEN }, @@ -603,6 +604,10 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) lexrc >> icon_set; break; + case RC_UI_STYLE: + lexrc >> ui_style; + break; + case RC_USE_SYSTEM_THEME_ICONS: lexrc >> use_system_theme_icons; break; @@ -1624,6 +1629,15 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c if (tag != RC_LAST) break; // fall through + case RC_UI_STYLE: + if (ignore_system_lyxrc || + ui_style != system_lyxrc.ui_style) { + os << "\\ui_style \"" << ui_style + << "\"\n"; + } + if (tag != RC_LAST) + break; + // fall through case RC_USE_SYSTEM_THEME_ICONS: if (ignore_system_lyxrc || use_system_theme_icons != system_lyxrc.use_system_theme_icons) { @@ -2950,6 +2964,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) case LyXRC::RC_GROUP_LAYOUTS: case LyXRC::RC_HUNSPELLDIR_PATH: case LyXRC::RC_ICON_SET: + case LyXRC::RC_UI_STYLE: case LyXRC::RC_INDEX_ALTERNATIVES: case LyXRC::RC_INDEX_COMMAND: case LyXRC::RC_JBIBTEX_COMMAND: diff --git a/src/LyXRC.h b/src/LyXRC.h index c196d579f1..039cf5658c 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -173,6 +173,7 @@ public: RC_TEXINPUTS_PREFIX, RC_THESAURUSDIRPATH, RC_UIFILE, + RC_UI_STYLE, RC_USELASTFILEPOS, RC_USER_EMAIL, RC_USER_INITIALS, @@ -473,6 +474,8 @@ public: std::string user_initials; /// icon set name std::string icon_set; + /// ui style name + std::string ui_style = "default"; /// whether to use the icons from the theme bool use_system_theme_icons = false; /// True if the TeX engine cannot handle posix paths diff --git a/src/frontends/Application.h b/src/frontends/Application.h index 053a699f8c..75298ca67a 100644 --- a/src/frontends/Application.h +++ b/src/frontends/Application.h @@ -253,6 +253,8 @@ public: // Add a buffer to the current view, do not switch to it. virtual bool unhide(Buffer * buf) = 0; + // Apply preferences at the start + static void applyPrefs(); }; /// Return the list of loadable formats. diff --git a/src/frontends/qt/GuiApplication.cpp b/src/frontends/qt/GuiApplication.cpp index b7abd4297f..d1c91fbb01 100644 --- a/src/frontends/qt/GuiApplication.cpp +++ b/src/frontends/qt/GuiApplication.cpp @@ -1268,6 +1268,11 @@ docstring Application::mathIcon(docstring const & c) return qstring_to_ucs4(findImg(toqstr(c))); } +void Application::applyPrefs() +{ + if (lyxrc.ui_style != system_lyxrc.ui_style) + lyx::frontend::GuiApplication::setStyle(toqstr(lyxrc.ui_style)); +} FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const { diff --git a/src/frontends/qt/GuiPrefs.cpp b/src/frontends/qt/GuiPrefs.cpp index 9836086a92..405f255787 100644 --- a/src/frontends/qt/GuiPrefs.cpp +++ b/src/frontends/qt/GuiPrefs.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -2494,6 +2495,8 @@ PrefUserInterface::PrefUserInterface(GuiPreferences * form) this, SIGNAL(changed())); connect(iconSetCO, SIGNAL(activated(int)), this, SIGNAL(changed())); + connect(uiStyleCO, SIGNAL(activated(int)), + this, SIGNAL(changed())); connect(useSystemThemeIconsCB, SIGNAL(clicked()), this, SIGNAL(changed())); connect(lastfilesSB, SIGNAL(valueChanged(int)), @@ -2516,6 +2519,12 @@ PrefUserInterface::PrefUserInterface(GuiPreferences * form) iconSetCO->addItem(qt_("Classic"), "classic"); iconSetCO->addItem(qt_("Oxygen"), "oxygen"); + uiStyleCO->addItem(toqstr(system_lyxrc.ui_style)); + for (const auto& style : QStyleFactory::keys()) + { + uiStyleCO->addItem(style.toLower()); + } + if (guiApp->platformName() != "xcb" && !guiApp->platformName().contains("wayland")) useSystemThemeIconsCB->hide(); @@ -2527,6 +2536,10 @@ void PrefUserInterface::applyRC(LyXRC & rc) const rc.icon_set = fromqstr(iconSetCO->itemData( iconSetCO->currentIndex()).toString()); + rc.ui_style = fromqstr(uiStyleCO->currentText()); + if (rc.ui_style!=system_lyxrc.ui_style) + frontend::GuiApplication::setStyle(uiStyleCO->currentText()); + rc.ui_file = internal_path(fromqstr(uiFileED->text())); rc.use_system_theme_icons = useSystemThemeIconsCB->isChecked(); rc.num_lastfiles = lastfilesSB->value(); @@ -2545,6 +2558,7 @@ void PrefUserInterface::updateRC(LyXRC const & rc) if (iconset < 0) iconset = 0; iconSetCO->setCurrentIndex(iconset); + uiStyleCO->setCurrentIndex(uiStyleCO->findText(toqstr(rc.ui_style))); useSystemThemeIconsCB->setChecked(rc.use_system_theme_icons); uiFileED->setText(toqstr(external_path(rc.ui_file))); lastfilesSB->setValue(rc.num_lastfiles); diff --git a/src/frontends/qt/ui/PrefUi.ui b/src/frontends/qt/ui/PrefUi.ui index d7551cbb3d..7a2c8d4711 100644 --- a/src/frontends/qt/ui/PrefUi.ui +++ b/src/frontends/qt/ui/PrefUi.ui @@ -7,7 +7,7 @@ 0 0 556 - 476 + 502 @@ -42,18 +42,8 @@ - - - - &User interface file: - - - uiFileED - - - - - + + @@ -62,6 +52,13 @@ + + + + The icon set to use. Warning: normal size of icons may be wrong until you save the preferences and restart LyX. + + + @@ -72,15 +69,38 @@ - - - - The icon set to use. Warning: normal size of icons may be wrong until you save the preferences and restart LyX. + + + + &User interface file: + + + uiFileED - - + + + + + + + User interface &style: + + + uiStyleCO + + + + + + + Only certain styles may support dark mode, e.g. fusion on Windows + + + + +