diff --git a/ede-preferred-applications/AppChoice.cpp b/ede-preferred-applications/AppChoice.cpp new file mode 100644 index 0000000..5adceb8 --- /dev/null +++ b/ede-preferred-applications/AppChoice.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include "AppChoice.h" + +#define STR_CMP(s1, s2) (strcmp(s1, s2) == 0) + +EDELIB_NS_USING(file_path) +EDELIB_NS_USING(String) + +/* TODO: move to edelib */ +static char* get_basename(const char* path) { + char* p = (char*)strrchr(path, '/'); + if(p) + return (p + 1); + + return (char*)path; +} + +static void select_cb(Fl_Widget *widget, void *c) { + AppChoice *o = (AppChoice*)c; + o->on_select(); +} + +AppChoice::AppChoice(int X, int Y, int W, int H, const char *l) : Fl_Choice(X, Y, W, H, l), known_apps(0), pvalue(0) { + align(FL_ALIGN_TOP_LEFT); + callback(select_cb, this); +} + +void AppChoice::add_programs(KnownApp *lst) { + E_RETURN_IF_FAIL(lst != 0); + String path; + + add(_("None")); + + for(int i = 0; lst[i].name; i++) { + /* first check if file exists in system */ + path = file_path(lst[i].cmd); + if(path.empty()) + continue; + + add(lst[i].name); + } + + add(_("Browse...")); + known_apps = lst; +} + +void AppChoice::add_if_user_program(const char *cmd) { + E_RETURN_IF_FAIL(known_apps != 0); + bool found = false; + + for(int i = 0; known_apps[i].name; i++) { + if(STR_CMP(known_apps[i].cmd, cmd)) { + found = true; + break; + } + } + + if(found) return; + + replace(size() - 2, get_basename(cmd)); + add(_("Browse...")); +} + +void AppChoice::select_by_cmd(const char *cmd) { + E_RETURN_IF_FAIL(cmd != 0); + E_RETURN_IF_FAIL(known_apps != 0); + + int pos; + + for(int i = 0; known_apps[i].name; i++) { + if(STR_CMP(cmd, known_apps[i].cmd)) { + /* now find menu entry with this name */ + pos = find_index(known_apps[i].name); + if(pos >= 0) { + value(pos); + pvalue = pos; + return; + } + } + } +} + +const char *AppChoice::selected(void) { + E_RETURN_VAL_IF_FAIL(known_apps != 0, 0); + int s = value(); + + /* skip first/last elements */ + if(s == 0 || s == (size() - 2)) + return 0; + + const char *n = text(); + + /* first check if user one was selected */ + if(!user_val.empty() && STR_CMP(get_basename(user_val.c_str()), n)); + return user_val.c_str(); + + for(int i = 0; known_apps[i].name; i++) { + if(STR_CMP(known_apps[i].name, n)) + return known_apps[i].cmd; + } + + return 0; +} + +void AppChoice::on_select(void) { + if(value() == (size() - 2)) { + const char *p = fl_file_chooser(_("Choose program"), "*", 0); + if(p) { + /* set it to last place where is 'Browse...', and later move to the end */ + replace(size() - 2, get_basename(p)); + user_val = p; + add(_("Browse...")); + + /* select it */ + value(size() - 3); + return; + } + + value(pvalue); + } + + pvalue = value(); +} diff --git a/ede-preferred-applications/AppChoice.h b/ede-preferred-applications/AppChoice.h new file mode 100644 index 0000000..a6ee95c --- /dev/null +++ b/ede-preferred-applications/AppChoice.h @@ -0,0 +1,27 @@ +#ifndef __APPCHOICE_H__ +#define __APPCHOICE_H__ + +#include +#include +#include "PredefApps.h" + +EDELIB_NS_USING(String) + +/* choices with name/value pair */ +class AppChoice : public Fl_Choice { +private: + KnownApp *known_apps; + /* previous selected val */ + int pvalue; + /* user selected program; for now allow only one */ + String user_val; +public: + AppChoice(int X, int Y, int W, int H, const char *l = 0); + void add_programs(KnownApp *lst); + void add_if_user_program(const char *cmd); + void select_by_cmd(const char *cmd); + const char *selected(void); + void on_select(void); +}; + +#endif diff --git a/ede-preferred-applications/Apps.cpp b/ede-preferred-applications/Apps.cpp deleted file mode 100644 index 63d3577..0000000 --- a/ede-preferred-applications/Apps.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include "Apps.h" - -EDELIB_NS_USING(file_path) -EDELIB_NS_USING(String) - -void app_for_each(KnownApp *lst, KnownAppCb cb, void *data) { - E_RETURN_IF_FAIL(lst != 0); - - for(int i = 0; lst[i].name; i++) - cb(lst[i], data); -} - -KnownApp *app_find_by_cmd(KnownApp *lst, const char *name) { - E_RETURN_VAL_IF_FAIL(lst != 0, 0); - E_RETURN_VAL_IF_FAIL(name, 0); - - for(int i = 0; lst[i].name; i++) - if(strcmp(lst[i].cmd, name) == 0) - return &lst[i]; - return 0; -} - -KnownApp *app_find_by_name(KnownApp *lst, const char *cmd) { - E_RETURN_VAL_IF_FAIL(lst != 0, 0); - E_RETURN_VAL_IF_FAIL(cmd, 0); - - for(int i = 0; lst[i].name; i++) - if(strcmp(lst[i].cmd, cmd) == 0) - return &lst[i]; - return 0; -} - -KnownApp *app_get(KnownApp *lst, int index) { - E_RETURN_VAL_IF_FAIL(lst != 0, 0); - return &lst[index]; -} - -int app_get_index(KnownApp *lst, const char *cmd) { - E_RETURN_VAL_IF_FAIL(lst != 0, -1); - E_RETURN_VAL_IF_FAIL(cmd != 0, -1); - - for(int i = 0; lst[i].name; i++) { - if(strcmp(lst[i].cmd, cmd) == 0) - return i; - } - - return -1; -} - -static void populate_menu(const KnownApp &item, void *data) { - Fl_Choice *c = (Fl_Choice*)data; - const char *cmd = item.cmd; - - /* check some magic values first */ - if(app_is_magic_cmd(cmd)) { - c->add(item.name); - return; - } - - /* check if binary exists */ - String ret = file_path(cmd); - if(ret.empty()) return; - - c->add(item.name); -} - -void app_populate_menu(KnownApp *lst, Fl_Choice *c) { - E_RETURN_IF_FAIL(lst != 0); - E_RETURN_IF_FAIL(c != 0); - - app_for_each(lst, populate_menu, c); -} - -bool app_is_magic_cmd(const char *cmd) { - E_RETURN_VAL_IF_FAIL(cmd != 0, false); - - if(cmd[0] == '_' && strlen(cmd) == 3 && (cmd[1] == 'n' || cmd[1] == 'b')) - return true; - return false; -} - -bool app_is_browse_item(KnownApp *lst, const char *name) { - E_RETURN_VAL_IF_FAIL(lst != 0, false); - E_RETURN_VAL_IF_FAIL(name != 0, false); - - for(int i = 0; lst[i].name; i++) { - if(strcmp(lst[i].name, name) == 0 && app_is_magic_cmd(lst[i].cmd) && lst[i].cmd[1] == 'b') - return true; - } - - return false; -} diff --git a/ede-preferred-applications/Apps.h b/ede-preferred-applications/Apps.h deleted file mode 100644 index 92924a3..0000000 --- a/ede-preferred-applications/Apps.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __EDE_PREFERRED_APPLICATIONS_APPS_H__ -#define __EDE_PREFERRED_APPLICATIONS_APPS_H__ - -class Fl_Choice; - -struct KnownApp { - const char *name; - const char *cmd; -}; - -/* _n_ and _b_ are special predefined values so we from callback knows what to do */ -#define KNOWN_APP_START {_("None"), "_n_"} -#define KNOWN_APP_END \ -{"Browse...", "_b_"}, \ -{0, 0} - -typedef void (*KnownAppCb)(const KnownApp &app, void *data); - -void app_for_each(KnownApp *lst, KnownAppCb cb, void *data = 0); -KnownApp *app_find_by_name(KnownApp *lst, const char *name); -KnownApp *app_find_by_cmd(KnownApp *lst, const char *cmd); -KnownApp *app_get(KnownApp *lst, int index); - -int app_get_index(KnownApp *lst, const char *cmd); -inline int app_get_index(KnownApp *lst, KnownApp &a) { return app_get_index(lst, a.cmd); } - -void app_populate_menu(KnownApp *lst, Fl_Choice *c); - -bool app_is_magic_cmd(const char *cmd); -inline bool app_is_magic_cmd(const KnownApp &a) { return app_is_magic_cmd(a.cmd); } - -bool app_is_browse_item(KnownApp *lst, const char *name); -#endif diff --git a/ede-preferred-applications/Jamfile b/ede-preferred-applications/Jamfile index e324ef4..619e072 100644 --- a/ede-preferred-applications/Jamfile +++ b/ede-preferred-applications/Jamfile @@ -4,7 +4,7 @@ SubDir TOP ede-preferred-applications ; -SOURCE = ede-preferred-applications.cpp Apps.cpp ; +SOURCE = ede-preferred-applications.cpp AppChoice.cpp ; EdeProgram ede-preferred-applications : $(SOURCE) ; TranslationStrings locale : $(SOURCE) ; diff --git a/ede-preferred-applications/PredefApps.h b/ede-preferred-applications/PredefApps.h index 558ad02..8708be3 100644 --- a/ede-preferred-applications/PredefApps.h +++ b/ede-preferred-applications/PredefApps.h @@ -1,10 +1,16 @@ -#ifndef __EDE_PREFERRED_APPLICATIONS_PREDEFAPPS_H__ -#define __EDE_PREFERRED_APPLICATIONS_PREDEFAPPS_H__ +#ifndef __PREDEFAPPS_H__ +#define __PREDEFAPPS_H__ -#include "Apps.h" +#include + +struct KnownApp { + const char *name; + const char *cmd; +}; + +#define KNOWN_APP_END {0, 0} static KnownApp app_browsers[] = { - KNOWN_APP_START, {"Mozilla Firefox", "firefox"}, {"Mozilla Seamonkey", "seamonkey"}, {"Google Chrome", "google-chrome"}, @@ -15,13 +21,11 @@ static KnownApp app_browsers[] = { }; static KnownApp app_mails[] = { - KNOWN_APP_START, {"Mozilla Thunderbird", "thunderbird"}, KNOWN_APP_END }; static KnownApp app_filemanagers[] = { - KNOWN_APP_START, {"Thunar", "thunar"}, {"Nautilus", "nautilus"}, {"Dolphin", "dolphin"}, @@ -30,7 +34,6 @@ static KnownApp app_filemanagers[] = { }; static KnownApp app_terminals[] = { - KNOWN_APP_START, {"X11 terminal", "xterm"}, {"Rxvt", "rxvt"}, {"Mrxvt", "mrxvt"}, diff --git a/ede-preferred-applications/ede-preferred-applications.cpp b/ede-preferred-applications/ede-preferred-applications.cpp index d952eae..2e598d4 100644 --- a/ede-preferred-applications/ede-preferred-applications.cpp +++ b/ede-preferred-applications/ede-preferred-applications.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -15,61 +14,39 @@ #include #include -#include "PredefApps.h" +#include "AppChoice.h" EDELIB_NS_USING_AS(Window, EdeWindow) EDELIB_NS_USING(Resource) -Fl_Choice *browser_choice, +AppChoice *browser_choice, *mail_choice, *filemgr_choice, *term_choice; /* store separate item */ -static void check_and_store(Fl_Choice *c, KnownApp *lst, const char *n, Resource &rc) { - int sel = c->value(); - KnownApp *app = app_get(lst, sel); - if(app_is_magic_cmd(*app)) - return; - - rc.set("Preferred", n, app->cmd); +static void check_and_store(AppChoice *c, const char *n, Resource &rc) { + const char *val = c->selected(); + if(val) rc.set("Preferred", n, val); } /* load separate item */ -static void check_and_load(Fl_Choice *c, KnownApp *lst, const char *n, Resource &rc) { +static void check_and_load(AppChoice *c, const char *n, Resource &rc) { static char buf[128]; - if(!rc.get("Preferred", n, buf, sizeof(buf))) - return; - - KnownApp *app = app_find_by_cmd(lst, buf); - if(!app) return; - - int i = app_get_index(lst, *app); - if(i < 0) return; - - c->value(i); + if(rc.get("Preferred", n, buf, sizeof(buf)) && strlen(buf) > 0) { + c->add_if_user_program(buf); + c->select_by_cmd(buf); + } } static void load_settings(void) { Resource rc; if(!rc.load("ede-launch")) return; - check_and_load(browser_choice, app_browsers, "browser", rc); - check_and_load(mail_choice, app_mails, "mail", rc); - check_and_load(filemgr_choice, app_filemanagers, "file_manager", rc); - check_and_load(term_choice, app_terminals, "terminal", rc); -} - -static void menu_cb(Fl_Widget *widget, void *ww) { - Fl_Choice *c = (Fl_Choice*)widget; - const char *name = c->text(); - KnownApp *lst = (KnownApp*)ww; - - if(!name || !app_is_browse_item(lst, name)) return; - const char *path = fl_file_chooser(_("Choose program"), "*", 0); - - /* go to first, as it will be None */ - if(!path) c->value(0); + check_and_load(browser_choice, "browser", rc); + check_and_load(mail_choice, "mail", rc); + check_and_load(filemgr_choice, "file_manager", rc); + check_and_load(term_choice, "terminal", rc); } static void close_cb(Fl_Widget *widget, void *ww) { @@ -79,11 +56,16 @@ static void close_cb(Fl_Widget *widget, void *ww) { static void ok_cb(Fl_Widget *widget, void *ww) { Resource rc; + /* + * if Resource does not have any items, it will refuse to save anything, keeping + * previous content of conf file. This happens if all items are set to be None + */ + rc.set("Preferred", "dummy", 0); - check_and_store(browser_choice, app_browsers, "browser", rc); - check_and_store(mail_choice, app_mails, "mail", rc); - check_and_store(filemgr_choice, app_filemanagers, "file_manager", rc); - check_and_store(term_choice, app_terminals, "terminal", rc); + check_and_store(browser_choice, "browser", rc); + check_and_store(mail_choice, "mail", rc); + check_and_store(filemgr_choice, "file_manager", rc); + check_and_store(term_choice, "terminal", rc); rc.save("ede-launch"); close_cb(widget, ww); @@ -97,33 +79,25 @@ int main(int argc, char** argv) { tabs->begin(); Fl_Group *gint = new Fl_Group(15, 30, 335, 140, _("Internet")); gint->begin(); - browser_choice = new Fl_Choice(20, 65, 320, 25, _("Web browser")); - browser_choice->align(FL_ALIGN_TOP_LEFT); - app_populate_menu(app_browsers, browser_choice); + browser_choice = new AppChoice(20, 65, 320, 25, _("Web browser")); + browser_choice->add_programs(app_browsers); browser_choice->value(0); - browser_choice->callback(menu_cb, app_browsers); - mail_choice = new Fl_Choice(20, 120, 320, 25, _("Mail reader")); - mail_choice->align(FL_ALIGN_TOP_LEFT); - app_populate_menu(app_mails, mail_choice); + mail_choice = new AppChoice(20, 120, 320, 25, _("Mail reader")); + mail_choice->add_programs(app_mails); mail_choice->value(0); - mail_choice->callback(menu_cb, app_mails); gint->end(); Fl_Group *gutil = new Fl_Group(15, 30, 335, 140, _("Utilities")); gutil->hide(); gutil->begin(); - filemgr_choice = new Fl_Choice(20, 65, 320, 25, _("File manager")); - filemgr_choice->align(FL_ALIGN_TOP_LEFT); - app_populate_menu(app_filemanagers, filemgr_choice); + filemgr_choice = new AppChoice(20, 65, 320, 25, _("File manager")); + filemgr_choice->add_programs(app_filemanagers); filemgr_choice->value(0); - filemgr_choice->callback(menu_cb, app_filemanagers); - term_choice = new Fl_Choice(20, 120, 320, 25, _("Terminal")); - term_choice->align(FL_ALIGN_TOP_LEFT); - app_populate_menu(app_terminals, term_choice); + term_choice = new AppChoice(20, 120, 320, 25, _("Terminal")); + term_choice->add_programs(app_terminals); term_choice->value(0); - term_choice->callback(menu_cb, app_terminals); gutil->end(); tabs->end();