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/WIN-packages/x64/libdialogs.dll b/WIN-packages/x64/libdialogs.dll deleted file mode 100644 index 79bce1b..0000000 Binary files a/WIN-packages/x64/libdialogs.dll and /dev/null differ diff --git a/WIN-packages/x86/libdialogs.dll b/WIN-packages/x86/libdialogs.dll deleted file mode 100644 index 0ecb1c9..0000000 Binary files a/WIN-packages/x86/libdialogs.dll and /dev/null differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2e348c..3d246e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,8 +48,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 @@ -87,13 +87,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) @@ -112,7 +105,6 @@ include_directories( ${GTKSVMM_INCLUDE_DIRS} ${LIBCLANG_INCLUDE_DIRS} ${ASPELL_INCLUDE_DIR} - ${DIALOGS_INCLUDE_DIRS} ../libclangmm/src ) @@ -137,8 +129,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/cmake.cc b/src/cmake.cc index 76b4aa0..334a1ab 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -1,14 +1,13 @@ #include "cmake.h" -#include "sourcefile.h" -#include #include "singletons.h" +#include #include //TODO: remove 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)) { @@ -18,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)) @@ -29,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)) { @@ -38,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); } } @@ -49,8 +48,8 @@ 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"; - auto compile_commands_file=juci::filesystem::read(compile_commands_path); + 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) { if(pos+3 #include "files.h" -#include "sourcefile.h" -#include "singletons.h" #include using namespace std; //TODO: remove MainConfig::MainConfig() { - find_or_create_config_files(); + init_home_path(); +} + +void MainConfig::read() { + 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_dir() + "config.json", cfg); + find_or_create_config_files(); + 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_dir() + "config.json: "+e.what()+"\n"); + Singleton::terminal()->print("Error reading "+config_json + "config.json: "+e.what()+"\n"); std::stringstream ss; ss << configjson; boost::property_tree::read_json(ss, cfg); retrieve_config(); } + cfg.clear(); } 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); - if (!boost::filesystem::is_regular_file(path)) { - if (file == "config.json") juci::filesystem::write(path, configjson); - if (file == "plugins.py") juci::filesystem::write(path, pluginspy); - } - } - - 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 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)) - juci::filesystem::write(juci_style_path, juci_light_style); - juci_style_path=Singleton::style_dir(); - juci_style_path+="juci-dark.xml"; + filesystem::write(juci_style_path, juci_light_style); + juci_style_path=juci_style_path.parent_path(); + juci_style_path/="juci-dark.xml"; if(!boost::filesystem::exists(juci_style_path)) - juci::filesystem::write(juci_style_path, juci_dark_style); - juci_style_path=Singleton::style_dir(); - juci_style_path+="juci-dark-blue.xml"; + filesystem::write(juci_style_path, juci_dark_style); + juci_style_path=juci_style_path.parent_path(); + juci_style_path/="juci-dark-blue.xml"; if(!boost::filesystem::exists(juci_style_path)) - juci::filesystem::write(juci_style_path, juci_dark_blue_style); + filesystem::write(juci_style_path, juci_dark_blue_style); } void MainConfig::retrieve_config() { @@ -58,7 +64,7 @@ void MainConfig::retrieve_config() { } 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"); @@ -79,12 +85,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; @@ -110,31 +116,32 @@ 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((home/"config"/"config.json").string(), cfg); + } } 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(); @@ -152,7 +159,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"); @@ -160,5 +166,30 @@ 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"); +} + +void 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) + continue; + else + if (boost::filesystem::exists(ptr)) { + home /= ptr; + home /= ".juci"; + break; + } + } + + if(home.empty()) { + std::string searched_envs = "["; + for(auto &env : locations) + 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); + } + return; } diff --git a/src/config.h b/src/config.h index 190de24..99ffa90 100644 --- a/src/config.h +++ b/src/config.h @@ -1,11 +1,16 @@ #ifndef JUCI_CONFIG_H_ #define JUCI_CONFIG_H_ #include +#include #include "menu.h" class MainConfig { public: MainConfig(); + void read(); + 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,7 +18,9 @@ public: void PrintMenu(); void GenerateSource(); void GenerateDirectoryFilter(); -private: + + void init_home_path(); boost::property_tree::ptree cfg; + boost::filesystem::path home; }; #endif diff --git a/src/dialogs.cc b/src/dialogs.cc index e8588e5..a2b9066 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -5,20 +5,22 @@ 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()); + 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); - // 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)}, @@ -38,7 +40,7 @@ std::string Dialog::new_folder() { } std::string Dialog::select_file() { - return open_dialog("Please choose a folder", + return open_dialog("Please choose a file", {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Select", Gtk::RESPONSE_OK)}, Gtk::FILE_CHOOSER_ACTION_OPEN); } @@ -46,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()); } diff --git a/src/dialogs.h b/src/dialogs.h index 5acf6ea..086a93b 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,6 +9,58 @@ class Dialog { static std::string new_file(); static std::string new_folder(); static std::string save_file(); -}; // namespace Dialog +}; // Dialog -#endif // JUCI_DIALOG_H_ \ No newline at end of file +#ifdef _WIN32 +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA + +#include +#include + +#include +#include +#include + +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; + std::wstring s2ws(const std::string& str); + std::string ws2s(const std::wstring& wstr); +}; + +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 // __WIN32 +#endif // JUCI_DIALOG_H_ diff --git a/src/dialogs_win.cc b/src/dialogs_win.cc index e6891ee..d7b2791 100644 --- a/src/dialogs_win.cc +++ b/src/dialogs_win.cc @@ -1,24 +1,96 @@ #ifdef _WIN32 #include "dialogs.h" -#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::runtime_error(error_message); \ +} +#endif // CHECK + + +// { WINSTRING +WinString::WinString(const std::string &string) { + std::wstringstream ss; + ss << s2ws(string); + ss >> str; +} + +std::string WinString::operator()() { + std::string res; + if (str != nullptr) { + std::wstring ss(str); + res = ws2s(ss); + } + return res; +} + +// 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) { + 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"); + WinString 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 diff --git a/src/directories.cc b/src/directories.cc index 0a269cc..1fe8459 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 @@ -121,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/files.h b/src/files.h index 28fb041..eee5f0d 100644 --- a/src/files.h +++ b/src/files.h @@ -2,6 +2,8 @@ #define JUCI_VERSION "0.9.4" +#define JUCI_ENV_SEARCH_LOCATIONS {"AppData", "HOME", "JUCI_HOME"} + const std::string configjson = "{\n" " \"version\": \""+std::string(JUCI_VERSION)+"\",\n" diff --git a/src/sourcefile.cc b/src/filesystem.cc similarity index 83% rename from src/sourcefile.cc rename to src/filesystem.cc index ef9fdd6..02d05fd 100644 --- a/src/sourcefile.cc +++ b/src/filesystem.cc @@ -1,11 +1,14 @@ -#include "sourcefile.h" #include +#include #include +#include "filesystem.h" +#include "logging.h" + const size_t buffer_size=131072; //Only use on small files -std::string juci::filesystem::read(const std::string &path) { +std::string filesystem::read(const std::string &path) { std::stringstream ss; std::ifstream input(path, std::ofstream::binary); if(input) { @@ -15,7 +18,7 @@ std::string juci::filesystem::read(const std::string &path) { return ss.str(); } -int juci::filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { +int filesystem::read(const std::string &path, Glib::RefPtr text_buffer) { std::ifstream input(path, std::ofstream::binary); if(input) { @@ -60,7 +63,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) { @@ -90,7 +93,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) { @@ -101,7 +104,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; @@ -111,7 +114,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 new file mode 100644 index 0000000..46bcc67 --- /dev/null +++ b/src/filesystem.h @@ -0,0 +1,29 @@ +#ifndef JUCI_SOURCEFILE_H_ +#define JUCI_SOURCEFILE_H_ +#include +#include +#include +#include + +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 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 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); } + +}; +#endif // JUCI_SOURCEFILE_H_ diff --git a/src/juci.cc b/src/juci.cc index fda51e8..a7cf2be 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -1,12 +1,12 @@ #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", + 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"); } @@ -38,8 +38,8 @@ int app::on_command_line(const Glib::RefPtr &cmd) { } void app::on_activate() { - 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 +64,7 @@ void app::on_activate() { } } for(auto &file: files) - window->notebook.open(file); + Singleton::window()->notebook.open(file); } void app::on_startup() { @@ -87,12 +87,12 @@ void app::on_startup() { } app::app() : Gtk::Application("no.sout.juci", Gio::APPLICATION_NON_UNIQUE | Gio::APPLICATION_HANDLES_COMMAND_LINE) { + init_logging(); Glib::set_application_name("juCi++"); Singleton::menu()->application=static_cast(this); //For Ubuntu 14... - window = std::unique_ptr(new Window()); + Singleton::window(); } int main(int argc, char *argv[]) { - init_logging(); return app().run(argc, argv); } diff --git a/src/juci.h b/src/juci.h index 46a07b8..fcf67b2 100644 --- a/src/juci.h +++ b/src/juci.h @@ -12,9 +12,9 @@ class app : public Gtk::Application { void on_startup(); private: - std::unique_ptr window; std::vector directories; std::vector files; + void init_logging(); }; #endif // JUCI_JUCI_H_ diff --git a/src/notebook.cc b/src/notebook.cc index ad33e19..ab044b5 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" @@ -170,7 +169,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 b4d1c82..1ca6c3b 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -4,8 +4,11 @@ std::unique_ptr Singleton::Config::source_=std::unique_ptr Singleton::Config::directories_=std::unique_ptr(new Directories::Config()); std::unique_ptr Singleton::Config::terminal_=std::unique_ptr(new Terminal::Config()); std::unique_ptr Singleton::Config::window_ = std::unique_ptr(new Window::Config()); +std::unique_ptr Singleton::Config::main_=std::unique_ptr(new MainConfig()); + std::unique_ptr Singleton::Config::menu_ = std::unique_ptr(new Menu::Config()); + std::unique_ptr Singleton::terminal_=std::unique_ptr(); Terminal *Singleton::terminal() { if(!terminal_) @@ -20,6 +23,13 @@ Directories *Singleton::directories() { return directories_.get(); } +std::unique_ptr Singleton::window_=std::unique_ptr(); +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 e72feca..4b4b234 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -1,21 +1,17 @@ - #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 - -#ifdef _WIN32 -#define HOME "AppData" -#else -#define HOME "HOME" -#endif +#include "window.h" +#include "config.h" class Singleton { public: @@ -26,6 +22,7 @@ public: static Window::Config *window() { return window_.get(); } static Terminal::Config *terminal() {return terminal_.get();} static Menu::Config *menu() {return menu_.get();} + static MainConfig *main() { return main_.get(); } private: static std::unique_ptr source_; @@ -33,21 +30,22 @@ public: static std::unique_ptr directories_; static std::unique_ptr terminal_; static std::unique_ptr menu_; + static std::unique_ptr main_; }; - 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 Terminal *terminal(); static Directories *directories(); static Gtk::Label *status(); static Gtk::Label *info(); static Menu *menu(); + 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 menu_; + static std::unique_ptr window_; }; #endif // JUCI_SINGLETONS_H_ diff --git a/src/source.cc b/src/source.cc index 3378d3c..de59144 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 @@ -86,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(); @@ -296,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::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/source.h b/src/source.h index bb7a308..f251297 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); diff --git a/src/source_clang.cc b/src/source_clang.cc index cba2025..533d7e7 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -1,6 +1,5 @@ #include "source_clang.h" #include "singletons.h" -#include "sourcefile.h" #include //TODO: remove using namespace std; //TODO: remove diff --git a/src/sourcefile.h b/src/sourcefile.h deleted file mode 100644 index 4507ab7..0000000 --- a/src/sourcefile.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef JUCI_SOURCEFILE_H_ -#define JUCI_SOURCEFILE_H_ -#include -#include -#include -#include "gtkmm.h" - -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); } - - 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 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); } - }; -} // namepace juci -#endif // JUCI_SOURCEFILE_H_ diff --git a/src/window.cc b/src/window.cc index 410d207..c1a4d56 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" @@ -127,8 +126,7 @@ Window::Window() : compiling(false) { } // Window constructor void Window::configure() { - MainConfig(); // Read the configs here - + Singleton::Config::main()->read(); 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); @@ -146,13 +144,12 @@ void Window::set_menu_actions() { about.present(); }); menu->add_action("preferences", [this]() { - notebook.open(Singleton::config_dir()+"config.json"); + notebook.open(Singleton::Config::main()->juci_home_path()/"config"/"config.json"); }); menu->add_action("quit", [this]() { hide(); }); - menu->add_action("new_file", [this]() { boost::filesystem::path path = Dialog::new_file(); if(path!="") { @@ -160,7 +157,7 @@ void Window::set_menu_actions() { 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()); @@ -173,17 +170,17 @@ void Window::set_menu_actions() { }); menu->add_action("new_folder", [this]() { auto time_now=std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - boost::filesystem::path path = Dialog::new_folder(); - if(path!="" && boost::filesystem::exists(path)) { - if(boost::filesystem::last_write_time(path)>=time_now) { - if(Singleton::directories()->current_path!="") - Singleton::directories()->update(); - Singleton::terminal()->print("New folder "+path.string()+" created.\n"); - } - else - Singleton::terminal()->print("Error: "+path.string()+" already exists.\n"); - Singleton::directories()->select(path); + boost::filesystem::path path = Dialog::new_folder(); + if(path!="" && boost::filesystem::exists(path)) { + if(boost::filesystem::last_write_time(path)>=time_now) { + if(Singleton::directories()->current_path!="") + Singleton::directories()->update(); + Singleton::terminal()->print("New folder "+path.string()+" created.\n"); } + else + Singleton::terminal()->print("Error: "+path.string()+" already exists.\n"); + Singleton::directories()->select(path); + } }); menu->add_action("new_project_cpp", [this]() { boost::filesystem::path project_path = Dialog::new_folder(); @@ -207,7 +204,7 @@ void Window::set_menu_actions() { } 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"); @@ -232,7 +229,7 @@ void Window::set_menu_actions() { if(notebook.get_current_page()!=-1) { 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::main()->juci_home_path()/"config"/"config.json") { configure(); for(int c=0;cconfigure(); @@ -262,7 +259,6 @@ void Window::set_menu_actions() { } }); - menu->add_action("edit_undo", [this]() { if(notebook.get_current_page()!=-1) { auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager(); @@ -308,7 +304,6 @@ void Window::set_menu_actions() { search_and_replace_entry(); }); - menu->add_action("source_spellcheck", [this]() { if(notebook.get_current_page()!=-1) notebook.get_current_view()->spellcheck(); @@ -436,7 +431,6 @@ void Window::set_menu_actions() { } }); - menu->add_action("compile_and_run", [this]() { if(notebook.get_current_page()==-1 || compiling) return; @@ -533,7 +527,6 @@ void Window::set_menu_actions() { Singleton::terminal()->kill_last_async_execute(true); }); - menu->add_action("next_tab", [this]() { if(notebook.get_current_page()!=-1) { notebook.open(notebook.get_view((notebook.get_current_page()+1)%notebook.size())->file_path);