diff --git a/rtdata/themes/RawTherapee.css b/rtdata/themes/RawTherapee-GTK3-20_.css similarity index 100% rename from rtdata/themes/RawTherapee.css rename to rtdata/themes/RawTherapee-GTK3-20_.css diff --git a/rtdata/themes/RawTherapee-GTK3-_19.css b/rtdata/themes/RawTherapee-GTK3-_19.css new file mode 100644 index 000000000..e6eac9793 --- /dev/null +++ b/rtdata/themes/RawTherapee-GTK3-_19.css @@ -0,0 +1,448 @@ +/* + This file is part of RawTherapee. + + Copyright (c) 2015 DrSlony + Copyright (c) 2016 Hombre + + RawTherapee is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + RawTherapee is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with RawTherapee. If not, see . +*/ + +* { + color: #AAAAAA; +} + +.view:selected { + color: #262626; + background-color: #AAAAAA +} + +/* The Places and Dir browser panels */ +.view { + background-color: #262626; +} +/* The headers of these panels */ +.view .button { + background-color: #363636; + padding: 2px; +} + +.plainback { + background-color: #404040; +} + +GtkBox { + border-width: 0; + border-style: none; + border-radius: 0; + margin: 0; + padding: 0; +} + +GtkGrid { + margin: 2px; + padding: 0; + border-width: 0; + border-style: none; + border-radius: 0; +} + +/* Affects all frames except in the toolbox */ +GtkFrame { + border-width: 0; + border-color: #303030; + border-radius: 0; + border-style: solid; + /*border-style: none none none solid;*/ + padding: 4px; +} + +GtkFrame > GtkLabel { + color: #D8D8D8; +} + +#FileBrowser { + padding: 10px; + margin: 10px; +} + +/* Frames in Preferences */ +#PrefNotebook GtkFrame { + background-color: #3B3B3B; + border: 1px solid #505050; + border-radius: 4px; +} + +/* Frames in the toolbox. Not MyExpander frames. */ +GtkEventBox .frame { + border-color: #565656; +} + +/*.EditorTopPanel .button, .ToolBarPanelFileBrowser .button, .EditorZoomPanel .button {*/ +.button { + padding: 1px; + margin: 1px; +} + +/* Adjusters */ +.text-button { + padding: 0; +} + +/* Any text-button which is a real button, unlike Slider label */ +.text-button.button { + padding: 4px; +} + +.separator { + color: #363636; +} + +GtkProgressBar { + -GtkProgressBar-min-vertical-bar-width: 10; + -GtkProgressBar-min-horizontal-bar-height: 10; +} + +GtkDrawingArea { + border-radius: 0; + background-color: #363636; + border: 1px solid #252525; +} + +GtkDrawingArea:selected { + background-color: #565656; + border-radius: 10px; +} + +GtkImage { + padding: 1px; +} + +/* Vertical group of buttons in 1 column */ +GtkButton.Top { + border-radius: 10px 4px 0 0; + border-style: solid solid none solid; + margin-bottom: 0; +} +GtkButton.MiddleV { + border-radius: 0; + border-style: none solid none solid; + margin-top: 0; + margin-bottom: 0; +} +GtkButton.Bottom { + border-radius: 0 0 4px 4px; + border-style: none solid solid solid; + margin-top: 0; +} +/* end */ + +/* Horizontal group of buttons in 1 row */ +GtkButton.Left { + border-radius: 4px 0 0 4px; + border-style: solid none solid solid; + margin-right: 0; +} +GtkButton.MiddleH { + border-radius: 0; + border-style: solid none solid none; + margin-left: 0; + margin-right: 0; +} +GtkButton.Right { + border-radius: 0 4px 4px 0; + border-style: solid solid solid none; + margin-left: 0; +} +/* end */ + +/* [1.23[-][+]] */ +GtkEntry, GtkSpinButton { + padding: 1px; + background-color: #262626; +} + +GtkEntry:insensitive, GtkSpinButton:insensitive { + background-color: #363636; +} + +GtkEntry:hover, GtkSpinButton:hover { + background-color: #565656; +} + +GtkEntry:selected { + color: #262626; + background-color: #AAAAAA; +} + +/* Context menus */ +GtkMenu { + background-color: #262626; + color: #909090; +} + +/* Context menu item */ +.menuitem { + padding: 2px; +} + +#MyExpander { + margin: 10px; + padding: 5px; +} + +/* Tool background */ +#ExpanderBox { + background-color: #363636; + border-width: 1px; + border-style: solid; + border-radius: 4px; + border-color: #252525; + margin: 9px; + padding: 4px; +} + +#ExpanderBox GtkDrawingArea { + background-color: #363636; +} + +#ExpanderBox GtkFrame { + background-color: #3B3B3B; + border-style: solid; + border-width: 1px; + border-radius: 4px; + border-color: #313131; + margin: 3px; + padding: 2px; +} + +#ExpanderBox GtkFrame GtkDrawingArea { + background-color: #3B3B3B; +} + +#ExpanderBox GtkFrame GtkFrame { + background-color: #414141; + border: 1px solid #373737; + border-radius: 4px; + margin: 3px; + padding: 2px; +} + +#ExpanderBox GtkFrame GtkFrame GtkDrawingArea { + background-color: #414141; +} + +/* Sub-tool (MyExpander) background */ +#ExpanderBox2 { + background-color: #3B3B3B; + border: 1px solid #2A2A2A; + border-radius: 4px; + margin: 9px; + padding: 4px; +} + +#ExpanderBox2 GtkDrawingArea { + background-color: #3B3B3B; +} + +#ExpanderBox2 GtkFrame { + background-color: #414141; + border: 1px solid #373737; + border-radius: 4px; + margin: 3px; + padding: 2px; +} + +#ExpanderBox2 GtkFrame GtkDrawingArea { + background-color: #414141; +} + +#ExpanderBox2 GtkFrame GtkFrame { + background-color: #474747; + border: 1px solid #3D3D3D; + border-radius: 4px; + margin: 3px; + padding: 2px; +} + +#ExpanderBox2 GtkFrame GtkFrame GtkDrawingArea { + background-color: #474747; +} + +#MyExpanderTitle { + margin: 5px; + padding: 3px 1px 3px 1px; + font-size: 120%; +} +#MyExpanderTitle GtkLabel { + color: #CCCCCC; +} +#MyExpanderTitle:hover { + background-color: #202020; +} +#MyExpanderTitle GtkEventBox:hover GtkImage { + background-color: #202020; + border-radius: 3px; +} +#MyExpanderTitle:hover GtkLabel { + color: #D8D8D8; +} + +#ExpanderBox2 GtkSeparator, #ExpanderBox3 GtkSeparator { + color: #292929; +} + +/* Editor tab button */ +#MainNotebook > GtkGrid GtkLabel, #MainNotebook > GtkGrid GtkImage { + /* OK */ + padding: 1px; +} + +/* File Browser right side tabs - Toolbox, Inspector, Fast Export, Filter */ +GtkNotebook tab { + background-color: #383838; + border-width: 1px; + border-style: none; + border-color: #262626; + border-radius: 0; + padding: 3px; +} + +GtkNotebook tab:hover { + background-color: #505050; +} + +GtkNotebook tab:active { + border-width: 5px; + border-color: #989898; +} + +/* Get rid of shitty notebook header shadow */ +GtkNotebook.top tab { + border-bottom-style: solid; + padding-bottom: 8px; +} +GtkNotebook.right tab { + border-left-style: solid; + padding-left: 8px; +} +GtkNotebook.bottom tab { + border-top-style: solid; + padding-top: 8px; +} +GtkNotebook.left tab { + border-right-style: solid; + padding-right: 8px; +} + +/* Get rid of notebook frame border - too many borders */ +GtkNotebook.top.header, GtkNotebook.right.header, GtkNotebook.bottom.header, GtkNotebook.left.header { + box-shadow: none; + border-width: 1px; + border-color: #262626; + border-style: none; + border-radius: 0; + background-color: #383838; + padding: 0; +} +/* Get rid of notebook header border - too many borders */ +GtkNotebook.top.header { + /* OK */ + border-bottom-style: solid; +} +GtkNotebook.right.header { + /* OK */ + border-left-style: solid; +} +GtkNotebook.bottom.header { + /* OK */ + border-top-style: solid; +} +GtkNotebook.left.header { + /* OK */ + border-right-style: solid; +} +GtkNotebook.frame { + /* OK */ + border-radius: 0; + border-style: none; +} + +/* Pad notebooks, makes the other borders look nicer */ +GtkNotebook { + /* OK */ + background-color: #484848; + padding: 0; +} + + +#MainNotebook.header { + /* OK */ + background-color: #2A2A2A; +} +#MainNotebook > tab { + /* OK */ + background-color: #2A2A2A; +} +#MainNotebook > tab:hover { + /* OK */ + background-color: #505050; +} +#MainNotebook > tab:active { + /* OK */ + border-color: #989898; +} + +#RightNotebook.header { + /* OK */ + background-color: #2A2A2A; +} +#RightNotebook > tab { + /* OK */ + background-color: #2A2A2A; +} +#RightNotebook > tab:hover { + /* OK */ + background-color: #505050; +} +#RightNotebook > tab:active { + /* OK */ + border-color: #989898; +} + + +/* All tool panels have a frame except for Meta which unlike the rest is a notebook itself. + * So we use CSS to make it look like a frame. */ +#MetaPanelNotebook.frame { + border: 1px solid #262626; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-top-width: 0; +} + +#MetaPanelNotebook.header { + border: 1px solid #262626; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-width: 0; + padding: 5px; + margin: 5px; +} + +.tooltip { + padding: 0; +} diff --git a/rtgui/main.cc b/rtgui/main.cc index 1933939f8..c984b4632 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -56,7 +56,6 @@ Glib::ustring creditsPath; Glib::ustring licensePath; Glib::ustring argv1; bool simpleEditor; -Glib::RefPtr cssForced; Glib::RefPtr cssRT; //Glib::Threads::Thread* mainThread; @@ -313,7 +312,13 @@ int main(int argc, char **argv) Glib::ustring filename = Glib::build_filename(argv0, "themes", options.theme + ".css"); if (!Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - options.theme = "RawTherapee"; + options.theme = "RawTherapee-GTK"; + // We're not testing GTK_MAJOR_VERSION == 3 here, since this branch requires Gtk3 only + if (GTK_MINOR_VERSION < 20) { + options.theme = options.theme + "3-_19"; + } else { + options.theme = options.theme + "3-20_"; + } filename = Glib::build_filename(argv0, "themes", options.theme + ".css"); } cssRT = Gtk::CssProvider::create(); diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 2be4cecd3..efc5d3972 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -41,6 +41,8 @@ Preferences::Preferences (RTWindow *rtwindow) , parent (rtwindow) , splash (nullptr) { + regex = Glib::Regex::create("^(.+)-GTK3-(\\d{1,2})?_(\\d{1,2})?\\.css$", Glib::RegexCompileFlags::REGEX_CASELESS); + moptions.copyFrom (&options); /* @@ -100,6 +102,19 @@ Preferences::~Preferences () options.preferencesHeight = get_height(); } +int Preferences::getThemeRowNumber(Glib::ustring& longThemeFName) +{ + + if (regex->match(longThemeFName + ".css", matchInfo)) { + for (size_t i=0 ; iset_active (0); - std::vector themes; - parseDir (argv0 + "/themes", themes, ".css"); + parseThemeDir (Glib::build_filename(argv0, "themes")); - for (size_t i = 0; i < themes.size(); i++) { - theme->append (themes[i]); + for (size_t i = 0; i < themeFNames.size(); i++) { + theme->append (themeFNames.at(i).shortFName); } themeGrid->attach_next_to(*themelab, Gtk::POS_LEFT, 1, 1); @@ -1337,6 +1351,59 @@ void Preferences::parseDir (Glib::ustring dirname, std::vector& i delete dir; } +void Preferences::parseThemeDir (Glib::ustring dirname) +{ + + if (dirname.empty()) { + return; + } + + // process directory + Glib::Dir* dir = nullptr; + + try { + dir = new Glib::Dir (dirname); + } catch (const Glib::Error& e) { + return; + } + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { + Glib::ustring fname = Glib::build_filename(dirname, *i); + Glib::ustring sname = *i; + + bool keepIt = false; + + // ignore directories and filter out unsupported theme + if (regex->match(sname, matchInfo) && !Glib::file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= 4) { + Glib::ustring fname2 = matchInfo.fetch(1); + Glib::ustring minMinor = matchInfo.fetch(2); + Glib::ustring maxMinor = matchInfo.fetch(3); + + if (!minMinor.empty()) { + guint64 minMinorVal = g_ascii_strtoll(minMinor.c_str(), 0, 0); + if ((guint64)GTK_MINOR_VERSION >= minMinorVal) { + keepIt = true; + } + } + if (!maxMinor.empty()) { + guint64 maxMinorVal = g_ascii_strtoll(maxMinor.c_str(), 0, 0); + if ((guint64)GTK_MINOR_VERSION <= maxMinorVal) { + keepIt = true; + } + } + if (keepIt) { + themeFNames.push_back(ThemeFilename(matchInfo.fetch(1), sname.substr(0, sname.size() - 4))); + } + } + } + std::sort(themeFNames.begin(), themeFNames.end(), [] (const ThemeFilename& firstDir, const ThemeFilename& secondDir) + { + return firstDir.longFName < secondDir.longFName; + }); + + delete dir; +} + void Preferences::storePreferences () { @@ -1369,7 +1436,7 @@ void Preferences::storePreferences () moptions.shadowThreshold = (int)shThresh->get_value (); moptions.language = languages->get_active_text (); moptions.languageAutoDetect = ckbLangAutoDetect->get_active (); - moptions.theme = theme->get_active_text (); + moptions.theme = themeFNames.at(theme->get_active_row_number ()).longFName; Gdk::RGBA cropCol = butCropCol->get_rgba(); moptions.cutOverlayBrush[0] = cropCol.get_red(); @@ -1585,7 +1652,8 @@ void Preferences::fillPreferences () ckbHistogramWorking->set_active (moptions.rtSettings.HistogramWorking); languages->set_active_text (moptions.language); ckbLangAutoDetect->set_active (moptions.languageAutoDetect); - theme->set_active_text (moptions.theme); + int themeNbr = getThemeRowNumber(moptions.theme); + theme->set_active (themeNbr==-1 ? 0 : themeNbr); Gdk::RGBA cropCol; cropCol.set_rgba(moptions.cutOverlayBrush[0], moptions.cutOverlayBrush[1], moptions.cutOverlayBrush[2]); @@ -1783,7 +1851,7 @@ void Preferences::okPressed () void Preferences::cancelPressed () { // set the initial theme back - if (theme->get_active_text() != options.theme) { + if (themeFNames.at(theme->get_active_row_number ()).longFName != options.theme) { RTImage::setPaths(options); RTImage::updateImages(); switchThemeTo(options.theme); @@ -1830,10 +1898,10 @@ void Preferences::aboutPressed () void Preferences::themeChanged () { - moptions.theme = theme->get_active_text (); + moptions.theme = themeFNames.at(theme->get_active_row_number ()).longFName; RTImage::setPaths(moptions); RTImage::updateImages(); - switchThemeTo(theme->get_active_text ()); + switchThemeTo(moptions.theme); } void Preferences::forRAWComboChanged () @@ -1961,10 +2029,12 @@ void Preferences::restoreValue() void Preferences::switchThemeTo(Glib::ustring newTheme) { - Glib::ustring filename(argv0 + "/themes/" + newTheme + ".css"); + Glib::ustring filename(Glib::build_filename(argv0, "themes", newTheme + ".css")); if (!css) { css = Gtk::CssProvider::create(); + Glib::RefPtr screen = Gdk::Screen::get_default(); + Gtk::StyleContext::add_provider_for_screen(screen, css, GTK_STYLE_PROVIDER_PRIORITY_USER); } try { diff --git a/rtgui/preferences.h b/rtgui/preferences.h index a1706f954..749b9669b 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -60,11 +60,21 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener add(addsetid); } }; + + class ThemeFilename + { + public: + Glib::ustring shortFName; + Glib::ustring longFName; + + ThemeFilename (Glib::ustring sfname, Glib::ustring lfname) : shortFName(sfname), longFName(lfname) {} + }; + Glib::RefPtr behModel; BehavColumns behavColumns; - - -protected: + std::vector themeFNames; + Glib::RefPtr regex; + Glib::MatchInfo matchInfo; Splash* splash; ProfileStoreComboBox* rprofiles; Gtk::TreeIter currRawRow; // :) @@ -198,6 +208,7 @@ protected: void fillPreferences (); void storePreferences (); void parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext); + void parseThemeDir (Glib::ustring dirname); void updateDFinfos (); void updateFFinfos (); void workflowUpdate(); @@ -210,6 +221,8 @@ protected: void switchThemeTo (Glib::ustring newTheme); bool splashClosed(GdkEventAny* event); + int getThemeRowNumber(Glib::ustring& longThemeFName); + void appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set); Gtk::Widget* getProcParamsPanel ();