mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-07-19 12:28:37 +00:00
Filemanager: go to parent directory keep track of the right selected … (#2702)
* Filemanager: go to parent directory keep track of the right selected item and page number * review: avoid unnecessary copies in get_extension
This commit is contained in:
parent
f53262783a
commit
e26f77ee77
@ -228,6 +228,8 @@ void FileManBaseView::load_directory_contents(const fs::path& dir_path) {
|
|||||||
|
|
||||||
text_current.set(dir_path.empty() ? "(sd root)" : truncate(dir_path, 24));
|
text_current.set(dir_path.empty() ? "(sd root)" : truncate(dir_path, 24));
|
||||||
|
|
||||||
|
// Collect all entries first
|
||||||
|
std::list<fileman_entry> all_entries;
|
||||||
for (const auto& entry : fs::directory_iterator(dir_path, u"*")) {
|
for (const auto& entry : fs::directory_iterator(dir_path, u"*")) {
|
||||||
// Hide files starting with '.' (hidden / tmp).
|
// Hide files starting with '.' (hidden / tmp).
|
||||||
if (!show_hidden_files && is_hidden_file(entry.path()))
|
if (!show_hidden_files && is_hidden_file(entry.path()))
|
||||||
@ -235,36 +237,40 @@ void FileManBaseView::load_directory_contents(const fs::path& dir_path) {
|
|||||||
|
|
||||||
if (fs::is_regular_file(entry.status())) {
|
if (fs::is_regular_file(entry.status())) {
|
||||||
if (!filtering || path_iequal(entry.path().extension(), extension_filter) || (cxx_file && is_cxx_capture_file(entry.path())))
|
if (!filtering || path_iequal(entry.path().extension(), extension_filter) || (cxx_file && is_cxx_capture_file(entry.path())))
|
||||||
insert_sorted(entry_list, {entry.path().string(), (uint32_t)entry.size(), false});
|
insert_sorted(all_entries, {entry.path().string(), (uint32_t)entry.size(), false});
|
||||||
} else if (fs::is_directory(entry.status())) {
|
} else if (fs::is_directory(entry.status())) {
|
||||||
insert_sorted(entry_list, {entry.path().string(), 0, true});
|
insert_sorted(all_entries, {entry.path().string(), 0, true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paginating
|
// Calculate pagination
|
||||||
auto list_size = entry_list.size();
|
nb_pages = (all_entries.size() + items_per_page - 1) / items_per_page;
|
||||||
nb_pages = 1 + (list_size / items_per_page);
|
if (nb_pages == 0) nb_pages = 1;
|
||||||
size_t start = pagination * items_per_page;
|
|
||||||
size_t stop = start + items_per_page;
|
size_t start_idx = pagination * items_per_page;
|
||||||
if (list_size > start) {
|
size_t end_idx = std::min(start_idx + items_per_page, all_entries.size());
|
||||||
if (list_size < stop)
|
|
||||||
stop = list_size;
|
// Add "parent" directory if not at the root and on first page
|
||||||
entry_list.erase(std::next(entry_list.begin(), stop), entry_list.end());
|
if (!dir_path.empty() && pagination == 0) {
|
||||||
entry_list.erase(entry_list.begin(), std::next(entry_list.begin(), start));
|
entry_list.push_back({parent_dir_path.string(), 0, true});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add "parent" directory if not at the root.
|
// Add prev page navigation if not on first page
|
||||||
if (!dir_path.empty() && pagination == 0)
|
|
||||||
entry_list.insert(entry_list.begin(), {parent_dir_path.string(), 0, true});
|
|
||||||
|
|
||||||
// add next page
|
|
||||||
if (list_size > start + items_per_page) {
|
|
||||||
entry_list.push_back({str_next, (uint32_t)pagination + 1, true});
|
|
||||||
}
|
|
||||||
|
|
||||||
// add prev page
|
|
||||||
if (pagination > 0) {
|
if (pagination > 0) {
|
||||||
entry_list.insert(entry_list.begin(), {str_back, (uint32_t)pagination - 1, true});
|
entry_list.push_back({str_back, (uint32_t)pagination - 1, true});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add entries for current page
|
||||||
|
auto it = all_entries.begin();
|
||||||
|
std::advance(it, start_idx);
|
||||||
|
|
||||||
|
for (size_t i = start_idx; i < end_idx && it != all_entries.end(); i++, ++it) {
|
||||||
|
entry_list.push_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add next page navigation if not on last page
|
||||||
|
if (end_idx < all_entries.size()) {
|
||||||
|
entry_list.push_back({str_next, (uint32_t)pagination + 1, true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,30 +326,49 @@ void FileManBaseView::focus() {
|
|||||||
} else {
|
} else {
|
||||||
menu_view.focus();
|
menu_view.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set menu to the correct page and select the correct item
|
||||||
|
menu_view.set_highlighted(prev_highlight % items_per_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push directory - store the global index (page * items_per_page + local_index)
|
||||||
void FileManBaseView::push_dir(const fs::path& path) {
|
void FileManBaseView::push_dir(const fs::path& path) {
|
||||||
if (path == parent_dir_path) {
|
if (path == parent_dir_path) {
|
||||||
pop_dir();
|
pop_dir();
|
||||||
} else {
|
} else {
|
||||||
|
// Save global index (combines page number and item position)
|
||||||
|
saved_index_stack.push_back(menu_view.highlighted_index() + (pagination * items_per_page));
|
||||||
|
|
||||||
current_path /= path;
|
current_path /= path;
|
||||||
saved_index_stack.push_back(menu_view.highlighted_index());
|
reload_current(true); // Reset pagination when entering new directory
|
||||||
menu_view.set_highlighted(0);
|
|
||||||
reload_current(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileManBaseView::pop_dir() {
|
void FileManBaseView::pop_dir() {
|
||||||
if (saved_index_stack.empty())
|
if (current_path.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to parent directory
|
||||||
current_path = current_path.parent_path();
|
current_path = current_path.parent_path();
|
||||||
reload_current(true);
|
|
||||||
menu_view.set_highlighted(saved_index_stack.back());
|
// Restore the previous global index if available
|
||||||
saved_index_stack.pop_back();
|
if (!saved_index_stack.empty()) {
|
||||||
|
uint32_t global_index = saved_index_stack.back();
|
||||||
|
saved_index_stack.pop_back();
|
||||||
|
|
||||||
|
// Calculate pagination from global index
|
||||||
|
pagination = global_index / items_per_page;
|
||||||
|
|
||||||
|
// Calculate local index within the page
|
||||||
|
prev_highlight = global_index % items_per_page;
|
||||||
|
restoring_navigation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_current(false); // Important: don't reset pagination
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_extension(std::string t) {
|
std::string FileManBaseView::get_extension(const std::string& t) const {
|
||||||
const auto index = t.find_last_of(u'.');
|
const auto index = t.find_last_of(u'.');
|
||||||
if (index == t.npos) {
|
if (index == t.npos) {
|
||||||
return {};
|
return {};
|
||||||
@ -372,7 +397,9 @@ void FileManBaseView::refresh_list() {
|
|||||||
if (on_refresh_widgets)
|
if (on_refresh_widgets)
|
||||||
on_refresh_widgets(false);
|
on_refresh_widgets(false);
|
||||||
|
|
||||||
prev_highlight = menu_view.highlighted_index();
|
if (!restoring_navigation) {
|
||||||
|
prev_highlight = menu_view.highlighted_index();
|
||||||
|
}
|
||||||
menu_view.clear();
|
menu_view.clear();
|
||||||
|
|
||||||
for (const auto& entry : entry_list) {
|
for (const auto& entry : entry_list) {
|
||||||
@ -411,10 +438,14 @@ void FileManBaseView::refresh_list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
menu_view.set_highlighted(prev_highlight);
|
menu_view.set_highlighted(prev_highlight);
|
||||||
|
restoring_navigation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileManBaseView::reload_current(bool reset_pagination) {
|
void FileManBaseView::reload_current(bool reset_pagination) {
|
||||||
if (reset_pagination) pagination = 0;
|
// Only reset pagination if explicitly requested
|
||||||
|
if (reset_pagination) {
|
||||||
|
pagination = 0;
|
||||||
|
}
|
||||||
load_directory_contents(current_path);
|
load_directory_contents(current_path);
|
||||||
refresh_list();
|
refresh_list();
|
||||||
}
|
}
|
||||||
@ -489,63 +520,6 @@ void FileLoadView::refresh_widgets(const bool) {
|
|||||||
set_dirty();
|
set_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FileSaveView **************************************************************/
|
|
||||||
/*
|
|
||||||
FileSaveView::FileSaveView(
|
|
||||||
NavigationView& nav,
|
|
||||||
const fs::path& path,
|
|
||||||
const fs::path& file
|
|
||||||
) : nav_{ nav },
|
|
||||||
path_{ path },
|
|
||||||
file_{ file }
|
|
||||||
{
|
|
||||||
add_children({
|
|
||||||
&text_path,
|
|
||||||
&button_edit_path,
|
|
||||||
&text_name,
|
|
||||||
&button_edit_name,
|
|
||||||
&button_save,
|
|
||||||
&button_cancel,
|
|
||||||
});
|
|
||||||
|
|
||||||
button_edit_path.on_select = [this](Button&) {
|
|
||||||
buffer_ = path_.string();
|
|
||||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
|
||||||
[this](std::string&) {
|
|
||||||
path_ = buffer_;
|
|
||||||
refresh_widgets();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
button_edit_name.on_select = [this](Button&) {
|
|
||||||
buffer_ = file_.string();
|
|
||||||
text_prompt(nav_, buffer_, max_filename_length,ENTER_KEYBOARD_MODE_ALPHA,
|
|
||||||
[this](std::string&) {
|
|
||||||
file_ = buffer_;
|
|
||||||
refresh_widgets();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
button_save.on_select = [this](Button&) {
|
|
||||||
if (on_save)
|
|
||||||
on_save(path_ / file_);
|
|
||||||
else
|
|
||||||
nav_.pop();
|
|
||||||
};
|
|
||||||
|
|
||||||
button_cancel.on_select = [this](Button&) {
|
|
||||||
nav_.pop();
|
|
||||||
};
|
|
||||||
|
|
||||||
refresh_widgets();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileSaveView::refresh_widgets() {
|
|
||||||
text_path.set(truncate(path_, 30));
|
|
||||||
text_name.set(truncate(file_, 30));
|
|
||||||
set_dirty();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/* FileManagerView ***********************************************************/
|
/* FileManagerView ***********************************************************/
|
||||||
|
|
||||||
void FileManagerView::refresh_widgets(const bool v) {
|
void FileManagerView::refresh_widgets(const bool v) {
|
||||||
|
@ -64,6 +64,7 @@ class FileManBaseView : public View {
|
|||||||
uint32_t prev_highlight = 0;
|
uint32_t prev_highlight = 0;
|
||||||
uint8_t pagination = 0;
|
uint8_t pagination = 0;
|
||||||
uint8_t nb_pages = 1;
|
uint8_t nb_pages = 1;
|
||||||
|
bool restoring_navigation = false;
|
||||||
static constexpr size_t max_filename_length = 20;
|
static constexpr size_t max_filename_length = 20;
|
||||||
static constexpr size_t max_items_loaded = 75; // too memory hungry, so won't sort it
|
static constexpr size_t max_items_loaded = 75; // too memory hungry, so won't sort it
|
||||||
static constexpr size_t items_per_page = 20;
|
static constexpr size_t items_per_page = 20;
|
||||||
@ -96,6 +97,7 @@ class FileManBaseView : public View {
|
|||||||
void load_directory_contents(const std::filesystem::path& dir_path);
|
void load_directory_contents(const std::filesystem::path& dir_path);
|
||||||
void load_directory_contents_unordered(const std::filesystem::path& dir_path, size_t file_cnt);
|
void load_directory_contents_unordered(const std::filesystem::path& dir_path, size_t file_cnt);
|
||||||
const file_assoc_t& get_assoc(const std::filesystem::path& ext) const;
|
const file_assoc_t& get_assoc(const std::filesystem::path& ext) const;
|
||||||
|
std::string get_extension(const std::string& t) const;
|
||||||
void copy_waterfall(std::filesystem::path path);
|
void copy_waterfall(std::filesystem::path path);
|
||||||
|
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user