From 0b48e12dd7c0ecb78b8b6d0b9f9357d039259580 Mon Sep 17 00:00:00 2001 From: luk1337 Date: Tue, 13 Jul 2021 12:57:10 +0200 Subject: [PATCH] FileManager: Convert properties window UI to GML (#8705) --- .../Applications/FileManager/CMakeLists.txt | 2 + .../FileManager/PropertiesWindow.cpp | 129 ++++---- .../FileManager/PropertiesWindow.h | 3 +- .../PropertiesWindowGeneralTab.gml | 279 ++++++++++++++++++ 4 files changed, 333 insertions(+), 80 deletions(-) create mode 100644 Userland/Applications/FileManager/PropertiesWindowGeneralTab.gml diff --git a/Userland/Applications/FileManager/CMakeLists.txt b/Userland/Applications/FileManager/CMakeLists.txt index b31ef527a7..3d66741994 100644 --- a/Userland/Applications/FileManager/CMakeLists.txt +++ b/Userland/Applications/FileManager/CMakeLists.txt @@ -7,6 +7,7 @@ serenity_component( compile_gml(FileManagerWindow.gml FileManagerWindowGML.h file_manager_window_gml) compile_gml(FileOperationProgress.gml FileOperationProgressGML.h file_operation_progress_gml) +compile_gml(PropertiesWindowGeneralTab.gml PropertiesWindowGeneralTabGML.h properties_window_general_tab_gml) set(SOURCES DesktopWidget.cpp @@ -17,6 +18,7 @@ set(SOURCES FileUtils.cpp main.cpp PropertiesWindow.cpp + PropertiesWindowGeneralTab.gml ) serenity_app(FileManager ICON app-file-manager) diff --git a/Userland/Applications/FileManager/PropertiesWindow.cpp b/Userland/Applications/FileManager/PropertiesWindow.cpp index 33bdb1eebc..3d2d4cf784 100644 --- a/Userland/Applications/FileManager/PropertiesWindow.cpp +++ b/Userland/Applications/FileManager/PropertiesWindow.cpp @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -37,26 +39,20 @@ PropertiesWindow::PropertiesWindow(const String& path, bool disable_rename, Wind set_rect({ 0, 0, 360, 420 }); set_resizable(false); + set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/properties.png")); + auto& tab_widget = main_widget.add(); auto& general_tab = tab_widget.add_tab("General"); - general_tab.set_layout(); - general_tab.layout()->set_margins({ 12, 8, 12, 8 }); - general_tab.layout()->set_spacing(10); - - auto& file_container = general_tab.add(); - file_container.set_layout(); - file_container.layout()->set_spacing(20); - file_container.set_fixed_height(34); - - m_icon = file_container.add(); - m_icon->set_fixed_size(32, 32); + general_tab.load_from_gml(properties_window_general_tab_gml); m_name = lexical_path.basename(); m_path = lexical_path.string(); m_parent_path = lexical_path.dirname(); - m_name_box = file_container.add(); + m_icon = general_tab.find_descendant_of_type_named("icon"); + + m_name_box = general_tab.find_descendant_of_type_named("name"); m_name_box->set_text(m_name); m_name_box->set_mode(disable_rename ? GUI::TextBox::Mode::DisplayOnly : GUI::TextBox::Mode::Editable); m_name_box->on_change = [&]() { @@ -64,9 +60,6 @@ PropertiesWindow::PropertiesWindow(const String& path, bool disable_rename, Wind m_apply_button->set_enabled(m_name_dirty || m_permissions_dirty); }; - set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/properties.png")); - general_tab.add(Gfx::Orientation::Horizontal); - struct stat st; if (lstat(path.characters(), &st)) { perror("stat"); @@ -91,37 +84,61 @@ PropertiesWindow::PropertiesWindow(const String& path, bool disable_rename, Wind m_mode = st.st_mode; m_old_mode = st.st_mode; - auto properties = Vector(); - properties.append({ "Type:", get_description(m_mode) }); - auto parent_link = URL::create_with_file_protocol(m_parent_path, m_name); - properties.append(PropertyValuePair { "Location:", path, parent_link }); + auto type = general_tab.find_descendant_of_type_named("type"); + type->set_text(get_description(m_mode)); + + auto location = general_tab.find_descendant_of_type_named("location"); + location->set_text(path); + location->on_click = [this] { + Desktop::Launcher::open(URL::create_with_file_protocol(m_parent_path, m_name)); + }; if (S_ISLNK(m_mode)) { auto link_destination = Core::File::read_link(path); if (link_destination.is_null()) { perror("readlink"); } else { - auto link_directory = LexicalPath(link_destination); - auto link_parent = URL::create_with_file_protocol(link_directory.dirname(), link_directory.basename()); - properties.append({ "Link target:", link_destination, link_parent }); + auto link_location = general_tab.find_descendant_of_type_named("link_location"); + link_location->set_text(link_destination); + link_location->on_click = [link_destination] { + auto link_directory = LexicalPath(link_destination); + Desktop::Launcher::open(URL::create_with_file_protocol(link_directory.dirname(), link_directory.basename())); + }; } + } else { + auto link_location_widget = general_tab.find_descendant_of_type_named("link_location_widget"); + general_tab.remove_child(*link_location_widget); } - properties.append({ "Size:", human_readable_size_long(st.st_size) }); - properties.append({ "Owner:", String::formatted("{} ({})", owner_name, st.st_uid) }); - properties.append({ "Group:", String::formatted("{} ({})", group_name, st.st_gid) }); - properties.append({ "Created at:", GUI::FileSystemModel::timestamp_string(st.st_ctime) }); - properties.append({ "Last modified:", GUI::FileSystemModel::timestamp_string(st.st_mtime) }); + auto size = general_tab.find_descendant_of_type_named("size"); + size->set_text(human_readable_size_long(st.st_size)); - make_property_value_pairs(properties, general_tab); + auto owner = general_tab.find_descendant_of_type_named("owner"); + owner->set_text(String::formatted("{} ({})", owner_name, st.st_uid)); - general_tab.add(Gfx::Orientation::Horizontal); + auto group = general_tab.find_descendant_of_type_named("group"); + group->set_text(String::formatted("{} ({})", group_name, st.st_gid)); - make_permission_checkboxes(general_tab, { S_IRUSR, S_IWUSR, S_IXUSR }, "Owner:", m_mode); - make_permission_checkboxes(general_tab, { S_IRGRP, S_IWGRP, S_IXGRP }, "Group:", m_mode); - make_permission_checkboxes(general_tab, { S_IROTH, S_IWOTH, S_IXOTH }, "Others:", m_mode); + auto created_at = general_tab.find_descendant_of_type_named("created_at"); + created_at->set_text(GUI::FileSystemModel::timestamp_string(st.st_ctime)); - general_tab.layout()->add_spacer(); + auto last_modified = general_tab.find_descendant_of_type_named("last_modified"); + last_modified->set_text(GUI::FileSystemModel::timestamp_string(st.st_mtime)); + + auto owner_read = general_tab.find_descendant_of_type_named("owner_read"); + auto owner_write = general_tab.find_descendant_of_type_named("owner_write"); + auto owner_execute = general_tab.find_descendant_of_type_named("owner_execute"); + setup_permission_checkboxes(*owner_read, *owner_write, *owner_execute, { S_IRUSR, S_IWUSR, S_IXUSR }, m_mode); + + auto group_read = general_tab.find_descendant_of_type_named("group_read"); + auto group_write = general_tab.find_descendant_of_type_named("group_write"); + auto group_execute = general_tab.find_descendant_of_type_named("group_execute"); + setup_permission_checkboxes(*group_read, *group_write, *group_execute, { S_IRGRP, S_IWGRP, S_IXGRP }, m_mode); + + auto others_read = general_tab.find_descendant_of_type_named("others_read"); + auto others_write = general_tab.find_descendant_of_type_named("others_write"); + auto others_execute = general_tab.find_descendant_of_type_named("others_execute"); + setup_permission_checkboxes(*others_read, *others_write, *others_execute, { S_IROTH, S_IWOTH, S_IXOTH }, m_mode); auto& button_widget = main_widget.add(); button_widget.set_layout(); @@ -208,16 +225,8 @@ bool PropertiesWindow::apply_changes() return true; } -void PropertiesWindow::make_permission_checkboxes(GUI::Widget& parent, PermissionMasks masks, String label_string, mode_t mode) +void PropertiesWindow::setup_permission_checkboxes(GUI::CheckBox& box_read, GUI::CheckBox& box_write, GUI::CheckBox& box_execute, PermissionMasks masks, mode_t mode) { - auto& widget = parent.add(); - widget.set_layout(); - widget.set_fixed_height(16); - widget.layout()->set_spacing(10); - - auto& label = widget.add(label_string); - label.set_text_alignment(Gfx::TextAlignment::CenterLeft); - struct stat st; if (lstat(m_path.characters(), &st)) { perror("stat"); @@ -226,55 +235,19 @@ void PropertiesWindow::make_permission_checkboxes(GUI::Widget& parent, Permissio auto can_edit_checkboxes = st.st_uid == getuid(); - auto& box_read = widget.add("Read"); box_read.set_checked(mode & masks.read); box_read.on_checked = [&, masks](bool checked) { permission_changed(masks.read, checked); }; box_read.set_enabled(can_edit_checkboxes); - auto& box_write = widget.add("Write"); box_write.set_checked(mode & masks.write); box_write.on_checked = [&, masks](bool checked) { permission_changed(masks.write, checked); }; box_write.set_enabled(can_edit_checkboxes); - auto& box_execute = widget.add("Execute"); box_execute.set_checked(mode & masks.execute); box_execute.on_checked = [&, masks](bool checked) { permission_changed(masks.execute, checked); }; box_execute.set_enabled(can_edit_checkboxes); } -void PropertiesWindow::make_property_value_pairs(const Vector& pairs, GUI::Widget& parent) -{ - int max_width = 0; - Vector> property_labels; - - property_labels.ensure_capacity(pairs.size()); - for (auto pair : pairs) { - auto& label_container = parent.add(); - label_container.set_layout(); - label_container.set_fixed_height(14); - label_container.layout()->set_spacing(12); - - auto& label_property = label_container.add(pair.property); - label_property.set_text_alignment(Gfx::TextAlignment::CenterLeft); - - if (!pair.link.has_value()) { - label_container.add(pair.value).set_text_alignment(Gfx::TextAlignment::CenterLeft); - } else { - auto& link = label_container.add(pair.value); - link.set_text_alignment(Gfx::TextAlignment::CenterLeft); - link.on_click = [pair]() { - Desktop::Launcher::open(pair.link.value()); - }; - } - - max_width = max(max_width, label_property.font().width(pair.property)); - property_labels.append(label_property); - } - - for (auto label : property_labels) - label->set_fixed_width(max_width); -} - GUI::Button& PropertiesWindow::make_button(String text, GUI::Widget& parent) { auto& button = parent.add(text); diff --git a/Userland/Applications/FileManager/PropertiesWindow.h b/Userland/Applications/FileManager/PropertiesWindow.h index 0dbb99ddde..d690175645 100644 --- a/Userland/Applications/FileManager/PropertiesWindow.h +++ b/Userland/Applications/FileManager/PropertiesWindow.h @@ -58,8 +58,7 @@ private: } GUI::Button& make_button(String, GUI::Widget& parent); - void make_property_value_pairs(const Vector& pairs, GUI::Widget& parent); - void make_permission_checkboxes(GUI::Widget& parent, PermissionMasks, String label_string, mode_t mode); + void setup_permission_checkboxes(GUI::CheckBox& box_read, GUI::CheckBox& box_write, GUI::CheckBox& box_execute, PermissionMasks masks, mode_t mode); void permission_changed(mode_t mask, bool set); bool apply_changes(); void update(); diff --git a/Userland/Applications/FileManager/PropertiesWindowGeneralTab.gml b/Userland/Applications/FileManager/PropertiesWindowGeneralTab.gml new file mode 100644 index 0000000000..449ab3a54d --- /dev/null +++ b/Userland/Applications/FileManager/PropertiesWindowGeneralTab.gml @@ -0,0 +1,279 @@ +@GUI::Widget { + layout: @GUI::VerticalBoxLayout { + margins: [12, 8, 12, 8] + spacing: 10 + } + + @GUI::Widget { + fixed_height: 34 + + layout: @GUI::HorizontalBoxLayout { + spacing: 20 + } + + @GUI::ImageWidget { + fixed_width: 32 + fixed_height: 32 + name: "icon" + } + + @GUI::TextBox { + text: "file" + name: "name" + } + } + + @GUI::HorizontalSeparator { + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Type:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "type" + text: "File" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Location:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::LinkLabel { + name: "location" + text: "/home/anon/file" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + name: "link_location_widget" + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Link location:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::LinkLabel { + name: "link_location" + text: "/home/anon/file" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Size:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "size" + text: "5.9 KiB (6097 bytes)" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Owner:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "owner" + text: "anon (100)" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Group:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "group" + text: "anon (100)" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Created at:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "created_at" + text: "2021-07-12 20:33:24" + text_alignment: "CenterLeft" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Last Modified:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "last_modified" + text: "2021-07-12 20:33:24" + text_alignment: "CenterLeft" + } + } + + @GUI::HorizontalSeparator { + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Owner:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::CheckBox { + name: "owner_read" + text: "Read" + } + + @GUI::CheckBox { + name: "owner_write" + text: "Write" + } + + @GUI::CheckBox { + name: "owner_execute" + text: "Execute" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Group:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::CheckBox { + name: "group_read" + text: "Read" + } + + @GUI::CheckBox { + name: "group_write" + text: "Write" + } + + @GUI::CheckBox { + name: "group_execute" + text: "Execute" + } + } + + @GUI::Widget { + fixed_height: 14 + + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Others:" + text_alignment: "CenterLeft" + fixed_width: 80 + } + + @GUI::CheckBox { + name: "others_read" + text: "Read" + } + + @GUI::CheckBox { + name: "others_write" + text: "Write" + } + + @GUI::CheckBox { + name: "others_execute" + text: "Execute" + } + } +}