diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /src/ui/dialog/startup.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/ui/dialog/startup.cpp | 849 |
1 files changed, 849 insertions, 0 deletions
diff --git a/src/ui/dialog/startup.cpp b/src/ui/dialog/startup.cpp new file mode 100644 index 0000000..21510cf --- /dev/null +++ b/src/ui/dialog/startup.cpp @@ -0,0 +1,849 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * @brief A dialog for the about screen + * + * Copyright (C) Martin Owens 2019 <doctormo@gmail.com> + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "startup.h" + +#include <fstream> +#include <glibmm/i18n.h> +#include <streambuf> +#include <string> + +#include "color-rgba.h" +#include "file.h" +#include "inkscape-application.h" +#include "inkscape-version-info.h" +#include "inkscape-version.h" +#include "inkscape.h" +#include "io/resource.h" +#include "object/sp-namedview.h" +#include "preferences.h" +#include "ui/dialog/filedialog.h" +#include "ui/shortcuts.h" +#include "ui/themes.h" +#include "ui/util.h" +#include "util/units.h" + +using namespace Inkscape::IO; +using namespace Inkscape::UI::View; +using Inkscape::Util::unit_table; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class NameIdCols: public Gtk::TreeModel::ColumnRecord { + public: + // These types must match those for the model in the .glade file + NameIdCols() { + this->add(this->col_name); + this->add(this->col_id); + } + Gtk::TreeModelColumn<Glib::ustring> col_name; + Gtk::TreeModelColumn<Glib::ustring> col_id; +}; + +class CanvasCols: public Gtk::TreeModel::ColumnRecord { + public: + // These types must match those for the model in the .glade file + CanvasCols() { + this->add(this->id); + this->add(this->name); + this->add(this->icon_filename); + this->add(this->pagecolor); + this->add(this->checkered); + this->add(this->bordercolor); + this->add(this->shadow); + } + Gtk::TreeModelColumn<Glib::ustring> id; + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> icon_filename; + Gtk::TreeModelColumn<Glib::ustring> pagecolor; + Gtk::TreeModelColumn<bool> checkered; + Gtk::TreeModelColumn<Glib::ustring> bordercolor; + Gtk::TreeModelColumn<bool> shadow; +}; + +class TemplateCols: public Gtk::TreeModel::ColumnRecord { + public: + // These types must match those for the model in the .glade file + TemplateCols() { + this->add(this->name); + this->add(this->icon); + this->add(this->filename); + this->add(this->width); + this->add(this->height); + } + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> icon; + Gtk::TreeModelColumn<Glib::ustring> filename; + Gtk::TreeModelColumn<Glib::ustring> width; + Gtk::TreeModelColumn<Glib::ustring> height; +}; + + +class ThemeCols: public Gtk::TreeModel::ColumnRecord { + public: + // These types must match those for the model in the .glade file + ThemeCols() { + this->add(this->id); + this->add(this->name); + this->add(this->theme); + this->add(this->icons); + this->add(this->base); + this->add(this->base_dark); + this->add(this->success); + this->add(this->warn); + this->add(this->error); + this->add(this->symbolic); + this->add(this->smallicons); + this->add(this->enabled); + } + Gtk::TreeModelColumn<Glib::ustring> id; + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> theme; + Gtk::TreeModelColumn<Glib::ustring> icons; + Gtk::TreeModelColumn<Glib::ustring> base; + Gtk::TreeModelColumn<Glib::ustring> base_dark; + Gtk::TreeModelColumn<Glib::ustring> success; + Gtk::TreeModelColumn<Glib::ustring> warn; + Gtk::TreeModelColumn<Glib::ustring> error; + Gtk::TreeModelColumn<bool> symbolic; + Gtk::TreeModelColumn<bool> smallicons; + Gtk::TreeModelColumn<bool> enabled; +}; + +/** + * Color is store as a string in the form #RRGGBBAA, '0' means "unset" + * + * @param color - The string color from glade. + */ +unsigned int get_color_value(const Glib::ustring color) +{ + Gdk::RGBA gdk_color = Gdk::RGBA(color); + ColorRGBA sp_color(gdk_color.get_red(), gdk_color.get_green(), + gdk_color.get_blue(), gdk_color.get_alpha()); + return sp_color.getIntValue(); +} + +StartScreen::StartScreen() + : Gtk::Dialog() +{ + set_can_focus(true); + grab_focus(); + set_can_default(true); + grab_default(); + set_urgency_hint(true); // Draw user's attention to this window! + set_modal(true); + set_position(Gtk::WIN_POS_CENTER_ALWAYS); + set_default_size(700, 360); + + Glib::ustring gladefile = Resource::get_filename(Resource::UIS, "inkscape-start.glade"); + + try { + builder = Gtk::Builder::create_from_file(gladefile); + } catch (const Glib::Error &ex) { + g_error("Glade file loading failed for boot screen"); + // cleanup? + } + + // Get window from Glade file. + builder->get_widget("start-screen-window", window); + set_name("start-screen-window"); + set_title(Inkscape::inkscape_version()); + + // Get references to various widgets used globally. + builder->get_widget("tabs", tabs); + builder->get_widget("kinds", kinds); + builder->get_widget("banner", banners); + builder->get_widget("themes", themes); + builder->get_widget("recent_treeview", recent_treeview); + + // Get references to various widget used locally. (In order of appearance.) + Gtk::ComboBox* canvas = nullptr; + Gtk::ComboBox* keys = nullptr; + Gtk::Button* save = nullptr; + Gtk::Button* thanks = nullptr; + Gtk::Button* close_btn = nullptr; + Gtk::Button* new_btn = nullptr; + Gtk::Button* show_toggle = nullptr; + Gtk::Switch* dark_toggle = nullptr; + builder->get_widget("canvas", canvas); + builder->get_widget("keys", keys); + builder->get_widget("save", save); + builder->get_widget("thanks", thanks); + builder->get_widget("show_toggle", show_toggle); + builder->get_widget("dark_toggle", dark_toggle); + builder->get_widget("load", load_btn); + builder->get_widget("new", new_btn); + builder->get_widget("close_window", close_btn); + + // Unparent to move to our dialog window. + auto parent = banners->get_parent(); + parent->remove(*banners); + parent->remove(*tabs); + + // Add signals and setup things. + auto prefs = Inkscape::Preferences::get(); + + tabs->signal_switch_page().connect(sigc::mem_fun(*this, &StartScreen::notebook_switch)); + + // Setup the lists of items + enlist_recent_files(); + enlist_keys(); + filter_themes(); + set_active_combo("themes", prefs->getString("/options/boot/theme")); + set_active_combo("canvas", prefs->getString("/options/boot/canvas")); + + // initialise dark depending on prefs and background + refresh_dark_switch(); + + // Welcome! tab + std::string welcome_text_file = Resource::get_filename_string(Resource::SCREENS, "start-welcome-text.svg", true); + Gtk::Image *welcome_text; + builder->get_widget("welcome_text", welcome_text); + welcome_text->set(welcome_text_file); + + canvas->signal_changed().connect(sigc::mem_fun(*this, &StartScreen::canvas_changed)); + keys->signal_changed().connect(sigc::mem_fun(*this, &StartScreen::keyboard_changed)); + themes->signal_changed().connect(sigc::mem_fun(*this, &StartScreen::theme_changed)); + dark_toggle->property_active().signal_changed().connect(sigc::mem_fun(*this, &StartScreen::theme_changed)); + save->signal_clicked().connect(sigc::bind<Gtk::Button *>(sigc::mem_fun(*this, &StartScreen::notebook_next), save)); + + // "Supported by You" tab + thanks->signal_clicked().connect(sigc::bind<Gtk::Button *>(sigc::mem_fun(*this, &StartScreen::notebook_next), thanks)); + + // "Time to Draw" tab + recent_treeview->signal_row_activated().connect(sigc::hide(sigc::hide((sigc::mem_fun(*this, &StartScreen::load_document))))); + recent_treeview->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &StartScreen::on_recent_changed)); + kinds->signal_switch_page().connect(sigc::mem_fun(*this, &StartScreen::on_kind_changed)); + load_btn->set_sensitive(true); + + for (auto widget : kinds->get_children()) { + auto container = dynamic_cast<Gtk::Container *>(widget); + if (container) { + widget = container->get_children()[0]; + } + auto template_list = dynamic_cast<Gtk::IconView *>(widget); + if (template_list) { + template_list->signal_selection_changed().connect([=]() { response(GTK_RESPONSE_APPLY); }); + } + } + + show_toggle->signal_clicked().connect(sigc::mem_fun(*this, &StartScreen::show_toggle)); + load_btn->signal_clicked().connect(sigc::mem_fun(*this, &StartScreen::load_document)); + new_btn->signal_clicked().connect([=] { response(GTK_RESPONSE_APPLY); }); + close_btn->signal_clicked().connect([=] { response(GTK_RESPONSE_CANCEL); }); + + // Reparent to our dialog window + set_titlebar(*banners); + Gtk::Box* box = get_content_area(); + box->add(*tabs); + + // Show the first tab ONLY on the first run for this version + std::string opt_shown = "/options/boot/shown/ver"; + opt_shown += Inkscape::version_string_without_revision; + _first_open = prefs->getBool(opt_shown, false); + if(!_first_open) { + theme_changed(); + tabs->set_current_page(0); + prefs->setBool(opt_shown, true); + } else { + tabs->set_current_page(2); + notebook_switch(nullptr, 2); + } + + set_modal(true); + set_position(Gtk::WIN_POS_CENTER_ALWAYS); + property_resizable() = false; + set_default_size(700, 360); + show(); +} + +StartScreen::~StartScreen() +{ + // These are "owned" by builder... don't delete them! + banners->get_parent()->remove(*banners); + tabs->get_parent()->remove(*tabs); +} + +/** + * Return the active row of the named combo box. + * + * @param widget_name - The name of the widget in the glade file + * @return Gtk Row object ready for use. + * @throws Three errors depending on where it failed. + */ +Gtk::TreeModel::Row +StartScreen::active_combo(std::string widget_name) +{ + Gtk::ComboBox *combo; + builder->get_widget(widget_name, combo); + if (!combo) throw 1; + Gtk::TreeModel::iterator iter = combo->get_active(); + if (!iter) throw 2; + Gtk::TreeModel::Row row = *iter; + if (!row) throw 3; + return row; +} + +/** + * Set the active item in the combo based on the unique_id (column set in glade) + * + * @param widget_name - The name of the widget in the glade file + * @param unique_id - The column id to activate, sets to first item if blank. + */ +void +StartScreen::set_active_combo(std::string widget_name, std::string unique_id) +{ + Gtk::ComboBox *combo; + builder->get_widget(widget_name, combo); + if (combo) { + if (unique_id.empty()) { + combo->set_active(0); // Select the first + } else if(!combo->set_active_id(unique_id)) { + combo->set_active(-1); // Select nothing + } + } +} + +/** + * When a notbook is switched, reveal the right banner image (gtk signal). + */ +void +StartScreen::notebook_switch(Gtk::Widget *tab, guint page_num) +{ + int page = 0; + for (auto banner : banners->get_children()) { + if (auto revealer = dynamic_cast<Gtk::Revealer *>(banner)) { + revealer->set_reveal_child(page == page_num); + page++; + } + } +} + +void +StartScreen::enlist_recent_files() +{ + NameIdCols cols; + if (!recent_treeview) return; + // We're not sure why we have to ask C for the TreeStore object + auto store = Glib::wrap(GTK_LIST_STORE(gtk_tree_view_get_model(recent_treeview->gobj()))); + store->clear(); + + // Open [other] + Gtk::TreeModel::Row first_row = *(store->append()); + first_row[cols.col_name] = _("Browse for other files..."); + first_row[cols.col_id] = ""; + recent_treeview->get_selection()->select(store->get_path(first_row)); + + Glib::RefPtr<Gtk::RecentManager> manager = Gtk::RecentManager::get_default(); + for (auto item : manager->get_items()) { + if (item->has_application(g_get_prgname()) + || item->has_application("org.inkscape.Inkscape") + || item->has_application("inkscape") + || item->has_application("inkscape.exe") + ) { + // This uri is a GVFS uri, so parse it with that or it will fail. + auto file = Gio::File::create_for_uri(item->get_uri()); + std::string path = file->get_path(); + if (!path.empty() && Glib::file_test(path, Glib::FILE_TEST_IS_REGULAR) + && item->get_mime_type() == "image/svg+xml") { + Gtk::TreeModel::Row row = *(store->append()); + row[cols.col_name] = item->get_display_name(); + row[cols.col_id] = item->get_uri(); + } + } + } +} + +/** + * Called when a new recent document is selected. + */ +void +StartScreen::on_recent_changed() +{ + // TODO: In the future this is where previews and other information can be loaded. +} + +/** + * Called when the left side tabs are changed. + */ +void +StartScreen::on_kind_changed(Gtk::Widget *tab, guint page_num) +{ + if (page_num == 0) { + load_btn->show(); + } else { + load_btn->hide(); + } +} + +/** + * Called when new button clicked or template is double clicked, or escape pressed. + */ +void +StartScreen::new_document() +{ + Glib::ustring filename = sp_file_default_template_uri(); + Glib::ustring width = ""; + Glib::ustring height = ""; + + // Find requested file name. + Glib::RefPtr<Gio::File> file; + if (kinds) { + Gtk::Widget *selected_widget = kinds->get_children()[kinds->get_current_page()]; + auto container = dynamic_cast<Gtk::Container *>(selected_widget); + if (container) { + selected_widget = container->get_children()[0]; + } + + auto template_list = dynamic_cast<Gtk::IconView *>(selected_widget); + if (template_list) { + auto items = template_list->get_selected_items(); + if (!items.empty()) { + auto iter = template_list->get_model()->get_iter(items[0]); + Gtk::TreeModel::Row row = *iter; + if (row) { + TemplateCols cols; + Glib::ustring template_filename = row[cols.filename]; + if (!(template_filename == "-")) { + filename = Resource::get_filename_string( + Resource::TEMPLATES, template_filename.c_str(), true); + } + // This isn't used on opening, just for checking it's existence. + file = Gio::File::create_for_path(filename); + width = row[cols.width]; + height = row[cols.height]; + } + } + } + } + + if (!file) { + // Failure to open, so open up a new document instead. + file = Gio::File::create_for_path(filename); + } + + if (!file) { + // We're really messed up... so give up! + std::cerr << "StartScreen::load_document(): Failed to find: " << filename << std::endl; + return; + } + + // Now we have filename, open document. + auto app = InkscapeApplication::instance(); + + // If it was a template file, modify the document according to user's input. + _document = app->document_new (filename); + auto nv = _document->getNamedView(); + + if (!width.empty()) { + // Set the width, height and default display units for the selected template + auto q_width = unit_table.parseQuantity(width); + _document->setWidthAndHeight(q_width, unit_table.parseQuantity(height), true); + nv->setAttribute("inkscape:document-units", q_width.unit->abbr); + _document->setDocumentScale(1.0); + } + + DocumentUndo::clearUndo(_document); + _document->setModifiedSinceSave(false); +} + +/** + * Called when load button clicked. + */ +void +StartScreen::load_document() +{ + NameIdCols cols; + auto prefs = Inkscape::Preferences::get(); + auto app = InkscapeApplication::instance(); + + if (!recent_treeview) + return; + + auto iter = recent_treeview->get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + if (row) { + Glib::ustring _file = row[cols.col_id]; + Glib::RefPtr<Gio::File> file; + + if (!_file.empty()) { + file = Gio::File::create_for_uri(_file); + } else { + Glib::ustring open_path = prefs->getString("/dialogs/open/path"); + if (open_path.empty()) { + open_path = g_get_home_dir(); + open_path.append(G_DIR_SEPARATOR_S); + } + + // Browse for file instead + auto browser = Inkscape::UI::Dialog::FileOpenDialog::create( + *this, open_path, Inkscape::UI::Dialog::SVG_TYPES, _("Open a different file")); + + if (browser->show()) { + prefs->setString("/dialogs/open/path", browser->getCurrentDirectory()); + file = Gio::File::create_for_path(browser->getFilename()); + delete browser; + } else { + delete browser; + return; // Cancel + } + } + + // Now we have filename, open document. + bool canceled = false; + _document = app->document_open(file, &canceled); + + if (!canceled && _document) { + // We're done, hand back to app. + response(GTK_RESPONSE_OK); + } + } + } +} + +/** + * When a button needs to go to the next notebook page. + */ +void +StartScreen::notebook_next(Gtk::Widget *button) +{ + int page = tabs->get_current_page(); + if (page == 2) { + response(GTK_RESPONSE_CANCEL); // Only occurs from keypress. + } else { + tabs->set_current_page(page + 1); + } +} + +/** + * When a key is pressed in the main window. + */ +bool +StartScreen::on_key_press_event(GdkEventKey* event) +{ +#ifdef GDK_WINDOWING_QUARTZ + // On macOS only, if user press Cmd+Q => exit + if (event->keyval == 'q' && event->state == (GDK_MOD2_MASK | GDK_META_MASK)) { + close(); + return false; + } +#endif + switch (event->keyval) { + case GDK_KEY_Escape: + // Prevent loading any selected items + response(GTK_RESPONSE_CANCEL); + return true; + case GDK_KEY_Return: + notebook_next(nullptr); + return true; + } + + return false; +} + +void +StartScreen::on_response(int response_id) +{ + if (response_id == GTK_RESPONSE_DELETE_EVENT) { + // Don't open a window for force closing. + return; + } + if (response_id == GTK_RESPONSE_CANCEL) { + kinds = nullptr; + if (_first_open) { + // Disable the screen if the user cancels on their first run. + auto prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/boot/enabled", false); + } + } + if (response_id != GTK_RESPONSE_OK) { + // Most actions cause a new document to appear. + new_document(); + } +} + +void +StartScreen::show_toggle() +{ + Gtk::ToggleButton *button; + builder->get_widget("show_toggle", button); + if (button) { + auto prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/boot/enabled", button->get_active()); + } else { + g_warning("Can't find toggle button widget."); + } +} + +/** + * Refresh theme in-place so user can see a semi-preview. This theme selection + * is not meant to be perfect, but hint to the user that they can set the + * theme if they want. + * + * @param theme_name - The name of the theme to load. + */ +void +StartScreen::refresh_theme(Glib::ustring theme_name) +{ + auto const screen = Gdk::Screen::get_default(); + if (INKSCAPE.themecontext->getContrastThemeProvider()) { + Gtk::StyleContext::remove_provider_for_screen(screen, INKSCAPE.themecontext->getContrastThemeProvider()); + } + auto settings = Gtk::Settings::get_default(); + + auto prefs = Inkscape::Preferences::get(); + + settings->property_gtk_theme_name() = theme_name; + settings->property_gtk_application_prefer_dark_theme() = prefs->getBool("/theme/preferDarkTheme", true); + settings->property_gtk_icon_theme_name() = prefs->getString("/theme/iconTheme", prefs->getString("/theme/defaultIconTheme", "")); + + if (prefs->getBool("/theme/symbolicIcons", false)) { + get_style_context()->add_class("symbolic"); + get_style_context()->remove_class("regular"); + } else { + get_style_context()->add_class("regular"); + get_style_context()->remove_class("symbolic"); + } + + if (INKSCAPE.themecontext->getColorizeProvider()) { + Gtk::StyleContext::remove_provider_for_screen(screen, INKSCAPE.themecontext->getColorizeProvider()); + } + if (!prefs->getBool("/theme/symbolicDefaultHighColors", false)) { + Gtk::CssProvider::create(); + Glib::ustring css_str = INKSCAPE.themecontext->get_symbolic_colors(); + try { + INKSCAPE.themecontext->getColorizeProvider()->load_from_data(css_str); + } catch (const Gtk::CssProviderError &ex) { + g_critical("CSSProviderError::load_from_data(): failed to load '%s'\n(%s)", css_str.c_str(), ex.what().c_str()); + } + Gtk::StyleContext::add_provider_for_screen(screen, INKSCAPE.themecontext->getColorizeProvider(), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + // set dark switch and disable if there is no prefer option for dark + refresh_dark_switch(); + + INKSCAPE.themecontext->getChangeThemeSignal().emit(); +} + +/** + * Set the theme, icon pack and other theme options from a set defined + * in the glade file. The combo box has a number of columns with the needed + * data describing how to set up the theme. + */ +void +StartScreen::theme_changed() +{ + auto prefs = Inkscape::Preferences::get(); + + ThemeCols cols; + try { + auto row = active_combo("themes"); + Glib::ustring theme_id = row[cols.id]; + if (theme_id == "custom") return; + prefs->setString("/options/boot/theme", row[cols.id]); + + // Update theme from combo. + Glib::ustring icons = row[cols.icons]; + prefs->setBool("/toolbox/tools/small", row[cols.smallicons]); + prefs->setString("/theme/gtkTheme", row[cols.theme]); + prefs->setString("/theme/iconTheme", icons); + prefs->setBool("/theme/symbolicIcons", row[cols.symbolic]); + + Gtk::Switch* dark_toggle = nullptr; + builder->get_widget("dark_toggle", dark_toggle); + bool is_dark = dark_toggle->get_active(); + prefs->setBool("/theme/preferDarkTheme", is_dark); + prefs->setBool("/theme/darkTheme", is_dark); + // Symbolic icon colours + if (get_color_value(row[cols.base]) == 0) { + prefs->setBool("/theme/symbolicDefaultBaseColors", true); + prefs->setBool("/theme/symbolicDefaultHighColors", true); + } else { + Glib::ustring prefix = "/theme/" + icons; + prefs->setBool("/theme/symbolicDefaultBaseColors", false); + prefs->setBool("/theme/symbolicDefaultHighColors", false); + if (is_dark) { + prefs->setUInt(prefix + "/symbolicBaseColor", get_color_value(row[cols.base_dark])); + } else { + prefs->setUInt(prefix + "/symbolicBaseColor", get_color_value(row[cols.base])); + } + prefs->setUInt(prefix + "/symbolicSuccessColor", get_color_value(row[cols.success])); + prefs->setUInt(prefix + "/symbolicWarningColor", get_color_value(row[cols.warn])); + prefs->setUInt(prefix + "/symbolicErrorColor", get_color_value(row[cols.error])); + } + + refresh_theme(prefs->getString("/theme/gtkTheme", prefs->getString("/theme/defaultGtkTheme", ""))); + } catch(int e) { + g_warning("Couldn't find theme value."); + } +} + +/** + * Called when the canvas dropdown changes. + */ +void +StartScreen::canvas_changed() +{ + CanvasCols cols; + try { + auto row = active_combo("canvas"); + + auto prefs = Inkscape::Preferences::get(); + prefs->setString("/options/boot/canvas", row[cols.id]); + + Gdk::RGBA gdk_color = Gdk::RGBA(row[cols.pagecolor]); + SPColor sp_color(gdk_color.get_red(), gdk_color.get_green(), gdk_color.get_blue()); + prefs->setString("/template/base/pagecolor", sp_color.toString()); + prefs->setDouble("/template/base/pageopacity", gdk_color.get_alpha()); + + Gdk::RGBA gdk_border = Gdk::RGBA(row[cols.bordercolor]); + SPColor sp_border(gdk_border.get_red(), gdk_border.get_green(), gdk_border.get_blue()); + prefs->setString("/template/base/bordercolor", sp_border.toString()); + prefs->setDouble("/template/base/borderopacity", gdk_border.get_alpha()); + + prefs->setBool("/template/base/pagecheckerboard", row[cols.checkered]); + prefs->setInt("/template/base/pageshadow", row[cols.shadow] ? 2 : 0); + + } catch(int e) { + g_warning("Couldn't find canvas value."); + } +} + +void +StartScreen::filter_themes() +{ + ThemeCols cols; + // We need to disable themes which aren't available. + auto store = Glib::wrap(GTK_LIST_STORE(gtk_combo_box_get_model(themes->gobj()))); + auto available = INKSCAPE.themecontext->get_available_themes(); + + // Detect use of custom theme here, detect defaults used in many systems. + auto settings = Gtk::Settings::get_default(); + Glib::ustring theme_name = settings->property_gtk_theme_name(); + Glib::ustring icons_name = settings->property_gtk_icon_theme_name(); + + bool has_system_theme = false; + if (theme_name != "Adwaita" || icons_name != "hicolor") { + has_system_theme = true; + /* Enable if/when we want custom to be the default. + if (prefs->getString("/options/boot/theme").empty()) { + prefs->setString("/options/boot/theme", "system") + theme_changed(); + }*/ + } + + for(auto row : store->children()) { + Glib::ustring theme = row[cols.theme]; + if (!row[cols.enabled]) { + // Available themes; We only "enable" them, we don't disable them. + row[cols.enabled] = available.find(theme) != available.end(); + } else if(row[cols.id] == "system" && !has_system_theme) { + // Disable system theme option if not available. + row[cols.enabled] = false; + } + } +} + +void +StartScreen::enlist_keys() +{ + NameIdCols cols; + Gtk::ComboBox *keys; + builder->get_widget("keys", keys); + if (!keys) return; + + auto store = Glib::wrap(GTK_LIST_STORE(gtk_combo_box_get_model(keys->gobj()))); + store->clear(); + + for(auto item: Inkscape::Shortcuts::get_file_names()){ + Gtk::TreeModel::Row row = *(store->append()); + row[cols.col_name] = item.first; + row[cols.col_id] = item.second; + } + + auto prefs = Inkscape::Preferences::get(); + auto current = prefs->getString("/options/kbshortcuts/shortcutfile"); + if (current.empty()) { + current = "inkscape.xml"; + } + keys->set_active_id(current); +} + +/** + * Set the keys file based on the keys set in the enlist above + */ +void +StartScreen::keyboard_changed() +{ + NameIdCols cols; + try { + auto row = active_combo("keys"); + auto prefs = Inkscape::Preferences::get(); + Glib::ustring set_to = row[cols.col_id]; + prefs->setString("/options/kbshortcuts/shortcutfile", set_to); + Inkscape::Shortcuts::getInstance().init(); + + Gtk::InfoBar* keys_warning; + builder->get_widget("keys_warning", keys_warning); + if (set_to != "inkscape.xml" && set_to != "default.xml") { + keys_warning->set_message_type(Gtk::MessageType::MESSAGE_WARNING); + keys_warning->show(); + } else { + keys_warning->hide(); + } + } catch(int e) { + g_warning("Couldn't find keys value."); + } +} + +/** + * Set Dark Switch based on current selected theme. + * We will disable switch if current theme doesn't have prefer dark theme option. + */ + +void StartScreen::refresh_dark_switch() +{ + auto prefs = Inkscape::Preferences::get(); + + Gtk::Container *window = dynamic_cast<Gtk::Container *>(get_toplevel()); + bool dark = INKSCAPE.themecontext->isCurrentThemeDark(window); + prefs->setBool("/theme/preferDarkTheme", dark); + prefs->setBool("/theme/darkTheme", dark); + + auto themes = INKSCAPE.themecontext->get_available_themes(); + Glib::ustring current_theme = prefs->getString("/theme/gtkTheme", prefs->getString("/theme/defaultGtkTheme", "")); + + Gtk::Switch *dark_toggle = nullptr; + builder->get_widget("dark_toggle", dark_toggle); + + if (!themes[current_theme]) { + dark_toggle->set_sensitive(false); + } else { + dark_toggle->set_sensitive(true); + } + dark_toggle->set_active(dark); +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |