diff --git a/src/gsc_init.cpp b/src/gsc_init.cpp index 7f73d98..80290f8 100644 --- a/src/gsc_init.cpp +++ b/src/gsc_init.cpp @@ -431,6 +431,8 @@ bool app_init_and_loop(int& argc, char**& argv) debug_out_info("app", "Current C locale: " << hz::locale_c_get() << "\n"); debug_out_info("app", "Current C++ locale: " << hz::locale_cpp_get() << "\n"); + debug_out_info("app", "Current working directory: " << Glib::get_current_dir() << "\n"); + #ifdef _WIN32 // Now that all program-specific locale setup has been performed, @@ -443,24 +445,28 @@ bool app_init_and_loop(int& argc, char**& argv) // This shows up in About dialog gtk. Glib::set_application_name(_("GSmartControl")); + // Check whether we're running from build directory, or it's a packaged program. + auto application_dir = hz::fs_get_application_dir(); + debug_out_info("app", "Application directory: " << application_dir << "\n"); + + bool is_from_source = !application_dir.empty() && hz::fs::exists((application_dir / "src")); // this covers standard cmake builds, but not VS. // Add data file search paths -#ifdef _WIN32 - hz::data_file_add_search_directory("icons", hz::fs::u8path(".")); // current dir, since shortcuts also use this icon. - hz::data_file_add_search_directory("ui", hz::fs::u8path("ui")); - hz::data_file_add_search_directory("doc", hz::fs::u8path("doc")); -#else - hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "icons"); // /usr/share/program_name/icons - hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "ui"); // /usr/share/program_name/ui - hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_DOC_DIR)); // /usr/share/doc/[packages/]gsmartcontrol -#endif - - // Paths in source tree -#ifdef DEBUG_BUILD - hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "data"); - hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "src/ui"); - hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "doc"); -#endif + if (is_from_source) { + hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "data"); + hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "src/ui"); + hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "doc"); + } else { + #ifdef _WIN32 + hz::data_file_add_search_directory("icons", application_dir); + hz::data_file_add_search_directory("ui", application_dir / "ui"); + hz::data_file_add_search_directory("doc", application_dir / "doc"); + #else + hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "icons"); // /usr/share/program_name/icons + hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "ui"); // /usr/share/program_name/ui + hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_DOC_DIR)); // /usr/share/doc/[packages/]gsmartcontrol + #endif + } #ifdef _WIN32 diff --git a/src/hz/CMakeLists.txt b/src/hz/CMakeLists.txt index 83d55c5..2a42782 100644 --- a/src/hz/CMakeLists.txt +++ b/src/hz/CMakeLists.txt @@ -36,6 +36,7 @@ target_link_libraries(hz # app_pcrecpp_interface app_gettext_interface # format_unit.h uses this libdebug # debug.h + whereami # whereami.h std::filesystem # fs_ns.h, linking to stdc++fs / c++fs if needed ) diff --git a/src/hz/fs.h b/src/hz/fs.h index a7598da..0dc21fc 100644 --- a/src/hz/fs.h +++ b/src/hz/fs.h @@ -20,6 +20,7 @@ Copyright: #include // off_t, fileno(), _fileno(), _wfopen() #include #include +#include #ifdef _WIN32 #include // _waccess*() @@ -39,6 +40,7 @@ Copyright: #endif #include "fs_ns.h" +#include "whereami.h" /// \def HAVE_POSIX_OFF_T_FUNCS @@ -419,6 +421,25 @@ inline fs::path fs_get_user_config_dir() +/// Get absolute path of the current executable +inline fs::path fs_get_application_dir() +{ + auto path_len = static_cast(wai_getExecutablePath(nullptr, 0, nullptr)); + if (path_len == 0) { + return {}; + } + std::vector vpath(path_len + 1); + + int dirname_length = 0; + + // In Windows the path is in utf-8. + wai_getExecutablePath(vpath.data(), int(path_len), &dirname_length); + + return {vpath.begin(), vpath.begin() + dirname_length}; +} + + + /// Check if the existing file can be fopen'ed with "rb", or the directory has read perms. /// Note: This function should be use only as an utility function (e.g. for GUI notification); /// other uses are not logically concurrent-safe (and therefore, insecure).