summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Nilsson <marcus.nilsson@genarp.com>2023-01-11 22:42:45 +0100
committerAndrew Kaster <andrewdkaster@gmail.com>2023-02-02 04:05:42 -0700
commitbe464c357a312f4301840de68b6be0f47732bedc (patch)
treee0b1fefcbd240dc22dc4752533d8b8b20d0fef3d
parentfe5dfe4cd5ef4ea0a73be2f9bd53a16c3c789b86 (diff)
downloadserenity-be464c357a312f4301840de68b6be0f47732bedc.zip
LibGUI: Add allowed file types to FilePicker
This patch adds a ComboBox to `FilePicker` where the user can select which file types to show, all files that doesn't have an extension that's in the selected file type will be hidden. When creating a FilePicker with `FilePicker::construct` or `FilePicker::get_open_filepath`, allowed file types can be specified as the last argument. If no file types are provided then there will be no visual change in the GUI. 'All Files' and 'Image Files' have shorthands with `GUI::FileTypeFilter::all_files()` and `GUI::FileTypeFilter::image_files()`, respectively.
-rw-r--r--Userland/Libraries/LibGUI/FilePicker.cpp40
-rw-r--r--Userland/Libraries/LibGUI/FilePicker.h10
-rw-r--r--Userland/Libraries/LibGUI/FilePickerDialog.gml18
-rw-r--r--Userland/Libraries/LibGUI/FileTypeFilter.h30
4 files changed, 85 insertions, 13 deletions
diff --git a/Userland/Libraries/LibGUI/FilePicker.cpp b/Userland/Libraries/LibGUI/FilePicker.cpp
index b05d9fc62f..d080187889 100644
--- a/Userland/Libraries/LibGUI/FilePicker.cpp
+++ b/Userland/Libraries/LibGUI/FilePicker.cpp
@@ -16,7 +16,9 @@
#include <LibGUI/FilePicker.h>
#include <LibGUI/FilePickerDialogGML.h>
#include <LibGUI/FileSystemModel.h>
+#include <LibGUI/FileTypeFilter.h>
#include <LibGUI/InputBox.h>
+#include <LibGUI/ItemListModel.h>
#include <LibGUI/Label.h>
#include <LibGUI/Menu.h>
#include <LibGUI/MessageBox.h>
@@ -25,6 +27,7 @@
#include <LibGUI/TextBox.h>
#include <LibGUI/Toolbar.h>
#include <LibGUI/Tray.h>
+#include <LibGUI/Widget.h>
#include <LibGfx/Font/FontDatabase.h>
#include <LibGfx/Palette.h>
#include <string.h>
@@ -32,9 +35,9 @@
namespace GUI {
-Optional<DeprecatedString> FilePicker::get_open_filepath(Window* parent_window, DeprecatedString const& window_title, StringView path, bool folder, ScreenPosition screen_position)
+Optional<DeprecatedString> FilePicker::get_open_filepath(Window* parent_window, DeprecatedString const& window_title, StringView path, bool folder, ScreenPosition screen_position, Optional<Vector<FileTypeFilter>> allowed_file_types)
{
- auto picker = FilePicker::construct(parent_window, folder ? Mode::OpenFolder : Mode::Open, ""sv, path, screen_position);
+ auto picker = FilePicker::construct(parent_window, folder ? Mode::OpenFolder : Mode::Open, ""sv, path, screen_position, move(allowed_file_types));
if (!window_title.is_null())
picker->set_title(window_title);
@@ -65,9 +68,10 @@ Optional<DeprecatedString> FilePicker::get_save_filepath(Window* parent_window,
return {};
}
-FilePicker::FilePicker(Window* parent_window, Mode mode, StringView filename, StringView path, ScreenPosition screen_position)
+FilePicker::FilePicker(Window* parent_window, Mode mode, StringView filename, StringView path, ScreenPosition screen_position, Optional<Vector<FileTypeFilter>> allowed_file_types)
: Dialog(parent_window, screen_position)
, m_model(FileSystemModel::create(path))
+ , m_allowed_file_types(move(allowed_file_types))
, m_mode(mode)
{
switch (m_mode) {
@@ -112,6 +116,36 @@ FilePicker::FilePicker(Window* parent_window, Mode mode, StringView filename, St
set_path(m_location_textbox->text());
};
+ auto* file_types_filters_combo = widget->find_descendant_of_type_named<GUI::ComboBox>("allowed_file_type_filters_combo");
+
+ if (m_allowed_file_types.has_value()) {
+ for (auto& filter : *m_allowed_file_types) {
+ if (!filter.extensions.has_value()) {
+ m_allowed_file_types_names.append(filter.name);
+ continue;
+ }
+
+ StringBuilder extension_list;
+ extension_list.join("; "sv, *filter.extensions);
+ m_allowed_file_types_names.append(DeprecatedString::formatted("{} ({})", filter.name, extension_list.to_deprecated_string()));
+ }
+
+ file_types_filters_combo->set_model(*GUI::ItemListModel<DeprecatedString, Vector<DeprecatedString>>::create(m_allowed_file_types_names));
+ file_types_filters_combo->on_change = [this](DeprecatedString const&, GUI::ModelIndex const& index) {
+ m_model->set_allowed_file_extensions((*m_allowed_file_types)[index.row()].extensions);
+ };
+ file_types_filters_combo->set_selected_index(0);
+ } else {
+ auto* file_types_filter_label = widget->find_descendant_of_type_named<GUI::Label>("allowed_file_types_label");
+ auto& spacer = file_types_filter_label->parent_widget()->add<GUI::Widget>();
+ spacer.set_fixed_height(22);
+ file_types_filter_label->remove_from_parent();
+
+ file_types_filters_combo->parent_widget()->insert_child_before(GUI::Widget::construct(), *file_types_filters_combo);
+
+ file_types_filters_combo->remove_from_parent();
+ }
+
auto open_parent_directory_action = Action::create(
"Open parent directory", { Mod_Alt, Key_Up }, Gfx::Bitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"sv).release_value_but_fixme_should_propagate_errors(), [this](Action const&) {
set_path(DeprecatedString::formatted("{}/..", m_model->root_path()));
diff --git a/Userland/Libraries/LibGUI/FilePicker.h b/Userland/Libraries/LibGUI/FilePicker.h
index 20b8ff89e0..8611aac51b 100644
--- a/Userland/Libraries/LibGUI/FilePicker.h
+++ b/Userland/Libraries/LibGUI/FilePicker.h
@@ -8,8 +8,11 @@
#include <AK/LexicalPath.h>
#include <AK/Optional.h>
+#include <AK/String.h>
#include <LibCore/StandardPaths.h>
+#include <LibGUI/ComboBox.h>
#include <LibGUI/Dialog.h>
+#include <LibGUI/FileTypeFilter.h>
#include <LibGUI/ImageWidget.h>
#include <LibGUI/Model.h>
@@ -28,7 +31,7 @@ public:
Save
};
- static Optional<DeprecatedString> get_open_filepath(Window* parent_window, DeprecatedString const& window_title = {}, StringView path = Core::StandardPaths::home_directory(), bool folder = false, ScreenPosition screen_position = Dialog::ScreenPosition::CenterWithinParent);
+ static Optional<DeprecatedString> get_open_filepath(Window* parent_window, DeprecatedString const& window_title = {}, StringView path = Core::StandardPaths::home_directory(), bool folder = false, ScreenPosition screen_position = Dialog::ScreenPosition::CenterWithinParent, Optional<Vector<FileTypeFilter>> allowed_file_types = {});
static Optional<DeprecatedString> get_save_filepath(Window* parent_window, DeprecatedString const& title, DeprecatedString const& extension, StringView path = Core::StandardPaths::home_directory(), ScreenPosition screen_position = Dialog::ScreenPosition::CenterWithinParent);
virtual ~FilePicker() override;
@@ -43,7 +46,7 @@ private:
// ^GUI::ModelClient
virtual void model_did_update(unsigned) override;
- FilePicker(Window* parent_window, Mode type = Mode::Open, StringView filename = "Untitled"sv, StringView path = Core::StandardPaths::home_directory(), ScreenPosition screen_position = Dialog::ScreenPosition::CenterWithinParent);
+ FilePicker(Window* parent_window, Mode type = Mode::Open, StringView filename = "Untitled"sv, StringView path = Core::StandardPaths::home_directory(), ScreenPosition screen_position = Dialog::ScreenPosition::CenterWithinParent, Optional<Vector<FileTypeFilter>> allowed_file_types = {});
static DeprecatedString ok_button_name(Mode mode)
{
@@ -68,6 +71,9 @@ private:
NonnullRefPtr<FileSystemModel> m_model;
DeprecatedString m_selected_file;
+ Vector<DeprecatedString> m_allowed_file_types_names;
+ Optional<Vector<FileTypeFilter>> m_allowed_file_types;
+
RefPtr<GUI::Label> m_error_label;
RefPtr<TextBox> m_filename_textbox;
diff --git a/Userland/Libraries/LibGUI/FilePickerDialog.gml b/Userland/Libraries/LibGUI/FilePickerDialog.gml
index d285d2ebf5..79760da794 100644
--- a/Userland/Libraries/LibGUI/FilePickerDialog.gml
+++ b/Userland/Libraries/LibGUI/FilePickerDialog.gml
@@ -25,11 +25,14 @@
@GUI::Label {
text: "Filename:"
text_alignment: "CenterRight"
- fixed_height: 24
+ fixed_height: 22
}
- @GUI::Widget {
- fixed_height: 20
+ @GUI::Label {
+ name: "allowed_file_types_label"
+ text: "Files of Type:"
+ text_alignment: "CenterRight"
+ fixed_height: 22
}
}
@@ -68,10 +71,6 @@
name: "filename_textbox"
}
- @GUI::Widget {
- fixed_width: 20
- }
-
@GUI::DialogButton {
name: "ok_button"
text: "OK"
@@ -82,7 +81,10 @@
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
- @GUI::Layout::Spacer {}
+ @GUI::ComboBox {
+ name: "allowed_file_type_filters_combo"
+ model_only: true
+ }
@GUI::DialogButton {
name: "cancel_button"
diff --git a/Userland/Libraries/LibGUI/FileTypeFilter.h b/Userland/Libraries/LibGUI/FileTypeFilter.h
new file mode 100644
index 0000000000..144ed765a3
--- /dev/null
+++ b/Userland/Libraries/LibGUI/FileTypeFilter.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023, Marcus Nilsson <marcus.nilsson@genarp.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/DeprecatedString.h>
+#include <AK/Optional.h>
+#include <AK/Vector.h>
+
+namespace GUI {
+
+struct FileTypeFilter {
+ DeprecatedString name;
+ Optional<Vector<DeprecatedString>> extensions;
+
+ static FileTypeFilter all_files()
+ {
+ return FileTypeFilter { "All Files", {} };
+ }
+
+ static FileTypeFilter image_files()
+ {
+ return FileTypeFilter { "Image Files", Vector<DeprecatedString> { "png", "gif", "bmp", "dip", "pbm", "pgm", "ppm", "ico", "jpeg", "jpg", "dds", "qoi" } };
+ }
+};
+
+}