Browse Source

Merge pull request #56 from eidheim/master

Various improvements
merge-requests/365/head
Jørgen Lien Sellæg 10 years ago
parent
commit
19aba63e24
  1. 3
      src/config.cc
  2. 22
      src/directories.cc
  3. 3
      src/directories.h
  4. 56
      src/files.h
  5. 58
      src/menu.cc
  6. 2
      src/menu.h
  7. 34
      src/notebook.cc
  8. 1
      src/notebook.h
  9. 6
      src/singletons.cc
  10. 2
      src/singletons.h
  11. 254
      src/source.cc
  12. 35
      src/source.h
  13. 38
      src/sourcefile.cc
  14. 3
      src/sourcefile.h
  15. 4
      src/tooltips.cc
  16. 20
      src/window.cc
  17. 2
      src/window.h

3
src/config.cc

@ -20,14 +20,13 @@ MainConfig::MainConfig() {
} }
void MainConfig::find_or_create_config_files() { void MainConfig::find_or_create_config_files() {
std::vector<std::string> files = {"config.json", "menu.xml", "plugins.py"}; std::vector<std::string> files = {"config.json", "plugins.py"};
boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir())); boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir()));
for (auto &file : files) { for (auto &file : files) {
auto path = boost::filesystem::path(Singleton::config_dir() + file); auto path = boost::filesystem::path(Singleton::config_dir() + file);
if (!boost::filesystem::is_regular_file(path)) { if (!boost::filesystem::is_regular_file(path)) {
if (file == "config.json") juci::filesystem::write(path, configjson); if (file == "config.json") juci::filesystem::write(path, configjson);
if (file == "plugins.py") juci::filesystem::write(path, pluginspy); if (file == "plugins.py") juci::filesystem::write(path, pluginspy);
if (file == "menu.xml") juci::filesystem::write(path, menuxml);
} }
} }

22
src/directories.cc

@ -29,6 +29,9 @@ Directories::Directories() : stop_update_thread(false) {
tree_store = Gtk::TreeStore::create(column_record); tree_store = Gtk::TreeStore::create(column_record);
tree_view.set_model(tree_store); tree_view.set_model(tree_store);
tree_view.append_column("", column_record.name); tree_view.append_column("", column_record.name);
auto renderer=dynamic_cast<Gtk::CellRendererText*>(tree_view.get_column(0)->get_first_cell());
tree_view.get_column(0)->add_attribute(renderer->property_foreground_rgba(), column_record.color);
tree_store->set_sort_column(column_record.id, Gtk::SortType::SORT_ASCENDING); tree_store->set_sort_column(column_record.id, Gtk::SortType::SORT_ASCENDING);
tree_view.set_enable_search(true); //TODO: why does this not work in OS X? tree_view.set_enable_search(true); //TODO: why does this not work in OS X?
tree_view.set_search_column(column_record.name); tree_view.set_search_column(column_record.name);
@ -67,6 +70,9 @@ Directories::Directories() : stop_update_thread(false) {
} }
auto child=tree_store->append(iter->children()); auto child=tree_store->append(iter->children());
child->set_value(column_record.name, std::string("(empty)")); child->set_value(column_record.name, std::string("(empty)"));
Gdk::RGBA rgba;
rgba.set_rgba(0.5, 0.5, 0.5);
child->set_value(column_record.color, rgba);
} }
}); });
@ -243,9 +249,20 @@ void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::T
child->set_value(column_record.id, "a"+filename); child->set_value(column_record.id, "a"+filename);
auto grandchild=tree_store->append(child->children()); auto grandchild=tree_store->append(child->children());
grandchild->set_value(column_record.name, std::string("(empty)")); grandchild->set_value(column_record.name, std::string("(empty)"));
Gdk::RGBA rgba;
rgba.set_rgba(0.5, 0.5, 0.5);
grandchild->set_value(column_record.color, rgba);
} }
else else {
child->set_value(column_record.id, "b"+filename); child->set_value(column_record.id, "b"+filename);
auto language=Source::guess_language(it->path().filename());
if(!language) {
Gdk::RGBA rgba;
rgba.set_rgba(0.5, 0.5, 0.5);
child->set_value(column_record.color, rgba);
}
}
} }
} }
} }
@ -261,5 +278,8 @@ void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::T
if(!*children) { if(!*children) {
auto child=tree_store->append(*children); auto child=tree_store->append(*children);
child->set_value(column_record.name, std::string("(empty)")); child->set_value(column_record.name, std::string("(empty)"));
Gdk::RGBA rgba;
rgba.set_rgba(0.5, 0.5, 0.5);
child->set_value(column_record.color, rgba);
} }
} }

3
src/directories.h

@ -24,10 +24,12 @@ public:
add(id); add(id);
add(name); add(name);
add(path); add(path);
add(color);
} }
Gtk::TreeModelColumn<std::string> id; Gtk::TreeModelColumn<std::string> id;
Gtk::TreeModelColumn<std::string> name; Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<std::string> path; Gtk::TreeModelColumn<std::string> path;
Gtk::TreeModelColumn<Gdk::RGBA> color;
}; };
Directories(); Directories();
@ -46,6 +48,7 @@ private:
Gtk::TreeView tree_view; Gtk::TreeView tree_view;
Glib::RefPtr<Gtk::TreeStore> tree_store; Glib::RefPtr<Gtk::TreeStore> tree_store;
ColumnRecord column_record; ColumnRecord column_record;
std::unordered_map<std::string, std::pair<Gtk::TreeModel::Row, std::time_t> > last_write_times; std::unordered_map<std::string, std::pair<Gtk::TreeModel::Row, std::time_t> > last_write_times;
std::mutex update_mutex; std::mutex update_mutex;
std::thread update_thread; std::thread update_thread;

56
src/files.h

