diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | include/DownloadUtils.hpp | 2 | ||||
-rw-r--r-- | include/Path.hpp | 5 | ||||
-rw-r--r-- | include/QuickMedia.hpp | 3 | ||||
-rw-r--r-- | plugins/FileManager.hpp | 3 | ||||
-rw-r--r-- | src/DownloadUtils.cpp | 11 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 58 | ||||
-rw-r--r-- | src/plugins/FileManager.cpp | 29 |
8 files changed, 71 insertions, 42 deletions
@@ -60,7 +60,7 @@ Press `Ctrl + V` to upload media to room in matrix if the clipboard contains a v Press `Ctrl + D` to remove the file that was previously selected with `U` in a 4chan thread.\ Press `Ctrl + I` to reverse image search the selected image on 4chan or matrix, or to select the url in the text to open in a browser.\ Press `Ctrl+Alt+Arrow up` / `Ctrl+Alt+Arrow down` or `Ctrl+Alt+K` / `Ctrl+Alt+J` to view the room above/below the selected room in matrix.\ -Press `Ctrl + S` to save the displaying image/video/audio (does currently not work for manga pages).\ +Press `Ctrl + S` to save the selected/displaying image/video/audio (does currently not work for manga pages).\ Press `Ctrl + Enter` to submit text, ignoring the selected item (when saving a file or selecting a server for matrix room directory).\ Press `Ctrl + Enter` to save the file to the selected directory with the selected name, when downloading a file. Text input in 4chan/matrix can be navigated with the arrow keys and if ctrl is pressed then the caret moves word by word. diff --git a/include/DownloadUtils.hpp b/include/DownloadUtils.hpp index 620b936..28684ef 100644 --- a/include/DownloadUtils.hpp +++ b/include/DownloadUtils.hpp @@ -30,6 +30,6 @@ namespace QuickMedia { // Note: This function saves the content to the file atomically DownloadResult download_to_file(const std::string &url, const std::string &destination_filepath, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false); // Returns false if there was an error trying to create the download process - bool download_async_gui(const std::string &url, bool use_youtube_dl, bool no_video); + bool download_async_gui(const std::string &url, const std::string &file_manager_start_dir, bool use_youtube_dl, bool no_video); DownloadResult download_to_json(const std::string &url, rapidjson::Document &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, bool fail_on_error = true); }
\ No newline at end of file diff --git a/include/Path.hpp b/include/Path.hpp index 571fb9e..fe49265 100644 --- a/include/Path.hpp +++ b/include/Path.hpp @@ -41,7 +41,10 @@ namespace QuickMedia { size_t slash_index = data.rfind('/'); if(slash_index != std::string::npos && slash_index > 0) return Path(data.substr(0, slash_index)); - return Path("/"); + if(!data.empty() && data[0] == '/') + return Path("/"); + else + return Path(""); } std::string data; diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp index 678451d..b2319ee 100644 --- a/include/QuickMedia.hpp +++ b/include/QuickMedia.hpp @@ -101,7 +101,7 @@ namespace QuickMedia { Json::Value load_video_history_json(); private: void init(Window parent_window, std::string &program_path); - void load_plugin_by_name(std::vector<Tab> &tabs, const char *start_dir, int &start_tab_index, FileManagerMimeType fm_mime_type, FileSelectionHandler file_selection_handler); + void load_plugin_by_name(std::vector<Tab> &tabs, int &start_tab_index, FileManagerMimeType fm_mime_type, FileSelectionHandler file_selection_handler); // Returns true if the window was closed bool handle_window_close(); void base_event_handler(sf::Event &event, PageType previous_page, Body *body, SearchBar *search_bar, bool handle_key_press = true, bool handle_searchbar = true); @@ -200,5 +200,6 @@ namespace QuickMedia { Window x11_window = None; Atom wm_delete_window_atom; XEvent xev; + std::filesystem::path file_manager_start_dir; }; }
\ No newline at end of file diff --git a/plugins/FileManager.hpp b/plugins/FileManager.hpp index e452c40..4e36b3c 100644 --- a/plugins/FileManager.hpp +++ b/plugins/FileManager.hpp @@ -27,6 +27,9 @@ namespace QuickMedia { bool set_current_directory(const std::string &path); const std::filesystem::path& get_current_directory() const { return current_dir; } PluginResult get_files_in_directory(BodyItems &result_items); + + // |fallback| is used if no directory has been accessed + static std::filesystem::path& get_last_accessed_directory(std::filesystem::path &fallback); private: std::filesystem::path current_dir; FileManagerMimeType mime_type; diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp index 7d2cbb8..b6d21b9 100644 --- a/src/DownloadUtils.cpp +++ b/src/DownloadUtils.cpp @@ -222,13 +222,12 @@ namespace QuickMedia { return DownloadResult::OK; } - bool download_async_gui(const std::string &url, bool use_youtube_dl, bool no_video) { - // TODO: Figure out why /proc/self/exe doesn't work when installed to /usr/bin/quickmedia - char quickmedia_path[PATH_MAX] = "quickmedia"; - //if(readlink("/proc/self/exe", quickmedia_path, sizeof(quickmedia_path)) == -1) - // return false; + bool download_async_gui(const std::string &url, const std::string &file_manager_start_dir, bool use_youtube_dl, bool no_video) { + char quickmedia_path[PATH_MAX]; + if(readlink("/proc/self/exe", quickmedia_path, sizeof(quickmedia_path)) == -1) + strcpy(quickmedia_path, "quickmedia"); - std::vector<const char*> args = { quickmedia_path, "download", "-u", url.c_str() }; + std::vector<const char*> args = { quickmedia_path, "download", "-u", url.c_str(), "--dir", file_manager_start_dir.c_str() }; if(use_youtube_dl) args.push_back("--youtube-dl"); if(no_video) args.push_back("--no-video"); args.push_back(nullptr); diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 498de29..e93536b 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -319,7 +319,7 @@ namespace QuickMedia { fprintf(stderr, " --use-system-mpv-config Use system mpv config instead of no config. Disabled by default\n"); fprintf(stderr, " --upscale-images Upscale low-resolution manga pages using waifu2x-ncnn-vulkan. Disabled by default\n"); fprintf(stderr, " --upscale-images-always Upscale manga pages using waifu2x-ncnn-vulkan, no matter what the original image resolution is. Disabled by default\n"); - fprintf(stderr, " --dir <directory> Set the start directory when using file-manager. Default is the user home directory\n"); + fprintf(stderr, " --dir <directory> Set the start directory when using file-manager. Default is the last accessed directory in QuickMedia or the users home directory\n"); fprintf(stderr, " -e <window> Embed QuickMedia into another window\n"); fprintf(stderr, "EXAMPLES:\n"); fprintf(stderr, " quickmedia launcher\n"); @@ -350,7 +350,6 @@ namespace QuickMedia { return -1; } - const char *start_dir = nullptr; Window parent_window = None; std::vector<Tab> tabs; const char *url = nullptr; @@ -377,7 +376,7 @@ namespace QuickMedia { upscale_image_action = UpscaleImageAction::FORCE; } else if(strcmp(argv[i], "--dir") == 0) { if(i < argc - 1) { - start_dir = argv[i + 1]; + file_manager_start_dir = argv[i + 1]; ++i; } else { fprintf(stderr, "Missing directory after --dir argument\n"); @@ -471,15 +470,9 @@ namespace QuickMedia { }); } - if(strcmp(plugin_name, "file-manager") != 0 && start_dir) { - fprintf(stderr, "Option --dir is only valid with file-manager\n"); - usage(); - return -1; - } - - Path home_dir = get_home_dir(); - if(!start_dir) - start_dir = home_dir.data.c_str(); + std::filesystem::path home_path = get_home_dir().data; + if(file_manager_start_dir.empty()) + file_manager_start_dir = FileManagerPage::get_last_accessed_directory(home_path); int start_tab_index = 0; FileManagerMimeType fm_mine_type = FILE_MANAGER_MIME_TYPE_ALL; @@ -510,7 +503,7 @@ namespace QuickMedia { file_selection_handler = std::move(saucenao_file_selection_handler); } - load_plugin_by_name(tabs, start_dir, start_tab_index, fm_mine_type, std::move(file_selection_handler)); + load_plugin_by_name(tabs, start_tab_index, fm_mine_type, std::move(file_selection_handler)); while(!tabs.empty() || matrix) { if(matrix) { @@ -535,7 +528,7 @@ namespace QuickMedia { fm_mine_type = FILE_MANAGER_MIME_TYPE_IMAGE; file_selection_handler = std::move(saucenao_file_selection_handler); } - load_plugin_by_name(tabs, start_dir, start_tab_index, fm_mine_type, std::move(file_selection_handler)); + load_plugin_by_name(tabs, start_tab_index, fm_mine_type, std::move(file_selection_handler)); } } @@ -671,6 +664,9 @@ namespace QuickMedia { if(create_directory_recursive(get_cache_dir().join("thumbnails")) != 0) throw std::runtime_error("Failed to create thumbnails directory"); + if(create_directory_recursive(get_storage_dir().join("file-manager")) != 0) + throw std::runtime_error("Failed to create file-manager directory"); + const char *qm_phone_factor = getenv("QM_PHONE_FACTOR"); if(qm_phone_factor && atoi(qm_phone_factor) == 1) show_room_side_panel = false; @@ -984,7 +980,7 @@ namespace QuickMedia { return PluginResult::OK; } - void Program::load_plugin_by_name(std::vector<Tab> &tabs, const char *start_dir, int &start_tab_index, FileManagerMimeType fm_mime_type, FileSelectionHandler file_selection_handler) { + void Program::load_plugin_by_name(std::vector<Tab> &tabs, int &start_tab_index, FileManagerMimeType fm_mime_type, FileSelectionHandler file_selection_handler) { if(!plugin_name || plugin_name[0] == '\0') return; @@ -1116,11 +1112,8 @@ namespace QuickMedia { tabs.push_back(Tab{std::move(boards_body), std::move(boards_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); } else if(strcmp(plugin_name, "file-manager") == 0) { auto file_manager_page = std::make_unique<FileManagerPage>(this, fm_mime_type, file_selection_handler); - if(start_dir && !file_manager_page->set_current_directory(start_dir)) { - fprintf(stderr, "Invalid directory provided with --dir: %s\n", start_dir); - exit_code = -3; - return; - } + if(!file_manager_page->set_current_directory(file_manager_start_dir)) + fprintf(stderr, "Warning: Invalid directory provided with --dir\n"); auto file_manager_body = create_body(); file_manager_page->get_files_in_directory(file_manager_body->items); tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); @@ -2453,7 +2446,7 @@ namespace QuickMedia { } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::C && event.key.control) { save_video_url_to_clipboard(); } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::S && event.key.control) { - download_async_gui(original_video_url, !is_matrix, no_video); + download_async_gui(original_video_url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), !is_matrix, no_video); } } handle_window_close(); @@ -2470,7 +2463,7 @@ namespace QuickMedia { } else if(pressed_keysym == XK_f && pressing_ctrl) { window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE); } else if(pressed_keysym == XK_s && pressing_ctrl) { - download_async_gui(original_video_url, !is_matrix, no_video); + download_async_gui(original_video_url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), !is_matrix, no_video); } else if(pressed_keysym == XK_r && pressing_ctrl) { if(!cursor_visible) window.setMouseCursorVisible(true); @@ -3411,8 +3404,9 @@ namespace QuickMedia { } } } else if(event.key.code == sf::Keyboard::U) { + std::filesystem::path &fm_dir = FileManagerPage::get_last_accessed_directory(file_manager_start_dir); auto file_manager_page = std::make_unique<FileManagerPage>(this, (FileManagerMimeType)(FILE_MANAGER_MIME_TYPE_IMAGE|FILE_MANAGER_MIME_TYPE_VIDEO)); - file_manager_page->set_current_directory(get_home_dir().data); + file_manager_page->set_current_directory(fm_dir.string()); auto file_manager_body = create_body(); file_manager_page->get_files_in_directory(file_manager_body->items); std::vector<Tab> file_manager_tabs; @@ -3453,6 +3447,10 @@ namespace QuickMedia { redraw = true; frame_skip_text_entry = true; } + } else if(event.key.code == sf::Keyboard::S && event.key.control) { + BodyItem *selected_item = thread_body->get_selected(); + if(selected_item && !selected_item->url.empty()) + download_async_gui(selected_item->url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), false, false); } BodyItem *selected_item = thread_body->get_selected(); @@ -3572,7 +3570,7 @@ namespace QuickMedia { redraw = true; frame_skip_text_entry = true; } else if(event.key.code == sf::Keyboard::S && event.key.control) { - download_async_gui(attached_image_url, false, false); + download_async_gui(attached_image_url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), false, false); } } } @@ -4965,7 +4963,7 @@ namespace QuickMedia { redraw = true; return true; } else if(message_type == MessageType::FILE) { - download_async_gui(selected->url, false, no_video); + download_async_gui(selected->url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), false, no_video); return true; } @@ -5006,7 +5004,7 @@ namespace QuickMedia { if(selected_item_message) { MessageType message_type = selected_item_message->type; if(!selected->url.empty() && message_type >= MessageType::IMAGE && message_type <= MessageType::FILE) { - download_async_gui(selected->url, false, no_video); + download_async_gui(selected->url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), false, no_video); return true; } } @@ -5436,8 +5434,9 @@ namespace QuickMedia { tab.body->clear_cache(); } + std::filesystem::path &fm_dir = FileManagerPage::get_last_accessed_directory(file_manager_start_dir); auto file_manager_page = std::make_unique<FileManagerPage>(this); - file_manager_page->set_current_directory(get_home_dir().data); + file_manager_page->set_current_directory(fm_dir.string()); auto file_manager_body = create_body(); file_manager_page->get_files_in_directory(file_manager_body->items); std::vector<Tab> file_manager_tabs; @@ -6510,14 +6509,13 @@ namespace QuickMedia { sf::Event event; auto file_manager_page = std::make_unique<FileManagerPage>(this); - std::string home_dir = get_home_dir().data; - file_manager_page->set_current_directory(home_dir); + file_manager_page->set_current_directory(file_manager_start_dir); auto file_manager_body = create_body(); file_manager_page->get_files_in_directory(file_manager_body->items); auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER); Tabs ui_tabs(&rounded_rectangle_shader); - const int tab_path_index = ui_tabs.add_tab(home_dir); + const int tab_path_index = ui_tabs.add_tab(file_manager_start_dir); search_bar->onTextUpdateCallback = [&file_manager_body](const std::string &text) { file_manager_body->filter_search_fuzzy(text); diff --git a/src/plugins/FileManager.cpp b/src/plugins/FileManager.cpp index 5ca7dc7..2207c65 100644 --- a/src/plugins/FileManager.cpp +++ b/src/plugins/FileManager.cpp @@ -4,6 +4,16 @@ #include "../../include/QuickMedia.hpp" namespace QuickMedia { + static bool last_accessed_dir_loaded = false; + static std::filesystem::path last_accessed_dir; + static Path last_accessed_dir_path; + static void set_last_accessed_dir(const std::filesystem::path &path) { + if(last_accessed_dir_path.data.empty()) + last_accessed_dir_path = get_storage_dir().join("file-manager").join("last_accessed_dir"); + file_overwrite_atomic(last_accessed_dir_path, path.string()); + last_accessed_dir = path; + } + // Returns empty string if no extension static const char* get_ext(const std::filesystem::path &path) { const char *path_c = path.c_str(); @@ -50,6 +60,7 @@ namespace QuickMedia { if(result != PluginResult::OK) return result; + set_last_accessed_dir(current_dir); auto body = create_body(); body->items = std::move(result_items); result_tabs.push_back(Tab{std::move(body), nullptr, nullptr}); @@ -57,9 +68,8 @@ namespace QuickMedia { } bool FileManagerPage::set_current_directory(const std::string &path) { - if(!std::filesystem::is_directory(path)) - return false; current_dir = path; + set_last_accessed_dir(current_dir); return true; } @@ -144,4 +154,19 @@ namespace QuickMedia { return PluginResult::OK; } + + // static + std::filesystem::path& FileManagerPage::get_last_accessed_directory(std::filesystem::path &fallback) { + if(!last_accessed_dir_loaded) { + last_accessed_dir_loaded = true; + std::string last_accessed_dir_str; + file_get_content(get_storage_dir().join("file-manager").join("last_accessed_dir"), last_accessed_dir_str); + last_accessed_dir = std::move(last_accessed_dir_str); + } + + if(last_accessed_dir.empty()) + return fallback; + else + return last_accessed_dir; + } }
\ No newline at end of file |