feat: system settings stored as applets in virtual folder
This commit is contained in:
@@ -9,33 +9,92 @@
|
||||
|
||||
namespace filemanager {
|
||||
|
||||
void filemanager_read_drives(FileManagerState* fm) {
|
||||
static int filemanager_find_external_app(DesktopState* ds, const char* bin_path) {
|
||||
if (!ds || !bin_path) return -1;
|
||||
for (int x = 0; x < ds->external_app_count; x++) {
|
||||
if (montauk::streq(ds->external_apps[x].binary_path, bin_path)) return x;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void filemanager_reset_list_state(FileManagerState* fm) {
|
||||
fm->selected = -1;
|
||||
fm->scroll_offset = 0;
|
||||
fm->scrollbar.scroll_offset = 0;
|
||||
fm->last_click_item = -1;
|
||||
fm->last_click_time = 0;
|
||||
}
|
||||
|
||||
static void filemanager_reset_virtual_entry(FileManagerVirtualEntry* entry) {
|
||||
if (!entry) return;
|
||||
entry->external_app_index = -1;
|
||||
entry->builtin_id = DESKTOP_BUILTIN_NONE;
|
||||
entry->icon_lg = {};
|
||||
entry->icon_sm = {};
|
||||
}
|
||||
|
||||
static void filemanager_add_root_entry(FileManagerState* fm,
|
||||
const char* name,
|
||||
FileManagerEntryType type,
|
||||
int drive_index) {
|
||||
if (!fm || fm->entry_count >= 64) return;
|
||||
|
||||
int idx = fm->entry_count++;
|
||||
montauk::strncpy(fm->entry_names[idx], name, 63);
|
||||
fm->entry_types[idx] = type;
|
||||
fm->entry_sizes[idx] = 0;
|
||||
fm->is_dir[idx] = true;
|
||||
fm->drive_indices[idx] = drive_index;
|
||||
}
|
||||
|
||||
static void filemanager_add_virtual_entry(FileManagerState* fm,
|
||||
const char* name,
|
||||
const char* icon_path,
|
||||
int external_index,
|
||||
DesktopBuiltinId builtin_id) {
|
||||
if (!fm || fm->entry_count >= 64) return;
|
||||
|
||||
int idx = fm->entry_count;
|
||||
montauk::strncpy(fm->entry_names[idx], name, 63);
|
||||
fm->entry_types[idx] = FM_ENTRY_VIRTUAL_APP;
|
||||
fm->entry_sizes[idx] = 0;
|
||||
fm->is_dir[idx] = false;
|
||||
fm->drive_indices[idx] = -1;
|
||||
filemanager_reset_virtual_entry(&fm->virtual_entries[idx]);
|
||||
fm->virtual_entries[idx].external_app_index = external_index;
|
||||
fm->virtual_entries[idx].builtin_id = builtin_id;
|
||||
|
||||
if (icon_path && icon_path[0]) {
|
||||
Color defColor = colors::ICON_COLOR;
|
||||
fm->virtual_entries[idx].icon_lg = svg_load(icon_path, 48, 48, defColor);
|
||||
fm->virtual_entries[idx].icon_sm = svg_load(icon_path, 16, 16, defColor);
|
||||
}
|
||||
|
||||
fm->entry_count++;
|
||||
fm->virtual_entry_count = fm->entry_count;
|
||||
}
|
||||
|
||||
static void filemanager_begin_virtual_view(FileManagerState* fm, FileManagerVirtualViewKind view) {
|
||||
filemanager_free_app_icons(fm);
|
||||
fm->current_path[0] = '\0';
|
||||
fm->virtual_view = view;
|
||||
fm->entry_count = 0;
|
||||
fm->at_drives_root = true;
|
||||
}
|
||||
|
||||
void filemanager_read_drives(FileManagerState* fm) {
|
||||
filemanager_free_app_icons(fm);
|
||||
fm->entry_count = 0;
|
||||
fm->virtual_view = FM_VIRTUAL_VIEW_NONE;
|
||||
fm->current_path[0] = '\0';
|
||||
|
||||
// Home folder entry (if we have a valid home directory)
|
||||
DesktopState* ds = fm->desktop;
|
||||
if (ds && ds->home_dir[0] != '\0') {
|
||||
int i = fm->entry_count;
|
||||
montauk::strncpy(fm->entry_names[i], "Home", 63);
|
||||
fm->entry_types[i] = 4; // home
|
||||
fm->entry_sizes[i] = 0;
|
||||
fm->is_dir[i] = true;
|
||||
fm->drive_indices[i] = -1;
|
||||
fm->entry_count++;
|
||||
filemanager_add_root_entry(fm, "Home", FM_ENTRY_HOME, -1);
|
||||
}
|
||||
|
||||
// Apps entry
|
||||
{
|
||||
int i = fm->entry_count;
|
||||
montauk::strncpy(fm->entry_names[i], "Apps", 63);
|
||||
fm->entry_types[i] = 5; // apps
|
||||
fm->entry_sizes[i] = 0;
|
||||
fm->is_dir[i] = true;
|
||||
fm->drive_indices[i] = -1;
|
||||
fm->entry_count++;
|
||||
}
|
||||
filemanager_add_root_entry(fm, "Apps", FM_ENTRY_APPS_ROOT, -1);
|
||||
|
||||
// Special user folders (Documents, Desktop, Music, etc.) - only if they exist
|
||||
if (ds && ds->home_dir[0] != '\0') {
|
||||
@@ -51,24 +110,20 @@ void filemanager_read_drives(FileManagerState* fm) {
|
||||
int probe_fd = montauk::open(probe_path);
|
||||
if (probe_fd >= 0) {
|
||||
montauk::close(probe_fd);
|
||||
int i = fm->entry_count;
|
||||
montauk::strncpy(fm->entry_names[i], sf_names[sf], 63);
|
||||
fm->entry_types[i] = 7; // special_dir
|
||||
fm->entry_sizes[i] = 0;
|
||||
fm->is_dir[i] = true;
|
||||
fm->drive_indices[i] = sf; // special folder index
|
||||
fm->entry_count++;
|
||||
filemanager_add_root_entry(fm, sf_names[sf], FM_ENTRY_SPECIAL_DIR, sf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// System configuration entry
|
||||
filemanager_add_root_entry(fm, "System Configuration", FM_ENTRY_SYSTEM_TOOLS_ROOT, -1);
|
||||
|
||||
// Drive entries
|
||||
int drives[FM_MAX_DRIVES];
|
||||
int driveCount = montauk::drivelist(drives, FM_MAX_DRIVES);
|
||||
|
||||
for (int di = 0; di < driveCount; di++) {
|
||||
int d = drives[di];
|
||||
int i = fm->entry_count;
|
||||
char probe[8];
|
||||
if (d < 10) {
|
||||
probe[0] = '0' + d;
|
||||
@@ -91,28 +146,22 @@ void filemanager_read_drives(FileManagerState* fm) {
|
||||
str_append(label, volume_label, 64);
|
||||
str_append(label, "]", 64);
|
||||
}
|
||||
montauk::strncpy(fm->entry_names[i], label, 63);
|
||||
fm->entry_types[i] = 3; // drive
|
||||
fm->entry_sizes[i] = 0;
|
||||
fm->is_dir[i] = true;
|
||||
fm->drive_indices[i] = d;
|
||||
fm->entry_count++;
|
||||
filemanager_add_root_entry(fm, label, FM_ENTRY_DRIVE, d);
|
||||
if (fm->entry_count >= 64) break;
|
||||
}
|
||||
|
||||
fm->selected = -1;
|
||||
fm->scroll_offset = 0;
|
||||
fm->scrollbar.scroll_offset = 0;
|
||||
fm->last_click_item = -1;
|
||||
fm->last_click_time = 0;
|
||||
filemanager_reset_list_state(fm);
|
||||
}
|
||||
|
||||
void filemanager_read_dir(FileManagerState* fm) {
|
||||
fm->at_drives_root = false;
|
||||
if (fm->at_apps_view) {
|
||||
fm->at_apps_view = false;
|
||||
filemanager_free_app_icons(fm);
|
||||
if (fm->current_path[0] == '\0') {
|
||||
filemanager_read_drives(fm);
|
||||
return;
|
||||
}
|
||||
|
||||
filemanager_free_app_icons(fm);
|
||||
fm->virtual_view = FM_VIRTUAL_VIEW_NONE;
|
||||
|
||||
const char* names[64];
|
||||
fm->entry_count = montauk::readdir(fm->current_path, names, 64);
|
||||
if (fm->entry_count < 0) fm->entry_count = 0;
|
||||
@@ -210,33 +259,36 @@ void filemanager_read_dir(FileManagerState* fm) {
|
||||
fm->is_dir[j + 1] = tmp_isdir;
|
||||
}
|
||||
|
||||
fm->selected = -1;
|
||||
fm->scroll_offset = 0;
|
||||
fm->scrollbar.scroll_offset = 0;
|
||||
fm->last_click_item = -1;
|
||||
fm->last_click_time = 0;
|
||||
filemanager_reset_list_state(fm);
|
||||
}
|
||||
|
||||
void filemanager_free_app_icons(FileManagerState* fm) {
|
||||
for (int i = 0; i < fm->app_icon_count; i++) {
|
||||
if (fm->app_icons_lg[i].pixels) {
|
||||
montauk::mfree(fm->app_icons_lg[i].pixels);
|
||||
fm->app_icons_lg[i].pixels = nullptr;
|
||||
if (!fm) return;
|
||||
|
||||
for (int i = 0; i < fm->virtual_entry_count; i++) {
|
||||
if (fm->virtual_entries[i].icon_lg.pixels) {
|
||||
montauk::mfree(fm->virtual_entries[i].icon_lg.pixels);
|
||||
fm->virtual_entries[i].icon_lg.pixels = nullptr;
|
||||
}
|
||||
if (fm->app_icons_sm[i].pixels) {
|
||||
montauk::mfree(fm->app_icons_sm[i].pixels);
|
||||
fm->app_icons_sm[i].pixels = nullptr;
|
||||
if (fm->virtual_entries[i].icon_sm.pixels) {
|
||||
montauk::mfree(fm->virtual_entries[i].icon_sm.pixels);
|
||||
fm->virtual_entries[i].icon_sm.pixels = nullptr;
|
||||
}
|
||||
filemanager_reset_virtual_entry(&fm->virtual_entries[i]);
|
||||
}
|
||||
fm->virtual_entry_count = 0;
|
||||
}
|
||||
|
||||
void filemanager_read_virtual_view(FileManagerState* fm, FileManagerVirtualViewKind view) {
|
||||
switch (view) {
|
||||
case FM_VIRTUAL_VIEW_APPS: filemanager_read_apps(fm); break;
|
||||
case FM_VIRTUAL_VIEW_SYSTEM_TOOLS: filemanager_read_system_tools(fm); break;
|
||||
default: filemanager_read_drives(fm); break;
|
||||
}
|
||||
fm->app_icon_count = 0;
|
||||
}
|
||||
|
||||
void filemanager_read_apps(FileManagerState* fm) {
|
||||
filemanager_free_app_icons(fm);
|
||||
|
||||
fm->at_drives_root = false;
|
||||
fm->at_apps_view = true;
|
||||
fm->entry_count = 0;
|
||||
filemanager_begin_virtual_view(fm, FM_VIRTUAL_VIEW_APPS);
|
||||
|
||||
DesktopState* ds = fm->desktop;
|
||||
if (!ds) return;
|
||||
@@ -283,45 +335,36 @@ void filemanager_read_apps(FileManagerState* fm) {
|
||||
const char* binary = doc.get_string("app.binary", "");
|
||||
const char* icon_file = doc.get_string("app.icon", "");
|
||||
|
||||
int idx = fm->entry_count;
|
||||
montauk::strncpy(fm->entry_names[idx], name, 63);
|
||||
fm->entry_types[idx] = 6; // app entry
|
||||
fm->entry_sizes[idx] = 0;
|
||||
fm->is_dir[idx] = false;
|
||||
|
||||
// Store binary path in drive_indices as an app_map index
|
||||
fm->app_map[idx] = -1;
|
||||
// Find matching external_app by binary path
|
||||
char bin_path[128];
|
||||
snprintf(bin_path, 128, "0:/apps/%s/%s", dirname, binary);
|
||||
for (int x = 0; x < ds->external_app_count; x++) {
|
||||
if (montauk::streq(ds->external_apps[x].binary_path, bin_path)) {
|
||||
fm->app_map[idx] = x;
|
||||
break;
|
||||
}
|
||||
char icon_path[128];
|
||||
icon_path[0] = '\0';
|
||||
if (icon_file[0]) {
|
||||
snprintf(icon_path, 128, "0:/apps/%s/%s", dirname, icon_file);
|
||||
}
|
||||
|
||||
// Load icons at file manager sizes
|
||||
fm->app_icons_lg[idx] = {};
|
||||
fm->app_icons_sm[idx] = {};
|
||||
if (icon_file[0]) {
|
||||
char icon_path[128];
|
||||
snprintf(icon_path, 128, "0:/apps/%s/%s", dirname, icon_file);
|
||||
Color defColor = colors::ICON_COLOR;
|
||||
fm->app_icons_lg[idx] = svg_load(icon_path, 48, 48, defColor);
|
||||
fm->app_icons_sm[idx] = svg_load(icon_path, 16, 16, defColor);
|
||||
}
|
||||
filemanager_add_virtual_entry(fm, name, icon_path,
|
||||
filemanager_find_external_app(ds, bin_path),
|
||||
DESKTOP_BUILTIN_NONE);
|
||||
|
||||
doc.destroy();
|
||||
fm->entry_count++;
|
||||
fm->app_icon_count = fm->entry_count;
|
||||
}
|
||||
|
||||
fm->selected = -1;
|
||||
fm->scroll_offset = 0;
|
||||
fm->scrollbar.scroll_offset = 0;
|
||||
fm->last_click_item = -1;
|
||||
fm->last_click_time = 0;
|
||||
filemanager_reset_list_state(fm);
|
||||
}
|
||||
|
||||
void filemanager_read_system_tools(FileManagerState* fm) {
|
||||
filemanager_begin_virtual_view(fm, FM_VIRTUAL_VIEW_SYSTEM_TOOLS);
|
||||
|
||||
int builtin_count = 0;
|
||||
const DesktopBuiltinEntry* builtins = desktop_builtin_registry(&builtin_count);
|
||||
for (int i = 0; i < builtin_count; i++) {
|
||||
if (!builtins[i].system_tools_applet) continue;
|
||||
filemanager_add_virtual_entry(fm, builtins[i].label, builtins[i].icon_path,
|
||||
-1, builtins[i].id);
|
||||
}
|
||||
|
||||
filemanager_reset_list_state(fm);
|
||||
}
|
||||
|
||||
bool filemanager_delete_recursive(const char* path) {
|
||||
|
||||
Reference in New Issue
Block a user