@ -83,62 +83,6 @@ const std::string configjson =
" }\n" " }\n"
"}\n"; "}\n";
const std::string menuxml =
"<ui>\n"
" <menubar name=\"MenuBar\">\n"
" <menu action=\"FileMenu\">\n"
" <menuitem action=\"FileNewFile\"/>\n"
" <menuitem action=\"FileNewFolder\"/>\n"
" <menu action=\"FileNewProject\">\n"
" <menuitem action=\"FileNewProjectCpp\"/>\n"
" </menu>\n"
" <separator/>\n"
" <menuitem action=\"FileOpenFile\"/>\n"
" <menuitem action=\"FileOpenFolder\"/>\n"
" <separator/>\n"
" <menuitem action=\"FileSave\"/>\n"
" <menuitem action=\"FileSaveAs\"/>\n"
" <separator/>\n"
" <menuitem action=\"FileQuit\"/>\n"
" </menu>\n"
" <menu action=\"EditMenu\">\n"
" <menuitem action=\"EditUndo\"/>\n"
" <menuitem action=\"EditRedo\"/>\n"
" <separator/>\n"
" <menuitem action=\"EditCopy\"/>\n"
" <menuitem action=\"EditCut\"/>\n"
" <menuitem action=\"EditPaste\"/>\n"
" <separator/>\n"
" <menuitem action=\"EditFind\"/>\n"
" </menu>\n"
" <menu action=\"SourceMenu\">\n"
" <menuitem action=\"SourceGotoLine\"/>\n"
" <menuitem action=\"SourceCenterCursor\"/>\n"
" <separator/>\n"
" <menuitem action=\"SourceGotoDeclaration\"/>\n"
" <menuitem action=\"SourceGotoMethod\"/>\n"
" <menuitem action=\"SourceRename\"/>\n"
" </menu>\n"
" <menu action=\"ProjectMenu\">\n"
" <menuitem action=\"ProjectCompileAndRun\"/>\n"
" <menuitem action=\"ProjectCompile\"/>\n"
" <separator/>\n"
" <menuitem action=\"ProjectRunCommand\"/>\n"
" <menuitem action=\"ProjectKillLastRunning\"/>\n"
" <menuitem action=\"ProjectForceKillLastRunning\"/>\n"
" </menu>\n"
" <menu action=\"WindowMenu\">\n"
" <menuitem action=\"WindowCloseTab\"/>\n"
" <menuitem action=\"WindowSplitWindow\"/>\n"
" </menu>\n"
" <menu action=\"PluginMenu\">\n"
" </menu>\n"
" <menu action=\"HelpMenu\">\n"
" <menuitem action=\"HelpAbout\"/>\n"
" </menu>\n"
" </menubar>\n"
"</ui>\n";
const std::string juci_light_style = const std::string juci_light_style =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"\n" "\n"

58
src/menu.cc

