From 23be4f05d5c89239f47203ed1d466c814ab6fa89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 12:04:11 +0200 Subject: [PATCH 01/23] Deduce home instead of setting it --- src/singletons.h | 16 +++++++--------- src/sourcefile.cc | 17 +++++++++++++++++ src/sourcefile.h | 1 + 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/singletons.h b/src/singletons.h index ed0d82d..9d96ec9 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -10,12 +10,7 @@ #include "menu.h" #include #include - -#ifdef _WIN32 -#define HOME "AppData" -#else -#define HOME "HOME" -#endif +#include "sourcefile.h" class Singleton { public: @@ -32,9 +27,12 @@ public: static std::unique_ptr directories_; static std::unique_ptr terminal_; }; - static std::string config_dir() { return std::string(getenv(HOME)) + "/.juci/config/"; } - static std::string log_dir() { return std::string(getenv(HOME)) + "/.juci/log/"; } - static std::string style_dir() { return std::string(getenv(HOME)) + "/.juci/styles/"; } + static std::string create_config_path(const std::string &subfolder) { + return juci::filesystem::get_home_folder() + subfolder; + } + static std::string config_dir() { return create_config_path("/.juci/config/"); } + static std::string log_dir() { return create_config_path("/.juci/log/"); } + static std::string style_dir() { return create_config_path("/.juci/styles/"); } static Terminal *terminal(); static Directories *directories(); static Gtk::Label *status(); diff --git a/src/sourcefile.cc b/src/sourcefile.cc index ef9fdd6..dd0bd1c 100644 --- a/src/sourcefile.cc +++ b/src/sourcefile.cc @@ -15,6 +15,23 @@ std::string juci::filesystem::read(const std::string &path) { return ss.str(); } +std::string safe_get_env(const std::string &env) { + auto ptr = std::getenv(env.c_str()); + return nullptr==ptr ? "" : std::string(ptr); +} + +std::string juci::filesystem::get_home_folder() { + auto home=safe_get_env("HOME"); + if(home.empty()) + home=safe_get_env("AppData"); + auto status = boost::filesystem::status(home); + if((status.permissions() & 0222)>=2) { + return home; + } else { + throw new std::exception; + } +} + int juci::filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); diff --git a/src/sourcefile.h b/src/sourcefile.h index 4507ab7..ef53fbe 100644 --- a/src/sourcefile.h +++ b/src/sourcefile.h @@ -25,6 +25,7 @@ namespace juci { static bool write(const boost::filesystem::path &path) { return write(path, ""); }; static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } + static std::string get_home_folder(); }; } // namepace juci #endif // JUCI_SOURCEFILE_H_ From 6f9f5a2a19c4beefcd8d600caf0ecf98eb95b2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 12:17:53 +0200 Subject: [PATCH 02/23] Better error reporting --- src/sourcefile.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sourcefile.cc b/src/sourcefile.cc index dd0bd1c..5f41c2c 100644 --- a/src/sourcefile.cc +++ b/src/sourcefile.cc @@ -1,4 +1,5 @@ #include "sourcefile.h" +#include "singletons.h" #include #include @@ -28,6 +29,7 @@ std::string juci::filesystem::get_home_folder() { if((status.permissions() & 0222)>=2) { return home; } else { + Singleton::terminal()->print("Invalid permissions. Cannot write in " + home + "\n"); throw new std::exception; } } From 5fb5f26bce5eef273e74e2dc0be7bb6cd516c605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 12:31:25 +0200 Subject: [PATCH 03/23] Rename sourcefile to filesystem --- src/CMakeLists.txt | 4 ++-- src/cmake.cc | 3 +-- src/config.cc | 2 -- src/directories.cc | 3 +-- src/{sourcefile.cc => filesystem.cc} | 3 ++- src/{sourcefile.h => filesystem.h} | 0 src/notebook.cc | 3 +-- src/singletons.h | 2 +- src/source.cc | 3 +-- src/window.cc | 1 - 10 files changed, 9 insertions(+), 15 deletions(-) rename src/{sourcefile.cc => filesystem.cc} (98%) rename src/{sourcefile.h => filesystem.h} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a79cfe7..e3dab84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,8 +37,8 @@ set(source_files juci.h selectiondialog.cc config.h config.cc - sourcefile.h - sourcefile.cc + filesystem.h + filesystem.cc window.cc window.h dialogs.h diff --git a/src/cmake.cc b/src/cmake.cc index 76b4aa0..37773a7 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -1,7 +1,6 @@ #include "cmake.h" -#include "sourcefile.h" -#include #include "singletons.h" +#include #include //TODO: remove using namespace std; //TODO: remove diff --git a/src/config.cc b/src/config.cc index 6b98535..1d476ea 100644 --- a/src/config.cc +++ b/src/config.cc @@ -3,8 +3,6 @@ #include "logging.h" #include #include "files.h" -#include "sourcefile.h" -#include "singletons.h" #include using namespace std; //TODO: remove diff --git a/src/directories.cc b/src/directories.cc index 0a269cc..f8303b3 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -1,7 +1,6 @@ +#include "singletons.h" #include "directories.h" -#include "sourcefile.h" #include "logging.h" -#include "singletons.h" #include #include diff --git a/src/sourcefile.cc b/src/filesystem.cc similarity index 98% rename from src/sourcefile.cc rename to src/filesystem.cc index 5f41c2c..bbf6baf 100644 --- a/src/sourcefile.cc +++ b/src/filesystem.cc @@ -1,7 +1,8 @@ -#include "sourcefile.h" +#include "filesystem.h" #include "singletons.h" #include #include +#include const size_t buffer_size=131072; diff --git a/src/sourcefile.h b/src/filesystem.h similarity index 100% rename from src/sourcefile.h rename to src/filesystem.h diff --git a/src/notebook.cc b/src/notebook.cc index 4cf8d7d..14834c7 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -1,7 +1,6 @@ +#include "singletons.h" #include "notebook.h" #include "logging.h" -#include "sourcefile.h" -#include "singletons.h" #include #include #include "cmake.h" diff --git a/src/singletons.h b/src/singletons.h index 9d96ec9..de53031 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -10,7 +10,7 @@ #include "menu.h" #include #include -#include "sourcefile.h" +#include "filesystem.h" class Singleton { public: diff --git a/src/source.cc b/src/source.cc index 154232f..c0c1511 100644 --- a/src/source.cc +++ b/src/source.cc @@ -1,9 +1,8 @@ +#include "singletons.h" #include "source.h" -#include "sourcefile.h" #include #include "logging.h" #include -#include "singletons.h" #include #include diff --git a/src/window.cc b/src/window.cc index 142a8c1..d5d3d20 100644 --- a/src/window.cc +++ b/src/window.cc @@ -1,7 +1,6 @@ #include "window.h" #include "logging.h" #include "singletons.h" -#include "sourcefile.h" #include "config.h" //#include "api.h" #include "dialogs.h" From 09f4f517c15f06745fee3c6983357443f5df813a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 15:09:30 +0200 Subject: [PATCH 04/23] Even better handling of home directory --- src/filesystem.cc | 20 ++++++++++++++++++-- src/filesystem.h | 1 + src/singletons.cc | 23 +++++++++++++++++++++++ src/singletons.h | 11 +++++------ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/filesystem.cc b/src/filesystem.cc index bbf6baf..9895e84 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -22,6 +22,9 @@ std::string safe_get_env(const std::string &env) { return nullptr==ptr ? "" : std::string(ptr); } +/** + * Returns home folder, empty on error + */ std::string juci::filesystem::get_home_folder() { auto home=safe_get_env("HOME"); if(home.empty()) @@ -30,11 +33,24 @@ std::string juci::filesystem::get_home_folder() { if((status.permissions() & 0222)>=2) { return home; } else { - Singleton::terminal()->print("Invalid permissions. Cannot write in " + home + "\n"); - throw new std::exception; + JERROR("No write permissions in home, var:"); + DEBUG_VAR(home); + return ""; } } +/** + * Returns tmp folder, empty on error. + */ +std::string juci::filesystem::get_tmp_folder() { + boost::system::error_code code; + auto path = boost::filesystem::temp_directory_path(code); + if (code.value()!=0) { + return ""; + } + return path.string(); +} + int juci::filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); diff --git a/src/filesystem.h b/src/filesystem.h index ef53fbe..955b1be 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -26,6 +26,7 @@ namespace juci { static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } static std::string get_home_folder(); + static std::string get_tmp_folder(); }; } // namepace juci #endif // JUCI_SOURCEFILE_H_ diff --git a/src/singletons.cc b/src/singletons.cc index 9040d55..b8734ec 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -30,3 +30,26 @@ Gtk::Label *Singleton::info() { info_=std::unique_ptr(new Gtk::Label()); return info_.get(); } + +std::string Singleton::create_config_path(const std::string &subfolder) { + boost::filesystem::path home; + home = juci::filesystem::get_home_folder(); + if(home.empty()) { + Singleton::terminal()->print("Could not find/write to home directory. Using defaults, no settings will be saved."); + home = juci::filesystem::get_tmp_folder(); + if(home.empty()) { + std::string message("Please fix permissions of your home folder"); + std::cerr << message << std::endl; + JFATAL(message); + throw new std::exception; + } + } + home /= subfolder; + return home.string(); +} + +std::string Singleton::config_dir() { return create_config_path(".juci/config"); } +std::string Singleton::log_dir() { return create_config_path(".juci/log"); } +std::string Singleton::style_dir() { return create_config_path(".juci/styles"); } + + diff --git a/src/singletons.h b/src/singletons.h index de53031..968356a 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -11,6 +11,7 @@ #include #include #include "filesystem.h" +#include class Singleton { public: @@ -27,12 +28,10 @@ public: static std::unique_ptr directories_; static std::unique_ptr terminal_; }; - static std::string create_config_path(const std::string &subfolder) { - return juci::filesystem::get_home_folder() + subfolder; - } - static std::string config_dir() { return create_config_path("/.juci/config/"); } - static std::string log_dir() { return create_config_path("/.juci/log/"); } - static std::string style_dir() { return create_config_path("/.juci/styles/"); } + static std::string create_config_path(const std::string &subfolder); + static std::string config_dir(); + static std::string log_dir(); + static std::string style_dir(); static Terminal *terminal(); static Directories *directories(); static Gtk::Label *status(); From 7076f79895a8c200255697b8f564526ac3ad4865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 15:10:06 +0200 Subject: [PATCH 05/23] Cleanup of headers --- src/filesystem.cc | 7 ++++--- src/filesystem.h | 2 +- src/juci.cc | 6 ++---- src/juci.h | 1 + src/singletons.h | 8 +++----- src/source.h | 12 ++++++------ 6 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/filesystem.cc b/src/filesystem.cc index 9895e84..e8d8ce3 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -1,8 +1,9 @@ -#include "filesystem.h" -#include "singletons.h" #include -#include #include +#include + +#include "filesystem.h" +#include "logging.h" const size_t buffer_size=131072; diff --git a/src/filesystem.h b/src/filesystem.h index 955b1be..fd945af 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -3,7 +3,7 @@ #include #include #include -#include "gtkmm.h" +#include namespace juci { class filesystem { diff --git a/src/juci.cc b/src/juci.cc index a7d5cb7..6171496 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -1,10 +1,9 @@ #include "juci.h" #include "singletons.h" -#include using namespace std; //TODO: remove -void init_logging() { +void app::init_logging() { boost::log::add_common_attributes(); boost::log::add_file_log(boost::log::keywords::file_name = Singleton::log_dir() + "juci.log", boost::log::keywords::auto_flush = true); @@ -69,10 +68,9 @@ void app::on_activate() { } app::app() : Gtk::Application("no.sout.juci", Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_COMMAND_LINE) { - + init_logging(); } int main(int argc, char *argv[]) { - init_logging(); return app().run(argc, argv); } diff --git a/src/juci.h b/src/juci.h index 551a352..e672254 100644 --- a/src/juci.h +++ b/src/juci.h @@ -14,6 +14,7 @@ class app : public Gtk::Application { std::unique_ptr window; std::vector directories; std::vector files; + void init_logging(); }; #endif // JUCI_JUCI_H_ diff --git a/src/singletons.h b/src/singletons.h index 968356a..4f6fbab 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -1,17 +1,15 @@ - #ifndef JUCI_SINGLETONS_H_ #define JUCI_SINGLETONS_H_ +#include + +#include "filesystem.h" #include "source.h" #include "window.h" #include "directories.h" #include "terminal.h" #include "notebook.h" #include "menu.h" -#include -#include -#include "filesystem.h" -#include class Singleton { public: diff --git a/src/source.h b/src/source.h index 2b60633..f142d8b 100644 --- a/src/source.h +++ b/src/source.h @@ -1,15 +1,15 @@ #ifndef JUCI_SOURCE_H_ #define JUCI_SOURCE_H_ +#include +#include +#include +#include #include #include -#include "gtkmm.h" -#include -#include "gtksourceviewmm.h" + +#include "selectiondialog.h" #include "terminal.h" #include "tooltips.h" -#include "selectiondialog.h" -#include -#include namespace Source { Glib::RefPtr guess_language(const boost::filesystem::path &file_path); From dd63dfdc506660ea13304020818586df183ac4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sat, 17 Oct 2015 15:53:09 +0200 Subject: [PATCH 06/23] Move windows to singleton and remove transient error --- src/dialogs.cc | 3 +-- src/juci.cc | 7 +++---- src/juci.h | 1 - src/singletons.cc | 8 ++++++++ src/singletons.h | 3 +++ 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/dialogs.cc b/src/dialogs.cc index e8588e5..cbaaad7 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -12,13 +12,12 @@ std::string open_dialog(const std::string &title, else gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().string().c_str()); dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS); - // dialog.set_transient_for(parent); TODO add parent + dialog.set_transient_for(*Singleton::window()); for (auto &button : buttons) dialog.add_button(button.first, button.second); return dialog.run() == Gtk::RESPONSE_OK ? dialog.get_filename() : ""; } - std::string Dialog::select_folder() { return open_dialog("Please choose a folder", {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Open", Gtk::RESPONSE_OK)}, diff --git a/src/juci.cc b/src/juci.cc index 6171496..a01c77f 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -37,9 +37,8 @@ int app::on_command_line(const Glib::RefPtr &cmd) { } void app::on_activate() { - window = std::unique_ptr(new Window()); - add_window(*window); - window->show(); + add_window(*Singleton::window()); + Singleton::window()->show(); bool first_directory=true; for(auto &directory: directories) { if(first_directory) { @@ -64,7 +63,7 @@ void app::on_activate() { } } for(auto &file: files) - window->notebook.open(file); + Singleton::window()->notebook.open(file); } app::app() : Gtk::Application("no.sout.juci", Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_COMMAND_LINE) { diff --git a/src/juci.h b/src/juci.h index e672254..76a66d7 100644 --- a/src/juci.h +++ b/src/juci.h @@ -11,7 +11,6 @@ class app : public Gtk::Application { void on_activate(); private: - std::unique_ptr window; std::vector directories; std::vector files; void init_logging(); diff --git a/src/singletons.cc b/src/singletons.cc index b8734ec..a24cc82 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -6,6 +6,7 @@ std::unique_ptr Singleton::Config::terminal_=std::unique_ptr Singleton::Config::window_ = std::unique_ptr(new Window::Config()); std::unique_ptr Singleton::terminal_=std::unique_ptr(); std::unique_ptr Singleton::directories_=std::unique_ptr(); +std::unique_ptr Singleton::window_=std::unique_ptr(); Terminal *Singleton::terminal() { if(!terminal_) @@ -18,6 +19,13 @@ Directories *Singleton::directories() { directories_=std::unique_ptr(new Directories()); return directories_.get(); } + +Window *Singleton::window() { + if(!window_) + window_=std::unique_ptr(new Window()); + return window_.get(); +} + std::unique_ptr Singleton::status_=std::unique_ptr(); Gtk::Label *Singleton::status() { if(!status_) diff --git a/src/singletons.h b/src/singletons.h index 4f6fbab..f22f57b 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -10,6 +10,7 @@ #include "terminal.h" #include "notebook.h" #include "menu.h" +#include "window.h" class Singleton { public: @@ -34,11 +35,13 @@ public: static Directories *directories(); static Gtk::Label *status(); static Gtk::Label *info(); + static Window *window(); private: static std::unique_ptr terminal_; static std::unique_ptr status_; static std::unique_ptr info_; static std::unique_ptr directories_; + static std::unique_ptr window_; }; #endif // JUCI_SINGLETONS_H_ From 70630fc656884508da9a02557fb224d0ded11830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sun, 18 Oct 2015 23:42:45 +0200 Subject: [PATCH 07/23] Remove juci namespace from filesystem --- src/cmake.cc | 8 ++++---- src/config.cc | 10 +++++----- src/filesystem.cc | 16 ++++++++-------- src/filesystem.h | 35 +++++++++++++++++++++-------------- src/notebook.cc | 2 +- src/singletons.cc | 4 ++-- src/source.cc | 4 ++-- src/window.cc | 4 ++-- 8 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/cmake.cc b/src/cmake.cc index 37773a7..883b49a 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -7,7 +7,7 @@ using namespace std; //TODO: remove CMake::CMake(const boost::filesystem::path &path) { const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) { - for(auto &line: juci::filesystem::read_lines(cmake_path)) { + for(auto &line: filesystem::read_lines(cmake_path)) { const std::regex project_regex("^ *project *\\(.*$"); std::smatch sm; if(std::regex_match(line, sm, project_regex)) { @@ -49,7 +49,7 @@ bool CMake::create_compile_commands(const boost::filesystem::path &path) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang auto compile_commands_path=path; compile_commands_path+="/compile_commands.json"; - auto compile_commands_file=juci::filesystem::read(compile_commands_path); + auto compile_commands_file=filesystem::read(compile_commands_path); size_t pos=0; while((pos=compile_commands_file.find("-I/", pos))!=std::string::npos) { if(pos+3 text_buffer) { +int filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); if(input) { @@ -97,7 +97,7 @@ int juci::filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { +int filesystem::read_non_utf8(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); if(input) { @@ -127,7 +127,7 @@ int juci::filesystem::read_non_utf8(const std::string &path, Glib::RefPtr juci::filesystem::read_lines(const std::string &path) { +std::vector filesystem::read_lines(const std::string &path) { std::vector res; std::ifstream input(path, std::ofstream::binary); if (input) { @@ -138,7 +138,7 @@ std::vector juci::filesystem::read_lines(const std::string &path) { } //Only use on small files -bool juci::filesystem::write(const std::string &path, const std::string &new_content) { +bool filesystem::write(const std::string &path, const std::string &new_content) { std::ofstream output(path, std::ofstream::binary); if(output) output << new_content; @@ -148,7 +148,7 @@ bool juci::filesystem::write(const std::string &path, const std::string &new_con return true; } -bool juci::filesystem::write(const std::string &path, Glib::RefPtr buffer) { +bool filesystem::write(const std::string &path, Glib::RefPtr buffer) { std::ofstream output(path, std::ofstream::binary); if(output) { auto start_iter=buffer->begin(); diff --git a/src/filesystem.h b/src/filesystem.h index fd945af..a417825 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -13,20 +13,27 @@ namespace juci { static int read(const std::string &path, Glib::RefPtr text_buffer); static int read(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read(path.string(), text_buffer); } - static int read_non_utf8(const std::string &path, Glib::RefPtr text_buffer); - static int read_non_utf8(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read_non_utf8(path.string(), text_buffer); } +class filesystem { +public: + static std::string read(const std::string &path); + static std::string read(const boost::filesystem::path &path) { return read(path.string()); } + static int read(const std::string &path, Glib::RefPtr text_buffer); + static int read(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read(path.string(), text_buffer); } - static std::vector read_lines(const std::string &path); - static std::vector read_lines(const boost::filesystem::path &path) { return read_lines(path.string()); }; + static int read_non_utf8(const std::string &path, Glib::RefPtr text_buffer); + static int read_non_utf8(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read_non_utf8(path.string(), text_buffer); } - static bool write(const std::string &path, const std::string &new_content); - static bool write(const boost::filesystem::path &path, const std::string &new_content) { return write(path.string(), new_content); } - static bool write(const std::string &path) { return write(path, ""); }; - static bool write(const boost::filesystem::path &path) { return write(path, ""); }; - static bool write(const std::string &path, Glib::RefPtr text_buffer); - static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } - static std::string get_home_folder(); - static std::string get_tmp_folder(); - }; -} // namepace juci + static std::vector read_lines(const std::string &path); + static std::vector read_lines(const boost::filesystem::path &path) { return read_lines(path.string()); }; + + static bool write(const std::string &path, const std::string &new_content); + static bool write(const boost::filesystem::path &path, const std::string &new_content) { return write(path.string(), new_content); } + static bool write(const std::string &path) { return write(path, ""); }; + static bool write(const boost::filesystem::path &path) { return write(path, ""); }; + static bool write(const std::string &path, Glib::RefPtr text_buffer); + static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } + + static std::string get_home_folder(); + static std::string get_tmp_folder(); +}; #endif // JUCI_SOURCEFILE_H_ diff --git a/src/notebook.cc b/src/notebook.cc index 14834c7..895c18f 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -159,7 +159,7 @@ bool Notebook::save(int page, bool reparse_needed) { } auto view=get_view(page); if (view->file_path != "" && view->get_buffer()->get_modified()) { - if(juci::filesystem::write(view->file_path, view->get_buffer())) { + if(filesystem::write(view->file_path, view->get_buffer())) { if(reparse_needed) { if(auto clang_view=dynamic_cast(view)) { if(clang_view->language->get_id()=="chdr" || clang_view->language->get_id()=="cpphdr") { diff --git a/src/singletons.cc b/src/singletons.cc index a24cc82..8ace5c8 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -41,10 +41,10 @@ Gtk::Label *Singleton::info() { std::string Singleton::create_config_path(const std::string &subfolder) { boost::filesystem::path home; - home = juci::filesystem::get_home_folder(); + home = filesystem::get_home_folder(); if(home.empty()) { Singleton::terminal()->print("Could not find/write to home directory. Using defaults, no settings will be saved."); - home = juci::filesystem::get_tmp_folder(); + home = filesystem::get_tmp_folder(); if(home.empty()) { std::string message("Please fix permissions of your home folder"); std::cerr << message << std::endl; diff --git a/src/source.cc b/src/source.cc index c0c1511..d52806c 100644 --- a/src/source.cc +++ b/src/source.cc @@ -85,11 +85,11 @@ AspellConfig* Source::View::spellcheck_config=NULL; Source::View::View(const boost::filesystem::path &file_path, const boost::filesystem::path &project_path, Glib::RefPtr language): file_path(file_path), project_path(project_path), language(language) { get_source_buffer()->begin_not_undoable_action(); if(language) { - if(juci::filesystem::read_non_utf8(file_path, get_buffer())==-1) + if(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) + if(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(); diff --git a/src/window.cc b/src/window.cc index d5d3d20..462f5db 100644 --- a/src/window.cc +++ b/src/window.cc @@ -177,7 +177,7 @@ void Window::create_menu() { Singleton::terminal()->print("Error: "+path.string()+" already exists.\n"); } else { - if(juci::filesystem::write(path)) { + if(filesystem::write(path)) { if(Singleton::directories()->current_path!="") Singleton::directories()->update(); notebook.open(path.string()); @@ -226,7 +226,7 @@ void Window::create_menu() { } std::string cmakelists="cmake_minimum_required(VERSION 2.8)\n\nproject("+project_name+")\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y -Wall\")\n\nadd_executable("+project_name+" main.cpp)\n"; std::string cpp_main="#include \n\nusing namespace std;\n\nint main() {\n cout << \"Hello World!\" << endl;\n\n return 0;\n}\n"; - if(juci::filesystem::write(cmakelists_path, cmakelists) && juci::filesystem::write(cpp_main_path, cpp_main)) { + if(filesystem::write(cmakelists_path, cmakelists) && filesystem::write(cpp_main_path, cpp_main)) { Singleton::directories()->open(project_path); notebook.open(cpp_main_path); Singleton::terminal()->print("C++ project "+project_name+" created.\n"); From c086052188a4c31b513ff1f3355c72ffc4fba0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Sun, 18 Oct 2015 23:44:20 +0200 Subject: [PATCH 08/23] Finish namespace removal and add directory content functionality --- src/filesystem.cc | 35 +++++++++++++++++++++++++++++++++++ src/filesystem.h | 18 +++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/filesystem.cc b/src/filesystem.cc index 43357ed..37907ef 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -169,3 +169,38 @@ bool filesystem::write(const std::string &path, Glib::RefPtr bu } return false; } + +std::vector filesystem::get_directory_content(const boost::filesystem::path &path, int filter) { + std::vector dirs; + if (boost::filesystem::is_directory(path)) { + for (boost::filesystem::directory_iterator it(path); it != boost::filesystem::directory_iterator(); it++) { + if (filter & DIRS && boost::filesystem::is_directory(it->path())) + dirs.emplace_back(it->path()); + if (filter & FILES && boost::filesystem::is_regular_file(it->path())) + dirs.emplace_back(it->path()); + } + } + if (filter & SORTED) + std::sort(dirs.begin(), dirs.end()); + return dirs; +}; + +std::vector filesystem::dirs(const boost::filesystem::path &path) { + return filesystem::get_directory_content(path, DIRS | SORTED); +} + +std::vector filesystem::files(const boost::filesystem::path &path) { + return filesystem::get_directory_content(path, FILES | SORTED); +} + +std::vector filesystem::contents(const boost::filesystem::path &path) { + return filesystem::get_directory_content(path, ALL | SORTED); +} + +std::vector filesystem::seperate_contents(const boost::filesystem::path &path) { + auto a = dirs(path); + auto b = files(path); + a.insert(a.end(), b.begin(), b.end()); + return a; +} + diff --git a/src/filesystem.h b/src/filesystem.h index a417825..4472a12 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -5,13 +5,12 @@ #include #include -namespace juci { - class filesystem { - public: - static std::string read(const std::string &path); - static std::string read(const boost::filesystem::path &path) { return read(path.string()); } - static int read(const std::string &path, Glib::RefPtr text_buffer); - static int read(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read(path.string(), text_buffer); } +enum filesystem_options { + DIRS = 1, + FILES = 2, + ALL = DIRS | FILES, + SORTED = 4 +}; class filesystem { public: @@ -32,6 +31,11 @@ public: static bool write(const boost::filesystem::path &path) { return write(path, ""); }; static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } + static std::vector get_directory_content(const boost::filesystem::path &path, int filter); + static std::vector dirs(const boost::filesystem::path &path); + static std::vector files(const boost::filesystem::path &path); + static std::vector contents(const boost::filesystem::path &path); + static std::vector seperate_contents(const boost::filesystem::path &path); static std::string get_home_folder(); static std::string get_tmp_folder(); From 4910e6436f304f276aa6882c6a963b344aa6980b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 19 Oct 2015 19:26:48 +0200 Subject: [PATCH 09/23] Remove wrapper methods --- src/filesystem.cc | 35 ----------------------------------- src/filesystem.h | 12 ------------ 2 files changed, 47 deletions(-) diff --git a/src/filesystem.cc b/src/filesystem.cc index 37907ef..43357ed 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -169,38 +169,3 @@ bool filesystem::write(const std::string &path, Glib::RefPtr bu } return false; } - -std::vector filesystem::get_directory_content(const boost::filesystem::path &path, int filter) { - std::vector dirs; - if (boost::filesystem::is_directory(path)) { - for (boost::filesystem::directory_iterator it(path); it != boost::filesystem::directory_iterator(); it++) { - if (filter & DIRS && boost::filesystem::is_directory(it->path())) - dirs.emplace_back(it->path()); - if (filter & FILES && boost::filesystem::is_regular_file(it->path())) - dirs.emplace_back(it->path()); - } - } - if (filter & SORTED) - std::sort(dirs.begin(), dirs.end()); - return dirs; -}; - -std::vector filesystem::dirs(const boost::filesystem::path &path) { - return filesystem::get_directory_content(path, DIRS | SORTED); -} - -std::vector filesystem::files(const boost::filesystem::path &path) { - return filesystem::get_directory_content(path, FILES | SORTED); -} - -std::vector filesystem::contents(const boost::filesystem::path &path) { - return filesystem::get_directory_content(path, ALL | SORTED); -} - -std::vector filesystem::seperate_contents(const boost::filesystem::path &path) { - auto a = dirs(path); - auto b = files(path); - a.insert(a.end(), b.begin(), b.end()); - return a; -} - diff --git a/src/filesystem.h b/src/filesystem.h index 4472a12..1a81a7d 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -5,13 +5,6 @@ #include #include -enum filesystem_options { - DIRS = 1, - FILES = 2, - ALL = DIRS | FILES, - SORTED = 4 -}; - class filesystem { public: static std::string read(const std::string &path); @@ -31,11 +24,6 @@ public: static bool write(const boost::filesystem::path &path) { return write(path, ""); }; static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } - static std::vector get_directory_content(const boost::filesystem::path &path, int filter); - static std::vector dirs(const boost::filesystem::path &path); - static std::vector files(const boost::filesystem::path &path); - static std::vector contents(const boost::filesystem::path &path); - static std::vector seperate_contents(const boost::filesystem::path &path); static std::string get_home_folder(); static std::string get_tmp_folder(); From 3dfa3be4236215426cd669df7bc142faea857298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 19 Oct 2015 20:22:42 +0200 Subject: [PATCH 10/23] More robust path handling. Fixes some bugs on windows --- src/config.cc | 20 +++++++++++--------- src/filesystem.cc | 6 +++--- src/filesystem.h | 4 ++-- src/juci.cc | 4 +++- src/singletons.cc | 19 +++++++++++-------- src/singletons.h | 9 +++++---- src/source.cc | 2 +- src/window.cc | 4 ++-- 8 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/config.cc b/src/config.cc index d50e375..35f7289 100644 --- a/src/config.cc +++ b/src/config.cc @@ -10,12 +10,12 @@ using namespace std; //TODO: remove MainConfig::MainConfig() { find_or_create_config_files(); try { - boost::property_tree::json_parser::read_json(Singleton::config_dir() + "config.json", cfg); + boost::property_tree::json_parser::read_json(Singleton::config_json(), cfg); update_config_file(); retrieve_config(); } catch(const std::exception &e) { - Singleton::terminal()->print("Error reading "+Singleton::config_dir() + "config.json: "+e.what()+"\n"); + Singleton::terminal()->print("Error reading "+ Singleton::config_json()+": "+e.what()+"\n"); std::stringstream ss; ss << configjson; boost::property_tree::read_json(ss, cfg); @@ -27,7 +27,8 @@ void MainConfig::find_or_create_config_files() { std::vector files = {"config.json", "plugins.py"}; boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir())); for (auto &file : files) { - auto path = boost::filesystem::path(Singleton::config_dir() + file); + auto path = Singleton::config_dir(); + path /= file; if (!boost::filesystem::is_regular_file(path)) { if (file == "config.json") filesystem::write(path, configjson); if (file == "plugins.py") filesystem::write(path, pluginspy); @@ -35,16 +36,16 @@ void MainConfig::find_or_create_config_files() { } boost::filesystem::create_directories(boost::filesystem::path(Singleton::style_dir())); - boost::filesystem::path juci_style_path=Singleton::style_dir(); - juci_style_path+="juci-light.xml"; + auto juci_style_path=Singleton::style_dir(); + juci_style_path/="juci-light.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_light_style); juci_style_path=Singleton::style_dir(); - juci_style_path+="juci-dark.xml"; + juci_style_path/="juci-dark.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_dark_style); juci_style_path=Singleton::style_dir(); - juci_style_path+="juci-dark-blue.xml"; + juci_style_path/="juci-dark-blue.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_dark_blue_style); } @@ -105,8 +106,9 @@ void MainConfig::update_config_file() { cfg_ok=false; } cfg_ok&=check_config_file(default_cfg); - if(!cfg_ok) - boost::property_tree::write_json(Singleton::config_dir()+"config.json", cfg); + if(!cfg_ok) { + boost::property_tree::write_json(Singleton::config_json(), cfg); + } } void MainConfig::GenerateSource() { diff --git a/src/filesystem.cc b/src/filesystem.cc index 43357ed..7ea66a3 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -26,7 +26,7 @@ std::string safe_get_env(const std::string &env) { /** * Returns home folder, empty on error */ -std::string filesystem::get_home_folder() { +boost::filesystem::path filesystem::get_home_folder() { auto home=safe_get_env("HOME"); if(home.empty()) home=safe_get_env("AppData"); @@ -43,13 +43,13 @@ std::string filesystem::get_home_folder() { /** * Returns tmp folder, empty on error. */ -std::string filesystem::get_tmp_folder() { +boost::filesystem::path filesystem::get_tmp_folder() { boost::system::error_code code; auto path = boost::filesystem::temp_directory_path(code); if (code.value()!=0) { return ""; } - return path.string(); + return path; } int filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { diff --git a/src/filesystem.h b/src/filesystem.h index 1a81a7d..ab2921d 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -25,7 +25,7 @@ public: static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } - static std::string get_home_folder(); - static std::string get_tmp_folder(); + static boost::filesystem::path get_home_folder(); + static boost::filesystem::path get_tmp_folder(); }; #endif // JUCI_SOURCEFILE_H_ diff --git a/src/juci.cc b/src/juci.cc index a01c77f..6348538 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -5,7 +5,9 @@ using namespace std; //TODO: remove void app::init_logging() { boost::log::add_common_attributes(); - boost::log::add_file_log(boost::log::keywords::file_name = Singleton::log_dir() + "juci.log", + auto log_dir = Singleton::log_dir(); + log_dir /= "juci.log"; + boost::log::add_file_log(boost::log::keywords::file_name = log_dir, boost::log::keywords::auto_flush = true); JINFO("Logging initalized"); } diff --git a/src/singletons.cc b/src/singletons.cc index 8ace5c8..1a032f6 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -39,9 +39,8 @@ Gtk::Label *Singleton::info() { return info_.get(); } -std::string Singleton::create_config_path(const std::string &subfolder) { - boost::filesystem::path home; - home = filesystem::get_home_folder(); +boost::filesystem::path Singleton::create_config_path(const std::string &subfolder) { + auto home = filesystem::get_home_folder(); if(home.empty()) { Singleton::terminal()->print("Could not find/write to home directory. Using defaults, no settings will be saved."); home = filesystem::get_tmp_folder(); @@ -53,11 +52,15 @@ std::string Singleton::create_config_path(const std::string &subfolder) { } } home /= subfolder; - return home.string(); + return home; } -std::string Singleton::config_dir() { return create_config_path(".juci/config"); } -std::string Singleton::log_dir() { return create_config_path(".juci/log"); } -std::string Singleton::style_dir() { return create_config_path(".juci/styles"); } - +boost::filesystem::path Singleton::config_dir() { return create_config_path(".juci/config"); } +boost::filesystem::path Singleton::log_dir() { return create_config_path(".juci/log"); } +boost::filesystem::path Singleton::style_dir() { return create_config_path(".juci/styles"); } +std::string Singleton::config_json() { + auto conf_dir = Singleton::config_dir(); + conf_dir /= "config.json"; // to ensure correct paths on windows + return conf_dir.string(); +} diff --git a/src/singletons.h b/src/singletons.h index f22f57b..3ac440d 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -27,10 +27,11 @@ public: static std::unique_ptr directories_; static std::unique_ptr terminal_; }; - static std::string create_config_path(const std::string &subfolder); - static std::string config_dir(); - static std::string log_dir(); - static std::string style_dir(); + static boost::filesystem::path create_config_path(const std::string &subfolder); + static boost::filesystem::path config_dir(); + static boost::filesystem::path log_dir(); + static boost::filesystem::path style_dir(); + static std::string config_json(); static Terminal *terminal(); static Directories *directories(); static Gtk::Label *status(); diff --git a/src/source.cc b/src/source.cc index d52806c..3e9e8a7 100644 --- a/src/source.cc +++ b/src/source.cc @@ -295,7 +295,7 @@ void Source::View::set_tab_char_and_size(char tab_char, unsigned tab_size) { void Source::View::configure() { //TODO: Move this to notebook? Might take up too much memory doing this for every tab. auto style_scheme_manager=Gsv::StyleSchemeManager::get_default(); - style_scheme_manager->prepend_search_path(Singleton::style_dir()); + style_scheme_manager->prepend_search_path(Singleton::style_dir().string()); if(Singleton::Config::source()->style.size()>0) { auto scheme = style_scheme_manager->get_scheme(Singleton::Config::source()->style); diff --git a/src/window.cc b/src/window.cc index 462f5db..31974da 100644 --- a/src/window.cc +++ b/src/window.cc @@ -259,13 +259,13 @@ void Window::create_menu() { } }); menu.action_group->add(Gtk::Action::create("Preferences", "Preferences..."), Gtk::AccelKey(menu.key_map["preferences"]), [this]() { - notebook.open(Singleton::config_dir()+"config.json"); + notebook.open(Singleton::config_json()); }); menu.action_group->add(Gtk::Action::create("FileSave", "Save"), Gtk::AccelKey(menu.key_map["save"]), [this]() { if(notebook.save_current()) { if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->file_path==Singleton::config_dir()+"config.json") { + if(notebook.get_current_view()->file_path==Singleton::config_json()) { configure(); for(int c=0;cconfigure(); From c7666077a14188327a6455a46dabb78cd21f46b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 19 Oct 2015 21:53:17 +0200 Subject: [PATCH 11/23] Fix filename for save as dialog --- src/dialogs.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dialogs.cc b/src/dialogs.cc index cbaaad7..ab48ced 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -5,12 +5,15 @@ std::string open_dialog(const std::string &title, const std::vector> &buttons, - Gtk::FileChooserAction gtk_options) { + Gtk::FileChooserAction gtk_options, + const std::string &file_name = "") { Gtk::FileChooserDialog dialog(title, gtk_options); if(Singleton::directories()->current_path!="") gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), Singleton::directories()->current_path.string().c_str()); else gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().string().c_str()); + if (!file_name.empty()) + gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str()); dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS); dialog.set_transient_for(*Singleton::window()); for (auto &button : buttons) @@ -45,6 +48,7 @@ std::string Dialog::select_file() { std::string Dialog::save_file() { return open_dialog("Please choose a file", {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Save", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FILE_CHOOSER_ACTION_SAVE, + Singleton::window()->notebook.get_current_view()->file_path.string()); } From cb5f86d6f7f7de0e2dc6e9c85dec5a348614d9ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 19 Oct 2015 22:20:22 +0200 Subject: [PATCH 12/23] Add windows implementation --- src/dialogs.h | 78 +++++++++++++++++++++++++++++++++++++++++++++- src/dialogs_win.cc | 58 ++++++++++++++++++++++++++++++---- 2 files changed, 129 insertions(+), 7 deletions(-) diff --git a/src/dialogs.h b/src/dialogs.h index 5acf6ea..9611783 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -11,4 +11,80 @@ class Dialog { static std::string save_file(); }; // namespace Dialog -#endif // JUCI_DIALOG_H_ \ No newline at end of file +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA + +#include +#include + +#include +#include +#include +#include "singletons.h" + +#ifndef check +HRESULT __hr__; +#define check(__fun__, error_message) \ + __hr__ = __fun__; \ + if (FAILED(__hr__)) { \ + Singleton::terminal()->print(error_message); \ + throw std::exception(error_message); + } +#endif + + +// http://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string +std::wstring s2ws(const std::string& str) { + typedef std::codecvt_utf8 convert_typeX; + std::wstring_convert converterX; + return converterX.from_bytes(str); +} + +std::string ws2s(const std::wstring& wstr) { + typedef std::codecvt_utf8 convert_typeX; + std::wstring_convert converterX; + return converterX.to_bytes(wstr); +} + +class WinString { +public: + WinString() : str(nullptr) { } + WinString(const std::string &string); + ~WinString() { CoTaskMemFree(static_cast(str)); } + std::string operator()(); + wchar_t** operator&() { return &str; } +private: + wchar_t* str; +}; + +class CommonDialog { +public: + CommonDialog(CLSID type); + void add_option(unsigned option); + void set_title(const std::string &title); + std::string show(); + +private: + IFileDialog * dialog; + DWORD options; +}; + +class OpenDialog : public CommonDialog { +public: + OpenDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) { + set_title(title); + add_option(option); + } +}; + +class SaveDialog : public CommonDialog { +public: + SaveDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileSaveDialog) { + set_title(title); + add_option(option); + } +}; +#endif +#endif // JUCI_DIALOG_H_ diff --git a/src/dialogs_win.cc b/src/dialogs_win.cc index e6891ee..ee1b30e 100644 --- a/src/dialogs_win.cc +++ b/src/dialogs_win.cc @@ -1,24 +1,70 @@ #ifdef _WIN32 #include "dialogs.h" -#include +// { WIN_STRING +WinString::WinString(const std::string &string) { + std::wstringstream ss; + ss << s2ws(string); + ss >> str; +} + +WinString::operator()() { + std::string res; + if (str != nullptr) { + std::wstring ss(str); + res = ws2s(ss); + } + return res; +} +// WIN_STRING } + +// { COMMON_DIALOG +CommonDialog::CommonDialog(CLSID type) : dialog(nullptr) { + check(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog)), "Failed to create instance"); + check(dialog->GetOptions(&options), "Failed to get options from instance"); +} + +void CommonDialog::set_title(const std::string &title) { + auto tmp = std::wstring(title.begin(), title.end()); + auto t = tmp.data(); + check(dialog->SetTitle(t), "Failed to set dialog title"); +} + +void CommonDialog::add_option(unsigned option) { + check(dialog->SetOptions(options | option), "Failed to set options"); +} + +std::string CommonDialog::show() { + try { + check(dialog->Show(nullptr), "Failed to show dialog"); + IShellItem *result = nullptr; + check(dialog->GetResult(&result), "Failed to get result from dialog"); + win_string str; + check(result->GetDisplayName(SIGDN_FILESYSPATH, &str), "Failed to get display name from dialog"); + result->Release(); + return str(); + } catch (std::exception e) { + return ""; + } +} +// COMMON_DIALOG }} std::string Dialog::select_folder() { - return c_select_folder(); + return (OpenDialog("Select folder", FOS_PICKFOLDERS)).show(); } std::string Dialog::new_file() { - return c_new_file(); + return (SaveDialog("Please choose your destination", 0)).show(); } std::string Dialog::new_folder() { - return c_new_folder(); + return Dialog::select_folder(); } std::string Dialog::select_file() { - return c_select_file(); + return (OpenDialog("Open file", 0)).show(); } std::string Dialog::save_file() { - return c_save_file(); + return (SaveDialog("Please choose your destination", 0)).show(); } #endif From 980920f661b906c42944caec4d56cc14e0375233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Tue, 20 Oct 2015 01:12:58 +0200 Subject: [PATCH 13/23] Compiles in windows --- WIN-packages/README.md | 1 - WIN-packages/dialogs_win.h | 11 ----------- src/CMakeLists.txt | 11 +---------- src/dialogs.h | 32 ++++---------------------------- src/dialogs_win.cc | 34 ++++++++++++++++++++++++++++++---- 5 files changed, 35 insertions(+), 54 deletions(-) delete mode 100644 WIN-packages/README.md delete mode 100644 WIN-packages/dialogs_win.h diff --git a/WIN-packages/README.md b/WIN-packages/README.md deleted file mode 100644 index 11b5099..0000000 --- a/WIN-packages/README.md +++ /dev/null @@ -1 +0,0 @@ -Source code for the dll's can be found at https://github.com/cppit/dialogs \ No newline at end of file diff --git a/WIN-packages/dialogs_win.h b/WIN-packages/dialogs_win.h deleted file mode 100644 index 37a1d37..0000000 --- a/WIN-packages/dialogs_win.h +++ /dev/null @@ -1,11 +0,0 @@ -extern "C" { -#ifndef JUCI_C_DIALOGS -#define JUCI_C_DIALOGS - __declspec(dllimport) const char* c_select_folder(); - __declspec(dllimport) const char* c_select_file(); - __declspec(dllimport) const char* c_new_file(); - __declspec(dllimport) const char* c_new_folder(); - __declspec(dllimport) const char* c_save_file(); -#endif // JUCI_C_DIALOGS -}; - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e3dab84..6448e52 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,13 +76,6 @@ set(source_files juci.h if(MSYS) list(APPEND source_files terminal_win.cc) list(APPEND source_files dialogs_win.cc) - set(DIALOGS_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/WIN-packages/") - # if (64 bit) - set(DIALOGS_LIBRARIES "${CMAKE_SOURCE_DIR}/WIN-packages/x64/libdialogs.dll") - message(${DIALOGS_LIBRARIES}) - # else - # set(DIALOGS_LIBRARIES "${CMAKE_SOURCE_DIR}/WIN-packages/x32/libdialogs.dll") - #TODO figure out how to do this.... else() list(APPEND source_files terminal.cc) list(APPEND source_files dialogs.cc) @@ -101,7 +94,6 @@ include_directories( ${GTKSVMM_INCLUDE_DIRS} ${LIBCLANG_INCLUDE_DIRS} ${ASPELL_INCLUDE_DIR} - ${DIALOGS_INCLUDE_DIRS} ../libclangmm/src ) @@ -126,8 +118,7 @@ target_link_libraries(${project_name} ${GTKSVMM_LIBRARIES} ${Boost_LIBRARIES} ${ASPELL_LIBRARIES} - ${DIALOGS_LIBRARIES} -# ${PYTHON_LIBRARIES} + #${PYTHON_LIBRARIES} ) # install(TARGETS ${project_name} ${module} diff --git a/src/dialogs.h b/src/dialogs.h index 9611783..086a93b 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,10 +9,9 @@ class Dialog { static std::string new_file(); static std::string new_folder(); static std::string save_file(); -}; // namespace Dialog +}; // Dialog #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN #define NTDDI_VERSION NTDDI_VISTA #define _WIN32_WINNT _WIN32_WINNT_VISTA @@ -22,31 +21,6 @@ class Dialog { #include #include #include -#include "singletons.h" - -#ifndef check -HRESULT __hr__; -#define check(__fun__, error_message) \ - __hr__ = __fun__; \ - if (FAILED(__hr__)) { \ - Singleton::terminal()->print(error_message); \ - throw std::exception(error_message); - } -#endif - - -// http://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string -std::wstring s2ws(const std::string& str) { - typedef std::codecvt_utf8 convert_typeX; - std::wstring_convert converterX; - return converterX.from_bytes(str); -} - -std::string ws2s(const std::wstring& wstr) { - typedef std::codecvt_utf8 convert_typeX; - std::wstring_convert converterX; - return converterX.to_bytes(wstr); -} class WinString { public: @@ -57,6 +31,8 @@ public: wchar_t** operator&() { return &str; } private: wchar_t* str; + std::wstring s2ws(const std::string& str); + std::string ws2s(const std::wstring& wstr); }; class CommonDialog { @@ -86,5 +62,5 @@ public: add_option(option); } }; -#endif +#endif // __WIN32 #endif // JUCI_DIALOG_H_ diff --git a/src/dialogs_win.cc b/src/dialogs_win.cc index ee1b30e..d7b2791 100644 --- a/src/dialogs_win.cc +++ b/src/dialogs_win.cc @@ -1,14 +1,26 @@ #ifdef _WIN32 #include "dialogs.h" +#include "singletons.h" -// { WIN_STRING +#ifndef check +HRESULT __hr__; +#define check(__fun__, error_message) \ + __hr__ = __fun__; \ + if (FAILED(__hr__)) { \ + Singleton::terminal()->print(error_message); \ + throw std::runtime_error(error_message); \ +} +#endif // CHECK + + +// { WINSTRING WinString::WinString(const std::string &string) { std::wstringstream ss; ss << s2ws(string); ss >> str; } -WinString::operator()() { +std::string WinString::operator()() { std::string res; if (str != nullptr) { std::wstring ss(str); @@ -16,7 +28,21 @@ WinString::operator()() { } return res; } -// WIN_STRING } + +// http://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string +std::wstring WinString::s2ws(const std::string& str) { + typedef std::codecvt_utf8 convert_typeX; + std::wstring_convert converterX; + return converterX.from_bytes(str); +} + +std::string WinString::ws2s(const std::wstring& wstr) { + typedef std::codecvt_utf8 convert_typeX; + std::wstring_convert converterX; + return converterX.to_bytes(wstr); +} + +// WINSTRING } // { COMMON_DIALOG CommonDialog::CommonDialog(CLSID type) : dialog(nullptr) { @@ -39,7 +65,7 @@ std::string CommonDialog::show() { check(dialog->Show(nullptr), "Failed to show dialog"); IShellItem *result = nullptr; check(dialog->GetResult(&result), "Failed to get result from dialog"); - win_string str; + WinString str; check(result->GetDisplayName(SIGDN_FILESYSPATH, &str), "Failed to get display name from dialog"); result->Release(); return str(); From 8f6149c81def4f09fbfda9986a6c98830309ce98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Tue, 20 Oct 2015 01:16:19 +0200 Subject: [PATCH 14/23] Remove dlls --- WIN-packages/x64/libdialogs.dll | Bin 74752 -> 0 bytes WIN-packages/x86/libdialogs.dll | Bin 26624 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 WIN-packages/x64/libdialogs.dll delete mode 100644 WIN-packages/x86/libdialogs.dll diff --git a/WIN-packages/x64/libdialogs.dll b/WIN-packages/x64/libdialogs.dll deleted file mode 100644 index 79bce1bbfa13b57360df67271a6cf37b0e96dc6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74752 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 W$Enj@AyxoltZGcc;^%+wf&T)2c1O?v diff --git a/WIN-packages/x86/libdialogs.dll b/WIN-packages/x86/libdialogs.dll deleted file mode 100644 index 0ecb1c9ac7ce7e41d581a88b9287f82a27d841d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26624 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 P0sR<1MFhhC;OqYY#$R{s From 47d3cfb140a384cc42e929308c40cc6f2d270494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Tue, 20 Oct 2015 15:35:54 +0200 Subject: [PATCH 15/23] Begin simplify of paths --- src/singletons.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/singletons.cc b/src/singletons.cc index 1a032f6..7f07185 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -55,12 +55,8 @@ boost::filesystem::path Singleton::create_config_path(const std::string &subfold return home; } -boost::filesystem::path Singleton::config_dir() { return create_config_path(".juci/config"); } -boost::filesystem::path Singleton::log_dir() { return create_config_path(".juci/log"); } -boost::filesystem::path Singleton::style_dir() { return create_config_path(".juci/styles"); } -std::string Singleton::config_json() { - auto conf_dir = Singleton::config_dir(); - conf_dir /= "config.json"; // to ensure correct paths on windows - return conf_dir.string(); -} +boost::filesystem::path Singleton::config_dir() { return create_config_path({".juci", "config"}); } +boost::filesystem::path Singleton::log_dir() { return create_config_path({".juci", "log"}); } +boost::filesystem::path Singleton::style_dir() { return create_config_path({".juci", "styles"}); } +std::string Singleton::config_json() { return (Singleton::config_dir()/"config.json").string(); } From e56f39aa0cefa718005810a61a8390078ecd10ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 13:40:39 +0100 Subject: [PATCH 16/23] Use correct operators for concatination of paths --- src/cmake.cc | 12 ++++++------ src/dialogs.cc | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmake.cc b/src/cmake.cc index 883b49a..334a1ab 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -17,9 +17,9 @@ CMake::CMake(const boost::filesystem::path &path) { return false; }; - auto search_path=boost::filesystem::path(path); + auto search_path=path; auto search_cmake_path=search_path; - search_cmake_path+="/CMakeLists.txt"; + search_cmake_path/="CMakeLists.txt"; if(boost::filesystem::exists(search_cmake_path)) paths.emplace(paths.begin(), search_cmake_path); if(find_cmake_project(search_cmake_path)) @@ -28,7 +28,7 @@ CMake::CMake(const boost::filesystem::path &path) { do { search_path=search_path.parent_path(); search_cmake_path=search_path; - search_cmake_path+="/CMakeLists.txt"; + search_cmake_path/="CMakeLists.txt"; if(boost::filesystem::exists(search_cmake_path)) paths.emplace(paths.begin(), search_cmake_path); if(find_cmake_project(search_cmake_path)) { @@ -37,8 +37,8 @@ CMake::CMake(const boost::filesystem::path &path) { } } while(search_path!=search_path.root_directory()); } - if(project_path!="") { - if(boost::filesystem::exists(project_path.string()+"/CMakeLists.txt") && !boost::filesystem::exists(project_path.string()+"/compile_commands.json")) + if(!project_path.empty()) { + if(boost::filesystem::exists(project_path/"CMakeLists.txt") && !boost::filesystem::exists(project_path/"compile_commands.json")) create_compile_commands(project_path); } } @@ -48,7 +48,7 @@ bool CMake::create_compile_commands(const boost::filesystem::path &path) { if(Singleton::terminal()->execute(Singleton::Config::terminal()->cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path)==EXIT_SUCCESS) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang auto compile_commands_path=path; - compile_commands_path+="/compile_commands.json"; + compile_commands_path/="compile_commands.json"; auto compile_commands_file=filesystem::read(compile_commands_path); size_t pos=0; while((pos=compile_commands_file.find("-I/", pos))!=std::string::npos) { diff --git a/src/dialogs.cc b/src/dialogs.cc index ab48ced..56fb0c9 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -8,10 +8,10 @@ std::string open_dialog(const std::string &title, Gtk::FileChooserAction gtk_options, const std::string &file_name = "") { Gtk::FileChooserDialog dialog(title, gtk_options); - if(Singleton::directories()->current_path!="") - gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), Singleton::directories()->current_path.string().c_str()); + if(!Singleton::directories()->current_path.empty()) + gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), Singleton::directories()->current_path.c_str()); else - gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().string().c_str()); + gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().c_str()); if (!file_name.empty()) gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str()); dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS); From ae1bd136a9abae28e8876c2fa41ed39b0c97ee43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 15:56:02 +0100 Subject: [PATCH 17/23] Minor replace tabs with spaces and remove whitespace --- src/config.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/config.cc b/src/config.cc index 35f7289..8c121da 100644 --- a/src/config.cc +++ b/src/config.cc @@ -75,12 +75,12 @@ bool MainConfig::check_config_file(const boost::property_tree::ptree &default_cf } catch(const std::exception &e) { cfg.add(path, node.second.data()); - exists=false; + exists=false; } try { exists&=check_config_file(node.second, path); } - catch(const std::exception &e) { + catch(const std::exception &e) { } } return exists; @@ -114,27 +114,27 @@ void MainConfig::update_config_file() { void MainConfig::GenerateSource() { auto source_cfg = Singleton::Config::source(); auto source_json = cfg.get_child("source"); - + Singleton::Config::source()->style=source_json.get("style"); source_cfg->font=source_json.get("font"); - + source_cfg->show_map = source_json.get("show_map"); source_cfg->map_font_size = source_json.get("map_font_size"); - + source_cfg->spellcheck_language = source_json.get("spellcheck_language"); - + source_cfg->default_tab_char = source_json.get("default_tab_char"); source_cfg->default_tab_size = source_json.get("default_tab_size"); source_cfg->auto_tab_char_and_size = source_json.get("auto_tab_char_and_size"); - + source_cfg->wrap_lines = source_json.get("wrap_lines"); - + source_cfg->highlight_current_line = source_json.get("highlight_current_line"); source_cfg->show_line_numbers = source_json.get("show_line_numbers"); - + for (auto &i : source_json.get_child("clang_types")) source_cfg->clang_types[i.first] = i.second.get_value(); - + auto pt_doc_search=cfg.get_child("documentation_searches"); for(auto &pt_doc_search_lang: pt_doc_search) { source_cfg->documentation_searches[pt_doc_search_lang.first].separator=pt_doc_search_lang.second.get("separator"); From 2ee625232de39584548ec4bad6193cf6434dfe7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 16:00:11 +0100 Subject: [PATCH 18/23] Better lookup of home directory, fixing rest of paths that were concatinated incorrectly, removal of singletons that aren't singletons --- src/config.cc | 66 +++++++++++++++++++++++++++++++++-------------- src/config.h | 4 +++ src/files.h | 2 ++ src/filesystem.cc | 34 ------------------------ src/filesystem.h | 2 -- src/singletons.cc | 21 --------------- 6 files changed, 53 insertions(+), 76 deletions(-) diff --git a/src/config.cc b/src/config.cc index 8c121da..20d4e08 100644 --- a/src/config.cc +++ b/src/config.cc @@ -8,14 +8,24 @@ using namespace std; //TODO: remove MainConfig::MainConfig() { - find_or_create_config_files(); + auto search_envs = init_home_path(); + auto config_json = (home/"config"/"config.json").string(); // This causes some redundant copies, but assures windows support try { - boost::property_tree::json_parser::read_json(Singleton::config_json(), cfg); + find_or_create_config_files(); + if(home.empty()) { + std::string searched_envs = "["; + for(auto &env : search_envs) + searched_envs+=env+", "; + searched_envs.erase(searched_envs.end()-2, searched_envs.end()); + searched_envs+="]"; + throw std::runtime_error("One of these environment variables needs to point to a writable directory to save configuration." + searched_envs); + } + boost::property_tree::json_parser::read_json(config_json, cfg); update_config_file(); retrieve_config(); } catch(const std::exception &e) { - Singleton::terminal()->print("Error reading "+ Singleton::config_json()+": "+e.what()+"\n"); + Singleton::terminal()->print("Error reading "+ config_json + ": "+e.what()+"\n"); std::stringstream ss; ss << configjson; boost::property_tree::read_json(ss, cfg); @@ -24,27 +34,28 @@ MainConfig::MainConfig() { } void MainConfig::find_or_create_config_files() { - std::vector files = {"config.json", "plugins.py"}; - boost::filesystem::create_directories(boost::filesystem::path(Singleton::config_dir())); - for (auto &file : files) { - auto path = Singleton::config_dir(); - path /= file; - if (!boost::filesystem::is_regular_file(path)) { - if (file == "config.json") filesystem::write(path, configjson); - if (file == "plugins.py") filesystem::write(path, pluginspy); - } - } - - boost::filesystem::create_directories(boost::filesystem::path(Singleton::style_dir())); - auto juci_style_path=Singleton::style_dir(); + auto config_dir = home/"config"; + auto config_json = config_dir/"config.json"; + auto plugins_py = config_dir/"plugins.py"; + + boost::filesystem::create_directories(config_dir); // io exp captured by calling method + + if (!boost::filesystem::exists(config_json)) + filesystem::write(config_json, configjson); // vars configjson and pluginspy + if (!boost::filesystem::exists(plugins_py)) // live in files.h + filesystem::write(plugins_py, pluginspy); + + auto juci_style_path = home/"styles"; + boost::filesystem::create_directories(juci_style_path); // io exp captured by calling method + juci_style_path/="juci-light.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_light_style); - juci_style_path=Singleton::style_dir(); + juci_style_path=juci_style_path.parent_path(); juci_style_path/="juci-dark.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_dark_style); - juci_style_path=Singleton::style_dir(); + juci_style_path=juci_style_path.parent_path(); juci_style_path/="juci-dark-blue.xml"; if(!boost::filesystem::exists(juci_style_path)) filesystem::write(juci_style_path, juci_dark_blue_style); @@ -107,7 +118,7 @@ void MainConfig::update_config_file() { } cfg_ok&=check_config_file(default_cfg); if(!cfg_ok) { - boost::property_tree::write_json(Singleton::config_json(), cfg); + boost::property_tree::write_json((home/"config"/"config.json").string(), cfg); } } @@ -157,3 +168,20 @@ void MainConfig::GenerateDirectoryFilter() { dir_cfg->ignored.emplace_back(i.second.get_value()); JDEBUG("Directory filter fetched"); } +std::vector MainConfig::init_home_path(){ + std::vector locations = JUCI_ENV_SEARCH_LOCATIONS; + char *ptr = nullptr; + for (auto &env : locations) { + ptr=std::getenv(env.c_str()); + if (ptr==nullptr) + break; + else + if (boost::filesystem::exists(ptr)) { + home /= ".juci"; + home /= ptr; + return locations; + } + } + home=""; + return locations; +} diff --git a/src/config.h b/src/config.h index 190de24..47a032a 100644 --- a/src/config.h +++ b/src/config.h @@ -13,7 +13,11 @@ public: void PrintMenu(); void GenerateSource(); void GenerateDirectoryFilter(); + const boost::filesystem::path& juci_home_path() { return home; } const; + private: + std::vector init_home_path(); boost::property_tree::ptree cfg; + boost::filesystem::path home; }; #endif diff --git a/src/files.h b/src/files.h index 8f49573..39c7cc8 100644 --- a/src/files.h +++ b/src/files.h @@ -2,6 +2,8 @@ #define JUCI_VERSION "0.9.3" +#define JUCI_ENV_SEARCH_LOCATIONS {"AppData", "HOME", "JUCI_HOME"} + const std::string configjson = "{\n" " \"version\": \""+std::string(JUCI_VERSION)+"\",\n" diff --git a/src/filesystem.cc b/src/filesystem.cc index 7ea66a3..02d05fd 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -18,40 +18,6 @@ std::string filesystem::read(const std::string &path) { return ss.str(); } -std::string safe_get_env(const std::string &env) { - auto ptr = std::getenv(env.c_str()); - return nullptr==ptr ? "" : std::string(ptr); -} - -/** - * Returns home folder, empty on error - */ -boost::filesystem::path filesystem::get_home_folder() { - auto home=safe_get_env("HOME"); - if(home.empty()) - home=safe_get_env("AppData"); - auto status = boost::filesystem::status(home); - if((status.permissions() & 0222)>=2) { - return home; - } else { - JERROR("No write permissions in home, var:"); - DEBUG_VAR(home); - return ""; - } -} - -/** - * Returns tmp folder, empty on error. - */ -boost::filesystem::path filesystem::get_tmp_folder() { - boost::system::error_code code; - auto path = boost::filesystem::temp_directory_path(code); - if (code.value()!=0) { - return ""; - } - return path; -} - int filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); diff --git a/src/filesystem.h b/src/filesystem.h index ab2921d..46bcc67 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -25,7 +25,5 @@ public: static bool write(const std::string &path, Glib::RefPtr text_buffer); static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } - static boost::filesystem::path get_home_folder(); - static boost::filesystem::path get_tmp_folder(); }; #endif // JUCI_SOURCEFILE_H_ diff --git a/src/singletons.cc b/src/singletons.cc index 7f07185..32a44cb 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -39,24 +39,3 @@ Gtk::Label *Singleton::info() { return info_.get(); } -boost::filesystem::path Singleton::create_config_path(const std::string &subfolder) { - auto home = filesystem::get_home_folder(); - if(home.empty()) { - Singleton::terminal()->print("Could not find/write to home directory. Using defaults, no settings will be saved."); - home = filesystem::get_tmp_folder(); - if(home.empty()) { - std::string message("Please fix permissions of your home folder"); - std::cerr << message << std::endl; - JFATAL(message); - throw new std::exception; - } - } - home /= subfolder; - return home; -} - -boost::filesystem::path Singleton::config_dir() { return create_config_path({".juci", "config"}); } -boost::filesystem::path Singleton::log_dir() { return create_config_path({".juci", "log"}); } -boost::filesystem::path Singleton::style_dir() { return create_config_path({".juci", "styles"}); } -std::string Singleton::config_json() { return (Singleton::config_dir()/"config.json").string(); } - From 94bc501ab657238266abc5b5a4b9f213f380a51a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 16:18:28 +0100 Subject: [PATCH 19/23] Remove the rest of the references to the removed singletons and adding main config as singleton --- src/config.h | 6 ++++-- src/directories.cc | 4 ++-- src/juci.cc | 3 +-- src/singletons.cc | 1 + src/singletons.h | 9 ++++----- src/source.cc | 2 +- src/window.cc | 7 +++---- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/config.h b/src/config.h index 47a032a..c84ded6 100644 --- a/src/config.h +++ b/src/config.h @@ -1,11 +1,15 @@ #ifndef JUCI_CONFIG_H_ #define JUCI_CONFIG_H_ #include +#include #include "menu.h" class MainConfig { public: MainConfig(); + const boost::filesystem::path& juci_home_path() const { return home; } + +private: void find_or_create_config_files(); void retrieve_config(); bool check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path=""); @@ -13,9 +17,7 @@ public: void PrintMenu(); void GenerateSource(); void GenerateDirectoryFilter(); - const boost::filesystem::path& juci_home_path() { return home; } const; -private: std::vector init_home_path(); boost::property_tree::ptree cfg; boost::filesystem::path home; diff --git a/src/directories.cc b/src/directories.cc index f8303b3..1fe8459 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -120,8 +120,8 @@ Directories::~Directories() { void Directories::open(const boost::filesystem::path& dir_path) { JDEBUG("start"); - if(dir_path=="") - return; + if(dir_path.empty()) + return; tree_store->clear(); update_mutex.lock(); diff --git a/src/juci.cc b/src/juci.cc index 6348538..aaa43c4 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -5,8 +5,7 @@ using namespace std; //TODO: remove void app::init_logging() { boost::log::add_common_attributes(); - auto log_dir = Singleton::log_dir(); - log_dir /= "juci.log"; + auto log_dir = Singleton::Config::main()->juci_home_path()/"log"/"juci.log"; boost::log::add_file_log(boost::log::keywords::file_name = log_dir, boost::log::keywords::auto_flush = true); JINFO("Logging initalized"); diff --git a/src/singletons.cc b/src/singletons.cc index 32a44cb..1c99230 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -7,6 +7,7 @@ std::unique_ptr Singleton::Config::window_ = std::unique_ptr Singleton::terminal_=std::unique_ptr(); std::unique_ptr Singleton::directories_=std::unique_ptr(); std::unique_ptr Singleton::window_=std::unique_ptr(); +std::unique_ptr Singleton::Config::main_=std::unique_ptr(new MainConfig()); Terminal *Singleton::terminal() { if(!terminal_) diff --git a/src/singletons.h b/src/singletons.h index 3ac440d..2d58fe5 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -11,6 +11,7 @@ #include "notebook.h" #include "menu.h" #include "window.h" +#include "config.h" class Singleton { public: @@ -20,23 +21,21 @@ public: static Directories::Config *directories() {return directories_.get();} static Window::Config *window() { return window_.get(); } static Terminal::Config *terminal() {return terminal_.get();} + static MainConfig *main() { return main_.get(); } private: static std::unique_ptr source_; static std::unique_ptr window_; static std::unique_ptr directories_; static std::unique_ptr terminal_; + static std::unique_ptr main_; }; - static boost::filesystem::path create_config_path(const std::string &subfolder); - static boost::filesystem::path config_dir(); - static boost::filesystem::path log_dir(); - static boost::filesystem::path style_dir(); - static std::string config_json(); static Terminal *terminal(); static Directories *directories(); static Gtk::Label *status(); static Gtk::Label *info(); static Window *window(); + private: static std::unique_ptr terminal_; static std::unique_ptr status_; diff --git a/src/source.cc b/src/source.cc index 3e9e8a7..ce453d4 100644 --- a/src/source.cc +++ b/src/source.cc @@ -295,7 +295,7 @@ void Source::View::set_tab_char_and_size(char tab_char, unsigned tab_size) { void Source::View::configure() { //TODO: Move this to notebook? Might take up too much memory doing this for every tab. auto style_scheme_manager=Gsv::StyleSchemeManager::get_default(); - style_scheme_manager->prepend_search_path(Singleton::style_dir().string()); + style_scheme_manager->prepend_search_path((Singleton::Config::main()->juci_home_path()/"styles").string()); if(Singleton::Config::source()->style.size()>0) { auto scheme = style_scheme_manager->get_scheme(Singleton::Config::source()->style); diff --git a/src/window.cc b/src/window.cc index 31974da..fa72035 100644 --- a/src/window.cc +++ b/src/window.cc @@ -158,7 +158,6 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), compiling(false) { } // Window constructor void Window::configure() { - MainConfig(); // Read the configs here auto style_context = Gtk::StyleContext::create(); auto screen = Gdk::Screen::get_default(); auto css_provider = Gtk::CssProvider::get_named(Singleton::Config::window()->theme_name, Singleton::Config::window()->theme_variant); @@ -235,7 +234,7 @@ void Window::create_menu() { Singleton::terminal()->print("Error: Could not create project "+project_path.string()+"\n"); }); menu.action_group->add(Gtk::Action::create("FileOpenFile", "Open File"), Gtk::AccelKey(menu.key_map["open_file"]), [this]() { - notebook.open(Dialog::select_file()); + notebook.open(Dialog::select_file()); }); menu.action_group->add(Gtk::Action::create("FileOpenFolder", "Open Folder"), Gtk::AccelKey(menu.key_map["open_folder"]), [this]() { auto path = Dialog::select_folder(); @@ -259,13 +258,13 @@ void Window::create_menu() { } }); menu.action_group->add(Gtk::Action::create("Preferences", "Preferences..."), Gtk::AccelKey(menu.key_map["preferences"]), [this]() { - notebook.open(Singleton::config_json()); + notebook.open(Singleton::Config::main()->juci_home_path()/"config"/"config.json"); }); menu.action_group->add(Gtk::Action::create("FileSave", "Save"), Gtk::AccelKey(menu.key_map["save"]), [this]() { if(notebook.save_current()) { if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->file_path==Singleton::config_json()) { + if(notebook.get_current_view()->file_path==Singleton::Config::main()->juci_home_path()/"config"/"config.json") { configure(); for(int c=0;cconfigure(); From 2510fb1e916b3973605118cf27c8519c3431163d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 20:40:20 +0100 Subject: [PATCH 20/23] Using wrong keyword, one hour of my life I never get back --- src/config.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/config.cc b/src/config.cc index 20d4e08..3926604 100644 --- a/src/config.cc +++ b/src/config.cc @@ -18,18 +18,18 @@ MainConfig::MainConfig() { searched_envs+=env+", "; searched_envs.erase(searched_envs.end()-2, searched_envs.end()); searched_envs+="]"; - throw std::runtime_error("One of these environment variables needs to point to a writable directory to save configuration." + searched_envs); + throw std::runtime_error("One of these environment variables needs to point to a writable directory to save configuration: " + searched_envs); } boost::property_tree::json_parser::read_json(config_json, cfg); update_config_file(); retrieve_config(); } catch(const std::exception &e) { - Singleton::terminal()->print("Error reading "+ config_json + ": "+e.what()+"\n"); std::stringstream ss; ss << configjson; boost::property_tree::read_json(ss, cfg); retrieve_config(); + JERROR("Error reading "+ config_json + ": "+e.what()+"\n"); // logs will print to cerr when init_log haven't been run yet } } @@ -65,7 +65,7 @@ void MainConfig::retrieve_config() { Singleton::Config::window()->keybindings = cfg.get_child("keybindings"); GenerateSource(); GenerateDirectoryFilter(); - + Singleton::Config::window()->theme_name=cfg.get("gtk_theme.name"); Singleton::Config::window()->theme_variant=cfg.get("gtk_theme.variant"); Singleton::Config::window()->version = cfg.get("version"); @@ -174,11 +174,11 @@ std::vector MainConfig::init_home_path(){ for (auto &env : locations) { ptr=std::getenv(env.c_str()); if (ptr==nullptr) - break; + continue; else if (boost::filesystem::exists(ptr)) { - home /= ".juci"; home /= ptr; + home /= ".juci"; return locations; } } From 23e9068dbb6c71d2205104849ca077a64b95308d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 20:59:27 +0100 Subject: [PATCH 21/23] Removed two log lines since they theoretically end up in cerr. --- src/config.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/config.cc b/src/config.cc index 3926604..84ac03a 100644 --- a/src/config.cc +++ b/src/config.cc @@ -158,7 +158,6 @@ void MainConfig::GenerateSource() { void MainConfig::GenerateDirectoryFilter() { auto dir_cfg=Singleton::Config::directories(); - JDEBUG("Fetching directory filter"); boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter"); boost::property_tree::ptree ignore_json = dir_json.get_child("ignore"); boost::property_tree::ptree except_json = dir_json.get_child("exceptions"); @@ -166,7 +165,6 @@ void MainConfig::GenerateDirectoryFilter() { dir_cfg->exceptions.emplace_back(i.second.get_value()); for ( auto &i : ignore_json ) dir_cfg->ignored.emplace_back(i.second.get_value()); - JDEBUG("Directory filter fetched"); } std::vector MainConfig::init_home_path(){ std::vector locations = JUCI_ENV_SEARCH_LOCATIONS; From cefb1c419dd5d74237b343ed8afb1855e30caba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Mon, 26 Oct 2015 21:00:54 +0100 Subject: [PATCH 22/23] Clear the propterty tree after assigning to singleton configuration --- src/config.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config.cc b/src/config.cc index 84ac03a..c05e382 100644 --- a/src/config.cc +++ b/src/config.cc @@ -31,6 +31,7 @@ MainConfig::MainConfig() { retrieve_config(); JERROR("Error reading "+ config_json + ": "+e.what()+"\n"); // logs will print to cerr when init_log haven't been run yet } + cfg.clear(); } void MainConfig::find_or_create_config_files() { From a488eb4c582af0c5c2cf6a53fe635361a021f03b Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 27 Oct 2015 10:56:55 +0100 Subject: [PATCH 23/23] Trying to link to correct libclangmm tree. --- libclangmm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libclangmm b/libclangmm index e060dec..f1f784d 160000 --- a/libclangmm +++ b/libclangmm @@ -1 +1 @@ -Subproject commit e060dec32bb8306eff6f9114092cdbefe8fea5fb +Subproject commit f1f784dd02d78da35a27034c6cc854e676d4f78b