ladybird/Userland/Applications/FileManager/DirectoryView.h
Leonardo Nicolas 9aa0cf3265 FileManager: Do not allow rename files that cannot be modified
Pressing the F2 key on files that the user doesn't have permission was
opening the file name for editing.

This patch fixes the issue disabling the file name editing when the user
doesn't have permission to do it.

To reproduce the issue:

1) Open the File Manager
2) Click on the /etc directory
3) Select any file
4) Press the F2 key
5) Update the file name
2022-01-09 00:47:48 +01:00

190 lines
5.8 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/URL.h>
#include <AK/Vector.h>
#include <LibConfig/Listener.h>
#include <LibDesktop/Launcher.h>
#include <LibGUI/Action.h>
#include <LibGUI/ColumnsView.h>
#include <LibGUI/FileSystemModel.h>
#include <LibGUI/IconView.h>
#include <LibGUI/StackWidget.h>
#include <LibGUI/TableView.h>
#include <fcntl.h>
#include <sys/stat.h>
namespace FileManager {
void spawn_terminal(String const& directory);
class LauncherHandler : public RefCounted<LauncherHandler> {
public:
LauncherHandler(NonnullRefPtr<Desktop::Launcher::Details> const& details)
: m_details(details)
{
}
NonnullRefPtr<GUI::Action> create_launch_action(Function<void(LauncherHandler const&)>);
Desktop::Launcher::Details const& details() const { return *m_details; }
private:
NonnullRefPtr<Desktop::Launcher::Details> m_details;
};
class DirectoryView final
: public GUI::StackWidget
, private GUI::ModelClient
, public Config::Listener {
C_OBJECT(DirectoryView);
public:
enum class Mode {
Desktop,
Normal,
};
virtual ~DirectoryView() override;
bool open(String const& path);
String path() const { return model().root_path(); }
void open_parent_directory();
void open_previous_directory();
void open_next_directory();
int path_history_size() const { return m_path_history.size(); }
int path_history_position() const { return m_path_history_position; }
static RefPtr<LauncherHandler> get_default_launch_handler(NonnullRefPtrVector<LauncherHandler> const& handlers);
static NonnullRefPtrVector<LauncherHandler> get_launch_handlers(URL const& url);
static NonnullRefPtrVector<LauncherHandler> get_launch_handlers(String const& path);
void refresh();
void launch(URL const&, LauncherHandler const&) const;
Function<void(StringView path, bool can_read_in_path, bool can_write_in_path)> on_path_change;
Function<void(GUI::AbstractView&)> on_selection_change;
Function<void(GUI::ModelIndex const&, GUI::ContextMenuEvent const&)> on_context_menu_request;
Function<void(StringView)> on_status_message;
Function<void(int done, int total)> on_thumbnail_progress;
Function<void()> on_accepted_drop;
enum ViewMode {
Invalid,
Table,
Columns,
Icon
};
void set_view_mode(ViewMode);
ViewMode view_mode() const { return m_view_mode; }
void set_view_mode_from_string(String const&);
GUI::AbstractView& current_view()
{
switch (m_view_mode) {
case ViewMode::Table:
return *m_table_view;
case ViewMode::Columns:
return *m_columns_view;
case ViewMode::Icon:
return *m_icon_view;
default:
VERIFY_NOT_REACHED();
}
}
GUI::AbstractView const& current_view() const
{
return const_cast<DirectoryView*>(this)->current_view();
}
template<typename Callback>
void for_each_view_implementation(Callback callback)
{
if (m_icon_view)
callback(*m_icon_view);
if (m_table_view)
callback(*m_table_view);
if (m_columns_view)
callback(*m_columns_view);
}
void set_should_show_dotfiles(bool);
GUI::FileSystemModel::Node const& node(GUI::ModelIndex const&) const;
bool is_desktop() const { return m_mode == Mode::Desktop; }
Vector<String> selected_file_paths() const;
GUI::Action& mkdir_action() { return *m_mkdir_action; }
GUI::Action& touch_action() { return *m_touch_action; }
GUI::Action& open_terminal_action() { return *m_open_terminal_action; }
GUI::Action& delete_action() { return *m_delete_action; }
GUI::Action& force_delete_action() { return *m_force_delete_action; }
GUI::Action& rename_action() { return *m_rename_action; }
GUI::Action& view_as_icons_action() { return *m_view_as_icons_action; }
GUI::Action& view_as_table_action() { return *m_view_as_table_action; }
GUI::Action& view_as_columns_action() { return *m_view_as_columns_action; }
// ^Config::Listener
virtual void config_string_did_change(String const& domain, String const& group, String const& key, String const& value) override;
private:
explicit DirectoryView(Mode);
GUI::FileSystemModel const& model() const { return *m_model; }
GUI::FileSystemModel& model() { return *m_model; }
void handle_selection_change();
void handle_drop(GUI::ModelIndex const&, GUI::DropEvent const&);
void do_delete(bool should_confirm);
// ^GUI::ModelClient
virtual void model_did_update(unsigned) override;
void setup_actions();
void setup_model();
void setup_icon_view();
void setup_columns_view();
void setup_table_view();
void handle_activation(GUI::ModelIndex const&);
void set_status_message(StringView);
void update_statusbar();
bool can_modify_current_selection();
Mode m_mode { Mode::Normal };
ViewMode m_view_mode { Invalid };
NonnullRefPtr<GUI::FileSystemModel> m_model;
NonnullRefPtr<GUI::SortingProxyModel> m_sorting_model;
size_t m_path_history_position { 0 };
Vector<String> m_path_history;
void add_path_to_history(String);
RefPtr<GUI::Label> m_error_label;
RefPtr<GUI::TableView> m_table_view;
RefPtr<GUI::IconView> m_icon_view;
RefPtr<GUI::ColumnsView> m_columns_view;
RefPtr<GUI::Action> m_mkdir_action;
RefPtr<GUI::Action> m_touch_action;
RefPtr<GUI::Action> m_open_terminal_action;
RefPtr<GUI::Action> m_delete_action;
RefPtr<GUI::Action> m_force_delete_action;
RefPtr<GUI::Action> m_rename_action;
RefPtr<GUI::Action> m_view_as_table_action;
RefPtr<GUI::Action> m_view_as_icons_action;
RefPtr<GUI::Action> m_view_as_columns_action;
};
}