aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-11 14:24:52 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-11 14:24:52 +0200
commite308d77b06405b91885cf6f97c0dc2a1b70679ef (patch)
tree7fb0ed73c20354f3e0ff49ebb199e33ebc3427f7 /src
parent6b90f55f4dc14b9d39fa0dbf6b82b3c12ccc29d9 (diff)
Improve file saving gui
Diffstat (limited to 'src')
-rw-r--r--src/Body.cpp2
-rw-r--r--src/DownloadUtils.cpp1
-rw-r--r--src/Entry.cpp22
-rw-r--r--src/QuickMedia.cpp298
-rw-r--r--src/RoundedRectangle.cpp13
-rw-r--r--src/SearchBar.cpp39
-rw-r--r--src/Text.cpp7
-rw-r--r--src/gui/Button.cpp76
-rw-r--r--src/plugins/FileManager.cpp16
-rw-r--r--src/plugins/Mangadex.cpp2
10 files changed, 381 insertions, 95 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 9494e80..c186b9c 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -335,7 +335,6 @@ namespace QuickMedia {
void Body::clear_cache() {
clear_text_cache();
clear_thumbnails();
- malloc_trim(0);
}
void Body::clear_text_cache() {
@@ -348,6 +347,7 @@ namespace QuickMedia {
void Body::clear_thumbnails() {
item_thumbnail_textures.clear();
+ malloc_trim(0);
}
BodyItem* Body::get_selected() const {
diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp
index bb60ad6..248fda0 100644
--- a/src/DownloadUtils.cpp
+++ b/src/DownloadUtils.cpp
@@ -1,6 +1,7 @@
#include "../include/DownloadUtils.hpp"
#include "../include/Program.hpp"
#include "../include/Storage.hpp"
+#include "../include/NetUtils.hpp"
#include "../external/cppcodec/base64_url.hpp"
#include <unistd.h>
#include <limits.h>
diff --git a/src/Entry.cpp b/src/Entry.cpp
index 96a34f3..5e18340 100644
--- a/src/Entry.cpp
+++ b/src/Entry.cpp
@@ -7,7 +7,7 @@
#include <cmath>
const float background_margin_horizontal = std::floor(5.0f * QuickMedia::get_ui_scale());
-const float padding_vertical = std::floor(3.0f * QuickMedia::get_ui_scale());
+const float padding_vertical = std::floor(5.0f * QuickMedia::get_ui_scale());
const float background_margin_vertical = std::floor(0.0f * QuickMedia::get_ui_scale());
namespace QuickMedia {
@@ -16,7 +16,7 @@ namespace QuickMedia {
draw_background(true),
text("", false, std::floor(16 * get_ui_scale()), 0.0f),
width(0.0f),
- background(sf::Vector2f(1.0f, 1.0f), 7.0f, sf::Color(55, 60, 68), rounded_rectangle_shader),
+ background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(55, 60, 68), rounded_rectangle_shader),
placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())),
mouse_left_inside(false)
{
@@ -74,6 +74,10 @@ namespace QuickMedia {
}
}
+ void Entry::set_single_line(bool single_line) {
+ text.single_line_edit = single_line;
+ }
+
void Entry::set_editable(bool editable) {
text.setEditable(editable);
}
@@ -93,8 +97,8 @@ namespace QuickMedia {
void Entry::set_position(const sf::Vector2f &pos) {
background.set_position(pos);
- text.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical - std::floor(3.0f * get_ui_scale())));
- placeholder.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical + std::floor(3.0f * get_ui_scale())));
+ text.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical));
+ placeholder.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical));
}
void Entry::set_max_width(float width) {
@@ -102,8 +106,16 @@ namespace QuickMedia {
text.setMaxWidth(this->width - background_margin_horizontal * 2.0f);
}
+ bool Entry::is_editable() const {
+ return text.isEditable();
+ }
+
float Entry::get_height() {
text.updateGeometry();
- return std::floor(text.getHeight() + background_margin_vertical * 2.0f + padding_vertical *2.0f);
+ return std::floor(text.getHeight() + background_margin_vertical * 2.0f + padding_vertical * 2.0f);
+ }
+
+ const sf::String& Entry::get_text() const {
+ return text.getString();
}
} \ No newline at end of file
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index b4fa915..13b9369 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -29,6 +29,7 @@
#include "../include/ResourceLoader.hpp"
#include "../include/Utils.hpp"
#include "../include/Tabs.hpp"
+#include "../include/gui/Button.hpp"
#include "../external/hash-library/sha256.h"
#include <assert.h>
@@ -599,7 +600,7 @@ namespace QuickMedia {
window.create(x11_window);
- if(program_path.back() != '/')
+ if(!program_path.empty() && program_path.back() != '/')
program_path += '/';
resources_root = "/usr/share/quickmedia/";
@@ -1531,6 +1532,7 @@ namespace QuickMedia {
if(tabs[selected_tab].page->is_single_page()) {
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->clear();
if(new_tabs.size() == 1 && !new_tabs[0].page) {
+ tabs[selected_tab].body->clear_thumbnails();
tabs[selected_tab].body = std::move(new_tabs[0].body);
tabs[selected_tab].page->submit_body_item = prev_selected_item;
return;
@@ -1854,6 +1856,7 @@ namespace QuickMedia {
if(associated_data.fetch_status == FetchStatus::LOADING && associated_data.fetch_type == FetchType::SEARCH && associated_data.fetch_future.ready()) {
if(!associated_data.search_text_updated) {
FetchResult fetch_result = associated_data.fetch_future.get();
+ tabs[i].body->clear_thumbnails();
tabs[i].body->items = std::move(fetch_result.body_items);
tabs[i].body->select_first_item();
associated_data.fetched_page = 0;
@@ -2270,7 +2273,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, true, force_no_video);
+ download_async_gui(original_video_url, true, no_video);
}
}
handle_window_close();
@@ -2287,7 +2290,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, true, force_no_video);
+ download_async_gui(original_video_url, true, no_video);
} else if(pressed_keysym == XK_r && pressing_ctrl) {
if(!cursor_visible)
window.setMouseCursorVisible(true);
@@ -2595,7 +2598,7 @@ namespace QuickMedia {
};
} else if(website_url && website_url[0] != '\0') {
std::string website_url_str = website_url;
- if(website_url_str.back() != '/')
+ if(!website_url_str.empty() && website_url_str.back() != '/')
website_url_str.push_back('/');
extra_args = {
CommandArg { "-H", "referer: " + std::move(website_url_str) },
@@ -4733,7 +4736,7 @@ namespace QuickMedia {
if(selected_item_message) {
MessageType message_type = selected_item_message->type;
if(!selected->url.empty() && (message_type == MessageType::VIDEO || message_type == MessageType::IMAGE || message_type == MessageType::AUDIO)) {
- download_async_gui(selected->url, false, force_no_video);
+ download_async_gui(selected->url, false, no_video);
return true;
}
}
@@ -5919,60 +5922,57 @@ namespace QuickMedia {
bool no_video;
};
- static const char* get_filename(const char *path) {
- const char *p = (const char*)memrchr(path, '/', strlen(path));
- return p ? p + 1 : path;
+ static int accumulate_string(char *data, int size, void *userdata) {
+ std::string *str = (std::string*)userdata;
+ if(str->size() + size > 1024 * 1024 * 100) // 100mb sane limit, TODO: make configurable
+ return 1;
+ str->append(data, size);
+ return 0;
}
- class ConfirmationPage : public Page {
- public:
- ConfirmationPage(Program *program, FileManagerPage *file_manager_page, bool *file_overwrite, const std::string &title) : Page(program), file_manager_page(file_manager_page), file_overwrite(file_overwrite), title(title) {}
- const char* get_title() const override { return title.c_str(); }
- PluginResult submit(const std::string &title, const std::string&, std::vector<Tab>&) override {
- if(title == "Yes") {
- *file_overwrite = true;
- file_manager_page->close = true;
- } else {
- *file_overwrite = false;
+ void Program::download_page(const char *url, bool download_use_youtube_dl) {
+ window.setTitle("QuickMedia - Select where you want to save " + std::string(url));
+
+ std::string filename;
+ TaskResult task_result = run_task_with_loading_screen([this, url, &filename]{
+ std::string json_str;
+ std::vector<const char*> args = { "youtube-dl", "--skip-download", "--print-json", "--no-warnings" };
+ if(no_video)
+ args.push_back("-x");
+ args.insert(args.end(), { "--", url, nullptr });
+ if(exec_program(args.data(), accumulate_string, &json_str) != 0)
+ return false;
+
+ Json::Value result;
+ Json::CharReaderBuilder json_builder;
+ std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
+ std::string json_errors;
+ if(!json_reader->parse(json_str.data(), json_str.data() + json_str.size(), &result, &json_errors)) {
+ fprintf(stderr, "Failed to json response, error: %s\n", json_errors.c_str());
+ return false;
}
- program->set_go_to_previous_page();
- return PluginResult::OK;
- }
- static void add_items(BodyItems &items) {
- items.push_back(BodyItem::create("No"));
- items.push_back(BodyItem::create("Yes"));
- }
- private:
- FileManagerPage *file_manager_page;
- bool *file_overwrite;
- std::string title;
- };
+ const Json::Value &title_json = result["title"];
+ const Json::Value &ext_json = result["ext"];
+ if(title_json.isString())
+ filename = title_json.asString();
- void Program::download_page(const char *url, bool download_use_youtube_dl) {
- bool file_overwrite = true;
- FileSelectionHandler overwrite_confirm_handler = [this, &file_overwrite](FileManagerPage *file_manager_page, const std::filesystem::path &path) {
- file_overwrite = true;
- std::vector<Tab> tabs;
- if(std::filesystem::exists(path)) {
- auto body = create_body();
- ConfirmationPage::add_items(body->items);
- tabs.push_back(Tab{ std::move(body), std::make_unique<ConfirmationPage>(this, file_manager_page, &file_overwrite, "Are you sure you want to overwrite " + path.string() + "?"), nullptr });
+ if(ext_json.isString()) {
+ if(ext_json.asCString()[0] != '.' && (filename.empty() || filename.back() != '.'))
+ filename += ".";
+ filename += ext_json.asString();
}
- return tabs;
- };
- auto file_manager_page = std::make_unique<FileManagerPage>(this, FILE_MANAGER_MIME_TYPE_ALL, std::move(overwrite_confirm_handler), true, "Where do you want to save the file? Current directory: ");
- file_manager_page->set_current_directory(get_home_dir().data);
- auto file_manager_body = create_body();
- file_manager_page->get_files_in_directory(file_manager_body->items);
- std::vector<Tab> file_manager_tabs;
- file_manager_tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ return !filename.empty();
+ });
- selected_files.clear();
- page_loop(file_manager_tabs);
+ if(task_result == TaskResult::CANCEL) {
+ exit_code = 1;
+ return;
+ }
- if(!window.isOpen() || selected_files.empty() || !file_overwrite) {
+ std::string output_filepath = file_save_page(filename);
+ if(!window.isOpen() || output_filepath.empty()) {
exit_code = 1;
return;
}
@@ -5998,7 +5998,6 @@ namespace QuickMedia {
}
window.setPosition(sf::Vector2i(focused_monitor_center.x - window_size.x * 0.5f, focused_monitor_center.y - window_size.y * 0.5f));
- std::string output_filepath = selected_files[0];
std::string output_filepath_s = output_filepath;
char *output_dir = dirname(output_filepath_s.data());
if(create_directory_recursive(output_dir) != 0) {
@@ -6022,7 +6021,7 @@ namespace QuickMedia {
sf::Text progress_text("0kb/Unknown", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_ui_scale()));
sf::Text status_text("Downloading", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_ui_scale()));
- sf::Text filename_text(get_filename(output_filepath.c_str()), *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_ui_scale()));
+ sf::Text filename_text(filename.c_str(), *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_ui_scale()));
filename_text.setFillColor(sf::Color(179, 179, 179));
sf::Text download_speed_text("0 bytes/s", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_ui_scale()));
download_speed_text.setFillColor(sf::Color(179, 179, 179));
@@ -6032,7 +6031,7 @@ namespace QuickMedia {
std::unique_ptr<Downloader> downloader;
if(download_use_youtube_dl)
- downloader = std::make_unique<YoutubeDlDownloader>(url, output_filepath, force_no_video);
+ downloader = std::make_unique<YoutubeDlDownloader>(url, output_filepath, no_video);
else
downloader = std::make_unique<CurlDownloader>(url, output_filepath);
@@ -6139,4 +6138,197 @@ namespace QuickMedia {
}
exit(exit_code);
}
+
+ class ConfirmationPage : public Page {
+ public:
+ ConfirmationPage(Program *program, bool *file_overwrite, const std::string &title) : Page(program), file_overwrite(file_overwrite), title(title) {}
+ const char* get_title() const override { return title.c_str(); }
+ PluginResult submit(const std::string &title, const std::string&, std::vector<Tab>&) override {
+ if(title == "Yes")
+ *file_overwrite = true;
+ else
+ *file_overwrite = false;
+
+ program->set_go_to_previous_page();
+ return PluginResult::OK;
+ }
+
+ static void add_items(BodyItems &items) {
+ items.push_back(BodyItem::create("No"));
+ items.push_back(BodyItem::create("Yes"));
+ }
+ private:
+ bool *file_overwrite;
+ std::string title;
+ };
+
+ std::string Program::file_save_page(const std::string &filename) {
+ sf::Vector2f body_pos;
+ sf::Vector2f body_size;
+ bool redraw = true;
+ 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);
+ 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);
+
+ search_bar->onTextUpdateCallback = [&file_manager_body](const std::string &text) {
+ file_manager_body->filter_search_fuzzy(text);
+ file_manager_body->select_first_item();
+ };
+
+ search_bar->onTextSubmitCallback = [this, &search_bar, &file_manager_body, &file_manager_page, &ui_tabs, tab_path_index](const std::string&) {
+ if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
+ return;
+
+ BodyItem *selected = file_manager_body->get_selected();
+ if(!selected)
+ return;
+
+ std::vector<Tab> new_tabs;
+ TaskResult task_result = run_task_with_loading_screen([selected, &file_manager_page, &new_tabs]() {
+ return file_manager_page->submit(selected->get_title(), selected->url, new_tabs) == PluginResult::OK;
+ });
+
+ if(task_result == TaskResult::TRUE) {
+ if(!new_tabs.empty()) {
+ file_manager_body->clear_thumbnails();
+ file_manager_body->items = std::move(new_tabs[0].body->items);
+ }
+ } else if(task_result == TaskResult::FALSE) {
+ show_notification("QuickMedia", "Failed to change directory", Urgency::CRITICAL);
+ }
+
+ search_bar->clear();
+ ui_tabs.set_text(tab_path_index, file_manager_page->get_current_directory().string());
+ };
+
+ const float bottom_panel_padding = 10.0f;
+ const float bottom_panel_spacing = 10.0f;
+
+ Button cancel_button("Cancel", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_ui_scale());
+ cancel_button.set_background_color(sf::Color(104, 2, 2));
+
+ Button save_button("Save", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_ui_scale());
+ save_button.set_background_color(sf::Color(35, 35, 236));
+
+ sf::Text file_name_label("File name:", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16.0f * get_ui_scale()));
+
+ Entry file_name_entry("", &rounded_rectangle_shader);
+ file_name_entry.set_text(filename);
+ file_name_entry.set_single_line(true);
+ file_name_entry.set_editable(false);
+
+ sf::RectangleShape bottom_panel_background;
+ bottom_panel_background.setFillColor(sf::Color(33, 37, 44));
+
+ auto save_file = [this, &file_name_entry, &file_manager_page]() -> std::string {
+ auto u8 = file_name_entry.get_text().toUtf8();
+ std::string *filename = (std::string*)&u8;
+
+ Path filename_full_path = file_manager_page->get_current_directory().string();
+ filename_full_path.join(*filename);
+
+ if(filename->empty()) {
+ show_notification("QuickMedia", "The file name can't be empty", Urgency::CRITICAL);
+ } else if(*filename == "." || *filename == ".." || filename->find('/') != std::string::npos) {
+ show_notification("QuickMedia", "Invalid file name. File can't be ., .. or contain /", Urgency::CRITICAL);
+ } else if(filename->size() >= 255 || filename_full_path.data.size() >= 4096) {
+ show_notification("QuickMedia", "The file name has to be less than 255 characters and the full path has to be less than 4096 characters", Urgency::CRITICAL);
+ } else {
+ if(std::filesystem::exists(filename_full_path.data)) {
+ bool overwrite = false;
+ std::vector<Tab> tabs;
+ auto body = create_body();
+ ConfirmationPage::add_items(body->items);
+ tabs.push_back(Tab{ std::move(body), std::make_unique<ConfirmationPage>(this, &overwrite, "Are you sure you want to overwrite " + filename_full_path.data + "?"), nullptr });
+ page_loop(tabs);
+ if(overwrite)
+ return std::move(filename_full_path.data);
+ } else {
+ return std::move(filename_full_path.data);
+ }
+ }
+
+ return "";
+ };
+
+ while (window.isOpen()) {
+ while (window.pollEvent(event)) {
+ if(file_manager_body->on_event(window, event, !file_name_entry.is_editable()))
+ idle_active_handler();
+ else
+ event_idle_handler(event);
+
+ search_bar->on_event(event);
+ if(cancel_button.on_event(event) & BUTTON_EVENT_CLICKED)
+ return "";
+ if(save_button.on_event(event) & BUTTON_EVENT_CLICKED) {
+ std::string save_path = save_file();
+ if(!save_path.empty())
+ return save_path;
+ }
+ file_name_entry.process_event(event);
+
+ if(event.type == sf::Event::Resized) {
+ window_size.x = event.size.width;
+ window_size.y = event.size.height;
+ sf::FloatRect visible_area(0, 0, window_size.x, window_size.y);
+ window.setView(sf::View(visible_area));
+ redraw = true;
+ idle_active_handler();
+ } else if(event.type == sf::Event::GainedFocus) {
+ redraw = true;
+ } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Tab) {
+ file_name_entry.set_editable(!file_name_entry.is_editable());
+ search_bar->set_editable(!file_name_entry.is_editable());
+ } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && event.key.control) {
+ std::string save_path = save_file();
+ if(!save_path.empty())
+ return save_path;
+ }
+ }
+
+ update_idle_state();
+ handle_window_close();
+ search_bar->update();
+
+ if(redraw) {
+ redraw = false;
+ get_body_dimensions(window_size, search_bar.get(), body_pos, body_size);
+ body_pos.y += std::floor(10.0f * get_ui_scale()) + Tabs::get_height();
+ body_size.y -= std::floor(10.0f * get_ui_scale()) + Tabs::get_height();
+ save_button.set_position(window_size - sf::Vector2f(save_button.get_width(), save_button.get_height()) - sf::Vector2f(bottom_panel_padding, bottom_panel_padding));
+ cancel_button.set_position(save_button.get_position() - sf::Vector2f(cancel_button.get_width() + bottom_panel_spacing, 0.0f));
+ file_name_label.setPosition(sf::Vector2f(bottom_panel_spacing, std::floor(window_size.y - bottom_panel_padding - file_name_entry.get_height() * 0.5f - file_name_label.getLocalBounds().height * 0.5f - 5.0f * get_ui_scale())));
+ file_name_entry.set_position(sf::Vector2f(file_name_label.getPosition().x + file_name_label.getLocalBounds().width + bottom_panel_spacing, window_size.y - file_name_entry.get_height() - bottom_panel_padding));
+ file_name_entry.set_max_width(std::floor(cancel_button.get_position().x - bottom_panel_spacing - file_name_label.getLocalBounds().width - bottom_panel_spacing - bottom_panel_spacing));
+ bottom_panel_background.setPosition(0.0f, window_size.y - std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height()));
+ bottom_panel_background.setSize(sf::Vector2f(window_size.x, std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height())));
+ }
+
+ window.clear(back_color);
+
+ ui_tabs.draw(window, sf::Vector2f(0.0f, search_bar->getBottomWithoutShadow()), window_size.x);
+ search_bar->draw(window, window_size, true);
+
+ file_manager_body->draw(window, body_pos, body_size - sf::Vector2f(0.0f, bottom_panel_background.getSize().y));
+
+ window.draw(bottom_panel_background);
+ window.draw(file_name_label);
+ cancel_button.draw(window);
+ save_button.draw(window);
+ file_name_entry.draw(window);
+
+ window.display();
+ }
+
+ return "";
+ }
}
diff --git a/src/RoundedRectangle.cpp b/src/RoundedRectangle.cpp
index 6b956e8..4b06ea8 100644
--- a/src/RoundedRectangle.cpp
+++ b/src/RoundedRectangle.cpp
@@ -1,6 +1,6 @@
#include "../include/RoundedRectangle.hpp"
#include <SFML/Graphics/Shader.hpp>
-#include <SFML/Graphics/RenderWindow.hpp>
+#include <SFML/Graphics/RenderTarget.hpp>
#include <assert.h>
namespace QuickMedia {
@@ -30,6 +30,13 @@ namespace QuickMedia {
set_position(pos);
}
+ void RoundedRectangle::set_color(sf::Color color) {
+ vertices[0].color = color;
+ vertices[1].color = color;
+ vertices[2].color = color;
+ vertices[3].color = color;
+ }
+
sf::Vector2f RoundedRectangle::get_position() const {
return pos;
}
@@ -38,9 +45,9 @@ namespace QuickMedia {
return size;
}
- void RoundedRectangle::draw(sf::RenderWindow &window) {
+ void RoundedRectangle::draw(sf::RenderTarget &target) {
rounded_rectangle_shader->setUniform("resolution", size);
rounded_rectangle_shader->setUniform("radius", radius);
- window.draw(vertices, 4, sf::Quads, rounded_rectangle_shader);
+ target.draw(vertices, 4, sf::Quads, rounded_rectangle_shader);
}
} \ No newline at end of file
diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp
index 8362864..7d7f72d 100644
--- a/src/SearchBar.cpp
+++ b/src/SearchBar.cpp
@@ -82,7 +82,7 @@ namespace QuickMedia {
caret.setPosition(text.findCharacterPos(text.getString().getSize()) + sf::Vector2f(0.0f, 2.0f));
}
- if(caret_visible)
+ if(caret_visible && is_editable())
window.draw(caret);
if(draw_logo)
@@ -90,6 +90,22 @@ namespace QuickMedia {
}
void SearchBar::on_event(sf::Event &event) {
+ if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
+ sf::FloatRect box(background.get_position(), background.get_size());
+ if(box.contains(event.mouseButton.x, event.mouseButton.y))
+ mouse_left_inside = true;
+ else
+ mouse_left_inside = false;
+ } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) {
+ sf::FloatRect box(background.get_position(), background.get_size());
+ if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y))
+ show_virtual_keyboard();
+ mouse_left_inside = false;
+ }
+
+ if(!editable)
+ return;
+
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace)
backspace_pressed = true;
else if(event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Backspace)
@@ -110,19 +126,6 @@ namespace QuickMedia {
onTextEntered(event.text.unicode);
else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace)
onTextEntered(8);
-
- if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
- sf::FloatRect box(background.get_position(), background.get_size());
- if(box.contains(event.mouseButton.x, event.mouseButton.y))
- mouse_left_inside = true;
- else
- mouse_left_inside = false;
- } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) {
- sf::FloatRect box(background.get_position(), background.get_size());
- if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y))
- show_virtual_keyboard();
- mouse_left_inside = false;
- }
}
void SearchBar::update() {
@@ -303,6 +306,14 @@ namespace QuickMedia {
}
}
+ void SearchBar::set_editable(bool editable) {
+ this->editable = editable;
+ }
+
+ bool SearchBar::is_editable() const {
+ return editable;
+ }
+
void SearchBar::clear_autocomplete_if_text_not_substring() {
const sf::String &text_str = text.getString();
const sf::String &autocomplete_str = autocomplete_text.getString();
diff --git a/src/Text.cpp b/src/Text.cpp
index 0431c4e..2940520 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -60,10 +60,11 @@ namespace QuickMedia
{
//if(str != this->str)
//{
+ size_t prev_str_size = this->str.getSize();
this->str = std::move(str);
dirty = true;
dirtyText = true;
- if((int)this->str.getSize() < caretIndex)
+ if((int)this->str.getSize() < caretIndex || prev_str_size == 0)
{
caretIndex = this->str.getSize();
dirtyCaret = true;
@@ -821,7 +822,7 @@ namespace QuickMedia
}
else if(event.key.code == sf::Keyboard::Enter)
{
- if(event.key.shift)
+ if(event.key.shift && !single_line_edit)
{
if(caretAtEnd)
str += '\n';
@@ -849,7 +850,7 @@ namespace QuickMedia
{
stringToAdd = sf::Clipboard::getString();
}
- else if(event.text.unicode >= 32 || event.text.unicode == 9) // 9 == tab
+ else if(event.text.unicode >= 32 || (event.text.unicode == 9 && !single_line_edit)) // 9 == tab
stringToAdd = event.text.unicode;
else
return;
diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp
new file mode 100644
index 0000000..ebbb8bb
--- /dev/null
+++ b/src/gui/Button.cpp
@@ -0,0 +1,76 @@
+#include "../../include/gui/Button.hpp"
+#include <SFML/Graphics/RenderTarget.hpp>
+#include <SFML/Window/Event.hpp>
+#include <cmath>
+
+namespace QuickMedia {
+ static const float PADDING_Y = 10.0f;
+
+ Button::Button(const std::string &label, sf::Font *font, unsigned int character_size, float width, sf::Shader *rounded_rectangle_shader, float scale) :
+ label(label, *font, character_size * scale),
+ background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(33, 37, 44), rounded_rectangle_shader),
+ scale(scale)
+ {
+ background.set_size(sf::Vector2f(std::floor(width * scale), get_height()));
+ set_position(sf::Vector2f(0.0f, 0.0f));
+ }
+
+ ButtonEvent Button::on_event(sf::Event &event) {
+ ButtonEvent performed_event = BUTTON_EVENT_NONE;
+ if(event.type == sf::Event::MouseMoved) {
+ if(sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseMove.x, event.mouseMove.y)) {
+ const int inc = 20;
+ background.set_color(sf::Color(
+ std::min(255, (int)background_color.r + inc),
+ std::min(255, (int)background_color.g + inc),
+ std::min(255, (int)background_color.b + inc)));
+ } else {
+ background.set_color(background_color);
+ }
+ } else if(event.type == sf::Event::MouseButtonPressed) {
+ if(event.mouseButton.button == sf::Mouse::Left && sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseButton.x, event.mouseButton.y)) {
+ clicked_inside = true;
+ } else {
+ clicked_inside = false;
+ }
+ } else if(event.type == sf::Event::MouseButtonReleased) {
+ if(clicked_inside && event.mouseButton.button == sf::Mouse::Left && sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseButton.x, event.mouseButton.y)) {
+ performed_event = BUTTON_EVENT_CLICKED;
+ }
+ clicked_inside = false;
+ }
+ return performed_event;
+ }
+
+ void Button::draw(sf::RenderTarget &target) {
+ background.draw(target);
+ target.draw(label);
+ }
+
+ void Button::set_background_color(sf::Color color) {
+ background_color = color;
+ background.set_color(background_color);
+ }
+
+ void Button::set_position(sf::Vector2f pos) {
+ background.set_position(pos);
+
+ const auto label_bounds = label.getLocalBounds();
+ sf::Vector2f label_pos(pos + background.get_size() * 0.5f - sf::Vector2f(label_bounds.width * 0.5f, label_bounds.height * 0.5f) - sf::Vector2f(0.0f, 5.0f * scale));
+ label_pos.x = std::floor(label_pos.x);
+ label_pos.y = std::floor(label_pos.y);
+ label.setPosition(label_pos);
+ }
+
+ sf::Vector2f Button::get_position() const {
+ return background.get_position();
+ }
+
+ float Button::get_width() const {
+ return background.get_size().x;
+ }
+
+ float Button::get_height() const {
+ return std::floor((PADDING_Y * 2.0f) * scale + label.getLocalBounds().height);
+ }
+} \ No newline at end of file
diff --git a/src/plugins/FileManager.cpp b/src/plugins/FileManager.cpp
index e1f3b04..6ee7e71 100644
--- a/src/plugins/FileManager.cpp
+++ b/src/plugins/FileManager.cpp
@@ -39,18 +39,10 @@ namespace QuickMedia {
return PluginResult::OK;
}
- if(!std::filesystem::is_directory(new_path)) {
- if(allow_empty_match_submit) {
- program->select_file(new_path);
- if(selection_handler)
- result_tabs = selection_handler(this, new_path);
- return PluginResult::OK;
- }
+ if(!std::filesystem::is_directory(new_path))
return PluginResult::ERR;
- }
current_dir = std::move(new_path);
- this->title = title_prefix + current_dir.string();
BodyItems result_items;
PluginResult result = get_files_in_directory(result_items);
@@ -63,16 +55,10 @@ namespace QuickMedia {
return PluginResult::OK;
}
- void FileManagerPage::on_navigate_to_page(Body*) {
- if(close)
- program->set_go_to_previous_page();
- }
-
bool FileManagerPage::set_current_directory(const std::string &path) {
if(!std::filesystem::is_directory(path))
return false;
current_dir = path;
- title = title_prefix + current_dir.string();
return true;
}
diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp
index f69484b..0b50366 100644
--- a/src/plugins/Mangadex.cpp
+++ b/src/plugins/Mangadex.cpp
@@ -216,7 +216,7 @@ namespace QuickMedia {
return PluginResult::ERR;
std::string base_url = base_url_json.asString();
- if(base_url.back() != '/')
+ if(!base_url.empty() && base_url.back() != '/')
base_url += '/';
auto image_urls = static_cast<MangadexChapterImagesList*>(submit_body_item->extra.get())->image_urls;