From 1d581df887d4a7b05431c3c966e425020d731049 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 1 Aug 2015 23:04:26 +0200 Subject: [PATCH 01/12] Users should now experience no delay in Juci, even when closing tabs that are processing or when quitting the application while source files are processed. That is, resources are now freed from a seperate thread. --- src/notebook.cc | 10 +++++++++- src/notebook.h | 2 +- src/source.cc | 37 ++++++++++++++++++++++++------------- src/source.h | 16 ++++++++++------ 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index 24ad15e..b3d183f 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -19,7 +19,7 @@ int Notebook::size() { Source::View* Notebook::get_view(int page) { if(page>=size()) return nullptr; - return source_views.at(page).get(); + return source_views.at(page); } Source::View* Notebook::get_current_view() { @@ -125,9 +125,17 @@ bool Notebook::close_current_page() { } int page = get_current_page(); remove_page(page); + if(get_current_page()==-1) + Singleton::status()->set_text(""); + auto source_view=source_views.at(page); source_views.erase(source_views.begin()+ page); scrolled_windows.erase(scrolled_windows.begin()+page); hboxes.erase(hboxes.begin()+page); + if(auto source_clang_view=dynamic_cast(source_view)) { + source_clang_view->delete_object(); + } + else + delete source_view; } return true; } diff --git a/src/notebook.h b/src/notebook.h index 79fb9f9..be21b0b 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -23,7 +23,7 @@ public: private: bool save_modified_dialog(); - std::vector > source_views; + std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; std::vector > hboxes; }; diff --git a/src/source.cc b/src/source.cc index fe7f71c..d27e381 100644 --- a/src/source.cc +++ b/src/source.cc @@ -390,16 +390,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } -Source::ClangViewParse::~ClangViewParse() { - //TODO: Is it possible to stop the clang-process in progress? - parsing_in_progress->cancel("canceled"); - parse_thread_stop=true; - if(parse_thread.joinable()) - parse_thread.join(); - parsing_mutex.lock(); //Be sure not to destroy while still parsing with libclang - parsing_mutex.unlock(); -} - void Source::ClangViewParse:: init_syntax_highlighting(const std::map &buffers, @@ -872,14 +862,14 @@ void Source::ClangViewAutocomplete::autocomplete() { } buffer+="\n"; set_status("autocomplete..."); - std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){ + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + autocomplete_thread=std::thread([this, ac_data, line_nr, column_nr, buffer_map](){ parsing_mutex.lock(); *ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map)); autocomplete_done(); parsing_mutex.unlock(); }); - - autocomplete_thread.detach(); } } @@ -1051,3 +1041,24 @@ Source::ClangViewAutocomplete(file_path, project_path) { } }; } + +Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path): ClangViewRefactor(file_path, project_path) { + do_delete_object.connect([this](){ + if(delete_thread.joinable()) + delete_thread.join(); + delete this; + }); +} + +void Source::ClangView::delete_object() { + parsing_in_progress->cancel("canceled, freeing resources in the background"); + parse_thread_stop=true; + delete_thread=std::thread([this](){ + //TODO: Is it possible to stop the clang-process in progress? + if(parse_thread.joinable()) + parse_thread.join(); + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + do_delete_object(); + }); +} \ No newline at end of file diff --git a/src/source.h b/src/source.h index c874520..83f4e24 100644 --- a/src/source.h +++ b/src/source.h @@ -90,7 +90,6 @@ namespace Source { class ClangViewParse : public View { public: ClangViewParse(const std::string& file_path, const std::string& project_path); - ~ClangViewParse(); protected: void start_reparse(); bool on_key_press_event(GdkEventKey* key); @@ -101,6 +100,10 @@ namespace Source { bool clang_readable=false; sigc::connection delayed_reparse_connection; sigc::connection delayed_tooltips_connection; + + std::shared_ptr parsing_in_progress; + std::thread parse_thread; + std::atomic parse_thread_stop; private: std::map get_buffer_map() const; // inits the syntax highligthing on file open @@ -122,15 +125,12 @@ namespace Source { static clang::Index clang_index; std::vector get_compilation_commands(); - std::shared_ptr parsing_in_progress; Glib::Dispatcher parse_done; Glib::Dispatcher parse_start; - std::thread parse_thread; std::map parse_thread_buffer_map; std::mutex parse_thread_buffer_map_mutex; std::atomic parse_thread_go; std::atomic parse_thread_mapped; - std::atomic parse_thread_stop; }; class ClangViewAutocomplete : public ClangViewParse { @@ -139,6 +139,7 @@ namespace Source { protected: bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); + std::thread autocomplete_thread; private: void start_autocomplete(); void autocomplete(); @@ -166,8 +167,11 @@ namespace Source { class ClangView : public ClangViewRefactor { public: - ClangView(const std::string& file_path, const std::string& project_path): - ClangViewRefactor(file_path, project_path) {} + ClangView(const std::string& file_path, const std::string& project_path); + void delete_object(); + private: + Glib::Dispatcher do_delete_object; + std::thread delete_thread; }; }; // class Source #endif // JUCI_SOURCE_H_ From 05fe364e99371351fedd821c223db09eebd91ce3 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 2 Aug 2015 10:27:47 +0200 Subject: [PATCH 02/12] Added line wrapping to tooltips (80 chars max). --- src/menu.cc | 1 - src/notebook.cc | 3 +-- src/source.cc | 8 +++---- src/tooltips.cc | 60 +++++++++++++++++++++++++++++++++++++++++++------ src/tooltips.h | 6 ++--- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/menu.cc b/src/menu.cc index ca59401..4998bee 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -33,4 +33,3 @@ void Menu::build() { } ui_manager->insert_action_group(action_group); } - diff --git a/src/notebook.cc b/src/notebook.cc index b3d183f..71ec3ed 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -131,9 +131,8 @@ bool Notebook::close_current_page() { source_views.erase(source_views.begin()+ page); scrolled_windows.erase(scrolled_windows.begin()+page); hboxes.erase(hboxes.begin()+page); - if(auto source_clang_view=dynamic_cast(source_view)) { + if(auto source_clang_view=dynamic_cast(source_view)) source_clang_view->delete_object(); - } else delete source_view; } diff --git a/src/source.cc b/src/source.cc index d27e381..783ad12 100644 --- a/src/source.cc +++ b/src/source.cc @@ -496,14 +496,14 @@ void Source::ClangViewParse::update_diagnostics() { auto spelling=diagnostic.spelling; auto severity_spelling=diagnostic.severity_spelling; - auto get_tooltip_buffer=[this, spelling, severity_spelling, diagnostic_tag_name]() { + auto create_tooltip_buffer=[this, spelling, severity_spelling, diagnostic_tag_name]() { auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), severity_spelling, diagnostic_tag_name); tooltip_buffer->insert_at_cursor(":\n"+spelling); //TODO: Insert newlines to clang_tu->diagnostics[c].spelling (use 80 chars, then newline?) return tooltip_buffer; }; - diagnostic_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); + diagnostic_tooltips.emplace_back(create_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); get_buffer()->apply_tag_by_name(diagnostic_tag_name+"_underline", start, end); } @@ -516,7 +516,7 @@ void Source::ClangViewParse::update_types() { if(token.get_kind()==clang::Token_Identifier && token.has_type()) { 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 create_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(); @@ -525,7 +525,7 @@ void Source::ClangViewParse::update_types() { return tooltip_buffer; }; - type_tooltips.emplace_back(get_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); + type_tooltips.emplace_back(create_tooltip_buffer, *this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); } } } diff --git a/src/tooltips.cc b/src/tooltips.cc index 62b9476..5afc1f3 100644 --- a/src/tooltips.cc +++ b/src/tooltips.cc @@ -1,11 +1,15 @@ #include "tooltips.h" #include "singletons.h" +namespace sigc { + SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE +} + Gdk::Rectangle Tooltips::drawn_tooltips_rectangle=Gdk::Rectangle(); -Tooltip::Tooltip(std::function()> get_buffer, Gtk::TextView& text_view, +Tooltip::Tooltip(std::function()> create_tooltip_buffer, Gtk::TextView& text_view, Glib::RefPtr start_mark, Glib::RefPtr end_mark): -get_buffer(get_buffer), text_view(text_view), +create_tooltip_buffer(create_tooltip_buffer), text_view(text_view), start_mark(start_mark), end_mark(end_mark) {} Tooltip::~Tooltip() { @@ -38,13 +42,17 @@ void Tooltip::adjust(bool disregard_drawn) { window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); window->set_events(Gdk::POINTER_MOTION_MASK); - window->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Tooltip::tooltip_on_motion_notify_event), false); + window->signal_motion_notify_event().connect([this](GdkEventMotion* event){ + window->hide(); + return false; + }); window->property_decorated()=false; window->set_accept_focus(false); window->set_skip_taskbar_hint(true); window->set_default_size(0, 0); - tooltip_widget=std::unique_ptr(new Gtk::TextView(this->get_buffer())); + tooltip_widget=std::unique_ptr(new Gtk::TextView(create_tooltip_buffer())); + wrap_lines(tooltip_widget->get_buffer()); tooltip_widget->set_editable(false); tooltip_widget->override_background_color(Gdk::RGBA(Singleton::Config::source()->background_tooltips)); window->add(*tooltip_widget); @@ -76,9 +84,47 @@ void Tooltip::adjust(bool disregard_drawn) { window->move(rectangle.get_x(), rectangle.get_y()); } -bool Tooltip::tooltip_on_motion_notify_event(GdkEventMotion* event) { - window->hide(); - return false; +void Tooltip::wrap_lines(Glib::RefPtr text_buffer) { + INFO("Tooltip::wrap_lines"); + auto iter=text_buffer->begin(); + + while(iter) { + auto last_space=text_buffer->end(); + bool end=false; + for(unsigned c=0;c<=80;c++) { + if(!iter) { + end=true; + break; + } + if(*iter==' ') + last_space=iter; + if(*iter=='\n') { + end=true; + iter++; + break; + } + iter++; + } + if(!end) { + while(!last_space && iter) { //If no space (word longer than 80) + iter++; + if(iter && *iter==' ') + last_space=iter; + } + if(iter && last_space) { + auto mark=text_buffer->create_mark(last_space); + auto iter_mark=text_buffer->create_mark(iter); + auto last_space_p=last_space++; + text_buffer->erase(last_space, last_space_p); + text_buffer->insert(mark->get_iter(), "\n"); + + iter=iter_mark->get_iter(); + + text_buffer->delete_mark(mark); + text_buffer->delete_mark(iter_mark); + } + } + } } void Tooltips::show(const Gdk::Rectangle& rectangle, bool disregard_drawn) { diff --git a/src/tooltips.h b/src/tooltips.h index e41475f..3d52c27 100644 --- a/src/tooltips.h +++ b/src/tooltips.h @@ -6,7 +6,7 @@ class Tooltip { public: - Tooltip(std::function()> get_buffer, Gtk::TextView& text_view, Glib::RefPtr start_mark, Glib::RefPtr end_mark); + Tooltip(std::function()> create_tooltip_buffer, Gtk::TextView& text_view, Glib::RefPtr start_mark, Glib::RefPtr end_mark); ~Tooltip(); void update(); @@ -15,9 +15,9 @@ public: Gdk::Rectangle activation_rectangle; std::unique_ptr window; private: - bool tooltip_on_motion_notify_event(GdkEventMotion* event); + void wrap_lines(Glib::RefPtr text_buffer); - std::function()> get_buffer; + std::function()> create_tooltip_buffer; std::unique_ptr tooltip_widget; Glib::RefPtr start_mark; Glib::RefPtr end_mark; From cbaee6b3a14174391710b15dda352bfdd47e6ee8 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 2 Aug 2015 11:22:02 +0200 Subject: [PATCH 03/12] Added go to line and center cursor. Remember to rm ~./juci/config/config.json and ~./juci/config/menu.xml to update the keys and menu. --- src/files.h | 5 +++++ src/window.cc | 62 +++++++++++++++++++++++++++++++++++++++++---------- src/window.h | 1 + 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/files.h b/src/files.h index 0aa5e88..6a34e45 100644 --- a/src/files.h +++ b/src/files.h @@ -47,6 +47,8 @@ const std::string configjson = " \"edit_undo\": \"z\",\n" " \"edit_redo\": \"z\",\n" " \"edit_find\": \"f\",\n" +" \"source_goto_line\": \"g\",\n" +" \"source_center_cursor\": \"l\",\n" " \"source_goto_declaration\": \"d\",\n" " \"source_goto_method\": \"m\",\n" " \"source_rename\": \"r\",\n" @@ -112,6 +114,9 @@ const std::string menuxml = " \n" " \n" " \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" diff --git a/src/window.cc b/src/window.cc index 70c487c..3b8c102 100644 --- a/src/window.cc +++ b/src/window.cc @@ -148,6 +148,16 @@ void Window::create_menu() { INFO("Done Redo"); }); + menu.action_group->add(Gtk::Action::create("SourceGotoLine", "Go to line"), Gtk::AccelKey(menu.key_map["source_goto_line"]), [this]() { + goto_line_entry(); + }); + menu.action_group->add(Gtk::Action::create("SourceCenterCursor", "Center cursor"), Gtk::AccelKey(menu.key_map["source_center_cursor"]), [this]() { + if(notebook.get_current_page()!=-1) { + while(gtk_events_pending()) + gtk_main_iteration(); + notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + } + }); menu.action_group->add(Gtk::Action::create("SourceGotoDeclaration", "Go to declaration"), Gtk::AccelKey(menu.key_map["source_goto_declaration"]), [this]() { if(notebook.get_current_page()!=-1) { if(notebook.get_current_view()->get_declaration_location) { @@ -483,6 +493,34 @@ void Window::search_and_replace_entry() { entry_box.show(); } +void Window::goto_line_entry() { + entry_box.clear(); + if(notebook.get_current_page()!=-1) { + entry_box.entries.emplace_back("", [this](const std::string& content){ + auto buffer=notebook.get_current_view()->get_buffer(); + try { + auto line=stoul(content); + if(line>0 && (int)line<=buffer->get_line_count()) { + line--; + if(notebook.get_current_page()!=-1) { + buffer->place_cursor(buffer->get_iter_at_line(line)); + while(gtk_events_pending()) + gtk_main_iteration(); + notebook.get_current_view()->scroll_to(buffer->get_insert(), 0.0, 1.0, 0.5); + } + } + } + catch(const std::exception &e) {} + entry_box.hide(); + }); + auto entry_it=entry_box.entries.begin(); + entry_box.buttons.emplace_back("Go to line", [this, entry_it](){ + entry_it->activate(); + }); + entry_box.show(); + } +} + void Window::rename_token_entry() { entry_box.clear(); if(notebook.get_current_page()!=-1) { @@ -502,23 +540,23 @@ void Window::rename_token_entry() { }; label_it->update(0, ""); entry_box.entries.emplace_back(*token_name, [this, token_name, token](const std::string& content){ - if(notebook.get_current_page()!=-1 && content!=*token_name) { - for(int c=0;crename_similar_tokens) { - auto number=notebook.get_view(c)->rename_similar_tokens(*token, content); - if(number>0) { - Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path+"\n"); - notebook.save(c); - } + if(notebook.get_current_page()!=-1 && content!=*token_name) { + for(int c=0;crename_similar_tokens) { + auto number=notebook.get_view(c)->rename_similar_tokens(*token, content); + if(number>0) { + Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path+"\n"); + notebook.save(c); } } - entry_box.hide(); } - }); + entry_box.hide(); + } + }); auto entry_it=entry_box.entries.begin(); entry_box.buttons.emplace_back("Rename", [this, entry_it](){ - entry_it->activate(); - }); + entry_it->activate(); + }); entry_box.show(); } } diff --git a/src/window.h b/src/window.h index 992d2be..8d51c9a 100644 --- a/src/window.h +++ b/src/window.h @@ -33,6 +33,7 @@ private: void save_file_dialog(); void search_and_replace_entry(); + void goto_line_entry(); void rename_token_entry(); std::string last_search; std::string last_replace; From eb887d723d00a87a80ffc1e1dcffe46a40c001aa Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 2 Aug 2015 11:30:32 +0200 Subject: [PATCH 04/12] Fixed crash when using go to line after closing all the tabs. --- src/window.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/window.cc b/src/window.cc index 3b8c102..8f78129 100644 --- a/src/window.cc +++ b/src/window.cc @@ -497,21 +497,21 @@ void Window::goto_line_entry() { entry_box.clear(); if(notebook.get_current_page()!=-1) { entry_box.entries.emplace_back("", [this](const std::string& content){ - auto buffer=notebook.get_current_view()->get_buffer(); - try { - auto line=stoul(content); - if(line>0 && (int)line<=buffer->get_line_count()) { - line--; - if(notebook.get_current_page()!=-1) { + if(notebook.get_current_page()!=-1) { + auto buffer=notebook.get_current_view()->get_buffer(); + try { + auto line=stoul(content); + if(line>0 && (int)line<=buffer->get_line_count()) { + line--; buffer->place_cursor(buffer->get_iter_at_line(line)); while(gtk_events_pending()) gtk_main_iteration(); notebook.get_current_view()->scroll_to(buffer->get_insert(), 0.0, 1.0, 0.5); } } + catch(const std::exception &e) {} + entry_box.hide(); } - catch(const std::exception &e) {} - entry_box.hide(); }); auto entry_it=entry_box.entries.begin(); entry_box.buttons.emplace_back("Go to line", [this, entry_it](){ From 1ee401e18366924ae8e9d931a7526866c48e6ea3 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 2 Aug 2015 11:37:35 +0200 Subject: [PATCH 05/12] Minor fix to go to line. --- src/window.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window.cc b/src/window.cc index 8f78129..86395cd 100644 --- a/src/window.cc +++ b/src/window.cc @@ -501,7 +501,7 @@ void Window::goto_line_entry() { auto buffer=notebook.get_current_view()->get_buffer(); try { auto line=stoul(content); - if(line>0 && (int)line<=buffer->get_line_count()) { + if(line>0 && line<=(unsigned long)buffer->get_line_count()) { line--; buffer->place_cursor(buffer->get_iter_at_line(line)); while(gtk_events_pending()) From 722a55d3d2c6c937d9efb13b198283ee64e6ab17 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 2 Aug 2015 18:17:05 +0200 Subject: [PATCH 06/12] Moved entrybox to bottom of notepad widget, this way the cursor does not change position on screen when entrybox gets shown. Also the entry fields gets closer to the text where the focus of the user is. --- src/entrybox.cc | 11 ++++++----- src/window.cc | 26 +++++++++++--------------- src/window.h | 1 + 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/entrybox.cc b/src/entrybox.cc index d221393..f207e56 100644 --- a/src/entrybox.cc +++ b/src/entrybox.cc @@ -37,6 +37,7 @@ EntryBox::Label::Label(std::functionset_focus_chain({&lower_box}); } void EntryBox::clear() { @@ -50,16 +51,16 @@ void EntryBox::clear() { void EntryBox::show() { std::vector focus_chain; for(auto& entry: entries) { - upper_box.pack_start(entry, Gtk::PACK_SHRINK); + lower_box.pack_start(entry, Gtk::PACK_SHRINK); focus_chain.emplace_back(&entry); } for(auto& button: buttons) - upper_box.pack_start(button, Gtk::PACK_SHRINK); + lower_box.pack_start(button, Gtk::PACK_SHRINK); for(auto& toggle_button: toggle_buttons) - upper_box.pack_start(toggle_button, Gtk::PACK_SHRINK); + lower_box.pack_start(toggle_button, Gtk::PACK_SHRINK); for(auto& label: labels) - lower_box.pack_start(label, Gtk::PACK_SHRINK); - upper_box.set_focus_chain(focus_chain); + upper_box.pack_start(label, Gtk::PACK_SHRINK); + lower_box.set_focus_chain(focus_chain); show_all(); if(entries.size()>0) { entries.begin()->grab_focus(); diff --git a/src/window.cc b/src/window.cc index 86395cd..35c6902 100644 --- a/src/window.cc +++ b/src/window.cc @@ -21,10 +21,10 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL) { create_menu(); box.pack_start(menu.get_widget(), Gtk::PACK_SHRINK); - box.pack_start(entry_box, Gtk::PACK_SHRINK); - - directory_and_notebook_panes.pack1(directories, true, true); - directory_and_notebook_panes.pack2(notebook); + directory_and_notebook_panes.pack1(directories, Gtk::SHRINK); + notebook_vbox.pack_start(notebook); + notebook_vbox.pack_end(entry_box, Gtk::PACK_SHRINK); + directory_and_notebook_panes.pack2(notebook_vbox, Gtk::SHRINK); directory_and_notebook_panes.set_position(120); vpaned.set_position(300); vpaned.pack1(directory_and_notebook_panes, true, false); @@ -42,12 +42,16 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL) { }; entry_box.signal_show().connect([this](){ - std::vector focus_chain; - focus_chain.emplace_back(&entry_box); - box.set_focus_chain(focus_chain); + box.set_focus_chain({&vpaned}); + vpaned.set_focus_chain({&directory_and_notebook_panes}); + directory_and_notebook_panes.set_focus_chain({¬ebook_vbox}); + notebook_vbox.set_focus_chain({&entry_box}); }); entry_box.signal_hide().connect([this](){ box.unset_focus_chain(); + vpaned.unset_focus_chain(); + directory_and_notebook_panes.unset_focus_chain(); + notebook_vbox.unset_focus_chain(); }); entry_box.signal_hide().connect([this]() { if(notebook.get_current_page()!=-1) { @@ -456,14 +460,6 @@ void Window::search_and_replace_entry() { last_replace=replace_entry_it->get_text(); }); - entry_box.buttons.emplace_back("Find", [this](){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_forward(); - }); - entry_box.buttons.emplace_back("Replace", [this, replace_entry_it](){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->replace_forward(replace_entry_it->get_text()); - }); entry_box.buttons.emplace_back("Replace all", [this, replace_entry_it](){ if(notebook.get_current_page()!=-1) notebook.get_current_view()->replace_all(replace_entry_it->get_text()); diff --git a/src/window.h b/src/window.h index 8d51c9a..44c6afb 100644 --- a/src/window.h +++ b/src/window.h @@ -19,6 +19,7 @@ private: Gtk::Box box; Gtk::VPaned vpaned; Gtk::Paned directory_and_notebook_panes; + Gtk::VBox notebook_vbox; Gtk::VBox terminal_vbox; Gtk::HBox status_hbox; EntryBox entry_box; From 02513f9b98b168d35d927dd15148c3b6017ced7e Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 3 Aug 2015 11:57:12 +0200 Subject: [PATCH 07/12] Now attempts to make compile_commands.json if its missing, also remake it after changes to CMakeLists.txt and reparses the open clang-files. Some work left on terminal-execute/run/compile etc functions (only execute and async_execute (last one for compiling and running) will remain). --- src/notebook.cc | 39 ++++++++++++++++++++++++++++++-- src/notebook.h | 1 + src/source.cc | 60 ++++++++++++++++++++++++++++++++++++++++--------- src/source.h | 7 +++++- src/terminal.cc | 32 ++++++++++++++++++++++++++ src/terminal.h | 20 +++++++++-------- src/window.cc | 6 +++++ 7 files changed, 142 insertions(+), 23 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index 71ec3ed..af4f449 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -4,6 +4,9 @@ #include "singletons.h" #include +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -52,8 +55,12 @@ void Notebook::open(std::string path) { tmp_project_path=boost::filesystem::path(path).parent_path().string(); } auto language=Source::guess_language(path); - if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) + if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { + if(boost::filesystem::exists(tmp_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(tmp_project_path+"/compile_commands.json")) { + make_compile_commands(); + } source_views.emplace_back(new Source::ClangView(path, tmp_project_path)); + } else source_views.emplace_back(new Source::GenericView(path, tmp_project_path, language)); @@ -102,10 +109,38 @@ bool Notebook::save(int page) { if(juci::filesystem::write(view->file_path, view->get_buffer())) { view->get_buffer()->set_modified(false); Singleton::terminal()->print("File saved to: " +view->file_path+"\n"); + + //If CMakeLists.txt have been modified: + if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { + if(make_compile_commands()) { + for(auto source_view: source_views) { + if(auto source_clang_view=dynamic_cast(source_view)) { + if(project_path==source_view->project_path) { + if(source_clang_view->restart_parse()) + Singleton::terminal()->print("Reparsing "+source_clang_view->file_path+"\n"); + else + Singleton::terminal()->print("Already reparsing "+source_clang_view->file_path+". Please reopen the file manually.\n"); + } + } + } + } + } + + return true; + } + Singleton::terminal()->print("Error: could not save file " +view->file_path+"\n"); + } + return false; +} + +bool Notebook::make_compile_commands() { + if(project_path.size()>0) { + Singleton::terminal()->print("Creating "+boost::filesystem::path(project_path+"/compile_commands.json").string()+"\n"); + if(Singleton::terminal()->execute(project_path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { + //TODO: refresh directories return true; } } - Singleton::terminal()->print("Error: could not save file " +view->file_path+"\n"); return false; } diff --git a/src/notebook.h b/src/notebook.h index be21b0b..43254f6 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -22,6 +22,7 @@ public: std::string project_path; private: + bool make_compile_commands(); bool save_modified_dialog(); std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; diff --git a/src/source.cc b/src/source.cc index 783ad12..b78c6f9 100644 --- a/src/source.cc +++ b/src/source.cc @@ -278,8 +278,7 @@ Source::GenericView::GenericView(const std::string& file_path, const std::string clang::Index Source::ClangViewParse::clang_index(0, 0); 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) { +Source::View(file_path, project_path) { override_font(Pango::FontDescription(Singleton::Config::source()->font)); override_background_color(Gdk::RGBA(Singleton::Config::source()->background)); override_background_color(Gdk::RGBA(Singleton::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); @@ -308,6 +307,28 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } //TODO: clear tag_class and param_spec? + parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); + init_parse(); + + get_buffer()->signal_changed().connect([this]() { + start_reparse(); + type_tooltips.hide(); + diagnostic_tooltips.hide(); + }); + + get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); +} + +void Source::ClangViewParse::init_parse() { + type_tooltips.hide(); + diagnostic_tooltips.hide(); + get_buffer()->remove_all_tags(get_buffer()->begin(), get_buffer()->end()); + clang_readable=false; + 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(); @@ -340,7 +361,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go=true; }); - parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); parse_done.connect([this](){ if(parse_thread_mapped) { if(parsing_mutex.try_lock()) { @@ -361,6 +381,8 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { }); set_status("parsing..."); + if(parse_thread.joinable()) + parse_thread.join(); parse_thread=std::thread([this]() { while(true) { while(!parse_thread_go && !parse_thread_stop) @@ -380,14 +402,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } } }); - - get_buffer()->signal_changed().connect([this]() { - start_reparse(); - type_tooltips.hide(); - diagnostic_tooltips.hide(); - }); - - get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } void Source::ClangViewParse:: @@ -1048,6 +1062,10 @@ Source::ClangView::ClangView(const std::string& file_path, const std::string& pr delete_thread.join(); delete this; }); + do_restart_parse.connect([this](){ + init_parse(); + restart_parse_running=false; + }); } void Source::ClangView::delete_object() { @@ -1055,10 +1073,30 @@ void Source::ClangView::delete_object() { parse_thread_stop=true; delete_thread=std::thread([this](){ //TODO: Is it possible to stop the clang-process in progress? + if(restart_parse_thread.joinable()) + restart_parse_thread.join(); if(parse_thread.joinable()) parse_thread.join(); if(autocomplete_thread.joinable()) autocomplete_thread.join(); do_delete_object(); }); +} + +bool Source::ClangView::restart_parse() { + if(!restart_parse_running) { + restart_parse_running=true; + parse_thread_stop=true; + if(restart_parse_thread.joinable()) + restart_parse_thread.join(); + restart_parse_thread=std::thread([this](){ + if(parse_thread.joinable()) + parse_thread.join(); + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + do_restart_parse(); + }); + return true; + } + return false; } \ No newline at end of file diff --git a/src/source.h b/src/source.h index 83f4e24..4c6b8cc 100644 --- a/src/source.h +++ b/src/source.h @@ -91,13 +91,14 @@ namespace Source { public: ClangViewParse(const std::string& file_path, const std::string& project_path); protected: + void init_parse(); void start_reparse(); bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); std::unique_ptr clang_tu; std::mutex parsing_mutex; std::unique_ptr clang_tokens; - bool clang_readable=false; + bool clang_readable; sigc::connection delayed_reparse_connection; sigc::connection delayed_tooltips_connection; @@ -169,9 +170,13 @@ namespace Source { public: ClangView(const std::string& file_path, const std::string& project_path); void delete_object(); + bool restart_parse(); private: Glib::Dispatcher do_delete_object; + Glib::Dispatcher do_restart_parse; std::thread delete_thread; + std::thread restart_parse_thread; + bool restart_parse_running=false; }; }; // class Source #endif // JUCI_SOURCE_H_ diff --git a/src/terminal.cc b/src/terminal.cc index 5f36da1..9eeb84d 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -56,6 +56,38 @@ Terminal::Terminal() { }); } +bool Terminal::execute(const std::string &path, const std::string &command) { + boost::filesystem::path boost_path; + if(path=="") + boost_path=boost::filesystem::current_path(); + else + boost_path=boost::filesystem::path(path); + + auto cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; + + FILE* p = NULL; + p = popen(cd_path_and_command.c_str(), "r"); + if (p == NULL) { + print("Error: Failed to run command" + command + "\n"); + return false; + } + else { + char buffer[1028]; + while (fgets(buffer, 1028, p) != NULL) { + print(buffer); + } + int exit_code=pclose(p); + if(exit_code==0) + return true; + else + return false; + } +} + +void Terminal::async_execute(const std::string &path, const std::string &command) { + +} + void Terminal::set_change_folder_command(boost::filesystem::path CMake_path) { INFO("Terminal: set_change_folder_command"); path = CMake_path.string(); diff --git a/src/terminal.h b/src/terminal.h index 026884c..d7865c5 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -31,23 +31,25 @@ public: }; Terminal(); - void set_change_folder_command(boost::filesystem::path CMake_path); - void run(std::string executable); - void compile(); + bool execute(const std::string &path, const std::string &command); + void async_execute(const std::string &path, const std::string &command); + void set_change_folder_command(boost::filesystem::path CMake_path); //TODO: remove + void run(std::string executable); //TODO: remove + void compile(); //TODO: remove int print(std::string message); void print(int line_nr, std::string message); std::shared_ptr print_in_progress(std::string start_msg); private: - void execute_command(std::string command, std::string mode); + void execute_command(std::string command, std::string mode); //TODO: remove Gtk::TextView text_view; Gtk::ScrolledWindow scrolled_window; - std::string change_folder_command; - std::string path; - const std::string cmake_sucsess = "Build files have been written to:"; - const std::string make_built = "Built target"; - const std::string make_executable = "Linking CXX executable"; + std::string change_folder_command; //TODO: remove + std::string path; //TODO: remove + const std::string cmake_sucsess = "Build files have been written to:"; //TODO: remove + const std::string make_built = "Built target"; //TODO: remove + const std::string make_executable = "Linking CXX executable"; //TODO: remove }; #endif // JUCI_TERMINAL_H_ diff --git a/src/window.cc b/src/window.cc index 35c6902..b999717 100644 --- a/src/window.cc +++ b/src/window.cc @@ -5,6 +5,9 @@ #include "config.h" #include "api.h" +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -82,6 +85,9 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL) { Singleton::status()->set_text(notebook.get_current_view()->status); } }); + notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) { + entry_box.hide(); + }); INFO("Window created"); } // Window constructor From dd0392b4bd9eeeefed03b98d1170f6f2e5337829 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 3 Aug 2015 12:00:48 +0200 Subject: [PATCH 08/12] Added Windows TODOs. --- src/notebook.cc | 1 + src/terminal.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/src/notebook.cc b/src/notebook.cc index af4f449..b0226cf 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -136,6 +136,7 @@ bool Notebook::save(int page) { bool Notebook::make_compile_commands() { if(project_path.size()>0) { Singleton::terminal()->print("Creating "+boost::filesystem::path(project_path+"/compile_commands.json").string()+"\n"); + //TODO: Windows... if(Singleton::terminal()->execute(project_path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { //TODO: refresh directories return true; diff --git a/src/terminal.cc b/src/terminal.cc index 9eeb84d..de42e7c 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -63,6 +63,7 @@ bool Terminal::execute(const std::string &path, const std::string &command) { else boost_path=boost::filesystem::path(path); + //TODO: Windows... auto cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; FILE* p = NULL; From 08027264d075ba153293e2711ab965c60e709947 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 3 Aug 2015 15:34:01 +0200 Subject: [PATCH 09/12] Now searches for project path if a clang-file is opened without a directory opened. Some minor fixes also. --- src/notebook.cc | 71 ++++++++++++++++++++++++++++++++++++------------- src/notebook.h | 3 ++- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index b0226cf..3a39842 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -3,6 +3,7 @@ #include "sourcefile.h" #include "singletons.h" #include +#include #include //TODO: remove using namespace std; //TODO: remove @@ -50,19 +51,29 @@ void Notebook::open(std::string path) { } can_read.close(); - auto tmp_project_path=project_path; - if(tmp_project_path=="") { - tmp_project_path=boost::filesystem::path(path).parent_path().string(); - } auto language=Source::guess_language(path); if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { - if(boost::filesystem::exists(tmp_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(tmp_project_path+"/compile_commands.json")) { - make_compile_commands(); + auto view_project_path=project_path; + if(view_project_path=="") { + view_project_path=boost::filesystem::path(path).parent_path().string(); + auto found_project_path=find_project_path(view_project_path); + if(found_project_path!="") { + view_project_path=found_project_path; + Singleton::terminal()->print("Project path for "+path+" set to "+view_project_path+"\n"); + } + else + Singleton::terminal()->print("Error: could not find project path for "+path+"\n"); } - source_views.emplace_back(new Source::ClangView(path, tmp_project_path)); + if(boost::filesystem::exists(view_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(view_project_path+"/compile_commands.json")) + make_compile_commands(view_project_path); + source_views.emplace_back(new Source::ClangView(path, view_project_path)); + } + else { + auto view_project_path=project_path; + if(view_project_path=="") + view_project_path=boost::filesystem::path(path).parent_path().string(); + source_views.emplace_back(new Source::GenericView(path, view_project_path, language)); } - else - source_views.emplace_back(new Source::GenericView(path, tmp_project_path, language)); scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); hboxes.emplace_back(new Gtk::HBox()); @@ -101,6 +112,32 @@ void Notebook::open(std::string path) { }; } +std::string Notebook::find_project_path(const std::string &path) { + auto find_cmake_project=[this](const boost::filesystem::path &path) { + auto cmake_path=path; + cmake_path+="/CMakeLists.txt"; + for(auto &line: juci::filesystem::read_lines(cmake_path)) { + const std::regex cmake_project("^ *project *\\(.*$"); + std::smatch sm; + if(std::regex_match(line, sm, cmake_project)) { + return true; + } + } + return false; + }; + + auto boost_path=boost::filesystem::path(path); + if(find_cmake_project(boost_path)) + return boost_path.string(); + do { + boost_path=boost_path.parent_path(); + if(find_cmake_project(boost_path)) + return boost_path.string(); + } while(boost_path!=boost_path.root_directory()); + + return ""; +} + bool Notebook::save(int page) { if(page>=size()) return false; @@ -112,7 +149,7 @@ bool Notebook::save(int page) { //If CMakeLists.txt have been modified: if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { - if(make_compile_commands()) { + if(project_path!="" && make_compile_commands(project_path)) { for(auto source_view: source_views) { if(auto source_clang_view=dynamic_cast(source_view)) { if(project_path==source_view->project_path) { @@ -133,14 +170,12 @@ bool Notebook::save(int page) { return false; } -bool Notebook::make_compile_commands() { - if(project_path.size()>0) { - Singleton::terminal()->print("Creating "+boost::filesystem::path(project_path+"/compile_commands.json").string()+"\n"); - //TODO: Windows... - if(Singleton::terminal()->execute(project_path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { - //TODO: refresh directories - return true; - } +bool Notebook::make_compile_commands(const std::string &path) { + Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n"); + //TODO: Windows... + if(Singleton::terminal()->execute(path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { + //TODO: refresh directories + return true; } return false; } diff --git a/src/notebook.h b/src/notebook.h index 43254f6..2c9d980 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -22,7 +22,8 @@ public: std::string project_path; private: - bool make_compile_commands(); + std::string find_project_path(const std::string &path); + bool make_compile_commands(const std::string &path); bool save_modified_dialog(); std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; From a6ad9f2d2b1ba7e7a9554cf39375dc7f4c81e38d Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 3 Aug 2015 16:01:13 +0200 Subject: [PATCH 10/12] Minor fix: Added const to a std::function. --- src/notebook.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.cc b/src/notebook.cc index 3a39842..1ccbca7 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -113,7 +113,7 @@ void Notebook::open(std::string path) { } std::string Notebook::find_project_path(const std::string &path) { - auto find_cmake_project=[this](const boost::filesystem::path &path) { + const auto find_cmake_project=[this](const boost::filesystem::path &path) { auto cmake_path=path; cmake_path+="/CMakeLists.txt"; for(auto &line: juci::filesystem::read_lines(cmake_path)) { From 28ddd8ba9509b61a539721647bfb33db89d75ea6 Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 4 Aug 2015 09:13:44 +0200 Subject: [PATCH 11/12] Minor fixes. --- src/notebook.cc | 2 +- src/source.cc | 64 ++++++++++++++++++++++++------------------------- src/source.h | 4 ++-- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index 1ccbca7..c113daa 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -203,7 +203,7 @@ bool Notebook::close_current_page() { scrolled_windows.erase(scrolled_windows.begin()+page); hboxes.erase(hboxes.begin()+page); if(auto source_clang_view=dynamic_cast(source_view)) - source_clang_view->delete_object(); + source_clang_view->async_delete(); else delete source_view; } diff --git a/src/source.cc b/src/source.cc index b78c6f9..abbd4c9 100644 --- a/src/source.cc +++ b/src/source.cc @@ -308,6 +308,34 @@ Source::View(file_path, project_path) { //TODO: clear tag_class and param_spec? parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); + //GTK-calls must happen in main thread, so the parse_thread + //sends signals to the main thread that it is to call the following functions: + parse_start.connect([this]{ + if(parse_thread_buffer_map_mutex.try_lock()) { + parse_thread_buffer_map=get_buffer_map(); + parse_thread_mapped=true; + parse_thread_buffer_map_mutex.unlock(); + } + parse_thread_go=true; + }); + parse_done.connect([this](){ + if(parse_thread_mapped) { + if(parsing_mutex.try_lock()) { + INFO("Updating syntax"); + update_syntax(); + update_diagnostics(); + update_types(); + clang_readable=true; + set_status(""); + parsing_mutex.unlock(); + INFO("Syntax updated"); + } + parsing_in_progress->done("done"); + } + else { + parse_thread_go=true; + } + }); init_parse(); get_buffer()->signal_changed().connect([this]() { @@ -349,37 +377,7 @@ void Source::ClangViewParse::init_parse() { start_offset, end_offset); update_syntax(); - - //GTK-calls must happen in main thread, so the parse_thread - //sends signals to the main thread that it is to call the following functions: - parse_start.connect([this]{ - if(parse_thread_buffer_map_mutex.try_lock()) { - parse_thread_buffer_map=get_buffer_map(); - parse_thread_mapped=true; - parse_thread_buffer_map_mutex.unlock(); - } - parse_thread_go=true; - }); - - parse_done.connect([this](){ - if(parse_thread_mapped) { - if(parsing_mutex.try_lock()) { - INFO("Updating syntax"); - update_syntax(); - update_diagnostics(); - update_types(); - clang_readable=true; - set_status(""); - parsing_mutex.unlock(); - INFO("Syntax updated"); - } - parsing_in_progress->done("done"); - } - else { - parse_thread_go=true; - } - }); - + set_status("parsing..."); if(parse_thread.joinable()) parse_thread.join(); @@ -546,7 +544,7 @@ void Source::ClangViewParse::update_types() { bool Source::ClangViewParse::on_motion_notify_event(GdkEventMotion* event) { delayed_tooltips_connection.disconnect(); - if(clang_readable) { + if(clang_readable && event->state==0) { Gdk::Rectangle rectangle(event->x, event->y, 1, 1); Tooltips::init(); type_tooltips.show(rectangle); @@ -1068,7 +1066,7 @@ Source::ClangView::ClangView(const std::string& file_path, const std::string& pr }); } -void Source::ClangView::delete_object() { +void Source::ClangView::async_delete() { parsing_in_progress->cancel("canceled, freeing resources in the background"); parse_thread_stop=true; delete_thread=std::thread([this](){ diff --git a/src/source.h b/src/source.h index 4c6b8cc..7bec853 100644 --- a/src/source.h +++ b/src/source.h @@ -125,7 +125,7 @@ namespace Source { bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; std::vector get_compilation_commands(); - + Glib::Dispatcher parse_done; Glib::Dispatcher parse_start; std::map parse_thread_buffer_map; @@ -169,7 +169,7 @@ namespace Source { class ClangView : public ClangViewRefactor { public: ClangView(const std::string& file_path, const std::string& project_path); - void delete_object(); + void async_delete(); bool restart_parse(); private: Glib::Dispatcher do_delete_object; From 017d4480a7a2b379a8577670098f3535c49d538a Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 4 Aug 2015 09:25:59 +0200 Subject: [PATCH 12/12] Now refreshes directories after running cmake for compilation_commands.json. --- src/notebook.cc | 5 +++-- src/notebook.h | 4 +++- src/window.cc | 2 +- src/window.h | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/notebook.cc b/src/notebook.cc index c113daa..4e18c1f 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -12,7 +12,7 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } -Notebook::Notebook() : Gtk::Notebook() { +Notebook::Notebook(Directories &directories) : Gtk::Notebook(), directories(directories) { Gsv::init(); } @@ -174,7 +174,8 @@ bool Notebook::make_compile_commands(const std::string &path) { Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n"); //TODO: Windows... if(Singleton::terminal()->execute(path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { - //TODO: refresh directories + if(project_path!="") + directories.open_folder(project_path); return true; } return false; diff --git a/src/notebook.h b/src/notebook.h index 2c9d980..ef95143 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -8,10 +8,11 @@ #include #include #include +#include "directories.h" class Notebook : public Gtk::Notebook { public: - Notebook(); + Notebook(Directories &directories); Source::View* get_view(int page); int size(); Source::View* get_current_view(); @@ -25,6 +26,7 @@ private: std::string find_project_path(const std::string &path); bool make_compile_commands(const std::string &path); bool save_modified_dialog(); + Directories &directories; std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; std::vector > hboxes; diff --git a/src/window.cc b/src/window.cc index b999717..1c00711 100644 --- a/src/window.cc +++ b/src/window.cc @@ -12,7 +12,7 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } -Window::Window() : box(Gtk::ORIENTATION_VERTICAL) { +Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories) { INFO("Create Window"); set_title("juCi++"); set_default_size(600, 400); diff --git a/src/window.h b/src/window.h index 44c6afb..7100de6 100644 --- a/src/window.h +++ b/src/window.h @@ -10,8 +10,8 @@ class Window : public Gtk::Window { public: Window(); - Notebook notebook; Directories directories; + Notebook notebook; protected: bool on_key_press_event(GdkEventKey *event); bool on_delete_event (GdkEventAny *event);