@ -14,6 +14,62 @@ Menu::Menu() : box(Gtk::ORIENTATION_VERTICAL) {
action_group->add(Gtk::Action::create("SourceMenu", "_Source")); action_group->add(Gtk::Action::create("SourceMenu", "_Source"));
action_group->add(Gtk::Action::create("PluginMenu", "_Plugins")); action_group->add(Gtk::Action::create("PluginMenu", "_Plugins"));
action_group->add(Gtk::Action::create("HelpMenu", "Help")); action_group->add(Gtk::Action::create("HelpMenu", "Help"));
ui_xml =
"<ui>\n"
" <menubar name=\"MenuBar\">\n"
" <menu action=\"FileMenu\">\n"
" <menuitem action=\"FileNewFile\"/>\n"
" <menuitem action=\"FileNewFolder\"/>\n"
" <menu action=\"FileNewProject\">\n"
" <menuitem action=\"FileNewProjectCpp\"/>\n"
" </menu>\n"
" <separator/>\n"
" <menuitem action=\"FileOpenFile\"/>\n"
" <menuitem action=\"FileOpenFolder\"/>\n"
" <separator/>\n"
" <menuitem action=\"FileSave\"/>\n"
" <menuitem action=\"FileSaveAs\"/>\n"
" <separator/>\n"
" <menuitem action=\"FileQuit\"/>\n"
" </menu>\n"
" <menu action=\"EditMenu\">\n"
" <menuitem action=\"EditUndo\"/>\n"
" <menuitem action=\"EditRedo\"/>\n"
" <separator/>\n"
" <menuitem action=\"EditCopy\"/>\n"
" <menuitem action=\"EditCut\"/>\n"
" <menuitem action=\"EditPaste\"/>\n"
" <separator/>\n"
" <menuitem action=\"EditFind\"/>\n"
" </menu>\n"
" <menu action=\"SourceMenu\">\n"
" <menuitem action=\"SourceGotoLine\"/>\n"
" <menuitem action=\"SourceCenterCursor\"/>\n"
" <separator/>\n"
" <menuitem action=\"SourceGotoDeclaration\"/>\n"
" <menuitem action=\"SourceGotoMethod\"/>\n"
" <menuitem action=\"SourceRename\"/>\n"
" </menu>\n"
" <menu action=\"ProjectMenu\">\n"
" <menuitem action=\"ProjectCompileAndRun\"/>\n"
" <menuitem action=\"ProjectCompile\"/>\n"
" <separator/>\n"
" <menuitem action=\"ProjectRunCommand\"/>\n"
" <menuitem action=\"ProjectKillLastRunning\"/>\n"
" <menuitem action=\"ProjectForceKillLastRunning\"/>\n"
" </menu>\n"
" <menu action=\"WindowMenu\">\n"
" <menuitem action=\"WindowCloseTab\"/>\n"
" <menuitem action=\"WindowSplitWindow\"/>\n"
" </menu>\n"
" <menu action=\"PluginMenu\">\n"
" </menu>\n"
" <menu action=\"HelpMenu\">\n"
" <menuitem action=\"HelpAbout\"/>\n"
" </menu>\n"
" </menubar>\n"
"</ui>\n";
} }
Gtk::Widget& Menu::get_widget() { Gtk::Widget& Menu::get_widget() {
@ -22,7 +78,7 @@ Gtk::Widget& Menu::get_widget() {
void Menu::build() { void Menu::build() {
try { try {
ui_manager->add_ui_from_string(ui); ui_manager->add_ui_from_string(ui_xml);
} }
catch (const Glib::Error &ex) { catch (const Glib::Error &ex) {
std::cerr << "building menu failed" << ex.what(); std::cerr << "building menu failed" << ex.what();

2
src/menu.h

@ -13,7 +13,7 @@ public:
Gtk::Box box; Gtk::Box box;
std::unordered_map<std::string, std::string> key_map; std::unordered_map<std::string, std::string> key_map;
std::string ui; std::string ui_xml;
Glib::RefPtr<Gtk::UIManager> ui_manager; Glib::RefPtr<Gtk::UIManager> ui_manager;
Glib::RefPtr<Gtk::ActionGroup> action_group; Glib::RefPtr<Gtk::ActionGroup> action_group;
}; };

34
src/notebook.cc

@ -32,7 +32,15 @@ int Notebook::size() {
} }
Source::View* Notebook::get_view(int page) { Source::View* Notebook::get_view(int page) {
return source_views.at(page); return source_views.at(get_index(page));
}
size_t Notebook::get_index(int page) {
for(size_t c=0;c<hboxes.size();c++) {
if(page_num(*hboxes.at(c))==page)
return c;
}
return -1;
} }
Source::View* Notebook::get_current_view() { Source::View* Notebook::get_current_view() {
@ -76,13 +84,24 @@ void Notebook::open(const boost::filesystem::path &file_path) {
else else
source_views.emplace_back(new Source::GenericView(file_path, language)); source_views.emplace_back(new Source::GenericView(file_path, language));
source_views.back()->on_update_status=[this](Source::View* view, const std::string &status) {
if(get_current_page()!=-1 && get_current_view()==view)
Singleton::status()->set_text(status+" ");
};
source_views.back()->on_update_info=[this](Source::View* view, const std::string &info) {
if(get_current_page()!=-1 && get_current_view()==view)
Singleton::info()->set_text(" "+info);
};
scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); scrolled_windows.emplace_back(new Gtk::ScrolledWindow());
hboxes.emplace_back(new Gtk::HBox()); hboxes.emplace_back(new Gtk::HBox());
scrolled_windows.back()->add(*source_views.back()); scrolled_windows.back()->add(*source_views.back());
hboxes.back()->pack_start(*scrolled_windows.back(), true, true); hboxes.back()->pack_start(*scrolled_windows.back(), true, true);
std::string title=file_path.filename().string(); std::string title=file_path.filename().string();
append_page(*hboxes.back(), title); append_page(*hboxes.back(), title);
set_tab_reorderable(*hboxes.back(), true);
show_all_children(); show_all_children();
set_current_page(size()-1); set_current_page(size()-1);
set_focus_child(*source_views.back()); set_focus_child(*source_views.back());
@ -105,10 +124,6 @@ void Notebook::open(const boost::filesystem::path &file_path) {
set_tab_label_text(*(get_nth_page(page)), title); set_tab_label_text(*(get_nth_page(page)), title);
}); });
get_current_view()->on_update_status=[this](Source::View* view, const std::string &status) {
if(get_current_page()!=-1 && get_current_view()==view)
Singleton::status()->set_text(status);
};
DEBUG("end"); DEBUG("end");
} }
@ -176,15 +191,16 @@ bool Notebook::close_current_page() {
} }
} }
int page = get_current_page(); int page = get_current_page();
int index=get_index(page);
remove_page(page); remove_page(page);
auto source_view=source_views.at(page); auto source_view=source_views.at(index);
if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view)) if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view))
source_clang_view->async_delete(); source_clang_view->async_delete();
else else
delete source_view; delete source_view;
source_views.erase(source_views.begin()+ page); source_views.erase(source_views.begin()+index);
scrolled_windows.erase(scrolled_windows.begin()+page); scrolled_windows.erase(scrolled_windows.begin()+index);
hboxes.erase(hboxes.begin()+page); hboxes.erase(hboxes.begin()+index);
} }
DEBUG("end true"); DEBUG("end true");
return true; return true;

1
src/notebook.h

@ -14,6 +14,7 @@ class Notebook : public Gtk::Notebook {
public: public:
Notebook(Directories &directories); Notebook(Directories &directories);
Source::View* get_view(int page); Source::View* get_view(int page);
size_t get_index(int page);
int size(); int size();
Source::View* get_current_view(); Source::View* get_current_view();
bool close_current_page(); bool close_current_page();

6
src/singletons.cc

@ -17,3 +17,9 @@ Gtk::Label *Singleton::status() {
status_=std::unique_ptr<Gtk::Label>(new Gtk::Label()); status_=std::unique_ptr<Gtk::Label>(new Gtk::Label());
return status_.get(); return status_.get();
} }
std::unique_ptr<Gtk::Label> Singleton::info_=std::unique_ptr<Gtk::Label>();
Gtk::Label *Singleton::info() {
if(!info_)
info_=std::unique_ptr<Gtk::Label>(new Gtk::Label());
return info_.get();
}

2
src/singletons.h

@ -31,9 +31,11 @@ public:
static std::string style_dir() { return std::string(getenv("HOME")) + "/.juci/styles/"; } static std::string style_dir() { return std::string(getenv("HOME")) + "/.juci/styles/"; }
static Terminal *terminal(); static Terminal *terminal();
static Gtk::Label *status(); static Gtk::Label *status();
static Gtk::Label *info();
private: private:
static std::unique_ptr<Terminal> terminal_; static std::unique_ptr<Terminal> terminal_;
static std::unique_ptr<Gtk::Label> status_; static std::unique_ptr<Gtk::Label> status_;
static std::unique_ptr<Gtk::Label> info_;
}; };
#endif // JUCI_SINGLETONS_H_ #endif // JUCI_SINGLETONS_H_

254
src/source.cc

