From e8bab3e4c79287e0d62fbd77294e056ff42b5d98 Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Jul 2015 19:12:57 +0200 Subject: [PATCH 01/14] Changes corresponding to the libclangmm cleanup. Slightly faster range lookup for tokens. --- juci/source.cc | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/juci/source.cc b/juci/source.cc index 17e1378..179c853 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -302,17 +302,16 @@ get_compilation_commands() { void Source::ClangView::update_syntax() { std::vector ranges; for (auto &token : *clang_tokens) { - auto range_data=token.source_range.get_range_data(); if(token.kind()==0) // PunctuationToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, (int) token.get_cursor().get_kind()); + ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); else if(token.kind()==1) // KeywordToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 702); + ranges.emplace_back(token.offsets.first, token.offsets.second, 702); else if(token.kind()==2) // IdentifierToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, (int) token.get_cursor().get_kind()); + ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); else if(token.kind()==3) // LiteralToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 109); + ranges.emplace_back(token.offsets.first, token.offsets.second, 109); else if(token.kind()==4) // CommentToken - ranges.emplace_back(range_data.start_offset, range_data.end_offset, 705); + ranges.emplace_back(token.offsets.first, token.offsets.second, 705); } if (ranges.empty() || ranges.size() == 0) { return; @@ -338,9 +337,9 @@ void Source::ClangView::update_diagnostics() { diagnostic_tooltips.clear(); auto diagnostics=clang_tu->get_diagnostics(); for(auto &diagnostic: diagnostics) { - if(diagnostic.range.path==file_path) { - auto start=get_buffer()->get_iter_at_offset(diagnostic.range.start_offset); - auto end=get_buffer()->get_iter_at_offset(diagnostic.range.end_offset); + if(diagnostic.path==file_path) { + auto start=get_buffer()->get_iter_at_offset(diagnostic.offsets.first); + auto end=get_buffer()->get_iter_at_offset(diagnostic.offsets.second); std::string diagnostic_tag_name; if(diagnostic.severity<=CXDiagnostic_Warning) diagnostic_tag_name="diagnostic_warning"; @@ -376,21 +375,18 @@ void Source::ClangView::update_types() { type_tooltips.clear(); for(auto &token: *clang_tokens) { if(token.has_type()) { - auto range_data=token.source_range.get_range_data(); - if(range_data.path==file_path) { - auto start=get_buffer()->get_iter_at_offset(range_data.start_offset); - auto end=get_buffer()->get_iter_at_offset(range_data.end_offset); - auto get_tooltip_buffer=[this, &token]() { - auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); - tooltip_buffer->insert_at_cursor("Type: "+token.get_type()); - auto brief_comment=token.get_brief_comments(); - if(brief_comment!="") - tooltip_buffer->insert_at_cursor("\n\n"+brief_comment+"."); - return tooltip_buffer; - }; - - type_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); - } + auto start=get_buffer()->get_iter_at_offset(token.offsets.first); + auto end=get_buffer()->get_iter_at_offset(token.offsets.second); + auto get_tooltip_buffer=[this, &token]() { + auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); + tooltip_buffer->insert_at_cursor("Type: "+token.get_type()); + auto brief_comment=token.get_brief_comments(); + if(brief_comment!="") + tooltip_buffer->insert_at_cursor("\n\n"+brief_comment+"."); + return tooltip_buffer; + }; + + type_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); } } } @@ -439,9 +435,8 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c if(clang_readable) { for(auto &token: *clang_tokens) { if(token.has_type()) { - auto range_data=token.source_range.get_range_data(); auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); - if(range_data.path==file_path && insert_offset>=range_data.start_offset && insert_offset<=range_data.end_offset) { + if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { found=true; auto referenced_usr_and_token_spelling=token.get_cursor().get_referenced_usr()+token.get_token_spelling(); if(last_similar_tokens_tagged!=referenced_usr_and_token_spelling) { From e041a1f68f7974ff0bcf6e07bfa54767a2d5c34a Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Jul 2015 19:46:42 +0200 Subject: [PATCH 02/14] Minor changes corresponding to libclangmm cleanup. --- juci/source.cc | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/juci/source.cc b/juci/source.cc index 179c853..abc00c0 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -302,15 +302,15 @@ get_compilation_commands() { void Source::ClangView::update_syntax() { std::vector ranges; for (auto &token : *clang_tokens) { - if(token.kind()==0) // PunctuationToken + if(token.get_kind()==0) // PunctuationToken ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); - else if(token.kind()==1) // KeywordToken + else if(token.get_kind()==1) // KeywordToken ranges.emplace_back(token.offsets.first, token.offsets.second, 702); - else if(token.kind()==2) // IdentifierToken + else if(token.get_kind()==2) // IdentifierToken ranges.emplace_back(token.offsets.first, token.offsets.second, (int) token.get_cursor().get_kind()); - else if(token.kind()==3) // LiteralToken + else if(token.get_kind()==3) // LiteralToken ranges.emplace_back(token.offsets.first, token.offsets.second, 109); - else if(token.kind()==4) // CommentToken + else if(token.get_kind()==4) // CommentToken ranges.emplace_back(token.offsets.first, token.offsets.second, 705); } if (ranges.empty() || ranges.size() == 0) { @@ -438,15 +438,18 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { found=true; - auto referenced_usr_and_token_spelling=token.get_cursor().get_referenced_usr()+token.get_token_spelling(); - if(last_similar_tokens_tagged!=referenced_usr_and_token_spelling) { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - auto offsets=clang_tokens->get_similar_token_offsets(token); - for(auto &offset: offsets) { - get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + auto referenced=token.get_cursor().get_referenced(); + if(referenced) { + auto usr_and_spelling=referenced.get_usr()+token.get_spelling(); + if(last_similar_tokens_tagged!=usr_and_spelling) { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + auto offsets=clang_tokens->get_similar_token_offsets(token); + for(auto &offset: offsets) { + get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + } + last_similar_tokens_tagged=usr_and_spelling; + break; } - last_similar_tokens_tagged=referenced_usr_and_token_spelling; - break; } } } From 931dc124250dbae20ab6f549b5d9452e4c17696c Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 17 Jul 2015 13:54:30 +0200 Subject: [PATCH 03/14] Largeer cleanup in preparation to refactoring implementation. Also some smaller fixes. --- juci/api.cc | 27 +++---- juci/api.h | 3 +- juci/config.cc | 21 ++--- juci/config.h | 8 -- juci/directories.cc | 14 +--- juci/directories.h | 5 -- juci/juci.cc | 7 +- juci/keybindings.cc | 56 ++++--------- juci/keybindings.h | 68 ++++------------ juci/menu.cc | 34 ++++---- juci/menu.h | 6 +- juci/notebook.cc | 171 +++++++++++++++++---------------------- juci/notebook.h | 24 ++---- juci/singletons.cc | 30 ++++++- juci/singletons.h | 27 +++++-- juci/source.cc | 190 +++++++++++++++++++++++--------------------- juci/source.h | 54 +++++++------ juci/terminal.cc | 20 ++--- juci/terminal.h | 6 +- juci/tooltips.cc | 2 +- juci/window.cc | 121 ++++++++++++++-------------- juci/window.h | 5 -- 22 files changed, 411 insertions(+), 488 deletions(-) diff --git a/juci/api.cc b/juci/api.cc index cf1099d..eefe937 100644 --- a/juci/api.cc +++ b/juci/api.cc @@ -1,16 +1,16 @@ #include "api.h" #include "logging.h" +#include "singletons.h" Menu::Controller* PluginApi::menu_; Notebook::Controller* PluginApi::notebook_; ///////////////////////////// //// API ServiceProvider //// ///////////////////////////// -PluginApi::PluginApi(Menu::Controller& menu_ctl_, - Notebook::Controller& notebook_ctl_) { +PluginApi::PluginApi() { DEBUG("Adding pointers for the API"); - menu_ = &menu_ctl_; - notebook_ = ¬ebook_ctl_; + notebook_ = Singleton::notebook(); + menu_ = Singleton::menu(); DEBUG("Initiating plugins(from plugins.py).."); #ifndef __APPLE__ InitPlugins(); //TODO: fix this @@ -18,11 +18,6 @@ PluginApi::PluginApi(Menu::Controller& menu_ctl_, DEBUG("Plugins initiated.."); } -PluginApi::~PluginApi() { - menu_ = NULL; - notebook_ = NULL; -} - std::string PluginApi::ProjectPath() { int MAXPATHLEN = 50; char temp[MAXPATHLEN]; @@ -69,7 +64,7 @@ void PluginApi::AddMenuElement(std::string plugin_name) { DEBUG("Adding menu element for "+plugin_name); AddMenuXml(plugin_name, "PluginMenu"); std::string plugin_action_name = plugin_name+"Menu"; - menu_->keybindings_.action_group_menu() + Singleton::keybindings()->action_group_menu ->add(Gtk::Action::create(plugin_action_name, plugin_name)); } @@ -79,7 +74,7 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, std::string plugin_path, std::string menu_keybinding) { AddSubMenuXml(menu_func_name, parent_menu); - menu_->keybindings_.action_group_menu() + Singleton::keybindings()->action_group_menu ->add(Gtk::Action::create(menu_func_name, menu_name), Gtk::AccelKey(menu_keybinding), @@ -89,7 +84,7 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, } void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = menu_->keybindings_.model_.menu_ui_string(); + std::string temp_menu = Singleton::keybindings()->menu_ui_string; std::size_t plugin_menu_pos = temp_menu.find(parent_menu); // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc plugin_menu_pos+=parent_menu.size() +2; @@ -99,13 +94,13 @@ void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { " " " "; - menu_->keybindings_.model_.menu_ui_string_ = + Singleton::keybindings()->menu_ui_string = menu_prefix + menu_input + menu_suffix; } void PluginApi::AddSubMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = menu_->keybindings_.model_.menu_ui_string(); + std::string temp_menu = Singleton::keybindings()->menu_ui_string; std::size_t parent_menu_pos = temp_menu.find(parent_menu); // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc @@ -114,7 +109,7 @@ void PluginApi::AddSubMenuXml(std::string plugin_name, std::string menu_suffix = temp_menu.substr(parent_menu_pos); std::string menu_input =""; - menu_->keybindings_.model_.menu_ui_string_ = + Singleton::keybindings()->menu_ui_string = menu_prefix + menu_input + menu_suffix; } @@ -221,7 +216,7 @@ void libjuci::IterToWordEnd(Gtk::TextIter &iter) { Glib::RefPtr libjuci::BufferFromNotebook() { return Glib::RefPtr(PluginApi::notebook_ - ->CurrentTextView().get_buffer()); + ->CurrentSourceView()->get_buffer()); } Gtk::TextIter libjuci::IterFromNotebook() { diff --git a/juci/api.h b/juci/api.h index 900d206..64e72c1 100644 --- a/juci/api.h +++ b/juci/api.h @@ -12,8 +12,7 @@ //////////////////// class PluginApi { public: - PluginApi(Menu::Controller&, Notebook::Controller&); - ~PluginApi(); + PluginApi(); static Menu::Controller* menu_; static Notebook::Controller* notebook_; static void InitPlugins(); diff --git a/juci/config.cc b/juci/config.cc index 9fa2a69..6096a9e 100644 --- a/juci/config.cc +++ b/juci/config.cc @@ -1,8 +1,8 @@ +#include "singletons.h" #include "config.h" #include "logging.h" -MainConfig::MainConfig() : - keybindings_cfg() { +MainConfig::MainConfig() { INFO("Reading config file"); boost::property_tree::json_parser::read_json("config.json", cfg_); INFO("Config file read"); @@ -13,7 +13,7 @@ MainConfig::MainConfig() : } void MainConfig::GenerateSource() { - auto source_cfg=Singletons::Config::source(); + auto source_cfg=Singleton::Config::source(); DEBUG("Fetching source cfg"); // boost::property_tree::ptree auto source_json = cfg_.get_child("source"); @@ -58,39 +58,42 @@ void MainConfig::GenerateSource() { } void MainConfig::GenerateTerminalCommands() { + auto terminal_cfg=Singleton::Config::terminal(); boost::property_tree::ptree source_json = cfg_.get_child("project"); boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands"); boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands"); for (auto &i : compile_commands_json) { - terminal_cfg.compile_commands.emplace_back(i.second.get_value()); + terminal_cfg->compile_commands.emplace_back(i.second.get_value()); } for (auto &i : run_commands_json) { - terminal_cfg.run_command=(i.second.get_value()); //TODO: run_commands array->one run_command? + terminal_cfg->run_command=(i.second.get_value()); //TODO: run_commands array->one run_command? } } void MainConfig::GenerateKeybindings() { + auto keybindings_cfg=Singleton::Config::keybindings(); DEBUG("Fetching keybindings"); std::string line; std::ifstream menu_xml("menu.xml"); if (menu_xml.is_open()) { while (getline(menu_xml, line)) - keybindings_cfg.AppendXml(line); + keybindings_cfg->AppendXml(line); } boost::property_tree::ptree keys_json = cfg_.get_child("keybindings"); for (auto &i : keys_json) - keybindings_cfg.key_map()[i.first] = i.second.get_value(); + keybindings_cfg->key_map[i.first] = i.second.get_value(); DEBUG("Keybindings fetched"); } void MainConfig::GenerateDirectoryFilter() { + auto dir_cfg=Singleton::Config::directories(); DEBUG("Fetching directory filter"); boost::property_tree::ptree dir_json = cfg_.get_child("directoryfilter"); boost::property_tree::ptree ignore_json = dir_json.get_child("ignore"); boost::property_tree::ptree except_json = dir_json.get_child("exceptions"); for ( auto &i : except_json ) - dir_cfg.AddException(i.second.get_value()); + dir_cfg->AddException(i.second.get_value()); for ( auto &i : ignore_json ) - dir_cfg.AddIgnore(i.second.get_value()); + dir_cfg->AddIgnore(i.second.get_value()); DEBUG("Directory filter fetched"); } diff --git a/juci/config.h b/juci/config.h index c6913fc..e08c17b 100644 --- a/juci/config.h +++ b/juci/config.h @@ -4,17 +4,9 @@ #include #include #include -#include "singletons.h" -#include "keybindings.h" -#include "source.h" -#include "directories.h" -#include "terminal.h" class MainConfig { public: - Terminal::Config terminal_cfg; - Keybindings::Config keybindings_cfg; - Directories::Config dir_cfg; MainConfig(); void PrintMenu(); void GenerateSource(); diff --git a/juci/directories.cc b/juci/directories.cc index 6e8ca9e..65a28dd 100644 --- a/juci/directories.cc +++ b/juci/directories.cc @@ -1,8 +1,8 @@ #include "directories.h" #include "logging.h" +#include "singletons.h" -Directories::Controller::Controller(Directories::Config& cfg) : - config_(cfg) { +Directories::Controller::Controller() { DEBUG("adding treeview to scrolledwindow"); m_ScrolledWindow.add(m_TreeView); m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); @@ -29,10 +29,10 @@ open_folder(const boost::filesystem::path& dir_path) { bool Directories::Controller::IsIgnored(std::string path) { DEBUG("Checking if file-/directory is filtered"); std::transform(path.begin(), path.end(), path.begin(), ::tolower); - if (config().IsException(path)) { + if (Singleton::Config::directories()->IsException(path)) { return false; } - if (config().IsIgnored(path)) { + if (Singleton::Config::directories()->IsIgnored(path)) { return true; } return false; @@ -156,12 +156,6 @@ GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_na return "no project name"; } -Directories::Config::Config() { -} -Directories::Config::Config(Directories::Config& cfg) : - ignore_list_(cfg.ignore_list()), exception_list_(cfg.exception_list()) { -} - void Directories::Config::AddIgnore(std::string filter) { ignore_list_.push_back(filter); } diff --git a/juci/directories.h b/juci/directories.h index ff7d195..c6363c5 100644 --- a/juci/directories.h +++ b/juci/directories.h @@ -14,8 +14,6 @@ namespace Directories { class Config { public: - Config(Config &original); - Config(); std::vector ignore_list() { return ignore_list_; } std::vector exception_list() { return exception_list_; } void AddIgnore(std::string filter); @@ -43,10 +41,8 @@ namespace Directories { class Controller { public: Controller(); - Controller(Directories::Config& cfg); View& view() { return view_;} Model& model() { return model_;} - Directories::Config& config() { return config_;} Gtk::ScrolledWindow& widget() {return m_ScrolledWindow;} void open_folder(const boost::filesystem::path& dir_path); void list_dirs(const boost::filesystem::path& dir_path, @@ -64,7 +60,6 @@ namespace Directories { private: View view_; Model model_; - Directories::Config config_; protected: void on_treeview_row_activated(const Gtk::TreeModel::Path& path, diff --git a/juci/juci.cc b/juci/juci.cc index f19e7da..0785b9a 100644 --- a/juci/juci.cc +++ b/juci/juci.cc @@ -1,4 +1,5 @@ #include "juci.h" +#include "singletons.h" void init_logging() { add_common_attributes(); @@ -36,11 +37,11 @@ void Juci::on_activate() { window->show(); if(directory!="") { //TODO: use the following instead, window->notebook.open_directory(directory); - window->notebook.project_path=directory; - window->notebook.directories.open_folder(directory); + Singleton::notebook()->project_path=directory; + Singleton::notebook()->directories.open_folder(directory); } for(auto &f: files) - window->notebook.OnOpenFile(f); + Singleton::notebook()->OnOpenFile(f); } int main(int argc, char *argv[]) { diff --git a/juci/keybindings.cc b/juci/keybindings.cc index 2408155..afd2821 100644 --- a/juci/keybindings.cc +++ b/juci/keybindings.cc @@ -1,65 +1,41 @@ #include "keybindings.h" +#include "singletons.h" -Keybindings::Model::Model(Keybindings::Config &config) : - menu_ui_string_(config.menu_xml()) { - /* hidden_ui_string_ = - " " - " " - " " - " " - " ";*/ +Keybindings::Keybindings() { + menu_ui_string=Singleton::Config::keybindings()->menu_xml; + action_group_menu = Gtk::ActionGroup::create(); + ui_manager_menu = Gtk::UIManager::create(); + action_group_hidden = Gtk::ActionGroup::create(); + ui_manager_hidden = Gtk::UIManager::create(); } -Keybindings::Model::~Model() { -} - -Keybindings::Controller::Controller(Keybindings::Config &config) : - config_(config), model_(config) { - action_group_menu_ = Gtk::ActionGroup::create(); - ui_manager_menu_ = Gtk::UIManager::create(); - action_group_hidden_ = Gtk::ActionGroup::create(); - ui_manager_hidden_ = Gtk::UIManager::create(); -} - -Keybindings::Controller::~Controller() { -} - -void Keybindings::Controller::BuildMenu() { +void Keybindings::BuildMenu() { try { - ui_manager_menu_->add_ui_from_string(model_.menu_ui_string()); + ui_manager_menu->add_ui_from_string(menu_ui_string); } catch (const Glib::Error &ex) { std::cerr << "building menu failed" << ex.what(); } - ui_manager_menu_->insert_action_group(action_group_menu_); + ui_manager_menu->insert_action_group(action_group_menu); } -void Keybindings::Controller::BuildHiddenMenu() { +void Keybindings::BuildHiddenMenu() { try { - ui_manager_hidden_->add_ui_from_string(model_.hidden_ui_string()); + ui_manager_hidden->add_ui_from_string(hidden_ui_string); } catch (const Glib::Error &ex) { std::cerr << "building hidden menu failed" << ex.what(); } - ui_manager_hidden_->insert_action_group(action_group_hidden_); -} - -Keybindings::Config::Config(Keybindings::Config &original) { - SetMenu(original.menu_xml()); - SetKeyMap(original.key_map()); + ui_manager_hidden->insert_action_group(action_group_hidden); } -Keybindings::Config::Config() { - menu_xml_ = ""; - } - void Keybindings::Config::AppendXml(std::string &child) { - menu_xml_ += child; + menu_xml += child; } void Keybindings::Config::SetMenu(std::string &menu_xml) { - menu_xml_ = menu_xml; + menu_xml = menu_xml; } void Keybindings::Config::SetKeyMap(std::unordered_map &key_map) { - key_map_ = key_map; + key_map = key_map; } diff --git a/juci/keybindings.h b/juci/keybindings.h index eafccd5..deba952 100644 --- a/juci/keybindings.h +++ b/juci/keybindings.h @@ -2,65 +2,31 @@ #ifndef JUCI_KEYBINDINGS_H_ #define JUCI_KEYBINDINGS_H_ +#include #include -#include "gtkmm.h" #include -//#include "config.h" //TODO :: remove? - -namespace Keybindings { +class Keybindings { +public: class Config { public: - Config(Config &original); - Config(); - std::string& menu_xml() { return menu_xml_; } - std::unordered_map& key_map() { return key_map_; } void AppendXml(std::string &child); void SetMenu(std::string &menu_xml); void SetKeyMap(std::unordered_map &key_map); - private: - std::unordered_map key_map_; - std::string menu_xml_; - std::string hidden_ui_string_; + std::unordered_map key_map; + std::string menu_xml; };//Config - - class Model { - public: - Model(Keybindings::Config &config); - virtual ~Model(); - std::string menu_ui_string() { return menu_ui_string_; } - std::string hidden_ui_string() { return hidden_ui_string_; } - //private: - std::string menu_ui_string_; - std::string hidden_ui_string_; - }; // Model - class Controller { - public: - explicit Controller(Keybindings::Config &config); - virtual ~Controller(); - Glib::RefPtr action_group_menu() { - return action_group_menu_; - }; - Glib::RefPtr ui_manager_menu() { - return ui_manager_menu_; - }; - Glib::RefPtr action_group_hidden() { - return action_group_hidden_; - }; - Glib::RefPtr ui_manager_hidden() { - return ui_manager_hidden_; - }; - void BuildMenu(); - void BuildHiddenMenu(); - // protected: - Glib::RefPtr ui_manager_menu_; - Glib::RefPtr action_group_menu_; - Glib::RefPtr ui_manager_hidden_; - Glib::RefPtr action_group_hidden_; - // private: - Keybindings::Config config_; - Keybindings::Model model_; - };//Controller -} + Keybindings(); + void BuildMenu(); + void BuildHiddenMenu(); + + std::string menu_ui_string; + std::string hidden_ui_string; + + Glib::RefPtr ui_manager_menu; + Glib::RefPtr action_group_menu; + Glib::RefPtr ui_manager_hidden; + Glib::RefPtr action_group_hidden; +}; #endif // JUCI_KEYBINDINGS_H_ diff --git a/juci/menu.cc b/juci/menu.cc index 0f09906..774ba00 100644 --- a/juci/menu.cc +++ b/juci/menu.cc @@ -1,4 +1,5 @@ #include "menu.h" +#include "singletons.h" Menu::View::View(Gtk::Orientation orientation) : view_(orientation) { @@ -11,43 +12,42 @@ Gtk::Box &Menu::View::view( return view_; } -Menu::Controller::Controller(Keybindings::Controller& keybindings) : - menu_view_(Gtk::ORIENTATION_VERTICAL), - keybindings_(keybindings) { - keybindings_.action_group_menu()->add(Gtk::Action::create("FileNew", +Menu::Controller::Controller() : menu_view_(Gtk::ORIENTATION_VERTICAL) { + auto keybindings=Singleton::keybindings(); + keybindings->action_group_menu->add(Gtk::Action::create("FileNew", "New File")); - keybindings_.action_group_menu()->add(Gtk::Action::create("EditMenu", + keybindings->action_group_menu->add(Gtk::Action::create("EditMenu", Gtk::Stock::EDIT)); - keybindings_.action_group_menu()->add(Gtk::Action::create("WindowMenu", + keybindings->action_group_menu->add(Gtk::Action::create("WindowMenu", "_Window")); - keybindings_.action_group_menu()->add(Gtk::Action::create("WindowSplitWindow", + keybindings->action_group_menu->add(Gtk::Action::create("WindowSplitWindow", "Split window"), - Gtk::AccelKey(keybindings_.config_ - .key_map()["split_window"]),//"S"), + Gtk::AccelKey(Singleton::Config::keybindings() + ->key_map["split_window"]),//"S"), [this]() { OnWindowSplitWindow(); }); - keybindings_.action_group_menu()->add(Gtk::Action::create("ProjectMenu", + keybindings->action_group_menu->add(Gtk::Action::create("ProjectMenu", "P_roject")); - keybindings_.action_group_menu()->add(Gtk::Action::create("PluginMenu", + keybindings->action_group_menu->add(Gtk::Action::create("PluginMenu", "_Plugins")); - keybindings_.action_group_menu()->add(Gtk::Action::create("HelpMenu", + keybindings->action_group_menu->add(Gtk::Action::create("HelpMenu", Gtk::Stock::HELP)); - keybindings_.action_group_menu()->add(Gtk::Action::create("HelpAbout", + keybindings->action_group_menu->add(Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT), [this]() { OnHelpAbout(); }); - keybindings_.action_group_hidden()->add(Gtk::Action::create("Test"), + keybindings->action_group_hidden->add(Gtk::Action::create("Test"), Gtk::AccelKey("K"), [this]() { OnHelpAbout(); }); - //keybindings_.BuildMenu(); // moved to window.cc - keybindings_.BuildHiddenMenu(); + //keybindings->BuildMenu(); // moved to window.cc + keybindings->BuildHiddenMenu(); } // Controller Gtk::Box &Menu::Controller::view() { - return menu_view_.view(keybindings_.ui_manager_menu()); + return menu_view_.view(Singleton::keybindings()->ui_manager_menu); } void Menu::Controller::OnPluginAddSnippet() { //TODO(Forgi add you snippet magic code) diff --git a/juci/menu.h b/juci/menu.h index f743999..0396e96 100644 --- a/juci/menu.h +++ b/juci/menu.h @@ -2,8 +2,7 @@ #define JUCI_MENU_H_ #include -#include "gtkmm.h" -#include "keybindings.h" +#include namespace Menu { class View { @@ -15,10 +14,9 @@ namespace Menu { }; // class View class Controller { public: - explicit Controller(Keybindings::Controller& keybindings); + Controller(); Gtk::Box &view(); - Keybindings::Controller &keybindings_; View menu_view_; void OnFileNewEmptyfile(); void OnFileNewCCFile(); diff --git a/juci/notebook.cc b/juci/notebook.cc index 1398225..ac149d8 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -1,6 +1,7 @@ #include #include "notebook.h" #include "logging.h" +#include "singletons.h" #include // c-library @@ -9,95 +10,86 @@ Notebook::View::View() { set_position(120); } -Notebook::Controller::Controller(Keybindings::Controller& keybindings, - Terminal::Controller& terminal, - Directories::Config& dir_cfg) : - terminal(terminal), - directories(dir_cfg) { +Notebook::Controller::Controller() : + directories() { INFO("Create notebook"); - refClipboard_ = Gtk::Clipboard::get(); + clipboard = Gtk::Clipboard::get(); view.pack1(directories.widget(), true, true); - CreateKeybindings(keybindings); + CreateKeybindings(); INFO("Notebook Controller Success"); } // Constructor -void Notebook::Controller::CreateKeybindings(Keybindings::Controller - &keybindings) { +void Notebook::Controller::CreateKeybindings() { + auto keybindings=Singleton::keybindings(); + auto keybindings_cfg=Singleton::Config::keybindings(); INFO("Notebook create signal handlers"); directories.m_TreeView.signal_row_activated() .connect(sigc::mem_fun(*this, &Notebook::Controller::OnDirectoryNavigation)); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("FileMenu", Gtk::Stock::FILE)); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("FileNewFile", "New file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["new_file"]), + Gtk::AccelKey(keybindings_cfg->key_map["new_file"]), [this]() { OnFileNewFile(); }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("WindowCloseTab", "Close tab"), - Gtk::AccelKey(keybindings.config_ - .key_map()["close_tab"]), + Gtk::AccelKey(keybindings_cfg->key_map["close_tab"]), [this]() { OnCloseCurrentPage(); }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditFind", "Find"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_find"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_find"]), [this]() { entry.show_search(""); }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditCopy", "Copy"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_copy"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_copy"]), [this]() { if (Pages() != 0) { - CurrentTextView().get_buffer()->copy_clipboard(refClipboard_); + CurrentSourceView()->get_buffer()->copy_clipboard(clipboard); } }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditCut", "Cut"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_cut"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_cut"]), [this]() { if (Pages() != 0) { - CurrentTextView().get_buffer()->cut_clipboard(refClipboard_); + CurrentSourceView()->get_buffer()->cut_clipboard(clipboard); } }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditPaste", "Paste"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_paste"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_paste"]), [this]() { if (Pages() != 0) { - CurrentTextView().get_buffer()->paste_clipboard(refClipboard_); + CurrentSourceView()->get_buffer()->paste_clipboard(clipboard); } }); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditUndo", "Undo"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_undo"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_undo"]), [this]() { INFO("On undo"); Glib::RefPtr undo_manager = - CurrentTextView().get_source_buffer()->get_undo_manager(); + CurrentSourceView()->get_source_buffer()->get_undo_manager(); if (Pages() != 0 && undo_manager->can_undo()) { undo_manager->undo(); } @@ -105,15 +97,14 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller } ); - keybindings.action_group_menu()-> + keybindings->action_group_menu-> add(Gtk::Action::create("EditRedo", "Redo"), - Gtk::AccelKey(keybindings.config_ - .key_map()["edit_redo"]), + Gtk::AccelKey(keybindings_cfg->key_map["edit_redo"]), [this]() { INFO("On Redo"); Glib::RefPtr undo_manager = - CurrentTextView().get_source_buffer()->get_undo_manager(); + CurrentSourceView()->get_source_buffer()->get_undo_manager(); if (Pages() != 0 && undo_manager->can_redo()) { undo_manager->redo(); } @@ -162,56 +153,42 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller INFO("Notebook signal handlers sucsess"); } -Notebook::Controller::~Controller() { - INFO("Notebook destructor"); - for (auto &i : editor_vec_) delete i; - for (auto &i : scrolledtext_vec_) delete i; -} - void Notebook::Controller::OnOpenFile(std::string path) { INFO("Notebook open file"); INFO("Notebook create page"); - text_vec_.emplace_back(new Source::Controller(path, project_path, terminal)); - scrolledtext_vec_.push_back(new Gtk::ScrolledWindow()); - editor_vec_.push_back(new Gtk::HBox()); - scrolledtext_vec_.back()->add(*text_vec_.back()->view); - editor_vec_.back()->pack_start(*scrolledtext_vec_.back(), true, true); - size_t pos = path.find_last_of("/\\"); // TODO #windows - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().append_page(*editor_vec_.back(), filename); - Notebook().show_all_children(); - Notebook().set_current_page(Pages()-1); - Notebook().set_focus_child(*text_vec_.back()->view); + source_views.emplace_back(new Source(path, project_path)); + scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); + hboxes.emplace_back(new Gtk::HBox()); + scrolled_windows.back()->add(*source_views.back()->view); + hboxes.back()->pack_start(*scrolled_windows.back(), true, true); + boost::filesystem::path file_path(source_views.back()->view->file_path); + std::string title=file_path.filename().string(); + view.notebook.append_page(*hboxes.back(), title); + view.notebook.show_all_children(); + view.notebook.set_current_page(Pages()-1); + view.notebook.set_focus_child(*source_views.back()->view); + CurrentSourceView()->get_buffer()->set_modified(false); //Add star on tab label when the page is not saved: - //TODO: instead use Gtk::TextBuffer::set_modified and Gtk::TextBuffer::get_modified - text_vec_.back()->buffer()->signal_changed().connect([this]() { - if(text_vec_.at(CurrentPage())->is_saved) { - std::string path=CurrentTextView().file_path; - size_t pos = path.find_last_of("/\\"); - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().set_tab_label_text(*(Notebook().get_nth_page(CurrentPage())), filename+"*"); - } - text_vec_.at(CurrentPage())->is_saved=false; + CurrentSourceView()->get_buffer()->signal_modified_changed().connect([this]() { + boost::filesystem::path file_path(CurrentSourceView()->file_path); + std::string title=file_path.filename().string(); + if(CurrentSourceView()->get_buffer()->get_modified()) + title+="*"; + view.notebook.set_tab_label_text(*(view.notebook.get_nth_page(CurrentPage())), title); }); } void Notebook::Controller::OnCloseCurrentPage() { INFO("Notebook close page"); if (Pages() != 0) { - if(!text_vec_.at(CurrentPage())->is_saved){ + if(CurrentSourceView()->get_buffer()->get_modified()){ AskToSaveDialog(); } int page = CurrentPage(); - Notebook().remove_page(page); - delete scrolledtext_vec_.at(page); - delete editor_vec_.at(page); - text_vec_.erase(text_vec_.begin()+ page); - scrolledtext_vec_.erase(scrolledtext_vec_.begin()+page); - editor_vec_.erase(editor_vec_.begin()+page); + view.notebook.remove_page(page); + source_views.erase(source_views.begin()+ page); + scrolled_windows.erase(scrolled_windows.begin()+page); + hboxes.erase(hboxes.begin()+page); } } void Notebook::Controller::OnFileNewFile() { @@ -220,10 +197,10 @@ void Notebook::Controller::OnFileNewFile() { void Notebook::Controller::search(bool forward) { INFO("Notebook search"); - auto start = CurrentTextView().search_start; - auto end = CurrentTextView().search_end; + auto start = CurrentSourceView()->search_start; + auto end = CurrentSourceView()->search_end; // fetch buffer and greate settings - auto buffer = CurrentTextView().get_source_buffer(); + auto buffer = CurrentSourceView()->get_source_buffer(); auto settings = gtk_source_search_settings_new(); // get search text from entry gtk_source_search_settings_set_search_text(settings, entry().c_str()); @@ -247,9 +224,9 @@ void Notebook::Controller::search(bool forward) { end.gobj()); } buffer->apply_tag_by_name("search", start, end); - CurrentTextView().scroll_to(end); - CurrentTextView().search_start = start; - CurrentTextView().search_end = end; + CurrentSourceView()->scroll_to(end); + CurrentSourceView()->search_start = start; + CurrentSourceView()->search_end = end; } void Notebook::Controller @@ -274,40 +251,34 @@ void Notebook::Controller } } -Source::View& Notebook::Controller::CurrentTextView() { +Source::View* Notebook::Controller::CurrentSourceView() { INFO("Getting sourceview"); - return *text_vec_.at(CurrentPage())->view; + return source_views.at(CurrentPage())->view.get(); } int Notebook::Controller::CurrentPage() { - return Notebook().get_current_page(); + return view.notebook.get_current_page(); } int Notebook::Controller::Pages() { - return Notebook().get_n_pages(); -} -Gtk::Notebook& Notebook::Controller::Notebook() { - return view.notebook; + return view.notebook.get_n_pages(); } bool Notebook::Controller:: OnSaveFile() { - std::string path=CurrentTextView().file_path; + std::string path=CurrentSourceView()->file_path; return OnSaveFile(path); } bool Notebook::Controller:: OnSaveFile(std::string path) { INFO("Notebook save file with path"); - if (path != "") { + if (path != "" && CurrentSourceView()->get_buffer()->get_modified()) { std::ofstream file; file.open (path); - file << CurrentTextView().get_buffer()->get_text(); + file << CurrentSourceView()->get_buffer()->get_text(); file.close(); - CurrentTextView().file_path=path; - size_t pos = path.find_last_of("/\\"); - std::string filename=path; - if(pos!=std::string::npos) - filename=path.substr(pos+1); - Notebook().set_tab_label_text(*Notebook().get_nth_page(CurrentPage()), filename); - text_vec_.at(CurrentPage())->is_saved=true; + boost::filesystem::path path(CurrentSourceView()->file_path); + std::string title=path.filename().string(); + view.notebook.set_tab_label_text(*view.notebook.get_nth_page(CurrentPage()), title); + CurrentSourceView()->get_buffer()->set_modified(false); return true; } return false; @@ -350,7 +321,7 @@ void Notebook::Controller::AskToSaveDialog() { false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); dialog.set_secondary_text( "Do you want to save: " + - CurrentTextView().file_path+" ?"); + CurrentSourceView()->file_path+" ?"); DEBUG("AskToSaveDialog: run dialog"); int result = dialog.run(); diff --git a/juci/notebook.h b/juci/notebook.h index 8ff76b1..13808c2 100644 --- a/juci/notebook.h +++ b/juci/notebook.h @@ -11,8 +11,6 @@ #include #include #include "clangmm.h" -#include "keybindings.h" -#include "terminal.h" namespace Notebook { class View : public Gtk::Paned { @@ -22,13 +20,9 @@ namespace Notebook { }; class Controller { public: - Controller(Keybindings::Controller& keybindings, - Terminal::Controller& terminal, - Directories::Config& dir_cfg); - ~Controller(); - Source::View& CurrentTextView(); + Controller(); + Source::View* CurrentSourceView(); int CurrentPage(); - Gtk::Notebook& Notebook(); void OnCloseCurrentPage(); void OnFileNewFile(); bool OnSaveFile(); @@ -43,18 +37,14 @@ namespace Notebook { std::string project_path; Directories::Controller directories; //Todo: make private after creating open_directory() Entry entry; - std::vector > text_vec_; + std::vector > source_views; private: - void CreateKeybindings(Keybindings::Controller& keybindings); + void CreateKeybindings(); void AskToSaveDialog(); - Glib::RefPtr m_refBuilder; - Glib::RefPtr refActionGroup; - Terminal::Controller& terminal; - std::vector scrolledtext_vec_; - std::vector editor_vec_; - std::list listTargets_; - Glib::RefPtr refClipboard_; + std::vector > scrolled_windows; + std::vector > hboxes; + Glib::RefPtr clipboard; }; // class controller } // namespace Notebook #endif // JUCI_NOTEBOOK_H_ diff --git a/juci/singletons.cc b/juci/singletons.cc index eaa2909..08ba603 100644 --- a/juci/singletons.cc +++ b/juci/singletons.cc @@ -1,3 +1,31 @@ #include "singletons.h" -std::unique_ptr Singletons::Config::source_=std::unique_ptr(new Source::Config()); +std::unique_ptr Singleton::Config::source_=std::unique_ptr(new Source::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::keybindings_=std::unique_ptr(new Keybindings::Config()); + +std::unique_ptr Singleton::terminal_=std::unique_ptr(); +std::unique_ptr Singleton::keybindings_=std::unique_ptr(); +std::unique_ptr Singleton::notebook_=std::unique_ptr(); +std::unique_ptr Singleton::menu_=std::unique_ptr(); +Terminal::Controller *Singleton::terminal() { + if(!terminal_) + terminal_=std::unique_ptr(new Terminal::Controller()); + return terminal_.get(); +} +Keybindings *Singleton::keybindings() { + if(!keybindings_) + keybindings_=std::unique_ptr(new Keybindings()); + return keybindings_.get(); +} +Notebook::Controller *Singleton::notebook() { + if(!notebook_) + notebook_=std::unique_ptr(new Notebook::Controller()); + return notebook_.get(); +} +Menu::Controller *Singleton::menu() { + if(!menu_) + menu_=std::unique_ptr(new Menu::Controller()); + return menu_.get(); +} \ No newline at end of file diff --git a/juci/singletons.h b/juci/singletons.h index 6098094..35221ef 100644 --- a/juci/singletons.h +++ b/juci/singletons.h @@ -5,16 +5,33 @@ #include "source.h" #include "directories.h" #include "terminal.h" +#include "notebook.h" +#include "menu.h" -namespace Singletons { +class Singleton { +public: class Config { public: - static Source::Config *source() { - return source_.get(); - } + static Source::Config *source() {return source_.get();} + static Terminal::Config *terminal() {return terminal_.get();} + static Directories::Config *directories() {return directories_.get();} + static Keybindings::Config *keybindings() {return keybindings_.get();} private: static std::unique_ptr source_; + static std::unique_ptr terminal_; + static std::unique_ptr directories_; + static std::unique_ptr keybindings_; }; -} + + static Terminal::Controller *terminal(); + static Keybindings *keybindings(); + static Notebook::Controller *notebook(); + static Menu::Controller *menu(); +private: + static std::unique_ptr terminal_; + static std::unique_ptr keybindings_; + static std::unique_ptr notebook_; + static std::unique_ptr menu_; +}; #endif // JUCI_SINGLETONS_H_ diff --git a/juci/source.cc b/juci/source.cc index abc00c0..f01d35b 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -29,19 +29,19 @@ Source::View::View(const std::string& file_path, const std::string& project_path file_path(file_path), project_path(project_path) { Gsv::init(); set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); - set_show_line_numbers(Singletons::Config::source()->show_line_numbers); - set_highlight_current_line(Singletons::Config::source()->highlight_current_line); + set_show_line_numbers(Singleton::Config::source()->show_line_numbers); + set_highlight_current_line(Singleton::Config::source()->highlight_current_line); sourcefile s(file_path); get_source_buffer()->get_undo_manager()->begin_not_undoable_action(); get_source_buffer()->set_text(s.get_content()); get_source_buffer()->get_undo_manager()->end_not_undoable_action(); search_start = search_end = this->get_buffer()->end(); - override_font(Pango::FontDescription(Singletons::Config::source()->font)); + override_font(Pango::FontDescription(Singleton::Config::source()->font)); - override_background_color(Gdk::RGBA(Singletons::Config::source()->background)); - override_background_color(Gdk::RGBA(Singletons::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); - for (auto &item : Singletons::Config::source()->tags) { + 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; } } @@ -64,7 +64,7 @@ string Source::View::get_line_before_insert() { //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { - auto config=Singletons::Config::source(); + auto config=Singleton::Config::source(); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); //Indent as in next or previous line if(key->keyval==GDK_KEY_Return && key->state==0) { @@ -142,17 +142,14 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return Gsv::View::on_key_press_event(key); } -////////////////// -//// ClangView /// -////////////////// -clang::Index Source::ClangView::clang_index(0, 0); +///////////////////////// +//// ClangViewParse /// +///////////////////////// +clang::Index Source::ClangViewParse::clang_index(0, 0); -Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): -Source::View(file_path, project_path), terminal(terminal), -parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { - similar_tokens_tag=get_buffer()->create_tag(); - similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; - +Source::ClangViewParse::ClangViewParse(const std::string& file_path, const std::string& project_path): +Source::View(file_path, project_path), +parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { int start_offset = get_source_buffer()->begin().get_offset(); int end_offset = get_source_buffer()->end().get_offset(); auto buffer_map=get_buffer_map(); @@ -185,7 +182,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go=true; }); - parsing_in_progress=this->terminal.print_in_progress("Parsing "+file_path); + parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); parse_done.connect([this](){ if(parse_thread_mapped) { if(parsing_mutex.try_lock()) { @@ -228,16 +225,12 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { start_reparse(); type_tooltips.hide(); diagnostic_tooltips.hide(); - if(last_similar_tokens_tagged!="") { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_tokens_tagged=""; - } }); - get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::on_mark_set), false); + get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } -Source::ClangView::~ClangView() { +Source::ClangViewParse::~ClangViewParse() { //TODO: Is it possible to stop the clang-process in progress? parsing_in_progress->cancel("canceled"); parse_thread_stop=true; @@ -247,7 +240,7 @@ Source::ClangView::~ClangView() { parsing_mutex.unlock(); } -void Source::ClangView:: +void Source::ClangViewParse:: init_syntax_highlighting(const std::map &buffers, int start_offset, @@ -260,13 +253,13 @@ init_syntax_highlighting(const std::map clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path)->second.size()-1); } -std::map Source::ClangView::get_buffer_map() const { +std::map Source::ClangViewParse::get_buffer_map() const { std::map buffer_map; buffer_map[file_path]=get_source_buffer()->get_text().raw(); return buffer_map; } -void Source::ClangView::start_reparse() { +void Source::ClangViewParse::start_reparse() { parse_thread_mapped=false; clang_readable=false; delayed_reparse_connection.disconnect(); @@ -276,14 +269,13 @@ void Source::ClangView::start_reparse() { }, 1000); } -int Source::ClangView::reparse(const std::map &buffer) { +int Source::ClangViewParse::reparse(const std::map &buffer) { int status = clang_tu->ReparseTranslationUnit(buffer); clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path)->second.size()-1); return status; } -std::vector Source::ClangView:: -get_compilation_commands() { +std::vector Source::ClangViewParse::get_compilation_commands() { clang::CompilationDatabase db(project_path); clang::CompileCommands commands(file_path, db); std::vector cmds = commands.get_commands(); @@ -299,7 +291,7 @@ get_compilation_commands() { return arguments; } -void Source::ClangView::update_syntax() { +void Source::ClangViewParse::update_syntax() { std::vector ranges; for (auto &token : *clang_tokens) { if(token.get_kind()==0) // PunctuationToken @@ -321,19 +313,19 @@ void Source::ClangView::update_syntax() { for (auto &range : ranges) { std::string type = std::to_string(range.kind); try { - Singletons::Config::source()->types.at(type); + Singleton::Config::source()->types.at(type); } catch (std::exception) { continue; } Gtk::TextIter begin_iter = buffer->get_iter_at_offset(range.start_offset); Gtk::TextIter end_iter = buffer->get_iter_at_offset(range.end_offset); - buffer->apply_tag_by_name(Singletons::Config::source()->types.at(type), + buffer->apply_tag_by_name(Singleton::Config::source()->types.at(type), begin_iter, end_iter); } } -void Source::ClangView::update_diagnostics() { +void Source::ClangViewParse::update_diagnostics() { diagnostic_tooltips.clear(); auto diagnostics=clang_tu->get_diagnostics(); for(auto &diagnostic: diagnostics) { @@ -371,7 +363,7 @@ void Source::ClangView::update_diagnostics() { } } -void Source::ClangView::update_types() { +void Source::ClangViewParse::update_types() { type_tooltips.clear(); for(auto &token: *clang_tokens) { if(token.has_type()) { @@ -391,7 +383,7 @@ void Source::ClangView::update_types() { } } -bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) { +bool Source::ClangViewParse::on_motion_notify_event(GdkEventMotion* event) { delayed_tooltips_connection.disconnect(); if(clang_readable) { Gdk::Rectangle rectangle(event->x, event->y, 1, 1); @@ -407,7 +399,7 @@ bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) { return Source::View::on_motion_notify_event(event); } -void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark) { +void Source::ClangViewParse::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark) { if(get_buffer()->get_has_selection() && mark->get_name()=="selection_bound") delayed_tooltips_connection.disconnect(); @@ -429,47 +421,18 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c return false; }, 500); type_tooltips.hide(); - diagnostic_tooltips.hide(); - - bool found=false; - if(clang_readable) { - for(auto &token: *clang_tokens) { - if(token.has_type()) { - auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); - if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { - found=true; - auto referenced=token.get_cursor().get_referenced(); - if(referenced) { - auto usr_and_spelling=referenced.get_usr()+token.get_spelling(); - if(last_similar_tokens_tagged!=usr_and_spelling) { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - auto offsets=clang_tokens->get_similar_token_offsets(token); - for(auto &offset: offsets) { - get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); - } - last_similar_tokens_tagged=usr_and_spelling; - break; - } - } - } - } - } - } - if(!found && last_similar_tokens_tagged!="") { - get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_tokens_tagged=""; - } + diagnostic_tooltips.hide(); } } -bool Source::ClangView::on_focus_out_event(GdkEventFocus* event) { +bool Source::ClangViewParse::on_focus_out_event(GdkEventFocus* event) { delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); return Source::View::on_focus_out_event(event); } -bool Source::ClangView::on_scroll_event(GdkEventScroll* event) { +bool Source::ClangViewParse::on_scroll_event(GdkEventScroll* event) { delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); @@ -478,8 +441,8 @@ bool Source::ClangView::on_scroll_event(GdkEventScroll* event) { //Clang indentation //TODO: replace indentation methods with a better implementation or maybe use libclang -bool Source::ClangView::on_key_press_event(GdkEventKey* key) { - auto config=Singletons::Config::source(); +bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { + auto config=Singleton::Config::source(); const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$"); const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); const std::regex no_bracket_no_para_statement_regex(std::string("^(")+config->tab_char+"*)(else|try|do) *$"); @@ -566,8 +529,8 @@ bool Source::ClangView::on_key_press_event(GdkEventKey* key) { ////////////////////////////// //// ClangViewAutocomplete /// ////////////////////////////// -Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): -Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { +Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): +Source::ClangViewParse(file_path, project_path), selection_dialog(*this), autocomplete_cancel_starting(false) { selection_dialog.on_hide=[this](){ start_reparse(); }; @@ -606,7 +569,7 @@ bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { if(selection_dialog.on_key_press(key)) return true; } - return ClangView::on_key_press_event(key); + return ClangViewParse::on_key_press_event(key); } bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { @@ -614,13 +577,13 @@ bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { selection_dialog.hide(); } - return Source::ClangView::on_focus_out_event(event); + return Source::ClangViewParse::on_focus_out_event(event); } void Source::ClangViewAutocomplete::start_autocomplete() { - const std::regex autocomplete_keys("[a-zA-Z0-9_>\\.:]"); - std::smatch sm; - if(!std::regex_match(std::string()+(char)last_keyval, sm, autocomplete_keys)) { + if(!((last_keyval>='0' && last_keyval<='9') || + (last_keyval>='a' && last_keyval<='z') || (last_keyval>='A' && last_keyval<='Z') || + last_keyval=='_' || last_keyval=='>' || last_keyval=='.' || last_keyval==':')) { autocomplete_cancel_starting=true; return; } @@ -628,6 +591,7 @@ void Source::ClangViewAutocomplete::start_autocomplete() { if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) { const std::regex in_specified_namespace("^(.*[a-zA-Z0-9_\\)])(->|\\.|::)([a-zA-Z0-9_]*)$"); const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); + std::smatch sm; if(std::regex_match(line, sm, in_specified_namespace)) { prefix_mutex.lock(); prefix=sm[3].str(); @@ -730,7 +694,7 @@ get_autocomplete_suggestions(int line_number, int column, std::mapcreate_tag(); + similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; + + get_buffer()->signal_changed().connect([this]() { + if(last_similar_tokens_tagged!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_tokens_tagged=""; + } + }); + + get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ + if(mark->get_name()=="insert") { + bool found=false; + if(clang_readable) { + for(auto &token: *clang_tokens) { + if(token.has_type()) { + auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); + if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { + found=true; + auto referenced=token.get_cursor().get_referenced(); + if(referenced) { + auto usr_and_spelling=referenced.get_usr()+token.get_spelling(); + if(last_similar_tokens_tagged!=usr_and_spelling) { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + auto offsets=clang_tokens->get_similar_token_offsets(token); + for(auto &offset: offsets) { + get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + } + last_similar_tokens_tagged=usr_and_spelling; + break; + } + } + } + } + } + } + if(!found && last_similar_tokens_tagged!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_tokens_tagged=""; + } + } + }); +} + +//////////////// +//// Source //// +//////////////// + +Source::Source(const std::string& file_path, std::string project_path) { if(project_path=="") { project_path=boost::filesystem::path(file_path).parent_path().string(); } - if (Singletons::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) - view=std::unique_ptr(new ClangViewAutocomplete(file_path, project_path, terminal)); + if (Singleton::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) + view=std::unique_ptr(new ClangView(file_path, project_path)); else view=std::unique_ptr(new GenericView(file_path, project_path)); INFO("Source Controller with childs constructed"); } - -Glib::RefPtr Source::Controller::buffer() { - return view->get_source_buffer(); -} diff --git a/juci/source.h b/juci/source.h index 7a2a05a..6762980 100644 --- a/juci/source.h +++ b/juci/source.h @@ -14,7 +14,8 @@ #include "tooltips.h" #include "selectiondialog.h" -namespace Source { +class Source { +public: class Config { public: bool legal_extension(std::string e) const ; @@ -59,25 +60,23 @@ namespace Source { public: GenericView(const std::string& file_path, const std::string& project_path): View(file_path, project_path) {} - protected: - bool on_key_press_event(GdkEventKey* key) { - return Source::View::on_key_press_event(key); - } }; - class ClangView : public View { + class ClangViewParse : public View { public: - ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); - ~ClangView(); + ClangViewParse(const std::string& file_path, const std::string& project_path); + ~ClangViewParse(); protected: void start_reparse(); bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); std::unique_ptr clang_tu; - std::map get_buffer_map() const; std::mutex parsing_mutex; + std::unique_ptr clang_tokens; + bool clang_readable=false; sigc::connection delayed_reparse_connection; private: + std::map get_buffer_map() const; // inits the syntax highligthing on file open void init_syntax_highlighting(const std::map &buffers, @@ -92,15 +91,10 @@ namespace Source { bool on_motion_notify_event(GdkEventMotion* event); void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); sigc::connection delayed_tooltips_connection; - Glib::RefPtr similar_tokens_tag; - std::string last_similar_tokens_tagged; bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; - std::unique_ptr clang_tokens; - bool clang_readable=false; std::vector get_compilation_commands(); - Terminal::Controller& terminal; std::shared_ptr parsing_in_progress; Glib::Dispatcher parse_done; @@ -112,10 +106,10 @@ namespace Source { std::atomic parse_thread_mapped; std::atomic parse_thread_stop; }; - - class ClangViewAutocomplete : public ClangView { + + class ClangViewAutocomplete : public ClangViewParse { public: - ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); + ClangViewAutocomplete(const std::string& file_path, const std::string& project_path); protected: bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); @@ -133,14 +127,22 @@ namespace Source { std::mutex prefix_mutex; }; - class Controller { + class ClangViewRefactor : public ClangViewAutocomplete { public: - Controller(const std::string& file_path, std::string project_path, Terminal::Controller& terminal); - Glib::RefPtr buffer(); - - bool is_saved = true; - - std::unique_ptr view; - }; // class Controller -} // namespace Source + ClangViewRefactor(const std::string& file_path, const std::string& project_path); + private: + Glib::RefPtr similar_tokens_tag; + std::string last_similar_tokens_tagged; + }; + + class ClangView : public ClangViewRefactor { + public: + ClangView(const std::string& file_path, const std::string& project_path): + ClangViewRefactor(file_path, project_path) {} + }; + + Source(const std::string& file_path, std::string project_path); + + std::unique_ptr view; +}; // class Source #endif // JUCI_SOURCE_H_ diff --git a/juci/terminal.cc b/juci/terminal.cc index cce7496..20f1033 100644 --- a/juci/terminal.cc +++ b/juci/terminal.cc @@ -1,10 +1,11 @@ #include "terminal.h" #include #include "logging.h" +#include "singletons.h" -Terminal::InProgress::InProgress(Controller& terminal, const std::string& start_msg): terminal(terminal), stop(false) { +Terminal::InProgress::InProgress(const std::string& start_msg): stop(false) { waiting_print.connect([this](){ - this->terminal.print(line_nr-1, "."); + Singleton::terminal()->print(line_nr-1, "."); }); start(start_msg); } @@ -16,7 +17,7 @@ Terminal::InProgress::~InProgress() { } void Terminal::InProgress::start(const std::string& msg) { - line_nr=this->terminal.print(msg+"...\n"); + line_nr=Singleton::terminal()->print(msg+"...\n"); wait_thread=std::thread([this](){ size_t c=0; while(!stop) { @@ -31,14 +32,14 @@ void Terminal::InProgress::start(const std::string& msg) { void Terminal::InProgress::done(const std::string& msg) { if(!stop) { stop=true; - this->terminal.print(line_nr-1, msg); + Singleton::terminal()->print(line_nr-1, msg); } } void Terminal::InProgress::cancel(const std::string& msg) { if(!stop) { stop=true; - this->terminal.print(line_nr-1, msg); + Singleton::terminal()->print(line_nr-1, msg); } } @@ -48,8 +49,7 @@ Terminal::View::View(){ add(scrolled_window); } -Terminal::Controller::Controller(Terminal::Config& cfg) : - config(cfg) { +Terminal::Controller::Controller() { folder_command_ = ""; } @@ -65,7 +65,7 @@ void Terminal::Controller::Compile(){ view.text_view.get_buffer()->set_text(""); DEBUG("Terminal: Compile: running cmake command"); - std::vector commands = config.compile_commands; + std::vector commands = Singleton::Config::terminal()->compile_commands; for (size_t it = 0; it < commands.size(); ++it) { ExecuteCommand(commands.at(it), "r"); @@ -79,7 +79,7 @@ void Terminal::Controller::Run(std::string executable) { print("juCi++ execute: " + executable + "\n"); DEBUG("Terminal: Compile: running run command: "); DEBUG_VAR(executable); - ExecuteCommand("cd "+config.run_command + "; ./"+executable, "r"); + ExecuteCommand("cd "+Singleton::Config::terminal()->run_command + "; ./"+executable, "r"); print("\n"); } @@ -100,7 +100,7 @@ void Terminal::Controller::print(int line_nr, std::string message){ } std::shared_ptr Terminal::Controller::print_in_progress(std::string start_msg) { - std::shared_ptr in_progress=std::shared_ptr(new Terminal::InProgress(*this, start_msg)); + std::shared_ptr in_progress=std::shared_ptr(new Terminal::InProgress(start_msg)); return in_progress; } diff --git a/juci/terminal.h b/juci/terminal.h index 317e43e..a5e779b 100644 --- a/juci/terminal.h +++ b/juci/terminal.h @@ -27,13 +27,12 @@ namespace Terminal { //Temporary solution for displaying functions in progress, and when they are done. class InProgress { public: - InProgress(Controller& terminal, const std::string& start_msg); + InProgress(const std::string& start_msg); ~InProgress(); void done(const std::string& msg); void cancel(const std::string& msg); private: void start(const std::string& msg); - Controller& terminal; int line_nr; std::atomic stop; Glib::Dispatcher waiting_print; @@ -42,7 +41,7 @@ namespace Terminal { class Controller { public: - Controller(Terminal::Config& cfg); + Controller(); void SetFolderCommand(boost::filesystem::path CMake_path); void Run(std::string executable); void Compile(); @@ -51,7 +50,6 @@ namespace Terminal { std::shared_ptr print_in_progress(std::string start_msg); Terminal::View view; private: - Terminal::Config& config; void ExecuteCommand(std::string command, std::string mode); bool OnButtonRealeaseEvent(GdkEventKey* key); bool ExistInConsole(std::string string); diff --git a/juci/tooltips.cc b/juci/tooltips.cc index 01d05f5..62b9476 100644 --- a/juci/tooltips.cc +++ b/juci/tooltips.cc @@ -46,7 +46,7 @@ void Tooltip::adjust(bool disregard_drawn) { tooltip_widget=std::unique_ptr(new Gtk::TextView(this->get_buffer())); tooltip_widget->set_editable(false); - tooltip_widget->override_background_color(Gdk::RGBA(Singletons::Config::source()->background_tooltips)); + 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/juci/window.cc b/juci/window.cc index e281538..4d71aa6 100644 --- a/juci/window.cc +++ b/juci/window.cc @@ -1,128 +1,124 @@ #include "window.h" #include "logging.h" +#include "singletons.h" Window::Window() : - window_box_(Gtk::ORIENTATION_VERTICAL), - main_config(), - keybindings(main_config.keybindings_cfg), - terminal(main_config.terminal_cfg), - notebook(keybindings, terminal, - main_config.dir_cfg), - menu(keybindings), - api(menu, notebook) { + window_box_(Gtk::ORIENTATION_VERTICAL) { 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(window_box_); - keybindings.action_group_menu()->add(Gtk::Action::create("FileQuit", + auto keybindings=Singleton::keybindings(); + auto keybindings_cfg=Singleton::Config::keybindings(); + keybindings->action_group_menu->add(Gtk::Action::create("FileQuit", "Quit juCi++"), - Gtk::AccelKey(keybindings.config_ - .key_map()["quit"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["quit"]), [this]() { OnWindowHide(); }); - keybindings.action_group_menu()->add(Gtk::Action::create("FileOpenFile", + keybindings->action_group_menu->add(Gtk::Action::create("FileOpenFile", "Open file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["open_file"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["open_file"]), [this]() { OnOpenFile(); }); - keybindings.action_group_menu()->add(Gtk::Action::create("FileOpenFolder", + keybindings->action_group_menu->add(Gtk::Action::create("FileOpenFolder", "Open folder"), - Gtk::AccelKey(keybindings.config_ - .key_map()["open_folder"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["open_folder"]), [this]() { OnFileOpenFolder(); }); - keybindings. - action_group_menu()-> + keybindings-> + action_group_menu-> add(Gtk::Action::create("FileSaveAs", "Save as"), - Gtk::AccelKey(keybindings.config_ - .key_map()["save_as"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["save_as"]), [this]() { SaveFileAs(); }); - keybindings. - action_group_menu()-> + keybindings-> + action_group_menu-> add(Gtk::Action::create("FileSave", "Save"), - Gtk::AccelKey(keybindings.config_ - .key_map()["save"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["save"]), [this]() { SaveFile(); }); - keybindings. - action_group_menu()-> + keybindings-> + action_group_menu-> add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), - Gtk::AccelKey(keybindings.config_ - .key_map()["compile_and_run"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["compile_and_run"]), [this]() { SaveFile(); if (running.try_lock()) { - std::thread execute([=]() { - std::string path = notebook.CurrentTextView().file_path; + std::thread execute([this]() { + std::string path = Singleton::notebook()->CurrentSourceView()->file_path; size_t pos = path.find_last_of("/\\"); if(pos != std::string::npos) { path.erase(path.begin()+pos,path.end()); - terminal.SetFolderCommand(path); + Singleton::terminal()->SetFolderCommand(path); } - terminal.Compile(); - std::string executable = notebook.directories. + Singleton::terminal()->Compile(); + std::string executable = Singleton::notebook()->directories. GetCmakeVarValue(path,"add_executable"); - terminal.Run(executable); + Singleton::terminal()->Run(executable); running.unlock(); }); execute.detach(); } }); - keybindings. - action_group_menu()-> + keybindings-> + action_group_menu-> add(Gtk::Action::create("ProjectCompile", "Compile"), - Gtk::AccelKey(keybindings.config_ - .key_map()["compile"]), + Gtk::AccelKey(keybindings_cfg + ->key_map["compile"]), [this]() { SaveFile(); if (running.try_lock()) { - std::thread execute([=]() { - std::string path = notebook.CurrentTextView().file_path; + std::thread execute([this]() { + std::string path = Singleton::notebook()->CurrentSourceView()->file_path; size_t pos = path.find_last_of("/\\"); if(pos != std::string::npos){ path.erase(path.begin()+pos,path.end()); - terminal.SetFolderCommand(path); + Singleton::terminal()->SetFolderCommand(path); } - terminal.Compile(); + Singleton::terminal()->Compile(); running.unlock(); }); execute.detach(); } }); - add_accel_group(keybindings.ui_manager_menu()->get_accel_group()); - add_accel_group(keybindings.ui_manager_hidden()->get_accel_group()); - keybindings.BuildMenu(); + add_accel_group(keybindings->ui_manager_menu->get_accel_group()); + add_accel_group(keybindings->ui_manager_hidden->get_accel_group()); + keybindings->BuildMenu(); - window_box_.pack_start(menu.view(), Gtk::PACK_SHRINK); + window_box_.pack_start(Singleton::menu()->view(), Gtk::PACK_SHRINK); - window_box_.pack_start(notebook.entry, Gtk::PACK_SHRINK); + window_box_.pack_start(Singleton::notebook()->entry, Gtk::PACK_SHRINK); paned_.set_position(300); - paned_.pack1(notebook.view, true, false); - paned_.pack2(terminal.view, true, true); + paned_.pack1(Singleton::notebook()->view, true, false); + paned_.pack2(Singleton::terminal()->view, true, true); window_box_.pack_end(paned_); show_all_children(); INFO("Window created"); } // Window constructor void Window::OnWindowHide() { - for(size_t c=0;csource_views.size();c++) + Singleton::notebook()->OnCloseCurrentPage(); //TODO: This only works on one page at the momemt. Change to Singleton::notebook()->close_page(page_nr); hide(); } void Window::OnFileOpenFolder() { @@ -141,8 +137,8 @@ void Window::OnFileOpenFolder() { case(Gtk::RESPONSE_OK): { std::string project_path=dialog.get_filename(); - notebook.project_path=project_path; - notebook.directories.open_folder(project_path); + Singleton::notebook()->project_path=project_path; + Singleton::notebook()->directories.open_folder(project_path); break; } case(Gtk::RESPONSE_CANCEL): @@ -190,7 +186,7 @@ void Window::OnOpenFile() { switch (result) { case(Gtk::RESPONSE_OK): { std::string path = dialog.get_filename(); - notebook.OnOpenFile(path); + Singleton::notebook()->OnOpenFile(path); break; } case(Gtk::RESPONSE_CANCEL): { @@ -203,20 +199,19 @@ void Window::OnOpenFile() { } bool Window::SaveFile() { - if(notebook.OnSaveFile()) { - terminal.print("File saved to: " + - notebook.CurrentTextView().file_path+"\n"); + if(Singleton::notebook()->OnSaveFile()) { + Singleton::terminal()->print("File saved to: " + + Singleton::notebook()->CurrentSourceView()->file_path+"\n"); return true; } - terminal.print("File not saved"); return false; } bool Window::SaveFileAs() { - if(notebook.OnSaveFile(notebook.OnSaveFileAs())){ - terminal.print("File saved to: " + - notebook.CurrentTextView().file_path+"\n"); + if(Singleton::notebook()->OnSaveFile(Singleton::notebook()->OnSaveFileAs())){ + Singleton::terminal()->print("File saved to: " + + Singleton::notebook()->CurrentSourceView()->file_path+"\n"); return true; } - terminal.print("File not saved"); + Singleton::terminal()->print("File not saved"); return false; } diff --git a/juci/window.h b/juci/window.h index 782029a..2dce670 100644 --- a/juci/window.h +++ b/juci/window.h @@ -3,7 +3,6 @@ #include "api.h" #include "config.h" -#include "terminal.h" #include @@ -15,10 +14,6 @@ public: virtual ~Window() { } MainConfig main_config; - Keybindings::Controller keybindings; - Menu::Controller menu; - Notebook::Controller notebook; - Terminal::Controller terminal; PluginApi api; private: From ef6b48e507e10153f135051c91823733e5ba79cd Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 18 Jul 2015 23:34:39 +0200 Subject: [PATCH 04/14] Cleanup of menu and keybindings. --- juci/CMakeLists.txt | 2 - juci/api.cc | 24 ++++------ juci/api.h | 2 +- juci/config.cc | 8 ++-- juci/config.h | 2 - juci/keybindings.cc | 41 ---------------- juci/keybindings.h | 32 ------------- juci/menu.cc | 98 ++++++++++++-------------------------- juci/menu.h | 43 ++++++----------- juci/menu.xml | 2 +- juci/notebook.cc | 112 ++++++++++++++------------------------------ juci/singletons.cc | 13 ++--- juci/singletons.h | 9 +--- juci/window.cc | 98 ++++++++++++-------------------------- 14 files changed, 132 insertions(+), 354 deletions(-) delete mode 100644 juci/keybindings.cc delete mode 100644 juci/keybindings.h diff --git a/juci/CMakeLists.txt b/juci/CMakeLists.txt index b8474db..b6f672f 100644 --- a/juci/CMakeLists.txt +++ b/juci/CMakeLists.txt @@ -101,8 +101,6 @@ add_executable(${project_name} #list of every needed file to create the executable juci.h juci.cc - keybindings.h - keybindings.cc menu.h menu.cc source.h diff --git a/juci/api.cc b/juci/api.cc index eefe937..14acce7 100644 --- a/juci/api.cc +++ b/juci/api.cc @@ -2,8 +2,8 @@ #include "logging.h" #include "singletons.h" -Menu::Controller* PluginApi::menu_; -Notebook::Controller* PluginApi::notebook_; +Menu* PluginApi::menu_=nullptr; +Notebook::Controller* PluginApi::notebook_=nullptr; ///////////////////////////// //// API ServiceProvider //// ///////////////////////////// @@ -64,8 +64,7 @@ void PluginApi::AddMenuElement(std::string plugin_name) { DEBUG("Adding menu element for "+plugin_name); AddMenuXml(plugin_name, "PluginMenu"); std::string plugin_action_name = plugin_name+"Menu"; - Singleton::keybindings()->action_group_menu - ->add(Gtk::Action::create(plugin_action_name, plugin_name)); + Singleton::menu()->action_group->add(Gtk::Action::create(plugin_action_name, plugin_name)); } void PluginApi::AddSubMenuElement(std::string parent_menu, @@ -74,8 +73,7 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, std::string plugin_path, std::string menu_keybinding) { AddSubMenuXml(menu_func_name, parent_menu); - Singleton::keybindings()->action_group_menu - ->add(Gtk::Action::create(menu_func_name, + Singleton::menu()->action_group->add(Gtk::Action::create(menu_func_name, menu_name), Gtk::AccelKey(menu_keybinding), [=]() { @@ -84,9 +82,9 @@ void PluginApi::AddSubMenuElement(std::string parent_menu, } void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = Singleton::keybindings()->menu_ui_string; + std::string temp_menu = Singleton::menu()->ui; std::size_t plugin_menu_pos = temp_menu.find(parent_menu); - // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc + // +2 gets you outside of the tag:<'menu_name'> plugin_menu_pos+=parent_menu.size() +2; std::string menu_prefix = temp_menu.substr(0, plugin_menu_pos); std::string menu_suffix = temp_menu.substr(plugin_menu_pos); @@ -94,23 +92,21 @@ void PluginApi::AddMenuXml(std::string plugin_name, std::string parent_menu) { " " " "; - Singleton::keybindings()->menu_ui_string = - menu_prefix + menu_input + menu_suffix; + Singleton::menu()->ui = menu_prefix + menu_input + menu_suffix; } void PluginApi::AddSubMenuXml(std::string plugin_name, std::string parent_menu) { - std::string temp_menu = Singleton::keybindings()->menu_ui_string; + std::string temp_menu = Singleton::menu()->ui; std::size_t parent_menu_pos = temp_menu.find(parent_menu); - // +2 gets you outside of the tag:<'menu_name'> ref: keybindings.cc + // +2 gets you outside of the tag:<'menu_name'> parent_menu_pos+=parent_menu.size() +2; std::string menu_prefix = temp_menu.substr(0, parent_menu_pos); std::string menu_suffix = temp_menu.substr(parent_menu_pos); std::string menu_input =""; - Singleton::keybindings()->menu_ui_string = - menu_prefix + menu_input + menu_suffix; + Singleton::menu()->ui = menu_prefix + menu_input + menu_suffix; } /////////////////////// diff --git a/juci/api.h b/juci/api.h index 64e72c1..3f97710 100644 --- a/juci/api.h +++ b/juci/api.h @@ -13,7 +13,7 @@ class PluginApi { public: PluginApi(); - static Menu::Controller* menu_; + static Menu* menu_; static Notebook::Controller* notebook_; static void InitPlugins(); static std::string ProjectPath(); diff --git a/juci/config.cc b/juci/config.cc index 6096a9e..4cd3b71 100644 --- a/juci/config.cc +++ b/juci/config.cc @@ -1,6 +1,8 @@ #include "singletons.h" #include "config.h" #include "logging.h" +#include +#include MainConfig::MainConfig() { INFO("Reading config file"); @@ -71,17 +73,17 @@ void MainConfig::GenerateTerminalCommands() { } void MainConfig::GenerateKeybindings() { - auto keybindings_cfg=Singleton::Config::keybindings(); + auto menu=Singleton::menu(); DEBUG("Fetching keybindings"); std::string line; std::ifstream menu_xml("menu.xml"); if (menu_xml.is_open()) { while (getline(menu_xml, line)) - keybindings_cfg->AppendXml(line); + menu->ui+=line; } boost::property_tree::ptree keys_json = cfg_.get_child("keybindings"); for (auto &i : keys_json) - keybindings_cfg->key_map[i.first] = i.second.get_value(); + menu->key_map[i.first] = i.second.get_value(); DEBUG("Keybindings fetched"); } diff --git a/juci/config.h b/juci/config.h index e08c17b..9729467 100644 --- a/juci/config.h +++ b/juci/config.h @@ -2,8 +2,6 @@ #define JUCI_CONFIG_H_ #include #include -#include -#include class MainConfig { public: diff --git a/juci/keybindings.cc b/juci/keybindings.cc deleted file mode 100644 index afd2821..0000000 --- a/juci/keybindings.cc +++ /dev/null @@ -1,41 +0,0 @@ -#include "keybindings.h" -#include "singletons.h" - -Keybindings::Keybindings() { - menu_ui_string=Singleton::Config::keybindings()->menu_xml; - action_group_menu = Gtk::ActionGroup::create(); - ui_manager_menu = Gtk::UIManager::create(); - action_group_hidden = Gtk::ActionGroup::create(); - ui_manager_hidden = Gtk::UIManager::create(); -} - -void Keybindings::BuildMenu() { - try { - ui_manager_menu->add_ui_from_string(menu_ui_string); - } - catch (const Glib::Error &ex) { - std::cerr << "building menu failed" << ex.what(); - } - ui_manager_menu->insert_action_group(action_group_menu); -} -void Keybindings::BuildHiddenMenu() { - try { - ui_manager_hidden->add_ui_from_string(hidden_ui_string); - } - catch (const Glib::Error &ex) { - std::cerr << "building hidden menu failed" << ex.what(); - } - ui_manager_hidden->insert_action_group(action_group_hidden); -} - -void Keybindings::Config::AppendXml(std::string &child) { - menu_xml += child; -} - -void Keybindings::Config::SetMenu(std::string &menu_xml) { - menu_xml = menu_xml; -} - -void Keybindings::Config::SetKeyMap(std::unordered_map &key_map) { - key_map = key_map; -} diff --git a/juci/keybindings.h b/juci/keybindings.h deleted file mode 100644 index deba952..0000000 --- a/juci/keybindings.h +++ /dev/null @@ -1,32 +0,0 @@ -//juCi++ class that holds every keybinding. -#ifndef JUCI_KEYBINDINGS_H_ -#define JUCI_KEYBINDINGS_H_ - -#include -#include -#include - -class Keybindings { -public: - class Config { - public: - void AppendXml(std::string &child); - void SetMenu(std::string &menu_xml); - void SetKeyMap(std::unordered_map &key_map); - std::unordered_map key_map; - std::string menu_xml; - };//Config - - Keybindings(); - void BuildMenu(); - void BuildHiddenMenu(); - - std::string menu_ui_string; - std::string hidden_ui_string; - - Glib::RefPtr ui_manager_menu; - Glib::RefPtr action_group_menu; - Glib::RefPtr ui_manager_hidden; - Glib::RefPtr action_group_hidden; -}; -#endif // JUCI_KEYBINDINGS_H_ diff --git a/juci/menu.cc b/juci/menu.cc index 774ba00..f5ccefa 100644 --- a/juci/menu.cc +++ b/juci/menu.cc @@ -1,76 +1,36 @@ #include "menu.h" -#include "singletons.h" +#include -Menu::View::View(Gtk::Orientation orientation) : - view_(orientation) { - Gtk::MenuBar menutest; - view_.pack_end(menutest); -} -Gtk::Box &Menu::View::view( - Glib::RefPtr ui_manager) { - view_.pack_start(*ui_manager->get_widget("/MenuBar"), Gtk::PACK_SHRINK); - return view_; -} +Menu::Menu() : box(Gtk::ORIENTATION_VERTICAL) { + action_group = Gtk::ActionGroup::create(); + ui_manager = Gtk::UIManager::create(); -Menu::Controller::Controller() : menu_view_(Gtk::ORIENTATION_VERTICAL) { - auto keybindings=Singleton::keybindings(); - keybindings->action_group_menu->add(Gtk::Action::create("FileNew", - "New File")); - keybindings->action_group_menu->add(Gtk::Action::create("EditMenu", - Gtk::Stock::EDIT)); - keybindings->action_group_menu->add(Gtk::Action::create("WindowMenu", - "_Window")); - keybindings->action_group_menu->add(Gtk::Action::create("WindowSplitWindow", - "Split window"), - Gtk::AccelKey(Singleton::Config::keybindings() - ->key_map["split_window"]),//"S"), - [this]() { - OnWindowSplitWindow(); - }); - keybindings->action_group_menu->add(Gtk::Action::create("ProjectMenu", - "P_roject")); - keybindings->action_group_menu->add(Gtk::Action::create("PluginMenu", - "_Plugins")); - keybindings->action_group_menu->add(Gtk::Action::create("HelpMenu", - Gtk::Stock::HELP)); - keybindings->action_group_menu->add(Gtk::Action::create("HelpAbout", - Gtk::Stock::ABOUT), - [this]() { - OnHelpAbout(); - }); - keybindings->action_group_hidden->add(Gtk::Action::create("Test"), - Gtk::AccelKey("K"), - [this]() { - OnHelpAbout(); - }); - //keybindings->BuildMenu(); // moved to window.cc - keybindings->BuildHiddenMenu(); - } // Controller -Gtk::Box &Menu::Controller::view() { - return menu_view_.view(Singleton::keybindings()->ui_manager_menu); -} -void Menu::Controller::OnPluginAddSnippet() { - //TODO(Forgi add you snippet magic code) - std::cout << "Add snippet" << std::endl; - //juci_api::py::LoadPlugin("snippet"); -} -void Menu::Controller::OnFileOpenFile() { - std::cout << "Open file clicked" << std::endl; - //TODO(Oyvang) Legg til funksjon + action_group->add(Gtk::Action::create("FileNew", "New File")); + action_group->add(Gtk::Action::create("EditMenu", Gtk::Stock::EDIT)); + action_group->add(Gtk::Action::create("WindowMenu", "_Window")); + action_group->add(Gtk::Action::create("WindowSplitWindow", "Split window"), Gtk::AccelKey(key_map["split_window"]), [this]() { + }); + action_group->add(Gtk::Action::create("ProjectMenu", "P_roject")); + action_group->add(Gtk::Action::create("PluginMenu", "_Plugins")); + action_group->add(Gtk::Action::create("HelpMenu", Gtk::Stock::HELP)); + action_group->add(Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT), [this]() { + }); } -void Menu::Controller::OnEditCut() { - std::cout << "Clicked cut" << std::endl; - //TODO(Oyvang) Legg til funksjon -} -void Menu::Controller::OnEditFind() { - std::cout << "Clicked find" << std::endl; - //TODO(Oyvang) Legg til funksjon + +Gtk::Widget& Menu::get_widget() { + return *ui_manager->get_widget("/MenuBar"); } -void Menu::Controller::OnWindowSplitWindow() { - std::cout << "Clicked split window" << std::endl; - //TODO(Oyvang) Legg til funksjon + +Gtk::Menu& Menu::get_cpp() { + return *(Gtk::Menu*)ui_manager->get_widget("/MenuBar/CppMenu"); } -void Menu::Controller::OnHelpAbout() { - std::cout << "Clicked about" << std::endl; - //TODO(Oyvang) Legg til funksjon + +void Menu::build() { + try { + ui_manager->add_ui_from_string(ui); + } + catch (const Glib::Error &ex) { + std::cerr << "building menu failed" << ex.what(); + } + ui_manager->insert_action_group(action_group); } diff --git a/juci/menu.h b/juci/menu.h index 0396e96..dc95ce4 100644 --- a/juci/menu.h +++ b/juci/menu.h @@ -1,34 +1,21 @@ #ifndef JUCI_MENU_H_ #define JUCI_MENU_H_ -#include +#include +#include #include -namespace Menu { - class View { - public: - explicit View(Gtk::Orientation orient); - Gtk::Box &view(Glib::RefPtr ui_manager); - protected: - Gtk::Box view_; - }; // class View - class Controller { - public: - Controller(); - Gtk::Box &view(); - - View menu_view_; - void OnFileNewEmptyfile(); - void OnFileNewCCFile(); - void OnFileNewHeaderFile(); - void OnFileOpenFile(); - void OnFileOpenFolder(); - void OnPluginAddSnippet(); - void OnWindowCloseTab(); - void OnEditCut(); - void OnEditFind(); - void OnWindowSplitWindow(); - void OnHelpAbout(); - }; // class Controller -} // namespace Menu +class Menu { +public: + Menu(); + Gtk::Widget& get_widget(); + Gtk::Menu& get_cpp(); + void build(); + + Gtk::Box box; + std::unordered_map key_map; + std::string ui; + Glib::RefPtr ui_manager; + Glib::RefPtr action_group; +}; #endif // JUCI_MENU_H_ diff --git a/juci/menu.xml b/juci/menu.xml index 18f82e3..9c6a63f 100644 --- a/juci/menu.xml +++ b/juci/menu.xml @@ -16,7 +16,7 @@ - + diff --git a/juci/notebook.cc b/juci/notebook.cc index ac149d8..261b438 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -21,95 +21,55 @@ Notebook::Controller::Controller() : void Notebook::Controller::CreateKeybindings() { - auto keybindings=Singleton::keybindings(); - auto keybindings_cfg=Singleton::Config::keybindings(); + auto menu=Singleton::menu(); INFO("Notebook create signal handlers"); - directories.m_TreeView.signal_row_activated() - .connect(sigc::mem_fun(*this, - &Notebook::Controller::OnDirectoryNavigation)); + directories.m_TreeView.signal_row_activated().connect(sigc::mem_fun(*this, &Notebook::Controller::OnDirectoryNavigation)); - keybindings->action_group_menu-> - add(Gtk::Action::create("FileMenu", - Gtk::Stock::FILE)); + menu->action_group->add(Gtk::Action::create("FileMenu", Gtk::Stock::FILE)); - keybindings->action_group_menu-> - add(Gtk::Action::create("FileNewFile", - "New file"), - Gtk::AccelKey(keybindings_cfg->key_map["new_file"]), - [this]() { - OnFileNewFile(); - }); - keybindings->action_group_menu-> - add(Gtk::Action::create("WindowCloseTab", - "Close tab"), - Gtk::AccelKey(keybindings_cfg->key_map["close_tab"]), - [this]() { - OnCloseCurrentPage(); - }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditFind", - "Find"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_find"]), - [this]() { + menu->action_group->add(Gtk::Action::create("FileNewFile", "New file"), Gtk::AccelKey(menu->key_map["new_file"]), [this]() { + OnFileNewFile(); + }); + menu->action_group->add(Gtk::Action::create("WindowCloseTab", "Close tab"), Gtk::AccelKey(menu->key_map["close_tab"]), [this]() { + OnCloseCurrentPage(); + }); + menu->action_group->add(Gtk::Action::create("EditFind", "Find"), Gtk::AccelKey(menu->key_map["edit_find"]), [this]() { entry.show_search(""); - }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditCopy", - "Copy"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_copy"]), - - [this]() { - if (Pages() != 0) { - CurrentSourceView()->get_buffer()->copy_clipboard(clipboard); - } - }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditCut", - "Cut"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_cut"]), - [this]() { + }); + menu->action_group->add(Gtk::Action::create("EditCopy", "Copy"), Gtk::AccelKey(menu->key_map["edit_copy"]), [this]() { + if (Pages() != 0) { + CurrentSourceView()->get_buffer()->copy_clipboard(clipboard); + } + }); + menu->action_group->add(Gtk::Action::create("EditCut", "Cut"), Gtk::AccelKey(menu->key_map["edit_cut"]), [this]() { if (Pages() != 0) { CurrentSourceView()->get_buffer()->cut_clipboard(clipboard); } - }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditPaste", - "Paste"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_paste"]), - [this]() { + }); + menu->action_group->add(Gtk::Action::create("EditPaste", "Paste"), Gtk::AccelKey(menu->key_map["edit_paste"]), [this]() { if (Pages() != 0) { CurrentSourceView()->get_buffer()->paste_clipboard(clipboard); } - }); + }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditUndo", - "Undo"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_undo"]), - [this]() { + menu->action_group->add(Gtk::Action::create("EditUndo", "Undo"), Gtk::AccelKey(menu->key_map["edit_undo"]), [this]() { INFO("On undo"); - Glib::RefPtr undo_manager = - CurrentSourceView()->get_source_buffer()->get_undo_manager(); - if (Pages() != 0 && undo_manager->can_undo()) { - undo_manager->undo(); - } - INFO("Done undo"); - } - ); + Glib::RefPtr undo_manager = CurrentSourceView()->get_source_buffer()->get_undo_manager(); + if (Pages() != 0 && undo_manager->can_undo()) { + undo_manager->undo(); + } + INFO("Done undo"); + }); - keybindings->action_group_menu-> - add(Gtk::Action::create("EditRedo", - "Redo"), - Gtk::AccelKey(keybindings_cfg->key_map["edit_redo"]), - [this]() { - INFO("On Redo"); - Glib::RefPtr undo_manager = - CurrentSourceView()->get_source_buffer()->get_undo_manager(); - if (Pages() != 0 && undo_manager->can_redo()) { - undo_manager->redo(); - } - INFO("Done Redo"); - }); + menu->action_group->add(Gtk::Action::create("EditRedo", "Redo"), Gtk::AccelKey(menu->key_map["edit_redo"]), [this]() { + INFO("On Redo"); + Glib::RefPtr undo_manager = + CurrentSourceView()->get_source_buffer()->get_undo_manager(); + if (Pages() != 0 && undo_manager->can_redo()) { + undo_manager->redo(); + } + INFO("Done Redo"); + }); entry.button_apply_set_filename.signal_clicked().connect([this]() { std::string filename=entry(); diff --git a/juci/singletons.cc b/juci/singletons.cc index 08ba603..d2c82f8 100644 --- a/juci/singletons.cc +++ b/juci/singletons.cc @@ -3,29 +3,22 @@ std::unique_ptr Singleton::Config::source_=std::unique_ptr(new Source::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::keybindings_=std::unique_ptr(new Keybindings::Config()); std::unique_ptr Singleton::terminal_=std::unique_ptr(); -std::unique_ptr Singleton::keybindings_=std::unique_ptr(); std::unique_ptr Singleton::notebook_=std::unique_ptr(); -std::unique_ptr Singleton::menu_=std::unique_ptr(); +std::unique_ptr Singleton::menu_=std::unique_ptr(); Terminal::Controller *Singleton::terminal() { if(!terminal_) terminal_=std::unique_ptr(new Terminal::Controller()); return terminal_.get(); } -Keybindings *Singleton::keybindings() { - if(!keybindings_) - keybindings_=std::unique_ptr(new Keybindings()); - return keybindings_.get(); -} Notebook::Controller *Singleton::notebook() { if(!notebook_) notebook_=std::unique_ptr(new Notebook::Controller()); return notebook_.get(); } -Menu::Controller *Singleton::menu() { +Menu *Singleton::menu() { if(!menu_) - menu_=std::unique_ptr(new Menu::Controller()); + menu_=std::unique_ptr(new Menu()); return menu_.get(); } \ No newline at end of file diff --git a/juci/singletons.h b/juci/singletons.h index 35221ef..09cd50a 100644 --- a/juci/singletons.h +++ b/juci/singletons.h @@ -1,7 +1,6 @@ #ifndef JUCI_SINGLETONS_H_ #define JUCI_SINGLETONS_H_ -#include "keybindings.h" #include "source.h" #include "directories.h" #include "terminal.h" @@ -15,23 +14,19 @@ public: static Source::Config *source() {return source_.get();} static Terminal::Config *terminal() {return terminal_.get();} static Directories::Config *directories() {return directories_.get();} - static Keybindings::Config *keybindings() {return keybindings_.get();} private: static std::unique_ptr source_; static std::unique_ptr terminal_; static std::unique_ptr directories_; - static std::unique_ptr keybindings_; }; static Terminal::Controller *terminal(); - static Keybindings *keybindings(); static Notebook::Controller *notebook(); - static Menu::Controller *menu(); + static Menu *menu(); private: static std::unique_ptr terminal_; - static std::unique_ptr keybindings_; static std::unique_ptr notebook_; - static std::unique_ptr menu_; + static std::unique_ptr menu_; }; #endif // JUCI_SINGLETONS_H_ diff --git a/juci/window.cc b/juci/window.cc index 4d71aa6..63b2d8f 100644 --- a/juci/window.cc +++ b/juci/window.cc @@ -9,56 +9,25 @@ Window::Window() : set_default_size(600, 400); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK); add(window_box_); - auto keybindings=Singleton::keybindings(); - auto keybindings_cfg=Singleton::Config::keybindings(); - keybindings->action_group_menu->add(Gtk::Action::create("FileQuit", - "Quit juCi++"), - Gtk::AccelKey(keybindings_cfg - ->key_map["quit"]), - [this]() { - OnWindowHide(); - }); - keybindings->action_group_menu->add(Gtk::Action::create("FileOpenFile", - "Open file"), - Gtk::AccelKey(keybindings_cfg - ->key_map["open_file"]), - [this]() { - OnOpenFile(); - }); - keybindings->action_group_menu->add(Gtk::Action::create("FileOpenFolder", - "Open folder"), - Gtk::AccelKey(keybindings_cfg - ->key_map["open_folder"]), - [this]() { - OnFileOpenFolder(); - }); - keybindings-> - action_group_menu-> - add(Gtk::Action::create("FileSaveAs", - "Save as"), - Gtk::AccelKey(keybindings_cfg - ->key_map["save_as"]), - [this]() { + auto menu=Singleton::menu(); + menu->action_group->add(Gtk::Action::create("FileQuit", "Quit juCi++"), Gtk::AccelKey(menu->key_map["quit"]), [this]() { + OnWindowHide(); + }); + menu->action_group->add(Gtk::Action::create("FileOpenFile", "Open file"), Gtk::AccelKey(menu->key_map["open_file"]), [this]() { + OnOpenFile(); + }); + menu->action_group->add(Gtk::Action::create("FileOpenFolder", "Open folder"), Gtk::AccelKey(menu->key_map["open_folder"]), [this]() { + OnFileOpenFolder(); + }); + menu->action_group->add(Gtk::Action::create("FileSaveAs", "Save as"), Gtk::AccelKey(menu->key_map["save_as"]), [this]() { SaveFileAs(); }); - keybindings-> - action_group_menu-> - add(Gtk::Action::create("FileSave", - "Save"), - Gtk::AccelKey(keybindings_cfg - ->key_map["save"]), - [this]() { + menu->action_group->add(Gtk::Action::create("FileSave", "Save"), Gtk::AccelKey(menu->key_map["save"]), [this]() { SaveFile(); }); - keybindings-> - action_group_menu-> - add(Gtk::Action::create("ProjectCompileAndRun", - "Compile And Run"), - Gtk::AccelKey(keybindings_cfg - ->key_map["compile_and_run"]), - [this]() { + menu->action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu->key_map["compile_and_run"]), [this]() { SaveFile(); if (running.try_lock()) { std::thread execute([this]() { @@ -78,34 +47,27 @@ Window::Window() : } }); - keybindings-> - action_group_menu-> - add(Gtk::Action::create("ProjectCompile", - "Compile"), - Gtk::AccelKey(keybindings_cfg - ->key_map["compile"]), - [this]() { - SaveFile(); - if (running.try_lock()) { - std::thread execute([this]() { - std::string path = Singleton::notebook()->CurrentSourceView()->file_path; - size_t pos = path.find_last_of("/\\"); - if(pos != std::string::npos){ - path.erase(path.begin()+pos,path.end()); - Singleton::terminal()->SetFolderCommand(path); - } - Singleton::terminal()->Compile(); - running.unlock(); - }); - execute.detach(); + menu->action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu->key_map["compile"]), [this]() { + SaveFile(); + if (running.try_lock()) { + std::thread execute([this]() { + std::string path = Singleton::notebook()->CurrentSourceView()->file_path; + size_t pos = path.find_last_of("/\\"); + if(pos != std::string::npos){ + path.erase(path.begin()+pos,path.end()); + Singleton::terminal()->SetFolderCommand(path); } + Singleton::terminal()->Compile(); + running.unlock(); }); + execute.detach(); + } + }); - add_accel_group(keybindings->ui_manager_menu->get_accel_group()); - add_accel_group(keybindings->ui_manager_hidden->get_accel_group()); - keybindings->BuildMenu(); + add_accel_group(menu->ui_manager->get_accel_group()); + menu->build(); - window_box_.pack_start(Singleton::menu()->view(), Gtk::PACK_SHRINK); + window_box_.pack_start(menu->get_widget(), Gtk::PACK_SHRINK); window_box_.pack_start(Singleton::notebook()->entry, Gtk::PACK_SHRINK); paned_.set_position(300); From ffd7e2b1ecc416adc95985415a958865b3df75cf Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 14:31:39 +0200 Subject: [PATCH 05/14] Go to declaration implemented. Also some smaller fixes, including going to tab if opening an already open file. Scroll to iterator/cursor/insert/mark/whatever is bugged in GTK it seems, need a better workaround here. --- juci/config.json | 1 + juci/juci.cc | 2 +- juci/menu.cc | 5 +++-- juci/menu.h | 2 +- juci/menu.xml | 5 ++++- juci/notebook.cc | 29 ++++++++++++++++++++++++++--- juci/notebook.h | 2 +- juci/source.cc | 46 ++++++++++++++++++++++++++++++++++++++++++---- juci/source.h | 5 +++++ juci/sourcefile.h | 18 ++++++++---------- juci/terminal.cc | 6 ++++-- juci/window.cc | 2 +- 12 files changed, 97 insertions(+), 26 deletions(-) diff --git a/juci/config.json b/juci/config.json index 42effbb..9c3e0a0 100644 --- a/juci/config.json +++ b/juci/config.json @@ -58,6 +58,7 @@ "edit_undo": "z", "edit_redo": "y", "edit_find": "f", + "goto_declaration": "d", "compile_and_run": "r", "compile": "r" }, diff --git a/juci/juci.cc b/juci/juci.cc index 0785b9a..4ca0558 100644 --- a/juci/juci.cc +++ b/juci/juci.cc @@ -41,7 +41,7 @@ void Juci::on_activate() { Singleton::notebook()->directories.open_folder(directory); } for(auto &f: files) - Singleton::notebook()->OnOpenFile(f); + Singleton::notebook()->open_file(f); } int main(int argc, char *argv[]) { diff --git a/juci/menu.cc b/juci/menu.cc index f5ccefa..a613492 100644 --- a/juci/menu.cc +++ b/juci/menu.cc @@ -11,6 +11,7 @@ Menu::Menu() : box(Gtk::ORIENTATION_VERTICAL) { action_group->add(Gtk::Action::create("WindowSplitWindow", "Split window"), Gtk::AccelKey(key_map["split_window"]), [this]() { }); action_group->add(Gtk::Action::create("ProjectMenu", "P_roject")); + action_group->add(Gtk::Action::create("SourceMenu", "_Source")); action_group->add(Gtk::Action::create("PluginMenu", "_Plugins")); action_group->add(Gtk::Action::create("HelpMenu", Gtk::Stock::HELP)); action_group->add(Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT), [this]() { @@ -21,8 +22,8 @@ Gtk::Widget& Menu::get_widget() { return *ui_manager->get_widget("/MenuBar"); } -Gtk::Menu& Menu::get_cpp() { - return *(Gtk::Menu*)ui_manager->get_widget("/MenuBar/CppMenu"); +Gtk::Menu& Menu::get_source_menu() { + return *(Gtk::Menu*)ui_manager->get_widget("/MenuBar/SourceMenu"); } void Menu::build() { diff --git a/juci/menu.h b/juci/menu.h index dc95ce4..40e3cb3 100644 --- a/juci/menu.h +++ b/juci/menu.h @@ -9,7 +9,7 @@ class Menu { public: Menu(); Gtk::Widget& get_widget(); - Gtk::Menu& get_cpp(); + Gtk::Menu& get_source_menu(); void build(); Gtk::Box box; diff --git a/juci/menu.xml b/juci/menu.xml index 9c6a63f..5f79da8 100644 --- a/juci/menu.xml +++ b/juci/menu.xml @@ -17,7 +17,10 @@ - + + + + diff --git a/juci/notebook.cc b/juci/notebook.cc index 261b438..e812dcd 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -4,6 +4,8 @@ #include "singletons.h" #include // c-library +#include //TODO: remove +using namespace std; //TODO: remove Notebook::View::View() { pack2(notebook); @@ -13,6 +15,7 @@ Notebook::View::View() { Notebook::Controller::Controller() : directories() { INFO("Create notebook"); + Gsv::init(); clipboard = Gtk::Clipboard::get(); view.pack1(directories.widget(), true, true); CreateKeybindings(); @@ -70,6 +73,19 @@ void Notebook::Controller::CreateKeybindings() { } INFO("Done Redo"); }); + + menu->action_group->add(Gtk::Action::create("SourceGotoDeclaration", "Go to declaration"), Gtk::AccelKey(menu->key_map["goto_declaration"]), [this]() { + if(CurrentPage()!=-1) { + if(CurrentSourceView()->get_declaration_location) { + auto location=CurrentSourceView()->get_declaration_location(); + if(location.first.size()>0) { + open_file(location.first); + CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); + CurrentSourceView()->scroll_to_insert(); + } + } + } + }); entry.button_apply_set_filename.signal_clicked().connect([this]() { std::string filename=entry(); @@ -83,7 +99,7 @@ void Notebook::Controller::CreateKeybindings() { else { std::ofstream f(p.string().c_str()); if(f) { - OnOpenFile(boost::filesystem::canonical(p).string()); + open_file(boost::filesystem::canonical(p).string()); if(project_path!="") directories.open_folder(project_path); //TODO: Do refresh instead } @@ -113,14 +129,21 @@ void Notebook::Controller::CreateKeybindings() { INFO("Notebook signal handlers sucsess"); } -void Notebook::Controller::OnOpenFile(std::string path) { +void Notebook::Controller::open_file(std::string path) { INFO("Notebook open file"); INFO("Notebook create page"); + for(int c=0;cview->file_path) { + view.notebook.set_current_page(c); + return; + } + } source_views.emplace_back(new Source(path, project_path)); scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); hboxes.emplace_back(new Gtk::HBox()); scrolled_windows.back()->add(*source_views.back()->view); hboxes.back()->pack_start(*scrolled_windows.back(), true, true); + boost::filesystem::path file_path(source_views.back()->view->file_path); std::string title=file_path.filename().string(); view.notebook.append_page(*hboxes.back(), title); @@ -206,7 +229,7 @@ void Notebook::Controller std::stringstream sstm; sstm << row[directories.view().m_col_path]; std::string file = sstm.str(); - OnOpenFile(file); + open_file(file); } } } diff --git a/juci/notebook.h b/juci/notebook.h index 13808c2..9c1f507 100644 --- a/juci/notebook.h +++ b/juci/notebook.h @@ -29,7 +29,7 @@ namespace Notebook { bool OnSaveFile(std::string path); void OnDirectoryNavigation(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); - void OnOpenFile(std::string filename); + void open_file(std::string filename); int Pages(); void search(bool forward); View view; diff --git a/juci/source.cc b/juci/source.cc index f01d35b..6643431 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -8,6 +8,9 @@ #include #include "singletons.h" +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -27,7 +30,6 @@ bool Source::Config::legal_extension(std::string e) const { ////////////// Source::View::View(const std::string& file_path, const std::string& project_path): file_path(file_path), project_path(project_path) { - Gsv::init(); 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); @@ -44,6 +46,10 @@ file_path(file_path), project_path(project_path) { for (auto &item : Singleton::Config::source()->tags) { get_source_buffer()->create_tag(item.first)->property_foreground() = item.second; } + + scroll_to_insert_dispatcher.connect([this](){ + scroll_to(get_buffer()->get_insert()); + }); } string Source::View::get_line(size_t line_number) { @@ -62,12 +68,21 @@ string Source::View::get_line_before_insert() { return line; } +//TODO: Fix this dirty hack. Gtk's scroll_to is bugged... +void Source::View::scroll_to_insert() { + std::thread scroll_to_insert_thread([this](){ + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + scroll_to_insert_dispatcher(); + }); + scroll_to_insert_thread.detach(); +} + //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { auto config=Singleton::Config::source(); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); //Indent as in next or previous line - if(key->keyval==GDK_KEY_Return && key->state==0) { + if(key->keyval==GDK_KEY_Return && key->state==0 && !get_buffer()->get_has_selection()) { int line_nr=get_source_buffer()->get_insert()->get_iter().get_line(); string line(get_line_before_insert()); std::smatch sm; @@ -124,7 +139,7 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return true; } //"Smart" backspace key - else if(key->keyval==GDK_KEY_BackSpace) { + else if(key->keyval==GDK_KEY_BackSpace && !get_buffer()->get_has_selection()) { Gtk::TextIter insert_it=get_source_buffer()->get_insert()->get_iter(); int line_nr=insert_it.get_line(); if(line_nr>0) { @@ -421,7 +436,7 @@ void Source::ClangViewParse::on_mark_set(const Gtk::TextBuffer::iterator& iterat return false; }, 500); type_tooltips.hide(); - diagnostic_tooltips.hide(); + diagnostic_tooltips.hide(); } } @@ -442,6 +457,9 @@ bool Source::ClangViewParse::on_scroll_event(GdkEventScroll* event) { //Clang indentation //TODO: replace indentation methods with a better implementation or maybe use libclang bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { + if(get_buffer()->get_has_selection()) { + return Source::View::on_key_press_event(key); + } auto config=Singleton::Config::source(); const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$"); const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); @@ -766,6 +784,26 @@ Source::ClangViewAutocomplete(file_path, project_path) { } } }); + + get_declaration_location=[this](){ + std::pair location; + if(clang_readable) { + for(auto &token: *clang_tokens) { + if(token.has_type()) { + auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); + if(insert_offset>=token.offsets.first && insert_offset<=token.offsets.second) { + auto referenced=token.get_cursor().get_referenced(); + if(referenced) { + location.first=referenced.get_source_location().get_path(); + location.second=referenced.get_source_location().get_offset(); + break; + } + } + } + } + } + return location; + }; } //////////////// diff --git a/juci/source.h b/juci/source.h index 6762980..26dc02f 100644 --- a/juci/source.h +++ b/juci/source.h @@ -49,11 +49,16 @@ public: View(const std::string& file_path, const std::string& project_path); std::string get_line(size_t line_number); std::string get_line_before_insert(); + void scroll_to_insert(); std::string file_path; std::string project_path; Gtk::TextIter search_start, search_end; + + std::function()> get_declaration_location; protected: bool on_key_press_event(GdkEventKey* key); + private: + Glib::Dispatcher scroll_to_insert_dispatcher; }; // class View class GenericView : public View { diff --git a/juci/sourcefile.h b/juci/sourcefile.h index 608ea05..2afc263 100644 --- a/juci/sourcefile.h +++ b/juci/sourcefile.h @@ -4,20 +4,18 @@ #include #include -using namespace std; - class sourcefile { public: - explicit sourcefile(const string &filename); - vector get_lines(); - string get_content(); - string get_line(int line_number); - int save(const string &text); + explicit sourcefile(const std::string &filename); + std::vector get_lines(); + std::string get_content(); + std::string get_line(int line_number); + int save(const std::string &text); private: - void open(const string &filename); - vector lines; - string filename; + void open(const std::string &filename); + std::vector lines; + std::string filename; }; #endif // JUCI_SOURCEFILE_H_ diff --git a/juci/terminal.cc b/juci/terminal.cc index 20f1033..aad7e45 100644 --- a/juci/terminal.cc +++ b/juci/terminal.cc @@ -87,8 +87,10 @@ int Terminal::Controller::print(std::string message){ INFO("Terminal: PrintMessage"); view.text_view.get_buffer()->insert(view.text_view.get_buffer()->end(), "> "+message); auto mark_end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end()); - view.text_view.scroll_to(mark_end); - return mark_end->get_iter().get_line(); + view.text_view.scroll_to(view.text_view.get_buffer()->get_insert()); + auto line=mark_end->get_iter().get_line(); + view.text_view.get_buffer()->delete_mark(mark_end); + return line; } void Terminal::Controller::print(int line_nr, std::string message){ diff --git a/juci/window.cc b/juci/window.cc index 63b2d8f..cdf27d0 100644 --- a/juci/window.cc +++ b/juci/window.cc @@ -148,7 +148,7 @@ void Window::OnOpenFile() { switch (result) { case(Gtk::RESPONSE_OK): { std::string path = dialog.get_filename(); - Singleton::notebook()->OnOpenFile(path); + Singleton::notebook()->open_file(path); break; } case(Gtk::RESPONSE_CANCEL): { From 0be130dd94811a7e01648c73ec235086bad1af3d Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 15:27:08 +0200 Subject: [PATCH 06/14] Solved the scroll_to issue. --- juci/notebook.cc | 2 +- juci/source.cc | 12 ++---------- juci/source.h | 3 --- juci/terminal.cc | 10 +++++----- 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/juci/notebook.cc b/juci/notebook.cc index e812dcd..51093dc 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -81,7 +81,7 @@ void Notebook::Controller::CreateKeybindings() { if(location.first.size()>0) { open_file(location.first); CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); - CurrentSourceView()->scroll_to_insert(); + CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert()); } } } diff --git a/juci/source.cc b/juci/source.cc index 6643431..86c72fb 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -47,7 +47,8 @@ file_path(file_path), project_path(project_path) { get_source_buffer()->create_tag(item.first)->property_foreground() = item.second; } - scroll_to_insert_dispatcher.connect([this](){ + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); + signal_size_allocate().connect([this](Gtk::Allocation& allocation){ scroll_to(get_buffer()->get_insert()); }); } @@ -68,15 +69,6 @@ string Source::View::get_line_before_insert() { return line; } -//TODO: Fix this dirty hack. Gtk's scroll_to is bugged... -void Source::View::scroll_to_insert() { - std::thread scroll_to_insert_thread([this](){ - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - scroll_to_insert_dispatcher(); - }); - scroll_to_insert_thread.detach(); -} - //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { auto config=Singleton::Config::source(); diff --git a/juci/source.h b/juci/source.h index 26dc02f..14cc2a6 100644 --- a/juci/source.h +++ b/juci/source.h @@ -49,7 +49,6 @@ public: View(const std::string& file_path, const std::string& project_path); std::string get_line(size_t line_number); std::string get_line_before_insert(); - void scroll_to_insert(); std::string file_path; std::string project_path; Gtk::TextIter search_start, search_end; @@ -57,8 +56,6 @@ public: std::function()> get_declaration_location; protected: bool on_key_press_event(GdkEventKey* key); - private: - Glib::Dispatcher scroll_to_insert_dispatcher; }; // class View class GenericView : public View { diff --git a/juci/terminal.cc b/juci/terminal.cc index aad7e45..781a052 100644 --- a/juci/terminal.cc +++ b/juci/terminal.cc @@ -51,6 +51,10 @@ Terminal::View::View(){ Terminal::Controller::Controller() { folder_command_ = ""; + view.text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ + auto iter=view.text_view.get_buffer()->end(); + view.text_view.scroll_to(iter); + }); } void Terminal::Controller::SetFolderCommand( boost::filesystem::path @@ -86,11 +90,7 @@ void Terminal::Controller::Run(std::string executable) { int Terminal::Controller::print(std::string message){ INFO("Terminal: PrintMessage"); view.text_view.get_buffer()->insert(view.text_view.get_buffer()->end(), "> "+message); - auto mark_end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end()); - view.text_view.scroll_to(view.text_view.get_buffer()->get_insert()); - auto line=mark_end->get_iter().get_line(); - view.text_view.get_buffer()->delete_mark(mark_end); - return line; + return view.text_view.get_buffer()->end().get_line(); } void Terminal::Controller::print(int line_nr, std::string message){ From 36ce5fab10d9be7bd2c9d690d74af5d5c73a576a Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 15:33:56 +0200 Subject: [PATCH 07/14] Solved the scroll_to issue. --- juci/terminal.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/juci/terminal.cc b/juci/terminal.cc index 781a052..1e25e92 100644 --- a/juci/terminal.cc +++ b/juci/terminal.cc @@ -52,8 +52,9 @@ Terminal::View::View(){ Terminal::Controller::Controller() { folder_command_ = ""; view.text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ - auto iter=view.text_view.get_buffer()->end(); - view.text_view.scroll_to(iter); + auto end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end()); + view.text_view.scroll_to(end); + view.text_view.get_buffer()->delete_mark(end); }); } From 2169158689b135cb7b428109ca4c3cded57824e7 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 16:12:55 +0200 Subject: [PATCH 08/14] Improved scroll_to. --- juci/notebook.cc | 2 +- juci/source.cc | 9 ++++++++- juci/source.h | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/juci/notebook.cc b/juci/notebook.cc index 51093dc..3fdd7a7 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -81,7 +81,7 @@ void Notebook::Controller::CreateKeybindings() { if(location.first.size()>0) { open_file(location.first); CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); - CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert()); + CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } } } diff --git a/juci/source.cc b/juci/source.cc index 86c72fb..cbdacef 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -49,7 +49,8 @@ file_path(file_path), project_path(project_path) { get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); signal_size_allocate().connect([this](Gtk::Allocation& allocation){ - scroll_to(get_buffer()->get_insert()); + if(!user_input_started) + scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); }); } @@ -71,6 +72,7 @@ string Source::View::get_line_before_insert() { //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { + user_input_started=true; auto config=Singleton::Config::source(); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); //Indent as in next or previous line @@ -149,6 +151,11 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return Gsv::View::on_key_press_event(key); } +bool Source::View::on_button_press_event(GdkEventButton *event) { + user_input_started=true; + return Gsv::View::on_button_press_event(event); +} + ///////////////////////// //// ClangViewParse /// ///////////////////////// diff --git a/juci/source.h b/juci/source.h index 14cc2a6..c946c3e 100644 --- a/juci/source.h +++ b/juci/source.h @@ -56,6 +56,9 @@ public: std::function()> get_declaration_location; protected: bool on_key_press_event(GdkEventKey* key); + bool on_button_press_event(GdkEventButton *event); + private: + bool user_input_started=false; }; // class View class GenericView : public View { From 2161c9ce0939b368f813e3cc1114ed70204fda19 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 18:45:02 +0200 Subject: [PATCH 09/14] scroll_to hopefully working 100% now. --- juci/notebook.cc | 5 +++++ juci/source.cc | 14 +++++++------- juci/source.h | 4 +--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/juci/notebook.cc b/juci/notebook.cc index 3fdd7a7..04eb689 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -82,6 +82,11 @@ void Notebook::Controller::CreateKeybindings() { open_file(location.first); CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + + /*CurrentSourceView()->signal_size_allocate().connect([this](Gtk::Allocation& allocation){ + auto adj=scrolled_windows.at(CurrentPage())->get_vadjustment(); + cout << adj->get_upper() << ", " << adj->get_page_size() << endl; + });*/ } } } diff --git a/juci/source.cc b/juci/source.cc index cbdacef..187ffc6 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -49,9 +49,15 @@ file_path(file_path), project_path(project_path) { get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); signal_size_allocate().connect([this](Gtk::Allocation& allocation){ - if(!user_input_started) + if(!after_user_input) scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); }); + + signal_event().connect([this](GdkEvent* event){ + if(event->type==GDK_KEY_PRESS || event->type==GDK_BUTTON_PRESS || event->type==GDK_SCROLL) + after_user_input=true; + return false; + }); } string Source::View::get_line(size_t line_number) { @@ -72,7 +78,6 @@ string Source::View::get_line_before_insert() { //Basic indentation bool Source::View::on_key_press_event(GdkEventKey* key) { - user_input_started=true; auto config=Singleton::Config::source(); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); //Indent as in next or previous line @@ -151,11 +156,6 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { return Gsv::View::on_key_press_event(key); } -bool Source::View::on_button_press_event(GdkEventButton *event) { - user_input_started=true; - return Gsv::View::on_button_press_event(event); -} - ///////////////////////// //// ClangViewParse /// ///////////////////////// diff --git a/juci/source.h b/juci/source.h index c946c3e..53828cd 100644 --- a/juci/source.h +++ b/juci/source.h @@ -54,11 +54,9 @@ public: Gtk::TextIter search_start, search_end; std::function()> get_declaration_location; + bool after_user_input=false; protected: bool on_key_press_event(GdkEventKey* key); - bool on_button_press_event(GdkEventButton *event); - private: - bool user_input_started=false; }; // class View class GenericView : public View { From 7149d416b82539a86283e0febb187d5e74c6ef8a Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 19 Jul 2015 19:11:19 +0200 Subject: [PATCH 10/14] Apple users can now finally use the command key instead of control. --- juci/config.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/juci/config.cc b/juci/config.cc index 4cd3b71..7302984 100644 --- a/juci/config.cc +++ b/juci/config.cc @@ -82,8 +82,15 @@ void MainConfig::GenerateKeybindings() { menu->ui+=line; } boost::property_tree::ptree keys_json = cfg_.get_child("keybindings"); - for (auto &i : keys_json) - menu->key_map[i.first] = i.second.get_value(); + for (auto &i : keys_json) { + auto key=i.second.get_value(); +#ifdef __APPLE__ + auto pos=key.find(""); + if(pos!=std::string::npos) + key.replace(pos, 9, ""); +#endif + menu->key_map[i.first] = key; + } DEBUG("Keybindings fetched"); } From 57ffd22aa36cea970eab68ee79a93f63ac5fde24 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 20 Jul 2015 20:03:50 +0200 Subject: [PATCH 11/14] Divided SelectionDialog into SelectionDialog and CompleteDialog. SelectionDialog will be used to choose class method to go to. --- juci/config.json | 1 + juci/menu.xml | 1 + juci/notebook.cc | 13 +- juci/selectiondialog.cc | 283 +++++++++++++++++++++++++++------------- juci/selectiondialog.h | 48 ++++--- juci/source.cc | 60 +++++---- juci/source.h | 4 +- 7 files changed, 274 insertions(+), 136 deletions(-) diff --git a/juci/config.json b/juci/config.json index 9c3e0a0..efc9003 100644 --- a/juci/config.json +++ b/juci/config.json @@ -59,6 +59,7 @@ "edit_redo": "y", "edit_find": "f", "goto_declaration": "d", + "goto_method": "m", "compile_and_run": "r", "compile": "r" }, diff --git a/juci/menu.xml b/juci/menu.xml index 5f79da8..d9937d8 100644 --- a/juci/menu.xml +++ b/juci/menu.xml @@ -20,6 +20,7 @@ + diff --git a/juci/notebook.cc b/juci/notebook.cc index 04eb689..da6202d 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -82,15 +82,18 @@ void Notebook::Controller::CreateKeybindings() { open_file(location.first); CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second)); CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); - - /*CurrentSourceView()->signal_size_allocate().connect([this](Gtk::Allocation& allocation){ - auto adj=scrolled_windows.at(CurrentPage())->get_vadjustment(); - cout << adj->get_upper() << ", " << adj->get_page_size() << endl; - });*/ } } } }); + + menu->action_group->add(Gtk::Action::create("SourceGotoMethod", "Go to method"), Gtk::AccelKey(menu->key_map["goto_method"]), [this]() { + if(CurrentPage()!=-1) { + if(CurrentSourceView()->goto_method) { + CurrentSourceView()->goto_method(); + } + } + }); entry.button_apply_set_filename.signal_clicked().connect([this]() { std::string filename=entry(); diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 18e9f1a..49b15f4 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -1,14 +1,23 @@ #include "selectiondialog.h" -SelectionDialog::SelectionDialog(Gtk::TextView& text_view): text_view(text_view) {} +namespace sigc { + SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE +} -void SelectionDialog::show() { +SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, bool popup): text_view(text_view), popup(popup) {} + +void SelectionDialogBase::show() { if(rows.size()==0) return; - window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); + if(popup) + window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); + else + window=std::unique_ptr(new Gtk::Dialog()); scrolled_window=std::unique_ptr(new Gtk::ScrolledWindow()); list_view_text=std::unique_ptr(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_BROWSE)); + search_entry=std::unique_ptr(new Gtk::Entry()); + list_view_text->set_search_entry(*search_entry); window->set_default_size(0, 0); window->property_decorated()=false; @@ -24,43 +33,38 @@ void SelectionDialog::show() { last_selected=-1; - list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { - if(shown) { - select(); - } - }); list_view_text->signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true); list_view_text->signal_realize().connect([this](){ resize(); }); - show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); list_view_text->clear_items(); for (auto &i : rows) { list_view_text->append(i.first); } scrolled_window->add(*list_view_text); - window->add(*scrolled_window); - + if(popup) + window->add(*scrolled_window); + else { + auto dialog=(Gtk::Dialog*)window.get(); + dialog->get_vbox()->pack_start(*search_entry, false, false); + dialog->get_vbox()->pack_start(*scrolled_window, true, true); + dialog->set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); + } if(rows.size()>0) { list_view_text->get_selection()->select(*list_view_text->get_model()->children().begin()); list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); } - + move(); - window->show_all(); + search_entry->show(); shown=true; row_in_entry=false; - auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); - if(text.size()>0) { - search_entry.set_text(text); - list_view_text->set_search_entry(search_entry); - } } -void SelectionDialog::hide() { +void SelectionDialogBase::hide() { shown=false; window->hide(); if(tooltips) @@ -69,7 +73,167 @@ void SelectionDialog::hide() { on_hide(); } -void SelectionDialog::select(bool hide_window) { +void SelectionDialogBase::cursor_changed() { + auto selected=list_view_text->get_selected(); + if(selected.size()>0) { + if(selected[0]!=last_selected || last_selected==-1) { + if(tooltips) + tooltips->hide(); + auto row = rows.at(list_view_text->get_text(selected[0])); + if(row.second.size()>0) { + tooltips=std::unique_ptr(new Tooltips()); + auto tooltip_text=row.second; + auto get_tooltip_buffer=[this, tooltip_text]() { + auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); + //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) + tooltip_buffer->insert_at_cursor(tooltip_text); + return tooltip_buffer; + }; + tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); + tooltips->show(true); + } + } + } + else if(tooltips) + tooltips->hide(); + if(selected.size()>0) + last_selected=selected[0]; + else + last_selected=-1; +} + +void SelectionDialogBase::move() { + INFO("SelectionDialog set position"); + Gdk::Rectangle rectangle; + text_view.get_iter_location(start_mark->get_iter(), rectangle); + int buffer_x=rectangle.get_x(); + int buffer_y=rectangle.get_y()+rectangle.get_height(); + int window_x, window_y; + text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); + int root_x, root_y; + text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); + window->move(root_x, root_y+1); //TODO: replace 1 with some margin +} + +void SelectionDialogBase::resize() { + INFO("SelectionDialog set size"); + + if(list_view_text->get_realized()) { + int row_width=0, row_height; + Gdk::Rectangle rect; + list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); + row_width=rect.get_width(); + row_height=rect.get_height(); + + row_width+=rect.get_x()*2; //TODO: Add correct margin x and y + row_height+=rect.get_y()*2; + + if(row_width>text_view.get_width()/2) + row_width=text_view.get_width()/2; + else + scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); + + int window_height=std::min(row_height*(int)rows.size(), row_height*10); + if(!popup) + window_height+=search_entry->get_height(); + window->resize(row_width, window_height); + } +} + +SelectionDialog::SelectionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, false) {} + +void SelectionDialog::show() { + SelectionDialogBase::show(); + std::shared_ptr search_key(new std::string()); + auto filter_model=Gtk::TreeModelFilter::create(list_view_text->get_model()); + filter_model->set_visible_func([this, search_key](const Gtk::TreeModel::const_iterator& iter){ + std::string row; + iter->get_value(0, row); + if(row.find(*search_key)!=std::string::npos) + return true; + return false; + }); + list_view_text->set_model(filter_model); + list_view_text->set_search_equal_func([this](const Glib::RefPtr& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) { + return false; + }); + search_entry->signal_changed().connect([this, search_key, filter_model](){ + *search_key=search_entry->get_text(); + filter_model->refilter(); + list_view_text->set_search_entry(*search_entry); //TODO:Report the need of this to GTK's git (bug) + }); + search_entry->signal_event().connect([this, search_key, filter_model](GdkEvent* event) { + if(event->type==GDK_KEY_PRESS) { + auto key=(GdkEventKey*)event; + if(key->keyval==GDK_KEY_Down) { + auto it=list_view_text->get_selection()->get_selected(); + if(it) { + it++; + if(it) { + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + } + } + else + list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); + return true; + } + if(key->keyval==GDK_KEY_Up) { + auto it=list_view_text->get_selection()->get_selected(); + if(it) { + it--; + if(it) { + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + } + } + return true; + } + } + return false; + }); + auto activate=[this](){ + if(on_select && list_view_text->get_selected().size()>0) { + auto it=list_view_text->get_selection()->get_selected(); + std::string row; + it->get_value(0, row); + std::string selected = rows.at(row).first; + on_select(selected); + } + window->hide(); + }; + search_entry->signal_activate().connect([this, activate](){ + activate(); + }); + list_view_text->signal_row_activated().connect([this, activate](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + activate(); + }); + window->signal_focus_out_event().connect([this](GdkEventFocus*){ + window->hide(); + return true; + }); + list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); +} + +CompleteDialog::CompleteDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, true) {} + +void CompleteDialog::show() { + SelectionDialogBase::show(); + + show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); + + list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + if(shown) { + select(); + } + }); + + auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); + if(text.size()>0) { + search_entry->set_text(text); + list_view_text->set_search_entry(*search_entry); + } +} + +void CompleteDialog::select(bool hide_window) { row_in_entry=true; auto selected=list_view_text->get_selected(); std::pair select; @@ -97,7 +261,7 @@ void SelectionDialog::select(bool hide_window) { } } -bool SelectionDialog::on_key_release(GdkEventKey* key) { +bool CompleteDialog::on_key_release(GdkEventKey* key) { if(key->keyval==GDK_KEY_Down || key->keyval==GDK_KEY_Up) return false; @@ -107,15 +271,15 @@ bool SelectionDialog::on_key_release(GdkEventKey* key) { else { auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); if(text.size()>0) { - search_entry.set_text(text); - list_view_text->set_search_entry(search_entry); + search_entry->set_text(text); + list_view_text->set_search_entry(*search_entry); } cursor_changed(); } return false; } -bool SelectionDialog::on_key_press(GdkEventKey* key) { +bool CompleteDialog::on_key_press(GdkEventKey* key) { if((key->keyval>=GDK_KEY_0 && key->keyval<=GDK_KEY_9) || (key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) || (key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) || @@ -136,8 +300,7 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { if(it) { it++; if(it) { - list_view_text->get_selection()->select(it); - list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); } } select(false); @@ -149,8 +312,7 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { if(it) { it--; if(it) { - list_view_text->get_selection()->select(it); - list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); + list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); } } select(false); @@ -164,68 +326,3 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) { hide(); return false; } - -void SelectionDialog::cursor_changed() { - auto selected=list_view_text->get_selected(); - if(selected.size()>0) { - if(selected[0]!=last_selected || last_selected==-1) { - if(tooltips) - tooltips->hide(); - auto row = rows.at(list_view_text->get_text(selected[0])); - if(row.second.size()>0) { - tooltips=std::unique_ptr(new Tooltips()); - auto tooltip_text=row.second; - auto get_tooltip_buffer=[this, tooltip_text]() { - auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); - //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) - tooltip_buffer->insert_at_cursor(tooltip_text); - return tooltip_buffer; - }; - tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); - tooltips->show(true); - } - } - } - else if(tooltips) - tooltips->hide(); - if(selected.size()>0) - last_selected=selected[0]; - else - last_selected=-1; -} - -void SelectionDialog::move() { - INFO("SelectionDialog set position"); - Gdk::Rectangle rectangle; - text_view.get_iter_location(start_mark->get_iter(), rectangle); - int buffer_x=rectangle.get_x(); - int buffer_y=rectangle.get_y()+rectangle.get_height(); - int window_x, window_y; - text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); - int root_x, root_y; - text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); - window->move(root_x, root_y+1); //TODO: replace 1 with some margin -} - -void SelectionDialog::resize() { - INFO("SelectionDialog set size"); - - if(list_view_text->get_realized()) { - int row_width=0, row_height; - Gdk::Rectangle rect; - list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); - row_width=rect.get_width(); - row_height=rect.get_height(); - - row_width+=rect.get_x()*2; //TODO: Add correct margin x and y - row_height+=rect.get_y()*2; - - if(row_width>text_view.get_width()/2) - row_width=text_view.get_width()/2; - else - scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); - - int window_height=std::min(row_height*(int)rows.size(), row_height*10); - window->resize(row_width, window_height); - } -} diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index b497d6c..0f1c793 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -5,35 +5,53 @@ #include "logging.h" #include "tooltips.h" -class SelectionDialog { +class SelectionDialogBase { public: - SelectionDialog(Gtk::TextView& text_view); - void show(); - void hide(); - bool close(GdkEventFocus*); - void move(); - bool on_key_release(GdkEventKey* key); - bool on_key_press(GdkEventKey* key); - std::function on_hide; + SelectionDialogBase(Gtk::TextView& text_view, bool popup); + virtual void show(); + virtual void hide(); + virtual void move(); std::map > rows; + std::function on_hide; bool shown=false; Glib::RefPtr start_mark; -private: - void resize(); - void select(bool hide_window=true); - void cursor_changed(); +protected: + virtual void resize(); + virtual void cursor_changed(); - Gtk::Entry search_entry; - int show_offset; bool row_in_entry; Gtk::TextView& text_view; std::unique_ptr window; std::unique_ptr scrolled_window; std::unique_ptr list_view_text; + std::unique_ptr search_entry; std::unique_ptr tooltips; int last_selected; +private: + bool popup; +}; + +class SelectionDialog : public SelectionDialogBase { +public: + SelectionDialog(Gtk::TextView& text_view); + void show(); + std::function on_select; +}; + +class CompleteDialog : public SelectionDialogBase { +public: + CompleteDialog(Gtk::TextView& text_view); + void show(); + bool on_key_release(GdkEventKey* key); + bool on_key_press(GdkEventKey* key); + +private: + void select(bool hide_window=true); + + int show_offset; + bool row_in_entry; }; #endif // JUCI_SELECTIONDIALOG_H_ \ No newline at end of file diff --git a/juci/source.cc b/juci/source.cc index 187ffc6..8f1bdc9 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -547,32 +547,32 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { //// ClangViewAutocomplete /// ////////////////////////////// Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): -Source::ClangViewParse(file_path, project_path), selection_dialog(*this), autocomplete_cancel_starting(false) { - selection_dialog.on_hide=[this](){ +Source::ClangViewParse(file_path, project_path), complete_dialog(*this), autocomplete_cancel_starting(false) { + complete_dialog.on_hide=[this](){ start_reparse(); }; get_buffer()->signal_changed().connect([this](){ - if(selection_dialog.shown) + if(complete_dialog.shown) delayed_reparse_connection.disconnect(); start_autocomplete(); }); get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ if(mark->get_name()=="insert") { autocomplete_cancel_starting=true; - if(selection_dialog.shown) { - selection_dialog.hide(); + if(complete_dialog.shown) { + complete_dialog.hide(); } } }); signal_scroll_event().connect([this](GdkEventScroll* event){ - if(selection_dialog.shown) - selection_dialog.hide(); + if(complete_dialog.shown) + complete_dialog.hide(); return false; }, false); signal_key_release_event().connect([this](GdkEventKey* key){ - if(selection_dialog.shown) { - if(selection_dialog.on_key_release(key)) + if(complete_dialog.shown) { + if(complete_dialog.on_key_release(key)) return true; } @@ -582,16 +582,16 @@ Source::ClangViewParse(file_path, project_path), selection_dialog(*this), autoco bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { last_keyval=key->keyval; - if(selection_dialog.shown) { - if(selection_dialog.on_key_press(key)) + if(complete_dialog.shown) { + if(complete_dialog.on_key_press(key)) return true; } return ClangViewParse::on_key_press_event(key); } bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { - if(selection_dialog.shown) { - selection_dialog.hide(); + if(complete_dialog.shown) { + complete_dialog.hide(); } return Source::ClangViewParse::on_focus_out_event(event); @@ -613,7 +613,7 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !complete_dialog.shown) { autocomplete(); } else if(last_keyval=='.' && autocomplete_starting) @@ -623,13 +623,13 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !complete_dialog.shown) { autocomplete(); } } else autocomplete_cancel_starting=true; - if(autocomplete_starting || selection_dialog.shown) + if(autocomplete_starting || complete_dialog.shown) delayed_reparse_connection.disconnect(); } } @@ -644,12 +644,12 @@ void Source::ClangViewAutocomplete::autocomplete() { autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_starting=false; if(!autocomplete_cancel_starting) { - if(selection_dialog.start_mark) - get_buffer()->delete_mark(selection_dialog.start_mark); + if(complete_dialog.start_mark) + get_buffer()->delete_mark(complete_dialog.start_mark); auto start_iter=get_buffer()->get_insert()->get_iter(); for(size_t c=0;ccreate_mark(start_iter); + complete_dialog.start_mark=get_buffer()->create_mark(start_iter); std::map > rows; for (auto &data : *ac_data) { @@ -673,8 +673,8 @@ void Source::ClangViewAutocomplete::autocomplete() { if (rows.empty()) { rows["No suggestions found..."] = std::pair(); } - selection_dialog.rows=std::move(rows); - selection_dialog.show(); + complete_dialog.rows=std::move(rows); + complete_dialog.show(); } else start_autocomplete(); @@ -740,7 +740,7 @@ get_autocomplete_suggestions(int line_number, int column, std::mapcreate_tag(); similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; @@ -803,6 +803,22 @@ Source::ClangViewAutocomplete(file_path, project_path) { } return location; }; + + goto_method=[this](){ + if(selection_dialog.start_mark) + get_buffer()->delete_mark(selection_dialog.start_mark); + selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); + + std::map > rows; + rows["Not implemented yet"]=std::pair("1", ""); + rows["but you can try the selection search"]=std::pair("2", ""); + rows["search for instance for 'try'"]=std::pair("3", ""); + selection_dialog.rows=std::move(rows); + selection_dialog.on_select=[this](std::string selected) { + cout << selected << endl; + }; + selection_dialog.show(); + }; } //////////////// diff --git a/juci/source.h b/juci/source.h index 53828cd..1a3683d 100644 --- a/juci/source.h +++ b/juci/source.h @@ -54,6 +54,7 @@ public: Gtk::TextIter search_start, search_end; std::function()> get_declaration_location; + std::function goto_method; bool after_user_input=false; protected: bool on_key_press_event(GdkEventKey* key); @@ -119,7 +120,7 @@ public: private: void start_autocomplete(); void autocomplete(); - SelectionDialog selection_dialog; + CompleteDialog complete_dialog; std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); Glib::Dispatcher autocomplete_done; sigc::connection autocomplete_done_connection; @@ -136,6 +137,7 @@ public: private: Glib::RefPtr similar_tokens_tag; std::string last_similar_tokens_tagged; + SelectionDialog selection_dialog; }; class ClangView : public ClangViewRefactor { From bfdbe6b3c88bdde06d5f2ef8afceeb9d3d577320 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 20 Jul 2015 20:19:06 +0200 Subject: [PATCH 12/14] Renamed CompleteDialog to CompletionDialog and fixed a small issue. --- juci/selectiondialog.cc | 13 +++++++------ juci/selectiondialog.h | 6 ++---- juci/source.cc | 42 ++++++++++++++++++++--------------------- juci/source.h | 2 +- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 49b15f4..52a673a 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -61,7 +61,6 @@ void SelectionDialogBase::show() { window->show_all(); search_entry->show(); shown=true; - row_in_entry=false; } void SelectionDialogBase::hide() { @@ -213,9 +212,9 @@ void SelectionDialog::show() { list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); } -CompleteDialog::CompleteDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, true) {} +CompletionDialog::CompletionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, true) {} -void CompleteDialog::show() { +void CompletionDialog::show() { SelectionDialogBase::show(); show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); @@ -231,9 +230,11 @@ void CompleteDialog::show() { search_entry->set_text(text); list_view_text->set_search_entry(*search_entry); } + + row_in_entry=false; } -void CompleteDialog::select(bool hide_window) { +void CompletionDialog::select(bool hide_window) { row_in_entry=true; auto selected=list_view_text->get_selected(); std::pair select; @@ -261,7 +262,7 @@ void CompleteDialog::select(bool hide_window) { } } -bool CompleteDialog::on_key_release(GdkEventKey* key) { +bool CompletionDialog::on_key_release(GdkEventKey* key) { if(key->keyval==GDK_KEY_Down || key->keyval==GDK_KEY_Up) return false; @@ -279,7 +280,7 @@ bool CompleteDialog::on_key_release(GdkEventKey* key) { return false; } -bool CompleteDialog::on_key_press(GdkEventKey* key) { +bool CompletionDialog::on_key_press(GdkEventKey* key) { if((key->keyval>=GDK_KEY_0 && key->keyval<=GDK_KEY_9) || (key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) || (key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) || diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index 0f1c793..ffb631f 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -20,8 +20,6 @@ protected: virtual void resize(); virtual void cursor_changed(); - bool row_in_entry; - Gtk::TextView& text_view; std::unique_ptr window; std::unique_ptr scrolled_window; @@ -40,9 +38,9 @@ public: std::function on_select; }; -class CompleteDialog : public SelectionDialogBase { +class CompletionDialog : public SelectionDialogBase { public: - CompleteDialog(Gtk::TextView& text_view); + CompletionDialog(Gtk::TextView& text_view); void show(); bool on_key_release(GdkEventKey* key); bool on_key_press(GdkEventKey* key); diff --git a/juci/source.cc b/juci/source.cc index 8f1bdc9..ea1e34f 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -547,32 +547,32 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { //// ClangViewAutocomplete /// ////////////////////////////// Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): -Source::ClangViewParse(file_path, project_path), complete_dialog(*this), autocomplete_cancel_starting(false) { - complete_dialog.on_hide=[this](){ +Source::ClangViewParse(file_path, project_path), completion_dialog(*this), autocomplete_cancel_starting(false) { + completion_dialog.on_hide=[this](){ start_reparse(); }; get_buffer()->signal_changed().connect([this](){ - if(complete_dialog.shown) + if(completion_dialog.shown) delayed_reparse_connection.disconnect(); start_autocomplete(); }); get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ if(mark->get_name()=="insert") { autocomplete_cancel_starting=true; - if(complete_dialog.shown) { - complete_dialog.hide(); + if(completion_dialog.shown) { + completion_dialog.hide(); } } }); signal_scroll_event().connect([this](GdkEventScroll* event){ - if(complete_dialog.shown) - complete_dialog.hide(); + if(completion_dialog.shown) + completion_dialog.hide(); return false; }, false); signal_key_release_event().connect([this](GdkEventKey* key){ - if(complete_dialog.shown) { - if(complete_dialog.on_key_release(key)) + if(completion_dialog.shown) { + if(completion_dialog.on_key_release(key)) return true; } @@ -582,16 +582,16 @@ Source::ClangViewParse(file_path, project_path), complete_dialog(*this), autocom bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { last_keyval=key->keyval; - if(complete_dialog.shown) { - if(complete_dialog.on_key_press(key)) + if(completion_dialog.shown) { + if(completion_dialog.on_key_press(key)) return true; } return ClangViewParse::on_key_press_event(key); } bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { - if(complete_dialog.shown) { - complete_dialog.hide(); + if(completion_dialog.shown) { + completion_dialog.hide(); } return Source::ClangViewParse::on_focus_out_event(event); @@ -613,7 +613,7 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !complete_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { autocomplete(); } else if(last_keyval=='.' && autocomplete_starting) @@ -623,13 +623,13 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !complete_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { autocomplete(); } } else autocomplete_cancel_starting=true; - if(autocomplete_starting || complete_dialog.shown) + if(autocomplete_starting || completion_dialog.shown) delayed_reparse_connection.disconnect(); } } @@ -644,12 +644,12 @@ void Source::ClangViewAutocomplete::autocomplete() { autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_starting=false; if(!autocomplete_cancel_starting) { - if(complete_dialog.start_mark) - get_buffer()->delete_mark(complete_dialog.start_mark); + if(completion_dialog.start_mark) + get_buffer()->delete_mark(completion_dialog.start_mark); auto start_iter=get_buffer()->get_insert()->get_iter(); for(size_t c=0;ccreate_mark(start_iter); + completion_dialog.start_mark=get_buffer()->create_mark(start_iter); std::map > rows; for (auto &data : *ac_data) { @@ -673,8 +673,8 @@ void Source::ClangViewAutocomplete::autocomplete() { if (rows.empty()) { rows["No suggestions found..."] = std::pair(); } - complete_dialog.rows=std::move(rows); - complete_dialog.show(); + completion_dialog.rows=std::move(rows); + completion_dialog.show(); } else start_autocomplete(); diff --git a/juci/source.h b/juci/source.h index 1a3683d..2ead12c 100644 --- a/juci/source.h +++ b/juci/source.h @@ -120,7 +120,7 @@ public: private: void start_autocomplete(); void autocomplete(); - CompleteDialog complete_dialog; + CompletionDialog completion_dialog; std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); Glib::Dispatcher autocomplete_done; sigc::connection autocomplete_done_connection; From bac182a360ef2d0fcc7cc51f2c8ddb8da8f902ce Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 21 Jul 2015 13:43:14 +0200 Subject: [PATCH 13/14] Go to method implemented. --- juci/selectiondialog.cc | 26 +++++++++++++++----------- juci/selectiondialog.h | 6 +++++- juci/source.cc | 37 +++++++++++++++++++++++-------------- juci/source.h | 2 +- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 52a673a..6bee4cb 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -1,4 +1,5 @@ #include "selectiondialog.h" +#include namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE @@ -6,10 +7,7 @@ namespace sigc { SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, bool popup): text_view(text_view), popup(popup) {} -void SelectionDialogBase::show() { - if(rows.size()==0) - return; - +void SelectionDialogBase::init() { if(popup) window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); else @@ -39,10 +37,13 @@ void SelectionDialogBase::show() { }); list_view_text->clear_items(); - for (auto &i : rows) { - list_view_text->append(i.first); - } - +} + +void SelectionDialogBase::append(const std::string& row) { + list_view_text->append(row); +} + +void SelectionDialogBase::show() { scrolled_window->add(*list_view_text); if(popup) window->add(*scrolled_window); @@ -146,9 +147,12 @@ void SelectionDialog::show() { std::shared_ptr search_key(new std::string()); auto filter_model=Gtk::TreeModelFilter::create(list_view_text->get_model()); filter_model->set_visible_func([this, search_key](const Gtk::TreeModel::const_iterator& iter){ - std::string row; - iter->get_value(0, row); - if(row.find(*search_key)!=std::string::npos) + std::string row_lc; + iter->get_value(0, row_lc); + auto search_key_lc=*search_key; + std::transform(row_lc.begin(), row_lc.end(), row_lc.begin(), ::tolower); + std::transform(search_key_lc.begin(), search_key_lc.end(), search_key_lc.begin(), ::tolower); + if(row_lc.find(search_key_lc)!=std::string::npos) return true; return false; }); diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index ffb631f..7afad0e 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -8,11 +8,13 @@ class SelectionDialogBase { public: SelectionDialogBase(Gtk::TextView& text_view, bool popup); + virtual void init(); //TODO: use constructor instead of init + virtual void append(const std::string& row); virtual void show(); virtual void hide(); virtual void move(); - std::map > rows; + std::map > rows; //TODO: remove, instead add on_select std::function on_hide; bool shown=false; Glib::RefPtr start_mark; @@ -34,6 +36,7 @@ private: class SelectionDialog : public SelectionDialogBase { public: SelectionDialog(Gtk::TextView& text_view); + void init() {SelectionDialogBase::init();} void show(); std::function on_select; }; @@ -41,6 +44,7 @@ public: class CompletionDialog : public SelectionDialogBase { public: CompletionDialog(Gtk::TextView& text_view); + void init() {SelectionDialogBase::init();} void show(); bool on_key_release(GdkEventKey* key); bool on_key_press(GdkEventKey* key); diff --git a/juci/source.cc b/juci/source.cc index ea1e34f..17c4937 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -652,6 +652,7 @@ void Source::ClangViewAutocomplete::autocomplete() { completion_dialog.start_mark=get_buffer()->create_mark(start_iter); std::map > rows; + completion_dialog.init(); for (auto &data : *ac_data) { std::stringstream ss; std::string return_value; @@ -668,10 +669,12 @@ void Source::ClangViewAutocomplete::autocomplete() { if (ss_str.length() > 0) { // if length is 0 the result is empty auto pair=std::pair(ss_str, data.brief_comments); rows[ss.str() + " --> " + return_value] = pair; + completion_dialog.append(ss.str() + " --> " + return_value); } } if (rows.empty()) { rows["No suggestions found..."] = std::pair(); + completion_dialog.append("No suggestions found..."); } completion_dialog.rows=std::move(rows); completion_dialog.show(); @@ -804,20 +807,26 @@ Source::ClangViewAutocomplete(file_path, project_path), selection_dialog(*this) return location; }; - goto_method=[this](){ - if(selection_dialog.start_mark) - get_buffer()->delete_mark(selection_dialog.start_mark); - selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); - - std::map > rows; - rows["Not implemented yet"]=std::pair("1", ""); - rows["but you can try the selection search"]=std::pair("2", ""); - rows["search for instance for 'try'"]=std::pair("3", ""); - selection_dialog.rows=std::move(rows); - selection_dialog.on_select=[this](std::string selected) { - cout << selected << endl; - }; - selection_dialog.show(); + goto_method=[this](){ + if(clang_readable) { + if(selection_dialog.start_mark) + get_buffer()->delete_mark(selection_dialog.start_mark); + selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); + std::map > rows; + selection_dialog.init(); + for(auto &method: clang_tokens->get_cxx_methods()) { + rows[method.first]=std::pair(std::to_string(method.second), ""); + selection_dialog.append(method.first); + } + selection_dialog.rows=std::move(rows); + selection_dialog.on_select=[this](std::string selected) { + auto offset=stoul(selected); + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset)); + scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); + delayed_tooltips_connection.disconnect(); + }; + selection_dialog.show(); + } }; } diff --git a/juci/source.h b/juci/source.h index 2ead12c..6a2c75b 100644 --- a/juci/source.h +++ b/juci/source.h @@ -79,6 +79,7 @@ public: std::unique_ptr clang_tokens; bool clang_readable=false; sigc::connection delayed_reparse_connection; + sigc::connection delayed_tooltips_connection; private: std::map get_buffer_map() const; // inits the syntax highligthing on file open @@ -94,7 +95,6 @@ public: Tooltips type_tooltips; bool on_motion_notify_event(GdkEventMotion* event); void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); - sigc::connection delayed_tooltips_connection; bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; From 8313f00fb3e4babb15918c665b887366e3535fea Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 21 Jul 2015 14:00:58 +0200 Subject: [PATCH 14/14] Minor fix to crash when no methods existed in a c++ file. --- juci/selectiondialog.h | 2 +- juci/source.cc | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index 7afad0e..d55d9a3 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -14,7 +14,7 @@ public: virtual void hide(); virtual void move(); - std::map > rows; //TODO: remove, instead add on_select + std::map > rows; //TODO: remove, instead add on_select. Also remember to destroy start_mark in destructor std::function on_hide; bool shown=false; Glib::RefPtr start_mark; diff --git a/juci/source.cc b/juci/source.cc index 17c4937..d2c7804 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -814,7 +814,10 @@ Source::ClangViewAutocomplete(file_path, project_path), selection_dialog(*this) selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); std::map > rows; selection_dialog.init(); - for(auto &method: clang_tokens->get_cxx_methods()) { + auto methods=clang_tokens->get_cxx_methods(); + if(methods.size()==0) + return; + for(auto &method: methods) { rows[method.first]=std::pair(std::to_string(method.second), ""); selection_dialog.append(method.first); }