Browse Source

Additional information is stored and used between juCi++ sessions: line offsets of buffers, window size, run arguments, and debug run arguments, including remote debug settings.

merge-requests/365/head
eidheim 8 years ago
parent
commit
8a4cab0415
  1. 2
      CMakeLists.txt
  2. 1
      src/config.cc
  3. 1
      src/config.h
  4. 4
      src/files.h
  5. 52
      src/juci.cc
  6. 2
      src/juci.h
  7. 32
      src/notebook.cc
  8. 2
      src/notebook.h
  9. 87
      src/project.cc
  10. 38
      src/project.h
  11. 296
      src/window.cc
  12. 4
      src/window.h

2
CMakeLists.txt

@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 2.8.8)
project(juci)
set(JUCI_VERSION "1.4.0.1")
set(JUCI_VERSION "1.4.0.2")
set(CPACK_PACKAGE_NAME "jucipp")
set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>")

1
src/config.cc

@ -191,7 +191,6 @@ void Config::read(const boost::property_tree::ptree &cfg) {
window.theme_name=cfg.get<std::string>("gtk_theme.name");
window.theme_variant=cfg.get<std::string>("gtk_theme.variant");
window.version = cfg.get<std::string>("version");
window.default_size = {cfg.get<int>("default_window_size.width"), cfg.get<int>("default_window_size.height")};
project.default_build_path=cfg.get<std::string>("project.default_build_path");
project.debug_build_path=cfg.get<std::string>("project.debug_build_path");

1
src/config.h

@ -19,7 +19,6 @@ public:
std::string theme_name;
std::string theme_variant;
std::string version;
std::pair<int, int> default_size;
};
class Terminal {

4
src/files.h

@ -6,10 +6,6 @@
/// the changes to user's ~/.juci/config/config.json files
const std::string default_config_file = R"RAW({
"version": ")RAW"+std::string(JUCI_VERSION)+R"RAW(",
"default_window_size": {
"width": 800,
"height": 600
},
"gtk_theme": {
"name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh",
"name": "",

52
src/juci.cc

@ -46,30 +46,14 @@ int Application::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>
}
void Application::on_activate() {
add_window(Window::get());
Window::get().show();
std::vector<std::pair<int, int>> file_offsets;
std::string current_file;
Window::get().load_session(directories, files, file_offsets, current_file, directories.empty() && files.empty());
std::string last_current_file;
Window::get().add_widgets();
if(directories.empty() && files.empty()) {
try {
boost::property_tree::ptree pt;
boost::property_tree::read_json((Config::get().home_juci_path/"last_session.json").string(), pt);
auto folder=pt.get<std::string>("folder");
if(!folder.empty() && boost::filesystem::exists(folder) && boost::filesystem::is_directory(folder))
directories.emplace_back(folder);
for(auto &pt_file: pt.get_child("files")) {
auto notebook=pt_file.second.get<size_t>("notebook", -1);
auto file=pt_file.second.get<std::string>("file", "");
if(!file.empty() && boost::filesystem::exists(file) && !boost::filesystem::is_directory(file))
files.emplace_back(file, notebook);
}
last_current_file=pt.get<std::string>("current_file");
if(!boost::filesystem::exists(last_current_file) || boost::filesystem::is_directory(last_current_file))
last_current_file.clear();
}
catch(const std::exception &) {}
}
add_window(Window::get());
Window::get().show();
bool first_directory=true;
for(auto &directory: directories) {
@ -87,7 +71,7 @@ void Application::on_activate() {
else
it++;
}
std::thread another_juci_app([this, directory, files_in_directory](){
std::thread another_juci_app([directory, files_in_directory](){
Terminal::get().async_print("Executing: juci "+directory.string()+files_in_directory+"\n");
Terminal::get().process("juci "+directory.string()+files_in_directory, "", false);
});
@ -95,14 +79,28 @@ void Application::on_activate() {
}
}
for(auto &file: files)
Notebook::get().open(file.first, file.second);
for(size_t i=0;i<files.size();++i) {
Notebook::get().open(files[i].first, files[i].second);
if(i<file_offsets.size()) {
if(auto view=Notebook::get().get_current_view()) {
view->place_cursor_at_line_offset(file_offsets[i].first, file_offsets[i].second);
view->scroll_to_cursor_delayed(view, true, false);
}
}
}
for(auto &error: errors)
Terminal::get().print(error, true);
if(!last_current_file.empty())
Notebook::get().open(last_current_file);
if(!current_file.empty()) {
Notebook::get().open(current_file);
if(auto view=Notebook::get().get_current_view()) {
auto iter=view->get_buffer()->get_insert()->get_iter();
// To update cursor history
view->place_cursor_at_line_offset(iter.get_line(), iter.get_line_offset());
view->hide_tooltips();
}
}
}
void Application::on_startup() {

2
src/juci.h

@ -36,6 +36,6 @@ public:
void on_startup() override;
private:
std::vector<boost::filesystem::path> directories;
std::vector<std::pair<boost::filesystem::path, size_t> > files;
std::vector<std::pair<boost::filesystem::path, size_t>> files;
std::vector<std::string> errors;
};

32
src/notebook.cc

@ -450,27 +450,6 @@ bool Notebook::save_current() {
return false;
}
void Notebook::save_session() {
try {
boost::property_tree::ptree pt_root, pt_files;
pt_root.put("folder", Directories::get().path.string());
for(size_t notebook_index=0;notebook_index<notebooks.size();++notebook_index) {
for(int page=0;page<notebooks[notebook_index].get_n_pages();++page) {
auto view=get_view(notebook_index, page);
boost::property_tree::ptree pt_child;
pt_child.put("notebook", notebook_index);
pt_child.put("file", view->file_path.string());
pt_files.push_back(std::make_pair("", pt_child));
}
}
pt_root.add_child("files", pt_files);
if(auto view=Notebook::get().get_current_view())
pt_root.put("current_file", view->file_path.string());
boost::property_tree::write_json((Config::get().home_juci_path/"last_session.json").string(), pt_root);
}
catch(const std::exception &) {}
}
bool Notebook::close(size_t index) {
if(auto view=get_view(index)) {
if(view->get_buffer()->get_modified()){
@ -611,6 +590,17 @@ boost::filesystem::path Notebook::get_current_folder() {
return boost::filesystem::path();
}
std::vector<std::pair<size_t, Source::View *>> Notebook::get_notebook_views() {
std::vector<std::pair<size_t, Source::View *>> notebook_views;
for(size_t notebook_index=0;notebook_index<notebooks.size();++notebook_index) {
for(int page=0;page<notebooks[notebook_index].get_n_pages();++page) {
if(auto view=get_view(notebook_index, page))
notebook_views.emplace_back(notebook_index, view);
}
}
return notebook_views;
}
void Notebook::update_status(Source::View *view) {
if(view->update_status_location)
view->update_status_location(view);

2
src/notebook.h

@ -37,7 +37,6 @@ public:
void configure(size_t index);
bool save(size_t index);
bool save_current();
void save_session();
bool close(size_t index);
bool close_current();
void next();
@ -46,6 +45,7 @@ public:
/// Hide/Show tabs.
void toggle_tabs();
boost::filesystem::path get_current_folder();
std::vector<std::pair<size_t, Source::View*>> get_notebook_views();
Gtk::Label status_location;
Gtk::Label status_file_path;

87
src/project.cc

@ -19,15 +19,13 @@
boost::filesystem::path Project::debug_last_stop_file_path;
std::unordered_map<std::string, std::string> Project::run_arguments;
std::unordered_map<std::string, std::string> Project::debug_run_arguments;
std::unordered_map<std::string, Project::DebugRunArguments> Project::debug_run_arguments;
std::atomic<bool> Project::compiling(false);
std::atomic<bool> Project::debugging(false);
std::pair<boost::filesystem::path, std::pair<int, int> > Project::debug_stop;
std::string Project::debug_status;
std::shared_ptr<Project::Base> Project::current;
#ifdef JUCI_ENABLE_DEBUG
std::unordered_map<std::string, Project::LLDB::DebugOptions> Project::LLDB::debug_options;
#endif
std::unique_ptr<Project::DebugOptions> Project::Base::debug_options;
Gtk::Label &Project::debug_status_label() {
static Gtk::Label label;
@ -256,32 +254,6 @@ void Project::Base::debug_start() {
}
#ifdef JUCI_ENABLE_DEBUG
Project::LLDB::DebugOptions::DebugOptions() : Base::DebugOptions() {
remote_enabled.set_active(false);
remote_enabled.set_label("Enabled");
remote_enabled.signal_clicked().connect([this] {
remote_host.set_sensitive(remote_enabled.get_active());
});
remote_host.set_sensitive(false);
remote_host.set_placeholder_text("host:port");
remote_host.signal_activate().connect([this] {
set_visible(false);
});
auto remote_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
remote_vbox->pack_start(remote_enabled, true, true);
remote_vbox->pack_end(remote_host, true, true);
auto remote_frame=Gtk::manage(new Gtk::Frame());
remote_frame->set_label("Remote Debugging");
remote_frame->add(*remote_vbox);
vbox.pack_end(*remote_frame, true, true);
show_all();
set_visible(false);
}
std::pair<std::string, std::string> Project::LLDB::debug_get_run_arguments() {
auto debug_build_path=build->get_debug_path();
auto default_build_path=build->get_default_path();
@ -292,7 +264,7 @@ std::pair<std::string, std::string> Project::LLDB::debug_get_run_arguments() {
auto run_arguments_it=debug_run_arguments.find(project_path);
std::string arguments;
if(run_arguments_it!=debug_run_arguments.end())
arguments=run_arguments_it->second;
arguments=run_arguments_it->second.arguments;
if(arguments.empty()) {
auto view=Notebook::get().get_current_view();
@ -311,10 +283,47 @@ std::pair<std::string, std::string> Project::LLDB::debug_get_run_arguments() {
return {project_path, arguments};
}
Gtk::Popover *Project::LLDB::debug_get_options() {
if(!build->project_path.empty())
return &debug_options[build->project_path.string()];
return nullptr;
Project::DebugOptions *Project::LLDB::debug_get_options() {
if(build->project_path.empty())
return nullptr;
debug_options=std::make_unique<DebugOptions>();
auto &arguments=Project::debug_run_arguments[build->project_path.string()];
auto remote_enabled=Gtk::manage(new Gtk::CheckButton());
auto remote_host_port=Gtk::manage(new Gtk::Entry());
remote_enabled->set_active(arguments.remote_enabled);
remote_enabled->set_label("Enabled");
remote_enabled->signal_clicked().connect([remote_enabled, remote_host_port] {
remote_host_port->set_sensitive(remote_enabled->get_active());
});
remote_host_port->set_sensitive(arguments.remote_enabled);
remote_host_port->set_text(arguments.remote_host_port);
remote_host_port->set_placeholder_text("host:port");
remote_host_port->signal_activate().connect([] {
debug_options->hide();
});
auto self=this->shared_from_this();
debug_options->signal_hide().connect([self, remote_enabled, remote_host_port] {
auto &arguments=Project::debug_run_arguments[self->build->project_path.string()];
arguments.remote_enabled=remote_enabled->get_active();
arguments.remote_host_port=remote_host_port->get_text();
});
auto remote_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
remote_vbox->pack_start(*remote_enabled, true, true);
remote_vbox->pack_end(*remote_host_port, true, true);
auto remote_frame=Gtk::manage(new Gtk::Frame());
remote_frame->set_label("Remote Debugging");
remote_frame->add(*remote_vbox);
debug_options->vbox.pack_end(*remote_frame, true, true);
return debug_options.get();
}
void Project::LLDB::debug_start() {
@ -328,7 +337,7 @@ void Project::LLDB::debug_start() {
auto run_arguments_it=debug_run_arguments.find(project_path->string());
auto run_arguments=std::make_shared<std::string>();
if(run_arguments_it!=debug_run_arguments.end())
*run_arguments=run_arguments_it->second;
*run_arguments=run_arguments_it->second.arguments;
if(run_arguments->empty()) {
auto view=Notebook::get().get_current_view();
@ -368,9 +377,9 @@ void Project::LLDB::debug_start() {
}
std::string remote_host;
auto options_it=debug_options.find(project_path->string());
if(options_it!=debug_options.end() && options_it->second.remote_enabled.get_active())
remote_host=options_it->second.remote_host.get_text();
auto debug_run_arguments_it=debug_run_arguments.find(project_path->string());
if(debug_run_arguments_it!=debug_run_arguments.end() && debug_run_arguments_it->second.remote_enabled)
remote_host=debug_run_arguments_it->second.remote_host_port;
static auto on_exit_it=Debug::LLDB::get().on_exit.end();
if(on_exit_it!=Debug::LLDB::get().on_exit.end())

38
src/project.h

@ -9,13 +9,26 @@
#include "project_build.h"
namespace Project {
class DebugRunArguments {
public:
std::string arguments;
bool remote_enabled;
std::string remote_host_port;
};
class DebugOptions : public Gtk::Popover {
public:
DebugOptions() : Gtk::Popover(), vbox(Gtk::Orientation::ORIENTATION_VERTICAL) { add(vbox); }
Gtk::Box vbox;
};
Gtk::Label &debug_status_label();
void save_files(const boost::filesystem::path &path);
void on_save(size_t index);
extern boost::filesystem::path debug_last_stop_file_path;
extern std::unordered_map<std::string, std::string> run_arguments;
extern std::unordered_map<std::string, std::string> debug_run_arguments;
extern std::unordered_map<std::string, DebugRunArguments> debug_run_arguments;
extern std::atomic<bool> compiling;
extern std::atomic<bool> debugging;
extern std::pair<boost::filesystem::path, std::pair<int, int> > debug_stop;
@ -26,14 +39,7 @@ namespace Project {
class Base : public std::enable_shared_from_this<Base> {
protected:
#ifdef JUCI_ENABLE_DEBUG
class DebugOptions : public Gtk::Popover {
public:
DebugOptions() : Gtk::Popover(), vbox(Gtk::Orientation::ORIENTATION_VERTICAL) { add(vbox); }
protected:
Gtk::Box vbox;
};
#endif
static std::unique_ptr<DebugOptions> debug_options;
public:
Base() {}
Base(std::unique_ptr<Build> &&build): build(std::move(build)) {}
@ -51,7 +57,7 @@ namespace Project {
virtual void show_symbols();
virtual std::pair<std::string, std::string> debug_get_run_arguments();
virtual Gtk::Popover *debug_get_options() { return nullptr; }
virtual Project::DebugOptions *debug_get_options() { return nullptr; }
Tooltips debug_variable_tooltips;
virtual void debug_start();
virtual void debug_continue() {}
@ -71,23 +77,13 @@ namespace Project {
};
class LLDB : public virtual Base {
#ifdef JUCI_ENABLE_DEBUG
class DebugOptions : public Base::DebugOptions {
public:
DebugOptions();
Gtk::CheckButton remote_enabled;
Gtk::Entry remote_host;
};
static std::unordered_map<std::string, DebugOptions> debug_options;
#endif
public:
LLDB() {}
~LLDB() { dispatcher.disconnect(); }
#ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> debug_get_run_arguments() override;
Gtk::Popover *debug_get_options() override;
Project::DebugOptions *debug_get_options() override;
void debug_start() override;
void debug_continue() override;
void debug_stop() override;

296
src/window.cc

@ -21,95 +21,15 @@ Window::Window() {
Menu::get().right_click_line_menu->attach_to_widget(*this);
Menu::get().right_click_selected_menu->attach_to_widget(*this);
set_default_size(Config::get().window.default_size.first, Config::get().window.default_size.second);
auto directories_scrolled_window=Gtk::manage(new Gtk::ScrolledWindow());
directories_scrolled_window->add(Directories::get());
auto notebook_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
notebook_vbox->pack_start(Notebook::get());
notebook_vbox->pack_end(EntryBox::get(), Gtk::PACK_SHRINK);
auto terminal_scrolled_window=Gtk::manage(new Gtk::ScrolledWindow());
terminal_scrolled_window->add(Terminal::get());
auto notebook_and_terminal_vpaned=Gtk::manage(new Gtk::Paned(Gtk::Orientation::ORIENTATION_VERTICAL));
notebook_and_terminal_vpaned->set_position(static_cast<int>(0.75*Config::get().window.default_size.second));
notebook_and_terminal_vpaned->pack1(*notebook_vbox, Gtk::SHRINK);
notebook_and_terminal_vpaned->pack2(*terminal_scrolled_window, Gtk::SHRINK);
auto hpaned=Gtk::manage(new Gtk::Paned());
hpaned->set_position(static_cast<int>(0.2*Config::get().window.default_size.first));
hpaned->pack1(*directories_scrolled_window, Gtk::SHRINK);
hpaned->pack2(*notebook_and_terminal_vpaned, Gtk::SHRINK);
auto status_hbox=Gtk::manage(new Gtk::Box());
status_hbox->set_homogeneous(true);
status_hbox->pack_start(*Gtk::manage(new Gtk::Box()));
auto status_right_hbox=Gtk::manage(new Gtk::Box());
status_right_hbox->pack_end(Notebook::get().status_state, Gtk::PACK_SHRINK);
auto status_right_overlay=Gtk::manage(new Gtk::Overlay());
status_right_overlay->add(*status_right_hbox);
status_right_overlay->add_overlay(Notebook::get().status_diagnostics);
status_hbox->pack_end(*status_right_overlay);
auto status_overlay=Gtk::manage(new Gtk::Overlay());
status_overlay->add(*status_hbox);
auto status_file_info_hbox=Gtk::manage(new Gtk::Box);
status_file_info_hbox->pack_start(Notebook::get().status_file_path, Gtk::PACK_SHRINK);
status_file_info_hbox->pack_start(Notebook::get().status_branch, Gtk::PACK_SHRINK);
status_file_info_hbox->pack_start(Notebook::get().status_location, Gtk::PACK_SHRINK);
status_overlay->add_overlay(*status_file_info_hbox);
status_overlay->add_overlay(Project::debug_status_label());
auto vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
vbox->pack_start(*hpaned);
vbox->pack_start(*status_overlay, Gtk::PACK_SHRINK);
auto overlay_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
auto overlay_hbox=Gtk::manage(new Gtk::Box());
overlay_vbox->set_hexpand(false);
overlay_vbox->set_halign(Gtk::Align::ALIGN_START);
overlay_vbox->pack_start(Info::get(), Gtk::PACK_SHRINK, 20);
overlay_hbox->set_hexpand(false);
overlay_hbox->set_halign(Gtk::Align::ALIGN_END);
overlay_hbox->pack_end(*overlay_vbox, Gtk::PACK_SHRINK, 20);
auto overlay=Gtk::manage(new Gtk::Overlay());
overlay->add(*vbox);
overlay->add_overlay(*overlay_hbox);
overlay->set_overlay_pass_through(*overlay_hbox, true);
add(*overlay);
show_all_children();
Info::get().hide();
//Scroll to end of terminal whenever info is printed
Terminal::get().signal_size_allocate().connect([terminal_scrolled_window](Gtk::Allocation& allocation){
auto adjustment=terminal_scrolled_window->get_vadjustment();
adjustment->set_value(adjustment->get_upper()-adjustment->get_page_size());
Terminal::get().queue_draw();
});
EntryBox::get().signal_show().connect([this, hpaned, notebook_and_terminal_vpaned, notebook_vbox](){
hpaned->set_focus_chain({notebook_and_terminal_vpaned});
notebook_and_terminal_vpaned->set_focus_chain({notebook_vbox});
notebook_vbox->set_focus_chain({&EntryBox::get()});
});
EntryBox::get().signal_hide().connect([this, hpaned, notebook_and_terminal_vpaned, notebook_vbox](){
hpaned->unset_focus_chain();
notebook_and_terminal_vpaned->unset_focus_chain();
notebook_vbox->unset_focus_chain();
});
EntryBox::get().signal_hide().connect([this]() {
EntryBox::get().signal_hide().connect([]() {
if(auto view=Notebook::get().get_current_view())
view->grab_focus();
});
Notebook::get().on_change_page=[this](Source::View *view) {
if(search_entry_shown && EntryBox::get().labels.size()>0) {
view->update_search_occurrences=[this](int number){
view->update_search_occurrences=[](int number){
EntryBox::get().labels.begin()->update(0, std::to_string(number));
};
view->search_highlight(last_search, case_sensitive_search, regex_search);
@ -170,7 +90,7 @@ Window::Window() {
Project::current=nullptr;
});
Gtk::Settings::get_default()->connect_property_changed("gtk-theme-name", [this] {
Gtk::Settings::get_default()->connect_property_changed("gtk-theme-name", [] {
Directories::get().update();
if(auto view=Notebook::get().get_current_view())
Notebook::get().update_status(view);
@ -1115,15 +1035,15 @@ void Window::set_menu_actions() {
};
label_it->update(0, "");
EntryBox::get().entries.emplace_back(run_arguments.second, [this, run_arguments_first=std::move(run_arguments.first)](const std::string& content){
Project::debug_run_arguments[run_arguments_first]=content;
Project::debug_run_arguments[run_arguments_first].arguments=content;
EntryBox::get().hide();
}, 50);
auto entry_it=EntryBox::get().entries.begin();
entry_it->set_placeholder_text("Debug: Set Run Arguments");
if(auto options=project->debug_get_options()) {
EntryBox::get().buttons.emplace_back("", [this, options]() {
options->set_visible(true);
EntryBox::get().buttons.emplace_back("", [options]() {
options->show_all();
});
EntryBox::get().buttons.back().set_image_from_icon_name("preferences-system");
EntryBox::get().buttons.back().set_always_show_image(true);
@ -1281,6 +1201,90 @@ void Window::activate_menu_items() {
#endif
}
void Window::add_widgets() {
auto directories_scrolled_window=Gtk::manage(new Gtk::ScrolledWindow());
directories_scrolled_window->add(Directories::get());
auto notebook_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
notebook_vbox->pack_start(Notebook::get());
notebook_vbox->pack_end(EntryBox::get(), Gtk::PACK_SHRINK);
auto terminal_scrolled_window=Gtk::manage(new Gtk::ScrolledWindow());
terminal_scrolled_window->add(Terminal::get());
int width, height;
get_default_size(width, height);
auto notebook_and_terminal_vpaned=Gtk::manage(new Gtk::Paned(Gtk::Orientation::ORIENTATION_VERTICAL));
notebook_and_terminal_vpaned->set_position(static_cast<int>(0.75*height));
notebook_and_terminal_vpaned->pack1(*notebook_vbox, Gtk::SHRINK);
notebook_and_terminal_vpaned->pack2(*terminal_scrolled_window, Gtk::SHRINK);
auto hpaned=Gtk::manage(new Gtk::Paned());
hpaned->set_position(static_cast<int>(0.2*width));
hpaned->pack1(*directories_scrolled_window, Gtk::SHRINK);
hpaned->pack2(*notebook_and_terminal_vpaned, Gtk::SHRINK);
auto status_hbox=Gtk::manage(new Gtk::Box());
status_hbox->set_homogeneous(true);
status_hbox->pack_start(*Gtk::manage(new Gtk::Box()));
auto status_right_hbox=Gtk::manage(new Gtk::Box());
status_right_hbox->pack_end(Notebook::get().status_state, Gtk::PACK_SHRINK);
auto status_right_overlay=Gtk::manage(new Gtk::Overlay());
status_right_overlay->add(*status_right_hbox);
status_right_overlay->add_overlay(Notebook::get().status_diagnostics);
status_hbox->pack_end(*status_right_overlay);
auto status_overlay=Gtk::manage(new Gtk::Overlay());
status_overlay->add(*status_hbox);
auto status_file_info_hbox=Gtk::manage(new Gtk::Box);
status_file_info_hbox->pack_start(Notebook::get().status_file_path, Gtk::PACK_SHRINK);
status_file_info_hbox->pack_start(Notebook::get().status_branch, Gtk::PACK_SHRINK);
status_file_info_hbox->pack_start(Notebook::get().status_location, Gtk::PACK_SHRINK);
status_overlay->add_overlay(*status_file_info_hbox);
status_overlay->add_overlay(Project::debug_status_label());
auto vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
vbox->pack_start(*hpaned);
vbox->pack_start(*status_overlay, Gtk::PACK_SHRINK);
auto overlay_vbox=Gtk::manage(new Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL));
auto overlay_hbox=Gtk::manage(new Gtk::Box());
overlay_vbox->set_hexpand(false);
overlay_vbox->set_halign(Gtk::Align::ALIGN_START);
overlay_vbox->pack_start(Info::get(), Gtk::PACK_SHRINK, 20);
overlay_hbox->set_hexpand(false);
overlay_hbox->set_halign(Gtk::Align::ALIGN_END);
overlay_hbox->pack_end(*overlay_vbox, Gtk::PACK_SHRINK, 20);
auto overlay=Gtk::manage(new Gtk::Overlay());
overlay->add(*vbox);
overlay->add_overlay(*overlay_hbox);
overlay->set_overlay_pass_through(*overlay_hbox, true);
add(*overlay);
show_all_children();
Info::get().hide();
//Scroll to end of terminal whenever info is printed
Terminal::get().signal_size_allocate().connect([terminal_scrolled_window](Gtk::Allocation& allocation){
auto adjustment=terminal_scrolled_window->get_vadjustment();
adjustment->set_value(adjustment->get_upper()-adjustment->get_page_size());
Terminal::get().queue_draw();
});
EntryBox::get().signal_show().connect([this, hpaned, notebook_and_terminal_vpaned, notebook_vbox](){
hpaned->set_focus_chain({notebook_and_terminal_vpaned});
notebook_and_terminal_vpaned->set_focus_chain({notebook_vbox});
notebook_vbox->set_focus_chain({&EntryBox::get()});
});
EntryBox::get().signal_hide().connect([this, hpaned, notebook_and_terminal_vpaned, notebook_vbox](){
hpaned->unset_focus_chain();
notebook_and_terminal_vpaned->unset_focus_chain();
notebook_vbox->unset_focus_chain();
});
}
bool Window::on_key_press_event(GdkEventKey *event) {
if(event->keyval==GDK_KEY_Escape) {
EntryBox::get().hide();
@ -1321,7 +1325,7 @@ bool Window::on_key_press_event(GdkEventKey *event) {
}
bool Window::on_delete_event(GdkEventAny *event) {
Notebook::get().save_session();
save_session();
for(size_t c=Notebook::get().size()-1;c!=static_cast<size_t>(-1);--c) {
if(!Notebook::get().close(c))
@ -1552,3 +1556,121 @@ void Window::rename_token_entry() {
}
}
}
void Window::save_session() {
try {
boost::property_tree::ptree root_pt;
root_pt.put("folder", Directories::get().path.string());
boost::property_tree::ptree files_pt;
for(auto &notebook_view: Notebook::get().get_notebook_views()) {
boost::property_tree::ptree file_pt;
file_pt.put("path", notebook_view.second->file_path.string());
file_pt.put("notebook", notebook_view.first);
auto iter=notebook_view.second->get_buffer()->get_insert()->get_iter();
file_pt.put("line", iter.get_line());
file_pt.put("line_offset", iter.get_line_offset());
files_pt.push_back(std::make_pair("", file_pt));
}
root_pt.add_child("files", files_pt);
boost::property_tree::ptree current_file_pt;
if(auto view=Notebook::get().get_current_view()) {
current_file_pt.put("path", view->file_path.string());
auto iter=view->get_buffer()->get_insert()->get_iter();
current_file_pt.put("line", iter.get_line());
current_file_pt.put("line_offset", iter.get_line_offset());
}
std::string current_path;
if(auto view=Notebook::get().get_current_view())
current_path=view->file_path.string();
root_pt.put("current_file", current_path);
boost::property_tree::ptree run_arguments_pt;
for(auto &run_argument: Project::run_arguments) {
if(run_argument.second.empty())
continue;
boost::system::error_code ec;
if(boost::filesystem::exists(run_argument.first, ec) && boost::filesystem::is_directory(run_argument.first, ec)) {
boost::property_tree::ptree run_argument_pt;
run_argument_pt.put("path", run_argument.first);
run_argument_pt.put("arguments", run_argument.second);
run_arguments_pt.push_back(std::make_pair("", run_argument_pt));
}
}
root_pt.add_child("run_arguments", run_arguments_pt);
boost::property_tree::ptree debug_run_arguments_pt;
for(auto &debug_run_argument: Project::debug_run_arguments) {
if(debug_run_argument.second.arguments.empty() && !debug_run_argument.second.remote_enabled && debug_run_argument.second.remote_host_port.empty())
continue;
boost::system::error_code ec;
if(boost::filesystem::exists(debug_run_argument.first, ec) && boost::filesystem::is_directory(debug_run_argument.first, ec)) {
boost::property_tree::ptree debug_run_argument_pt;
debug_run_argument_pt.put("path", debug_run_argument.first);
debug_run_argument_pt.put("arguments", debug_run_argument.second.arguments);
debug_run_argument_pt.put("remote_enabled", debug_run_argument.second.remote_enabled);
debug_run_argument_pt.put("remote_host_port", debug_run_argument.second.remote_host_port);
debug_run_arguments_pt.push_back(std::make_pair("", debug_run_argument_pt));
}
}
root_pt.add_child("debug_run_arguments", debug_run_arguments_pt);
int width, height;
get_size(width, height);
boost::property_tree::ptree window_pt;
window_pt.put("width", width);
window_pt.put("height", height);
root_pt.add_child("window", window_pt);
boost::property_tree::write_json((Config::get().home_juci_path/"last_session.json").string(), root_pt);
}
catch(...) {}
}
void Window::load_session(std::vector<boost::filesystem::path> &directories, std::vector<std::pair<boost::filesystem::path, size_t> > &files, std::vector<std::pair<int, int> > &file_offsets, std::string &current_file, bool read_directories_and_files) {
try {
boost::property_tree::ptree root_pt;
boost::property_tree::read_json((Config::get().home_juci_path/"last_session.json").string(), root_pt);
if(read_directories_and_files) {
auto folder=root_pt.get<std::string>("folder");
if(!folder.empty() && boost::filesystem::exists(folder) && boost::filesystem::is_directory(folder))
directories.emplace_back(folder);
for(auto &file_pt: root_pt.get_child("files")) {
auto file=file_pt.second.get<std::string>("path");
auto notebook=file_pt.second.get<size_t>("notebook");
auto line=file_pt.second.get<int>("line");
auto line_offset=file_pt.second.get<int>("line_offset");
if(!file.empty() && boost::filesystem::exists(file) && !boost::filesystem::is_directory(file)) {
files.emplace_back(file, notebook);
file_offsets.emplace_back(line, line_offset);
}
}
current_file=root_pt.get<std::string>("current_file");
}
for(auto &run_argument: root_pt.get_child(("run_arguments"))) {
auto path=run_argument.second.get<std::string>("path");
boost::system::error_code ec;
if(boost::filesystem::exists(path, ec) && boost::filesystem::is_directory(path, ec))
Project::run_arguments.emplace(path, run_argument.second.get<std::string>("arguments"));
}
for(auto &debug_run_argument: root_pt.get_child(("debug_run_arguments"))) {
auto path=debug_run_argument.second.get<std::string>("path");
boost::system::error_code ec;
if(boost::filesystem::exists(path, ec) && boost::filesystem::is_directory(path, ec))
Project::debug_run_arguments.emplace(path, Project::DebugRunArguments{debug_run_argument.second.get<std::string>("arguments"),
debug_run_argument.second.get<bool>("remote_enabled"),
debug_run_argument.second.get<std::string>("remote_host_port")});
}
auto window_pt=root_pt.get_child("window");
set_default_size(window_pt.get<int>("width"), window_pt.get<int>("height"));
}
catch(...) {
set_default_size(800, 600);
}
}

4
src/window.h

@ -1,6 +1,7 @@
#pragma once
#include <gtkmm.h>
#include <atomic>
#include <boost/filesystem.hpp>
class Window : public Gtk::ApplicationWindow {
Window();
@ -9,6 +10,9 @@ public:
static Window singleton;
return singleton;
}
void add_widgets();
void save_session();
void load_session(std::vector<boost::filesystem::path> &directories, std::vector<std::pair<boost::filesystem::path, size_t>> &files, std::vector<std::pair<int, int>> &file_offsets, std::string &current_file, bool read_directories_and_files);
protected:
bool on_key_press_event(GdkEventKey *event) override;

Loading…
Cancel
Save