@ -48,13 +48,22 @@ Glib::RefPtr<Gsv::Language> Source::guess_language(const boost::filesystem::path
////////////// //////////////
AspellConfig* Source::View::spellcheck_config=NULL; AspellConfig* Source::View::spellcheck_config=NULL;
Source::View::View(const boost::filesystem::path &file_path): file_path(file_path) { Source::View::View(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language): file_path(file_path) {
set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); set_smart_home_end(Gsv::SMART_HOME_END_BEFORE);
get_source_buffer()->begin_not_undoable_action(); get_source_buffer()->begin_not_undoable_action();
if(juci::filesystem::read(file_path, get_buffer())==-1) if(language) {
Singleton::terminal()->print("Error: "+file_path.string()+" is not a valid UTF-8 file."); if(juci::filesystem::read_non_utf8(file_path, get_buffer())==-1)
Singleton::terminal()->print("Warning: "+file_path.string()+" is not a valid UTF-8 file. Saving might corrupt the file.\n");
}
else {
if(juci::filesystem::read(file_path, get_buffer())==-1)
Singleton::terminal()->print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n");
}
get_source_buffer()->end_not_undoable_action(); get_source_buffer()->end_not_undoable_action();
get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0));
search_settings = gtk_source_search_settings_new(); search_settings = gtk_source_search_settings_new();
gtk_source_search_settings_set_wrap_around(search_settings, true); gtk_source_search_settings_set_wrap_around(search_settings, true);
search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings); search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings);
@ -193,8 +202,8 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat
if(ends_line || *iter=='/' || *iter=='*') //iter_has_context_class is sadly bugged if(ends_line || *iter=='/' || *iter=='*') //iter_has_context_class is sadly bugged
backward_success=context_iter.backward_char(); backward_success=context_iter.backward_char();
if(backward_success) { if(backward_success) {
if(last_keyval_is_backspace && !is_word_iter(iter) && iter.forward_char()) {} //backspace fix
if((spellcheck_all && !get_source_buffer()->iter_has_context_class(context_iter, "no-spell-check")) || get_source_buffer()->iter_has_context_class(context_iter, "comment") || get_source_buffer()->iter_has_context_class(context_iter, "string")) { if((spellcheck_all && !get_source_buffer()->iter_has_context_class(context_iter, "no-spell-check")) || get_source_buffer()->iter_has_context_class(context_iter, "comment") || get_source_buffer()->iter_has_context_class(context_iter, "string")) {
if(last_keyval_is_backspace && !is_word_iter(iter) && iter.forward_char()) {} //backspace fix
if(!is_word_iter(iter)) { //Might have used space or - to split two words if(!is_word_iter(iter)) { //Might have used space or - to split two words
auto first=iter; auto first=iter;
auto second=iter; auto second=iter;
@ -211,6 +220,20 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat
spellcheck_word(word.first, word.second); spellcheck_word(word.first, word.second);
} }
} }
else {
auto tags=iter.get_tags();
bool has_spellcheck_error=false;
for(auto &tag: tags) {
if(tag->property_name()=="spellcheck_error") {
has_spellcheck_error=true;
break;
}
}
if(has_spellcheck_error) {
auto word=spellcheck_get_word(iter);
get_buffer()->remove_tag_by_name("spellcheck_error", word.first, word.second);
}
}
} }
} }
}); });
@ -230,6 +253,12 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat
} }
} }
if(need_suggestions) { if(need_suggestions) {
auto iter=get_buffer()->get_insert()->get_iter();
if(!((spellcheck_all && !get_source_buffer()->iter_has_context_class(iter, "no-spell-check")) || get_source_buffer()->iter_has_context_class(iter, "comment") || get_source_buffer()->iter_has_context_class(iter, "string"))) {
auto word=spellcheck_get_word(iter);
get_buffer()->remove_tag_by_name("spellcheck_error", word.first, word.second);
return false;
}
spellcheck_suggestions_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*this, get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()), false)); spellcheck_suggestions_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*this, get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()), false));
spellcheck_suggestions_dialog->on_hide=[this](){ spellcheck_suggestions_dialog->on_hide=[this](){
spellcheck_suggestions_dialog_shown=false; spellcheck_suggestions_dialog_shown=false;
@ -256,6 +285,10 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat
}); });
} }
get_buffer()->signal_changed().connect([this](){
set_info(info);
});
set_tooltip_events(); set_tooltip_events();
} }
@ -307,6 +340,7 @@ void Source::View::set_tooltip_events() {
}, 500); }, 500);
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
set_info(info);
} }
}); });
@ -521,6 +555,14 @@ void Source::View::set_status(const std::string &status) {
on_update_status(this, status); on_update_status(this, status);
} }
void Source::View::set_info(const std::string &info) {
this->info=info;
auto iter=get_buffer()->get_insert()->get_iter();
auto positions=std::to_string(iter.get_line()+1)+":"+std::to_string(iter.get_line_offset()+1);
if(on_update_info)
on_update_info(this, positions+" "+info);
}
std::string Source::View::get_line(const Gtk::TextIter &iter) { std::string Source::View::get_line(const Gtk::TextIter &iter) {
auto line_start_it = get_buffer()->get_iter_at_line(iter.get_line()); auto line_start_it = get_buffer()->get_iter_at_line(iter.get_line());
auto line_end_it = iter; auto line_end_it = iter;
@ -857,7 +899,7 @@ std::pair<char, unsigned> Source::View::find_tab_char_and_size() {
} }
bool Source::View::is_word_iter(const Gtk::TextIter& iter) { bool Source::View::is_word_iter(const Gtk::TextIter& iter) {
return ((*iter>=48 && *iter<=57) || (*iter>=65 && *iter<=90) || (*iter>=97 && *iter<=122) || *iter==39 || *iter>=128); return ((*iter>=65 && *iter<=90) || (*iter>=97 && *iter<=122) || *iter==39 || *iter>=128);
} }
std::pair<Gtk::TextIter, Gtk::TextIter> Source::View::spellcheck_get_word(Gtk::TextIter iter) { std::pair<Gtk::TextIter, Gtk::TextIter> Source::View::spellcheck_get_word(Gtk::TextIter iter) {
@ -908,7 +950,7 @@ std::vector<std::string> Source::View::spellcheck_get_suggestions(const Gtk::Tex
///////////////////// /////////////////////
//// GenericView //// //// GenericView ////
///////////////////// /////////////////////
Source::GenericView::GenericView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language) : View(file_path) { Source::GenericView::GenericView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language) : View(file_path, language) {
if(language) { if(language) {
get_source_buffer()->set_language(language); get_source_buffer()->set_language(language);
Singleton::terminal()->print("Language for file "+file_path.string()+" set to "+language->get_name()+".\n"); Singleton::terminal()->print("Language for file "+file_path.string()+" set to "+language->get_name()+".\n");
@ -928,8 +970,8 @@ Source::GenericView::GenericView(const boost::filesystem::path &file_path, Glib:
//////////////////////// ////////////////////////
clang::Index Source::ClangViewParse::clang_index(0, 0); clang::Index Source::ClangViewParse::clang_index(0, 0);
Source::ClangViewParse::ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): Source::ClangViewParse::ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language):
Source::View(file_path), project_path(project_path) { Source::View(file_path, language), project_path(project_path), parse_error(false) {
DEBUG("start"); DEBUG("start");
auto scheme = get_source_buffer()->get_style_scheme(); auto scheme = get_source_buffer()->get_style_scheme();
auto tag_table=get_buffer()->get_tag_table(); auto tag_table=get_buffer()->get_tag_table();
@ -983,6 +1025,7 @@ Source::View(file_path), project_path(project_path) {
parse_fail.connect([this](){ parse_fail.connect([this](){
Singleton::terminal()->print("Error: failed to reparse "+this->file_path.string()+".\n"); Singleton::terminal()->print("Error: failed to reparse "+this->file_path.string()+".\n");
set_status(""); set_status("");
set_info("");
parsing_in_progress->cancel("failed"); parsing_in_progress->cancel("failed");
}); });
init_parse(); init_parse();
@ -1025,7 +1068,8 @@ void Source::ClangViewParse::init_parse() {
} }
pos++; pos++;
} }
init_syntax_highlighting(buffer_map); clang_tu = std::unique_ptr<clang::TranslationUnit>(new clang::TranslationUnit(clang_index, file_path.string(), get_compilation_commands(), buffer_map));
clang_tokens=clang_tu->get_tokens(0, buffer_map.find(file_path.string())->second.size()-1);
update_syntax(); update_syntax();
set_status("parsing..."); set_status("parsing...");
@ -1042,31 +1086,25 @@ void Source::ClangViewParse::init_parse() {
parse_start(); parse_start();
} }
else if (parse_thread_mapped && parsing_mutex.try_lock() && parse_thread_buffer_map_mutex.try_lock()) { else if (parse_thread_mapped && parsing_mutex.try_lock() && parse_thread_buffer_map_mutex.try_lock()) {
int status=reparse(parse_thread_buffer_map); int status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_map);
if(status==0)
clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1);
else
parse_error=true;
parse_thread_go=false; parse_thread_go=false;
if(status!=0)
parse_thread_stop=true;
parsing_mutex.unlock(); parsing_mutex.unlock();
parse_thread_buffer_map_mutex.unlock(); parse_thread_buffer_map_mutex.unlock();
if(status!=0) { if(status!=0) {
parse_fail(); parse_fail();
return; parse_thread_stop=true;
} }
parse_done(); else
parse_done();
} }
} }
}); });
} }
void Source::ClangViewParse::init_syntax_highlighting(const std::map<std::string, std::string> &buffers) {
std::vector<string> arguments = get_compilation_commands();
clang_tu = std::unique_ptr<clang::TranslationUnit>(new clang::TranslationUnit(clang_index,
file_path.string(),
arguments,
buffers));
clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path.string())->second.size()-1);
}
std::map<std::string, std::string> Source::ClangViewParse::get_buffer_map() const { std::map<std::string, std::string> Source::ClangViewParse::get_buffer_map() const {
std::map<std::string, std::string> buffer_map; std::map<std::string, std::string> buffer_map;
buffer_map[file_path.string()]=get_source_buffer()->get_text(); buffer_map[file_path.string()]=get_source_buffer()->get_text();
@ -1077,23 +1115,12 @@ void Source::ClangViewParse::start_reparse() {
parse_thread_mapped=false; parse_thread_mapped=false;
source_readable=false; source_readable=false;
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
if(!parse_thread_stop) { delayed_reparse_connection=Glib::signal_timeout().connect([this]() {
delayed_reparse_connection=Glib::signal_timeout().connect([this]() { source_readable=false;
source_readable=false; parse_thread_go=true;
parse_thread_go=true; set_status("parsing...");
set_status("parsing..."); return false;
return false; }, 1000);
}, 1000);
}
}
int Source::ClangViewParse::reparse(const std::map<std::string, std::string> &buffer) {
int status = clang_tu->ReparseTranslationUnit(buffer);
if(status!=0) {
return status;
}
clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1);
return status;
} }
std::vector<std::string> Source::ClangViewParse::get_compilation_commands() { std::vector<std::string> Source::ClangViewParse::get_compilation_commands() {
@ -1192,6 +1219,8 @@ void Source::ClangViewParse::update_diagnostics() {
get_buffer()->remove_tag_by_name("def:warning_underline", get_buffer()->begin(), get_buffer()->end()); get_buffer()->remove_tag_by_name("def:warning_underline", get_buffer()->begin(), get_buffer()->end());
get_buffer()->remove_tag_by_name("def:error_underline", get_buffer()->begin(), get_buffer()->end()); get_buffer()->remove_tag_by_name("def:error_underline", get_buffer()->begin(), get_buffer()->end());
auto diagnostics=clang_tu->get_diagnostics(); auto diagnostics=clang_tu->get_diagnostics();
size_t warnings=0;
size_t errors=0;
for(auto &diagnostic: diagnostics) { for(auto &diagnostic: diagnostics) {
if(diagnostic.path==file_path.string()) { if(diagnostic.path==file_path.string()) {
auto start_line=get_line(diagnostic.offsets.first.line-1); //index is sometimes off the line auto start_line=get_line(diagnostic.offsets.first.line-1); //index is sometimes off the line
@ -1213,10 +1242,14 @@ void Source::ClangViewParse::update_diagnostics() {
auto start=get_buffer()->get_iter_at_line_index(diagnostic.offsets.first.line-1, start_line_index); auto start=get_buffer()->get_iter_at_line_index(diagnostic.offsets.first.line-1, start_line_index);
auto end=get_buffer()->get_iter_at_line_index(diagnostic.offsets.second.line-1, end_line_index); auto end=get_buffer()->get_iter_at_line_index(diagnostic.offsets.second.line-1, end_line_index);
std::string diagnostic_tag_name; std::string diagnostic_tag_name;
if(diagnostic.severity<=CXDiagnostic_Warning) if(diagnostic.severity<=CXDiagnostic_Warning) {
diagnostic_tag_name="def:warning"; diagnostic_tag_name="def:warning";
else warnings++;
}
else {
diagnostic_tag_name="def:error"; diagnostic_tag_name="def:error";
errors++;
}
auto spelling=diagnostic.spelling; auto spelling=diagnostic.spelling;
auto severity_spelling=diagnostic.severity_spelling; auto severity_spelling=diagnostic.severity_spelling;
@ -1237,6 +1270,20 @@ void Source::ClangViewParse::update_diagnostics() {
} }
} }
} }
std::string diagnostic_info;
if(warnings>0) {
diagnostic_info+=std::to_string(warnings)+" warning";
if(warnings>1)
diagnostic_info+='s';
}
if(errors>0) {
if(warnings>0)
diagnostic_info+=", ";
diagnostic_info+=std::to_string(errors)+" error";
if(errors>1)
diagnostic_info+='s';
}
set_info(" "+diagnostic_info);
} }
void Source::ClangViewParse::update_types() { void Source::ClangViewParse::update_types() {
@ -1401,8 +1448,8 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) {
////////////////////////////// //////////////////////////////
//// ClangViewAutocomplete /// //// ClangViewAutocomplete ///
////////////////////////////// //////////////////////////////
Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language):
Source::ClangViewParse(file_path, project_path), autocomplete_cancel_starting(false) { Source::ClangViewParse(file_path, project_path, language), autocomplete_cancel_starting(false) {
get_buffer()->signal_changed().connect([this](){ get_buffer()->signal_changed().connect([this](){
if(completion_dialog_shown) if(completion_dialog_shown)
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
@ -1436,6 +1483,23 @@ Source::ClangViewParse(file_path, project_path), autocomplete_cancel_starting(fa
return false; return false;
}); });
autocomplete_fail.connect([this]() {
Singleton::terminal()->print("Error: autocomplete failed, reparsing "+this->file_path.string()+"\n");
restart_parse();
autocomplete_starting=false;
autocomplete_cancel_starting=false;
});
do_delete_object.connect([this](){
if(delete_thread.joinable())
delete_thread.join();
delete this;
});
do_restart_parse.connect([this](){
init_parse();
restart_parse_running=false;
});
} }
bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) {
@ -1489,6 +1553,10 @@ void Source::ClangViewAutocomplete::start_autocomplete() {
} }
void Source::ClangViewAutocomplete::autocomplete() { void Source::ClangViewAutocomplete::autocomplete() {
if(parse_thread_stop) {
return;
}
if(!autocomplete_starting) { if(!autocomplete_starting) {
autocomplete_starting=true; autocomplete_starting=true;
autocomplete_cancel_starting=false; autocomplete_cancel_starting=false;
@ -1505,6 +1573,7 @@ void Source::ClangViewAutocomplete::autocomplete() {
completion_dialog->on_hide=[this](){ completion_dialog->on_hide=[this](){
get_source_buffer()->end_user_action(); get_source_buffer()->end_user_action();
completion_dialog_shown=false; completion_dialog_shown=false;
source_readable=false;
start_reparse(); start_reparse();
}; };
completion_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { completion_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) {
@ -1581,16 +1650,23 @@ void Source::ClangViewAutocomplete::autocomplete() {
parsing_mutex.lock(); parsing_mutex.lock();
if(!parse_thread_stop) if(!parse_thread_stop)
*ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map)); *ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map));
autocomplete_done(); if(!parse_thread_stop)
autocomplete_done();
else
autocomplete_fail();
parsing_mutex.unlock(); parsing_mutex.unlock();
}); });
} }
} }
std::vector<Source::AutoCompleteData> Source::ClangViewAutocomplete:: std::vector<Source::AutoCompleteData> Source::ClangViewAutocomplete::get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map) {
get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map) {
std::vector<Source::AutoCompleteData> suggestions; std::vector<Source::AutoCompleteData> suggestions;
auto results=clang_tu->get_code_completions(buffer_map, line_number, column); auto results=clang_tu->get_code_completions(buffer_map, line_number, column);
if(results.cx_results==NULL) {
parse_thread_stop=true;
return suggestions;
}
if(!autocomplete_cancel_starting) { if(!autocomplete_cancel_starting) {
prefix_mutex.lock(); prefix_mutex.lock();
auto prefix_copy=prefix; auto prefix_copy=prefix;
@ -1617,12 +1693,46 @@ get_autocomplete_suggestions(int line_number, int column, std::map<std::string,
return suggestions; return suggestions;
} }
void Source::ClangViewAutocomplete::async_delete() {
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(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::ClangViewAutocomplete::restart_parse() {
if(!restart_parse_running && !parse_error) {
reparse_needed=false;
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;
}
//////////////////////////// ////////////////////////////
//// ClangViewRefactor ///// //// ClangViewRefactor /////
//////////////////////////// ////////////////////////////
Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language):
Source::ClangViewAutocomplete(file_path, project_path) { Source::ClangViewAutocomplete(file_path, project_path, language) {
similar_tokens_tag=get_buffer()->create_tag(); similar_tokens_tag=get_buffer()->create_tag();
similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD;
@ -1767,53 +1877,9 @@ Source::ClangViewRefactor::~ClangViewRefactor() {
delayed_tag_similar_tokens_connection.disconnect(); delayed_tag_similar_tokens_connection.disconnect();
} }
Source::ClangView::ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language): ClangViewRefactor(file_path, project_path) { Source::ClangView::ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language): ClangViewRefactor(file_path, project_path, language) {
if(language) { if(language) {
get_source_buffer()->set_highlight_syntax(true); get_source_buffer()->set_highlight_syntax(true);
get_source_buffer()->set_language(language); get_source_buffer()->set_language(language);
} }
do_delete_object.connect([this](){
if(delete_thread.joinable())
delete_thread.join();
delete this;
});
do_restart_parse.connect([this](){
init_parse();
restart_parse_running=false;
});
}
void Source::ClangView::async_delete() {
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(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 && !parse_thread_stop) {
reparse_needed=false;
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;
} }

35
src/source.h

@ -52,7 +52,7 @@ namespace Source {
class View : public Gsv::View { class View : public Gsv::View {
public: public:
View(const boost::filesystem::path &file_path); View(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language);
~View(); ~View();
void search_highlight(const std::string &text, bool case_sensitive, bool regex); void search_highlight(const std::string &text, bool case_sensitive, bool regex);
@ -75,7 +75,11 @@ namespace Source {
std::function<size_t(const std::string &token, const std::string &text)> rename_similar_tokens; std::function<size_t(const std::string &token, const std::string &text)> rename_similar_tokens;
std::function<void(View* view, const std::string &status)> on_update_status; std::function<void(View* view, const std::string &status)> on_update_status;
std::function<void(View* view, const std::string &info)> on_update_info;
void set_status(const std::string &status);
void set_info(const std::string &info);
std::string status; std::string status;
std::string info;
protected: protected:
bool source_readable; bool source_readable;
Tooltips diagnostic_tooltips; Tooltips diagnostic_tooltips;
@ -85,8 +89,6 @@ namespace Source {
sigc::connection delayed_tooltips_connection; sigc::connection delayed_tooltips_connection;
void set_tooltip_events(); void set_tooltip_events();
void set_status(const std::string &status);
std::string get_line(const Gtk::TextIter &iter); std::string get_line(const Gtk::TextIter &iter);
std::string get_line(Glib::RefPtr<Gtk::TextBuffer::Mark> mark); std::string get_line(Glib::RefPtr<Gtk::TextBuffer::Mark> mark);
std::string get_line(int line_nr); std::string get_line(int line_nr);
@ -134,7 +136,7 @@ namespace Source {
class ClangViewParse : public View { class ClangViewParse : public View {
public: public:
ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language);
~ClangViewParse(); ~ClangViewParse();
boost::filesystem::path project_path; boost::filesystem::path project_path;
void start_reparse(); void start_reparse();
@ -150,15 +152,13 @@ namespace Source {
std::shared_ptr<Terminal::InProgress> parsing_in_progress; std::shared_ptr<Terminal::InProgress> parsing_in_progress;
std::thread parse_thread; std::thread parse_thread;
std::atomic<bool> parse_thread_stop; std::atomic<bool> parse_thread_stop;
std::atomic<bool> parse_error;
std::regex bracket_regex; std::regex bracket_regex;
std::regex no_bracket_statement_regex; std::regex no_bracket_statement_regex;
std::regex no_bracket_no_para_statement_regex; std::regex no_bracket_no_para_statement_regex;
private: private:
std::map<std::string, std::string> get_buffer_map() const; std::map<std::string, std::string> get_buffer_map() const;
// inits the syntax highligthing on file open
void init_syntax_highlighting(const std::map<std::string, std::string> &buffers);
int reparse(const std::map<std::string, std::string> &buffers);
void update_syntax(); void update_syntax();
std::set<std::string> last_syntax_tags; std::set<std::string> last_syntax_tags;
void update_diagnostics(); void update_diagnostics();
@ -178,7 +178,9 @@ namespace Source {
class ClangViewAutocomplete : public ClangViewParse { class ClangViewAutocomplete : public ClangViewParse {
public: public:
ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language);
void async_delete();
bool restart_parse();
protected: protected:
bool on_key_press_event(GdkEventKey* key); bool on_key_press_event(GdkEventKey* key);
std::thread autocomplete_thread; std::thread autocomplete_thread;
@ -190,16 +192,23 @@ namespace Source {
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map); std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map);
Glib::Dispatcher autocomplete_done; Glib::Dispatcher autocomplete_done;
sigc::connection autocomplete_done_connection; sigc::connection autocomplete_done_connection;
Glib::Dispatcher autocomplete_fail;
bool autocomplete_starting=false; bool autocomplete_starting=false;
std::atomic<bool> autocomplete_cancel_starting; std::atomic<bool> autocomplete_cancel_starting;
guint last_keyval=0; guint last_keyval=0;
std::string prefix; std::string prefix;
std::mutex prefix_mutex; std::mutex prefix_mutex;
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 ClangViewRefactor : public ClangViewAutocomplete { class ClangViewRefactor : public ClangViewAutocomplete {
public: public:
ClangViewRefactor(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); ClangViewRefactor(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language);
~ClangViewRefactor(); ~ClangViewRefactor();
private: private:
Glib::RefPtr<Gtk::TextTag> similar_tokens_tag; Glib::RefPtr<Gtk::TextTag> similar_tokens_tag;
@ -212,14 +221,6 @@ namespace Source {
class ClangView : public ClangViewRefactor { class ClangView : public ClangViewRefactor {
public: public:
ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language); ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr<Gsv::Language> language);
void async_delete();
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 }; // class Source
#endif // JUCI_SOURCE_H_ #endif // JUCI_SOURCE_H_

38
src/sourcefile.cc

@ -25,15 +25,6 @@ int juci::filesystem::read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer
Glib::ustring ustr=std::move(ss.str()); Glib::ustring ustr=std::move(ss.str());
bool valid=true; bool valid=true;
//This was way too slow...
/*Glib::ustring::iterator iter;
while(!ustr.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
ustr.replace(iter, next_char_iter, "?");
if(valid)
valid=false;
}*/
if(ustr.validate()) if(ustr.validate())
text_buffer->insert_at_cursor(ustr); text_buffer->insert_at_cursor(ustr);
@ -69,6 +60,35 @@ int juci::filesystem::read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer
return 0; return 0;
} }
int juci::filesystem::read_non_utf8(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) {
std::ifstream input(path, std::ofstream::binary);
if(input) {
//need to read the whole file to make this work...
std::stringstream ss;
ss << input.rdbuf();
Glib::ustring ustr=std::move(ss.str());
bool valid=true;
Glib::ustring::iterator iter;
while(!ustr.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
ustr.replace(iter, next_char_iter, "?");
valid=false;
}
text_buffer->insert_at_cursor(ustr);
input.close();
if(valid)
return 1;
else
return -1;
}
return 0;
}
//Only use on small files //Only use on small files
std::vector<std::string> juci::filesystem::read_lines(const std::string &path) { std::vector<std::string> juci::filesystem::read_lines(const std::string &path) {
std::vector<std::string> res; std::vector<std::string> res;

3
src/sourcefile.h

@ -13,6 +13,9 @@ namespace juci {
static int read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer); static int read(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer);
static int read(const boost::filesystem::path &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) { return read(path.string(), text_buffer); } static int read(const boost::filesystem::path &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) { return read(path.string(), text_buffer); }
static int read_non_utf8(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer);
static int read_non_utf8(const boost::filesystem::path &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) { return read_non_utf8(path.string(), text_buffer); }
static std::vector<std::string> read_lines(const std::string &path); static std::vector<std::string> read_lines(const std::string &path);
static std::vector<std::string> read_lines(const boost::filesystem::path &path) { return read_lines(path.string()); }; static std::vector<std::string> read_lines(const boost::filesystem::path &path) { return read_lines(path.string()); };

4
src/tooltips.cc

@ -1,8 +1,8 @@
#include "tooltips.h" #include "tooltips.h"
#include "singletons.h" #include "singletons.h"
#include <iostream> #include <iostream> //TODO: remove
using namespace std; using namespace std; //TODO: remove
namespace sigc { namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE #ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE

20
src/window.cc

@ -24,8 +24,6 @@ namespace sigc {
} }
void Window::generate_keybindings() { void Window::generate_keybindings() {
boost::filesystem::path path(Singleton::config_dir() + "menu.xml");
menu.ui = juci::filesystem::read(path);
for (auto &i : Singleton::Config::window()->keybindings) { for (auto &i : Singleton::Config::window()->keybindings) {
auto key = i.second.get_value<std::string>(); auto key = i.second.get_value<std::string>();
menu.key_map[i.first] = key; menu.key_map[i.first] = key;
@ -54,8 +52,9 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compil
terminal_scrolled_window.add(*Singleton::terminal()); terminal_scrolled_window.add(*Singleton::terminal());
terminal_vbox.pack_start(terminal_scrolled_window); terminal_vbox.pack_start(terminal_scrolled_window);
status_hbox.pack_end(*Singleton::status(), Gtk::PACK_SHRINK); info_and_status_hbox.pack_start(*Singleton::info(), Gtk::PACK_SHRINK);
terminal_vbox.pack_end(status_hbox, Gtk::PACK_SHRINK); info_and_status_hbox.pack_end(*Singleton::status(), Gtk::PACK_SHRINK);
terminal_vbox.pack_end(info_and_status_hbox, Gtk::PACK_SHRINK);
vpaned.pack2(terminal_vbox, true, true); vpaned.pack2(terminal_vbox, true, true);
box.pack_end(vpaned); box.pack_end(vpaned);
@ -110,7 +109,8 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compil
} }
} }
Singleton::status()->set_text(notebook.get_current_view()->status); notebook.get_current_view()->set_status(notebook.get_current_view()->status);
notebook.get_current_view()->set_info(notebook.get_current_view()->info);
} }
}); });
notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) { notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) {
@ -322,10 +322,14 @@ void Window::create_menu() {
}); });
menu.action_group->add(Gtk::Action::create("WindowCloseTab", "Close Tab"), Gtk::AccelKey(menu.key_map["close_tab"]), [this]() { menu.action_group->add(Gtk::Action::create("WindowCloseTab", "Close Tab"), Gtk::AccelKey(menu.key_map["close_tab"]), [this]() {
notebook.close_current_page(); notebook.close_current_page();
if(notebook.get_current_page()!=-1) if(notebook.get_current_page()!=-1) {
Singleton::status()->set_text(notebook.get_current_view()->status); notebook.get_current_view()->set_status(notebook.get_current_view()->status);
else notebook.get_current_view()->set_info(notebook.get_current_view()->info);
}
else {
Singleton::status()->set_text(""); Singleton::status()->set_text("");
Singleton::info()->set_text("");
}
}); });
menu.action_group->add(Gtk::Action::create("HelpAbout", "About"), [this] () { menu.action_group->add(Gtk::Action::create("HelpAbout", "About"), [this] () {
about.show(); about.show();

2
src/window.h

@ -33,7 +33,7 @@ private:
Gtk::VBox notebook_vbox; Gtk::VBox notebook_vbox;
Gtk::VBox terminal_vbox; Gtk::VBox terminal_vbox;
Gtk::ScrolledWindow terminal_scrolled_window; Gtk::ScrolledWindow terminal_scrolled_window;
Gtk::HBox status_hbox; Gtk::HBox info_and_status_hbox;
Gtk::AboutDialog about; Gtk::AboutDialog about;
EntryBox entry_box; EntryBox entry_box;
Menu menu; Menu menu;

Loading…
Cancel
Save