diff --git a/src/config.cc b/src/config.cc index 3cfc808..7aac125 100644 --- a/src/config.cc +++ b/src/config.cc @@ -5,17 +5,25 @@ #include "files.h" #include "sourcefile.h" -//TODO: add try-catch to json-get and get_child -MainConfig::MainConfig(Menu &menu) : menu(menu) { +MainConfig::MainConfig() { find_or_create_config_files(); boost::property_tree::json_parser::read_json(Singleton::config_dir() + "config.json", cfg); + Singleton::Config::window()->keybindings = cfg.get_child("keybindings"); GenerateSource(); - GenerateKeybindings(); + GenerateTheme(); GenerateDirectoryFilter(); - Singleton::Config::terminal()->make_command=cfg.get("project.make_command"); } +void MainConfig::GenerateTheme() { + auto config = Singleton::Config::theme(); + auto props = cfg.get_child("theme"); + for (auto &prop : props) { + if (prop.first == "theme") config->theme = prop.second.get_value(); + if (prop.first == "main") config->main = prop.second.get_value(); + } +} + void MainConfig::find_or_create_config_files() { std::vector files = {"config.json", "menu.xml", "plugins.py"}; boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir())); @@ -30,50 +38,18 @@ void MainConfig::find_or_create_config_files() { } void MainConfig::GenerateSource() { - auto source_cfg=Singleton::Config::source(); - DEBUG("Fetching source cfg"); - // boost::property_tree::ptree + auto source_cfg = Singleton::Config::source(); auto source_json = cfg.get_child("source"); - auto syntax_json = source_json.get_child("syntax"); - auto colors_json = source_json.get_child("colors"); - auto visual_json = source_json.get_child("visual"); - for (auto &i : visual_json) { - if (i.first == "background") - source_cfg->background = i.second.get_value(); - else if (i.first == "background_selected") - source_cfg->background_selected = i.second.get_value(); - else if (i.first == "background_tooltips") - source_cfg->background_tooltips = i.second.get_value(); - else if (i.first == "show_line_numbers") - source_cfg->show_line_numbers = i.second.get_value() == "1" ? true : false; - else if (i.first == "highlight_current_line") - source_cfg->highlight_current_line = i.second.get_value() == "1" ? true : false; - else if (i.first == "font") - source_cfg->font = i.second.get_value(); - } - source_cfg->tab_size = source_json.get("tab_size"); - for (unsigned c = 0; c < source_cfg->tab_size; c++) - source_cfg->tab+=" "; - for (auto &i : colors_json) - source_cfg->tags[i.first]=i.second.get_value(); - for (auto &i : syntax_json) - source_cfg->types[i.first]=i.second.get_value(); - DEBUG("Source cfg fetched"); -} - -void MainConfig::GenerateKeybindings() { - boost::filesystem::path path(Singleton::config_dir() + "menu.xml"); - if (!boost::filesystem::is_regular_file(path)) { - std::cerr << "menu.xml not found" << std::endl; - throw; - } - menu.ui = juci::filesystem::read(path); - boost::property_tree::ptree keys_json = cfg.get_child("keybindings"); - for (auto &i : keys_json) { - auto key=i.second.get_value(); - menu.key_map[i.first] = key; - } - DEBUG("Keybindings fetched"); + auto clang_types_json = source_json.get_child("clang_types"); + auto style_json = source_json.get_child("style"); + auto gsv_json = source_json.get_child("sourceview"); + + for (auto &i : gsv_json) + source_cfg->gsv[i.first] = i.second.get_value(); + for (auto &i : style_json) + source_cfg->tags[i.first] = i.second.get_value(); + for (auto &i : clang_types_json) + source_cfg->types[i.first] = i.second.get_value(); } void MainConfig::GenerateDirectoryFilter() { diff --git a/src/config.h b/src/config.h index 46f5142..4362fb0 100644 --- a/src/config.h +++ b/src/config.h @@ -6,15 +6,13 @@ class MainConfig { public: - MainConfig(Menu &menu); + MainConfig(); void find_or_create_config_files(); void PrintMenu(); void GenerateSource(); - void GenerateKeybindings(); void GenerateDirectoryFilter(); + void GenerateTheme(); private: boost::property_tree::ptree cfg; - boost::property_tree::ptree key_tree; - Menu &menu; }; #endif diff --git a/src/juci.cc b/src/juci.cc index 4cdde32..b95da2d 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -1,5 +1,6 @@ #include "juci.h" #include "singletons.h" +#include "config.h" #include void init_logging() { @@ -9,7 +10,7 @@ void init_logging() { INFO("Logging initalized"); } -int Juci::on_command_line(const Glib::RefPtr &cmd) { +int app::on_command_line(const Glib::RefPtr &cmd) { Glib::set_prgname("juci"); Glib::OptionContext ctx("[PATH ...]"); Glib::OptionGroup gtk_group(gtk_get_option_group(true)); @@ -35,7 +36,7 @@ int Juci::on_command_line(const Glib::RefPtr &cmd) return 0; } -void Juci::on_activate() { +void app::on_activate() { window = std::unique_ptr(new Window()); add_window(*window); window->show(); @@ -46,7 +47,16 @@ void Juci::on_activate() { window->notebook.open(f); } +app::app() : Gtk::Application("no.sout.juci", Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_COMMAND_LINE) { + MainConfig(); // Read the configs here + auto css_provider = Gtk::CssProvider::get_default(); + auto style_context = Gtk::StyleContext::create(); + auto screen = Gdk::Screen::get_default(); + style_context->add_provider_for_screen(screen, css_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + css_provider->load_from_path(Singleton::theme_dir() + Singleton::Config::theme()->current_theme()); +} + int main(int argc, char *argv[]) { init_logging(); - return Juci().run(argc, argv); + return app().run(argc, argv); } diff --git a/src/juci.h b/src/juci.h index 21c4447..2ae8bfe 100644 --- a/src/juci.h +++ b/src/juci.h @@ -3,18 +3,17 @@ #include "window.h" #include "logging.h" - -class Juci : public Gtk::Application { -public: - Juci(): Gtk::Application("no.sout.juci", Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_COMMAND_LINE) {} - +class app : public Gtk::Application { + public: + app(); int on_command_line(const Glib::RefPtr &cmd); void on_activate(); -private: + private: std::unique_ptr window; std::string directory; std::vector files; }; -#endif // JUCI_JUCI_H_ \ No newline at end of file +#endif // JUCI_JUCI_H_ + diff --git a/src/singletons.cc b/src/singletons.cc index 94d1a03..7039985 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -1,10 +1,11 @@ #include "singletons.h" std::unique_ptr Singleton::Config::source_=std::unique_ptr(new Source::Config()); -std::unique_ptr Singleton::Config::directories_=std::unique_ptr(new Directories::Config()); -std::unique_ptr Singleton::Config::terminal_=std::unique_ptr(new Terminal::Config()); - +std::unique_ptr Singleton::Config::directories_=std::unique_ptr(new Directories::Config());std::unique_ptr Singleton::Config::terminal_=std::unique_ptr(new Terminal::Config()); +std::unique_ptr Singleton::Config::theme_ = std::unique_ptr(new Theme::Config()); +std::unique_ptr Singleton::Config::window_ = std::unique_ptr(new Window::Config()); std::unique_ptr Singleton::terminal_=std::unique_ptr(); + Terminal *Singleton::terminal() { if(!terminal_) terminal_=std::unique_ptr(new Terminal()); diff --git a/src/singletons.h b/src/singletons.h index 2a09fc3..f65a3d9 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -1,10 +1,13 @@ + #ifndef JUCI_SINGLETONS_H_ #define JUCI_SINGLETONS_H_ #include "source.h" +#include "window.h" #include "directories.h" #include "terminal.h" #include "notebook.h" +#include "theme.h" #include "menu.h" #include #include @@ -15,14 +18,21 @@ public: public: static Source::Config *source() {return source_.get();} static Directories::Config *directories() {return directories_.get();} + static Theme::Config *theme() { return theme_.get(); } + static Window::Config *window() { return window_.get(); } static Terminal::Config *terminal() {return terminal_.get();} + private: static std::unique_ptr source_; + static std::unique_ptr theme_; + static std::unique_ptr window_; static std::unique_ptr directories_; static std::unique_ptr terminal_; }; static std::string config_dir() { return std::string(getenv("HOME")) + "/.juci/config/"; } + static std::string theme_dir() { return std::string(getenv("HOME")) + "/.juci/gtk-themes/"; } static std::string log_dir() { return std::string(getenv("HOME")) + "/.juci/log/"; } + static std::string style_dir() { return std::string(getenv("HOME")) + "/.juci/styles/"; } static Terminal *terminal(); static Gtk::Label *status(); private: diff --git a/src/source.cc b/src/source.cc index 8c7e322..ca6ca14 100644 --- a/src/source.cc +++ b/src/source.cc @@ -7,6 +7,7 @@ #include #include "singletons.h" #include +#include #include //TODO: remove using namespace std; //TODO: remove @@ -37,13 +38,9 @@ Glib::RefPtr Source::guess_language(const boost::filesystem::path ////////////// Source::View::View(const boost::filesystem::path &file_path): file_path(file_path) { set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); - set_show_line_numbers(Singleton::Config::source()->show_line_numbers); - set_highlight_current_line(Singleton::Config::source()->highlight_current_line); - get_source_buffer()->begin_not_undoable_action(); juci::filesystem::read(file_path, get_buffer()); get_source_buffer()->end_not_undoable_action(); - get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); search_settings = gtk_source_search_settings_new(); gtk_source_search_settings_set_wrap_around(search_settings, true); @@ -58,6 +55,19 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat //TODO: either use lambda if possible or create a gtkmm wrapper around search_context (including search_settings): //TODO: (gtkmm's Gtk::Object has connect_property_changed, so subclassing this might be an idea) g_signal_connect(search_context, "notify::occurrences-count", G_CALLBACK(search_occurrences_updated), this); + + // style + auto style_scheme_manager=Gsv::StyleSchemeManager::get_default(); + style_scheme_manager->prepend_search_path(Singleton::style_dir()); + + auto scheme = style_scheme_manager->get_scheme(Singleton::Config::theme()->theme); + + if(scheme) { + get_source_buffer()->set_style_scheme(scheme); + } + + property_highlight_current_line() = Singleton::Config::source()->gsv["highlight_current_line"] == "true"; + property_show_line_numbers() = Singleton::Config::source()->gsv["show_line_numbers"] == "true"; } void Source::View::search_occurrences_updated(GtkWidget* widget, GParamSpec* property, gpointer data) { @@ -358,16 +368,6 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { //// GenericView //// ///////////////////// Source::GenericView::GenericView(const boost::filesystem::path &file_path, Glib::RefPtr language) : View(file_path) { - auto style_scheme_manager=Gsv::StyleSchemeManager::get_default(); - //TODO: add?: style_scheme_manager->prepend_search_path("~/.juci/"); - auto scheme=style_scheme_manager->get_scheme("classic"); - if(scheme) { - get_source_buffer()->set_style_scheme(scheme); - auto style=scheme->get_style("def:comment"); - if(style) - cout << "TODO, in progress: def:comment in scheme " << scheme->get_name() << " has color " << style->property_foreground() << endl; - } - if(language) { get_source_buffer()->set_language(language); Singleton::terminal()->print("Language for file "+file_path.string()+" set to "+language->get_name()+".\n"); @@ -388,12 +388,28 @@ clang::Index Source::ClangViewParse::clang_index(0, 0); Source::ClangViewParse::ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): Source::View(file_path), project_path(project_path) { - override_font(Pango::FontDescription(Singleton::Config::source()->font)); - override_background_color(Gdk::RGBA(Singleton::Config::source()->background)); - override_background_color(Gdk::RGBA(Singleton::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); for (auto &item : Singleton::Config::source()->tags) { - get_source_buffer()->create_tag(item.first)->property_foreground() = item.second; + auto scheme = get_source_buffer()->get_style_scheme(); + auto style = scheme->get_style(item.second); + if (style) { + DEBUG("Style " + item.second + " found in style " + scheme->get_name()); + auto tag = get_source_buffer()->create_tag(item.first); + if (style->property_foreground_set()) + tag->property_foreground() = style->property_foreground(); + if (style->property_background_set()) + tag->property_background() = style->property_background(); + if (style->property_strikethrough_set()) + tag->property_strikethrough() = style->property_strikethrough(); + // // if (style->property_bold_set()) tag->property_weight() = style->property_bold(); + // // if (style->property_italic_set()) tag->property_italic() = style->property_italic(); + // // if (style->property_line_background_set()) tag->property_line_background() = style->property_line_background(); + // // if (style->property_underline_set()) tag->property_underline() = style->property_underline(); + } else { + DEBUG("Style " + item.second + " not found in " + scheme->get_name()); + get_source_buffer()->create_tag(item.first)->property_foreground() = item.second; + } } + INFO("Tagtable filled"); //Create underline color tags for diagnostic warnings and errors: auto diagnostic_tag=get_buffer()->get_tag_table()->lookup("diagnostic_warning"); @@ -586,7 +602,7 @@ void Source::ClangViewParse::update_syntax() { buffer->remove_tag_by_name(tag, buffer->begin(), buffer->end()); last_syntax_tags.clear(); for (auto &range : ranges) { - std::string type = std::to_string(range.kind); + auto type = boost::lexical_cast(range.kind); try { last_syntax_tags.emplace(Singleton::Config::source()->types.at(type)); } catch (std::exception) { @@ -597,6 +613,7 @@ void Source::ClangViewParse::update_syntax() { Gtk::TextIter end_iter = buffer->get_iter_at_offset(range.end_offset); buffer->apply_tag_by_name(Singleton::Config::source()->types.at(type), begin_iter, end_iter); + } } @@ -1213,4 +1230,4 @@ bool Source::ClangView::restart_parse() { return true; } return false; -} \ No newline at end of file +} diff --git a/src/source.h b/src/source.h index 5d0df3a..a888fae 100644 --- a/src/source.h +++ b/src/source.h @@ -20,12 +20,11 @@ namespace Source { class Config { public: - unsigned tab_size; - bool show_line_numbers, highlight_current_line; - std::string tab, background, background_selected, background_tooltips, font; - char tab_char=' '; - std::unordered_map tags, types; - }; // class Config + unsigned tab_size = 2; + char tab_char = ' '; + std::string tab = " "; + std::unordered_map tags, types, gsv; + }; class Range { public: diff --git a/src/theme.h b/src/theme.h new file mode 100644 index 0000000..7b915ea --- /dev/null +++ b/src/theme.h @@ -0,0 +1,14 @@ +#ifndef JUCI_THEME_H_ +#define JUCI_THEME_H_ + +#include + +namespace Theme { + class Config { + public: + std::string current_theme() { return theme + "/" + main; } + std::string theme, main; + }; +} + +#endif // JUCI_THEME_H_ diff --git a/src/tooltips.cc b/src/tooltips.cc index 5afc1f3..c76e7dc 100644 --- a/src/tooltips.cc +++ b/src/tooltips.cc @@ -54,7 +54,6 @@ void Tooltip::adjust(bool disregard_drawn) { tooltip_widget=std::unique_ptr(new Gtk::TextView(create_tooltip_buffer())); wrap_lines(tooltip_widget->get_buffer()); tooltip_widget->set_editable(false); - tooltip_widget->override_background_color(Gdk::RGBA(Singleton::Config::source()->background_tooltips)); window->add(*tooltip_widget); auto layout=Pango::Layout::create(tooltip_widget->get_pango_context()); diff --git a/src/window.cc b/src/window.cc index 1f2dc13..5314f91 100644 --- a/src/window.cc +++ b/src/window.cc @@ -4,6 +4,7 @@ #include "sourcefile.h" #include "config.h" #include "api.h" +#include #include //TODO: remove using namespace std; //TODO: remove @@ -12,15 +13,24 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } +void Window::generate_keybindings() { + boost::filesystem::path path(Singleton::config_dir() + "menu.xml"); + menu.ui = juci::filesystem::read(path); + for (auto &i : Singleton::Config::window()->keybindings) { + auto key = i.second.get_value(); + menu.key_map[i.first] = key; + } +} + Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compiling(false) { INFO("Create Window"); set_title("juCi++"); set_default_size(600, 400); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK); add(box); - - MainConfig(this->menu); //Read the configs here - PluginApi(&this->notebook, &this->menu); //Initialise plugins + + generate_keybindings(); + PluginApi(&this->notebook, &this->menu); create_menu(); box.pack_start(menu.get_widget(), Gtk::PACK_SHRINK); @@ -67,7 +77,7 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compil if(notebook.get_current_page()!=-1) { if(search_entry_shown && entry_box.labels.size()>0) { notebook.get_current_view()->update_search_occurrences=[this](int number){ - entry_box.labels.begin()->update(0, std::to_string(number)); + entry_box.labels.begin()->update(0, boost::lexical_cast(number)); }; notebook.get_current_view()->search_highlight(last_search, case_sensitive_search, regex_search); } @@ -226,7 +236,7 @@ void Window::create_menu() { compile_success(); //TODO: Windows... Singleton::terminal()->async_execute(executable_path.string(), project_path, [this, executable_path](int exit_code){ - Singleton::terminal()->async_print(executable_path.string()+" returned: "+std::to_string(exit_code)+'\n'); + Singleton::terminal()->async_print(executable_path.string()+" returned: "+boost::lexical_cast(exit_code)+'\n'); }); } }); @@ -261,7 +271,7 @@ void Window::create_menu() { last_run_command=content; Singleton::terminal()->async_print("Running: "+content+'\n'); Singleton::terminal()->async_execute(content, directories.current_path, [this, content](int exit_code){ - Singleton::terminal()->async_print(content+" returned: "+std::to_string(exit_code)+'\n'); + Singleton::terminal()->async_print(content+" returned: "+boost::lexical_cast(exit_code)+'\n'); }); } entry_box.hide(); @@ -500,13 +510,13 @@ void Window::search_and_replace_entry() { auto label_it=entry_box.labels.begin(); label_it->update=[label_it](int state, const std::string& message){ if(state==0) { - int number=stoi(message); + auto number = boost::lexical_cast(message); if(number==0) label_it->set_text(""); else if(number==1) label_it->set_text("1 result found"); else if(number>1) - label_it->set_text(std::to_string(number)+" results found"); + label_it->set_text(boost::lexical_cast(number)+" results found"); } }; entry_box.entries.emplace_back(last_search, [this](const std::string& content){ @@ -517,7 +527,7 @@ void Window::search_and_replace_entry() { search_entry_it->set_placeholder_text("Find"); if(notebook.get_current_page()!=-1) { notebook.get_current_view()->update_search_occurrences=[label_it](int number){ - label_it->update(0, std::to_string(number)); + label_it->update(0, boost::lexical_cast(number)); }; notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); } @@ -588,7 +598,7 @@ void Window::goto_line_entry() { if(notebook.get_current_page()!=-1) { auto buffer=notebook.get_current_view()->get_buffer(); try { - auto line=stoul(content); + auto line = boost::lexical_cast(content); if(line>0 && line<=(unsigned long)buffer->get_line_count()) { line--; buffer->place_cursor(buffer->get_iter_at_line(line)); @@ -633,7 +643,7 @@ void Window::rename_token_entry() { if(notebook.get_view(c)->rename_similar_tokens) { auto number=notebook.get_view(c)->rename_similar_tokens(*token, content); if(number>0) { - Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path.string()+"\n"); + Singleton::terminal()->print("Replaced "+boost::lexical_cast(number)+" occurrences in file "+notebook.get_view(c)->file_path.string()+"\n"); notebook.save(c); } } diff --git a/src/window.h b/src/window.h index 8255aa7..f2b57f1 100644 --- a/src/window.h +++ b/src/window.h @@ -6,6 +6,7 @@ #include "entrybox.h" #include "notebook.h" #include "menu.h" +#include #include class Window : public Gtk::Window { @@ -13,9 +14,15 @@ public: Window(); Directories directories; Notebook notebook; + class Config { + public: + boost::property_tree::ptree keybindings; + }; + protected: bool on_key_press_event(GdkEventKey *event); bool on_delete_event (GdkEventAny *event); + private: Gtk::Box box; Gtk::VPaned vpaned; @@ -36,10 +43,10 @@ private: void open_folder_dialog(); void open_file_dialog(); void save_file_dialog(); - void search_and_replace_entry(); void goto_line_entry(); void rename_token_entry(); + void generate_keybindings(); std::string last_search; std::string last_replace; std::string last_run_command;