From: skeezix Date: Wed, 9 Feb 2011 18:21:12 +0000 (-0500) Subject: mmenu; nearly done support for custom categories; not quite done, but nearly. X-Git-Tag: sz_beta3~78 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=commitdiff_plain;h=1db3cb8983949073d9fd9738072923521456c64c mmenu; nearly done support for custom categories; not quite done, but nearly. --- diff --git a/Makefile b/Makefile index 4220ac6..1f67e20 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_ all: ${SOLIB} ${LIB} conftest discotest evdevtest notifytest pndnotifyd rawpxmltest pndvalidator loggertest dbusnotifytest pnd_run pndevmapperd pnd_info evtest mmenu mmwrapper clean: - ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o evdevtest.o bin/evdevtest bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/* evtest.o bin/evtest bin/mmenu bin/mmwrapper mmenu.o mmwrapper.o deployment/usr/bin/mmenu deployment/usr/bin/mmwrapper mmcache.o mmui.o mmcat.o mmconf.o freedsktop_cats.o freedesktop_cats.o + ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o evdevtest.o bin/evdevtest bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/* evtest.o bin/evtest bin/mmenu bin/mmwrapper mmenu.o mmwrapper.o deployment/usr/bin/mmenu deployment/usr/bin/mmwrapper mmcache.o mmui.o mmcat.o mmconf.o freedsktop_cats.o freedesktop_cats.o mmcustom_cats.o ${RM} -rf deployment/media deployment/etc/pandora/mmenu find . -name "*~*" -exec rm {} \; -print @@ -60,8 +60,8 @@ pnd_info: pnd_info.o ${SOLIB1} pndevmapperd: pndevmapperd.o ${SOLIB1} ${CC} -lstdc++ -o bin/pndevmapperd pndevmapperd.o ${SOLIB1} -mmenu: mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o ${SOLIB1} - ${CC} -lstdc++ -o bin/mmenu mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o ${SOLIB1} -L${PNDSTUFF}/usr/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_gfx +mmenu: mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o mmcustom_cats.o ${SOLIB1} + ${CC} -lstdc++ -o bin/mmenu mmenu.o mmui.o mmcache.o mmcat.o mmconf.o freedesktop_cats.o mmcustom_cats.o ${SOLIB1} -L${PNDSTUFF}/usr/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_gfx mmwrapper: mmwrapper.o ${SOLIB1} ${CC} -lstdc++ -o bin/mmwrapper mmwrapper.o ${SOLIB1} diff --git a/minimenu/mmcat.c b/minimenu/mmcat.c index 2bf84e6..a8c40a6 100644 --- a/minimenu/mmcat.c +++ b/minimenu/mmcat.c @@ -363,7 +363,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco if ( ! fdcat ) { // requested cat is bad, send it to Other cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); // do the Other substitution right away, so remaining code has something to look at in fdcat fdcat = freedesktop_category_query ( BADCATNAME, NULL ); @@ -381,7 +381,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco if ( ! fdpcat ) { // requested cat is bad, send it to Other cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> parent bad cat\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); // fix immediately so code doesn't explode parentcatname = NULL; } else { @@ -401,12 +401,12 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco if ( fdcat -> parent_cat == NULL ) { // but wait, catname is actually a parent cat... cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child, but FD says its a parent\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child, but FD says its a parent\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); } if ( fdpcat -> parent_cat ) { // but wait, parent cat is actually a subcat! cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> parent cat, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> parent cat, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); } } else { @@ -415,7 +415,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco if ( fdcat -> parent_cat ) { // but wait, cat actually has a parent! cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be parent, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be parent, FD says its a child\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); } } @@ -427,11 +427,11 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco { // child cat points to a different parent than requested parent! cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (1)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (1)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); } else if ( strcasecmp ( fdcat -> parent_cat, fdpcat -> cat ) != 0 ) { // child cat points to a different parent than requested parent! cat_is_clean = 0; - printf ( "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (2)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); + pnd_log ( pndn_warning, "PXML Fail %s: Cat request %s (parent %s) -> cat wants to be child of a cat which FD says is the wrong parent (2)\n", app -> title_en ? app -> title_en : "no name?", catname, parentcatname ? parentcatname : "n/a" ); } } @@ -529,7 +529,7 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco // is app already in the target cat? (ie: its being pushed twice due to cat mapping or Other'ing or something..) if ( app ) { if ( category_contains_app ( catname, parentcatname, app -> unique_id ) ) { - printf ( "App Fail: app (%s %s) is already in cat %s\n", app -> title_en ? app -> title_en : "no name?", app -> unique_id, catname ); + pnd_log ( pndn_warning, "App Fail: app (%s %s) is already in cat %s\n", app -> title_en ? app -> title_en : "no name?", app -> unique_id, catname ); return ( 1 ); // success, already there! } } diff --git a/minimenu/mmcustom_cats.c b/minimenu/mmcustom_cats.c new file mode 100644 index 0000000..7cb341a --- /dev/null +++ b/minimenu/mmcustom_cats.c @@ -0,0 +1,225 @@ + +#include +#include /* for PATH_MAX */ +#define __USE_GNU /* for strndup */ +#include /* for strdup */ +#include /* getenv */ + +#include "pnd_container.h" +#include "pnd_conf.h" +#include "pnd_discovery.h" +#include "pnd_notify.h" +#include "pnd_dbusnotify.h" +#include "pnd_logger.h" + +#include "mmenu.h" +#include "mmcustom_cats.h" + +mmcustom_cat_t mmcustom_complete [ MMCUSTOM_CATS_MAX ]; +unsigned int mmcustom_count = 0; + +pnd_conf_handle g_custom_h = 0; + +char *mmcustom_determine_path ( void ) { + char *home = getenv ( "HOME" ); + static char path [ PATH_MAX ]; + bzero ( path, PATH_MAX ); + + snprintf ( path, PATH_MAX - 1, "%s/%s", home ? home : ".", MMCUSTOM_CATS_PREF_FILENAME ); + + return ( path ); +} + +static unsigned char loaded = 0; +unsigned char mmcustom_setup ( void ) { + + if ( ! loaded ) { + loaded = 1; + + // inhale conf file + char *path = mmcustom_determine_path(); + + g_custom_h = pnd_conf_fetch_by_path ( path ); + + if ( ! g_custom_h ) { + pnd_log ( pndn_rem, "Custom category conf file %s not found; is okay.\n", path ); + return ( 1 ); // file does not exist most likely + } + + // find its head; if no head (empty file), bail + char *iter = pnd_box_get_head ( g_custom_h ); + + if ( ! iter ) { + pnd_log ( pndn_rem, "Custom category conf file %s is empty. Fine.\n", path ); + return ( 1 ); + } + + // walk the conf, plucking out the values + while ( iter ) { + char *k = pnd_box_get_key ( iter ); + + // does this entry look like it is a custom category? + if ( strncmp ( k, MMCUSTOM_CATS_SECTION, strlen ( MMCUSTOM_CATS_SECTION ) ) == 0 ) { + // determine the actual category name part + k += ( strlen ( MMCUSTOM_CATS_SECTION ) + 1 ); + + mmcustom_complete [ mmcustom_count ].cat = strdup ( k ); + if ( iter && strcmp ( iter, MMCUSTOM_CATS_NOCAT ) != 0 ) { + mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( iter ); + } else { + mmcustom_complete [ mmcustom_count ].parent_cat = NULL; + } + + mmcustom_count += 1; + + } + + // next! + iter = pnd_box_get_next ( iter ); + + } // while + + pnd_log ( pndn_rem, "Found %u custom categories.\n", mmcustom_count ); + + } // loaded already? + + return ( 1 ); +} + +void mmcustom_shutdown ( void ) { + + bzero ( mmcustom_complete, sizeof(mmcustom_cat_t) * MMCUSTOM_CATS_MAX ); + mmcustom_count = 0; + loaded = 0; + + return; +} + +unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ) { + + if ( ! fullpath ) { + fullpath = mmcustom_determine_path(); + } + + FILE *f = fopen ( fullpath, "w" ); + + if ( ! f ) { + return ( 0 ); + } + + int i; + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].cat ) { + fprintf ( f, "%s.%s\t%s\n", MMCUSTOM_CATS_SECTION, mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat ? mmcustom_complete [ i ].parent_cat : MMCUSTOM_CATS_NOCAT ); + } + } + + fclose ( f ); + + return ( 1 ); +} + +mmcustom_cat_t *mmcustom_query ( char *name, char *parentcatname ) { + int i; + + // search for the cat/parent combination + for ( i = 0; i < mmcustom_count; i++ ) { + mmcustom_cat_t *p = &(mmcustom_complete [ i ]); + + if ( strcasecmp ( p -> cat, name ) == 0 ) { + + if ( parentcatname == NULL && p -> parent_cat == NULL ) { + return ( p ); + } else if ( parentcatname && p -> parent_cat && strcasecmp ( p -> parent_cat, parentcatname ) == 0 ) { + return ( p ); + } + + } + + } // for + + return ( NULL ); +} + +mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname ) { + mmcustom_complete [ mmcustom_count ].cat = strdup ( catname ); + if ( parentcatname ) { + mmcustom_complete [ mmcustom_count ].parent_cat = strdup ( parentcatname ); + } + mmcustom_count += 1; + return ( &(mmcustom_complete [ mmcustom_count - 1 ]) ); +} + +unsigned int mmcustom_count_subcats ( char *catname ) { + int i; + unsigned int counter = 0; + + for ( i = 0; i < mmcustom_count; i++ ) { + + if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 ) { + counter++; + } + + } + + return ( counter ); +} + +void mmcustom_unregister ( char *catname, char *parentcatname ) { + int i; + int parent_index = -1; + + if ( parentcatname ) { + pnd_log ( pndn_warning, "Goal: Remove subcat %s of %s\n", catname, parentcatname ); + } else { + pnd_log ( pndn_warning, "Goal: Remove parent cat %s and descendants\n", catname ); + } + + for ( i = 0; i < mmcustom_count; i++ ) { + + // killing a parent cat, or just a subcat? + if ( parentcatname ) { + + // killing a subcat, so match cat+subcat to kill + if ( mmcustom_complete [ i ].cat && strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 && + mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, parentcatname ) == 0 ) + { + pnd_log ( pndn_warning, " Removing subcat: %s of %s\n", catname, parentcatname ); + free ( mmcustom_complete [ i ].cat ); + mmcustom_complete [ i ].cat = NULL; + break; + } + + } else { + + // killing a parent cat, so kill it, and any children of it + if ( mmcustom_complete [ i ].parent_cat == NULL && + mmcustom_complete [ i ].cat && + strcmp ( mmcustom_complete [ i ].cat, catname ) == 0 ) + { + // flag the prent for future death (we need its name for now, since the caller is using it) + parent_index = i; + } + else if ( mmcustom_complete [ i ].cat && + mmcustom_complete [ i ].parent_cat && + strcmp ( mmcustom_complete [ i ].parent_cat, catname ) == 0 ) + { + // kill children of it + pnd_log ( pndn_warning, " Removing cascading subcat: %s of %s\n", mmcustom_complete [ i ].cat, mmcustom_complete [ i ].parent_cat ); + free ( mmcustom_complete [ i ].cat ); + mmcustom_complete [ i ].cat = NULL; + } + + } + + } // for + + // kill the actual cat itself + if ( i >= 0 ) { + pnd_log ( pndn_warning, " Removing cat: %s\n", catname ); + free ( mmcustom_complete [ i ].cat ); + mmcustom_complete [ i ].cat = NULL; + } + + return; +} diff --git a/minimenu/mmcustom_cats.h b/minimenu/mmcustom_cats.h new file mode 100644 index 0000000..a003451 --- /dev/null +++ b/minimenu/mmcustom_cats.h @@ -0,0 +1,32 @@ + +#ifndef h_mmcustom_cats_h +#define h_mmcustom_cats_h + +#define MMCUSTOM_CATS_MAX 255 +#define MMCUSTOM_CATS_PREF_FILENAME ".mmcats.conf" + +#define MMCUSTOM_CATS_SECTION "custom_categories" + +#define MMCUSTOM_CATS_NOCAT "*parent*" + +typedef struct { + char *cat; + char *parent_cat; +} mmcustom_cat_t; + +extern mmcustom_cat_t mmcustom_complete[]; +extern unsigned int mmcustom_count; + +unsigned char mmcustom_setup ( void ); // load +void mmcustom_shutdown ( void ); // unload +unsigned char mmcustom_write ( char *fullpath /* if NULL, uses canonical location */ ); // save +char *mmcustom_determine_path ( void ); + +mmcustom_cat_t *mmcustom_query ( char *catname, char *parentcatname ); // parentcatname NULL for parents + +mmcustom_cat_t *mmcustom_register ( char *catname, char *parentcatname ); +void mmcustom_unregister ( char *catname, char *parentcatname ); + +unsigned int mmcustom_count_subcats ( char *catname ); + +#endif diff --git a/minimenu/mmui.c b/minimenu/mmui.c index ceffeca..1770897 100644 --- a/minimenu/mmui.c +++ b/minimenu/mmui.c @@ -41,6 +41,7 @@ #include "mmconf.h" #include "mmui_context.h" #include "freedesktop_cats.h" +#include "mmcustom_cats.h" #define CHANGED_NOTHING (0) #define CHANGED_CATEGORY (1<<0) /* changed to different category */ @@ -1342,6 +1343,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { "Reveal hidden category", "Shutdown Pandora", "Configure Minimenu", + "Manage custom app categories", "Rescan for applications", "Cache previews to SD now", "Run a terminal/console", @@ -1350,7 +1352,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { "Select a Minimenu skin", "About Minimenu" }; - int sel = ui_modal_single_menu ( opts, 10, "Minimenu", "Enter to select; other to return." ); + int sel = ui_modal_single_menu ( opts, 11, "Minimenu", "Enter to select; other to return." ); char buffer [ 100 ]; if ( sel == 0 ) { @@ -1368,12 +1370,15 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { emit_and_quit ( MM_RESTART ); } } else if ( sel == 3 ) { + // manage custom categories + ui_manage_categories(); + } else if ( sel == 4 ) { // rescan apps pnd_log ( pndn_debug, "Freeing up applications\n" ); applications_free(); pnd_log ( pndn_debug, "Rescanning applications\n" ); applications_scan(); - } else if ( sel == 4 ) { + } else if ( sel == 5 ) { // cache preview to SD now extern pnd_box_handle g_active_apps; pnd_box_handle h = g_active_apps; @@ -1396,7 +1401,7 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { iter = pnd_box_get_next ( iter ); } // while - } else if ( sel == 5 ) { + } else if ( sel == 6 ) { // run terminal char *argv[5]; argv [ 0 ] = pnd_conf_get_as_char ( g_conf, "utility.terminal" ); @@ -1406,18 +1411,18 @@ void ui_process_input ( pnd_dbusnotify_handle dbh, pnd_notify_handle nh ) { ui_forkexec ( argv ); } - } else if ( sel == 6 ) { + } else if ( sel == 7 ) { char buffer [ PATH_MAX ]; sprintf ( buffer, "%s %s\n", MM_RUN, "/usr/pandora/scripts/op_switchgui.sh" ); emit_and_quit ( buffer ); - } else if ( sel == 7 ) { - emit_and_quit ( MM_QUIT ); } else if ( sel == 8 ) { + emit_and_quit ( MM_QUIT ); + } else if ( sel == 9 ) { // select skin if ( ui_pick_skin() ) { emit_and_quit ( MM_RESTART ); } - } else if ( sel == 9 ) { + } else if ( sel == 10 ) { // about char buffer [ PATH_MAX ]; sprintf ( buffer, "%s/about.txt", g_skinpath ); @@ -3576,6 +3581,16 @@ void ui_menu_context ( mm_appref_t *a ) { return; } +unsigned char ui_menu_oneby ( char *title, char *footer, char *one ) { + char *opts [ 2 ]; + opts [ 0 ] = one; + int sel = ui_modal_single_menu ( opts, 1, title, footer ); + if ( sel < 0 ) { + return ( 0 ); + } + return ( sel + 1 ); +} + unsigned char ui_menu_twoby ( char *title, char *footer, char *one, char *two ) { char *opts [ 3 ]; opts [ 0 ] = one; @@ -3696,6 +3711,10 @@ unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialva char *eol = strchr ( r_buffer, '\0' ); *( eol - 1 ) = '\0'; } + + } else if ( event.key.keysym.sym == SDLK_UP ) { + r_buffer [ 0 ] = '\0'; // truncate! + } else if ( event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_END ) { // return, or "B" return ( 1 ); @@ -3801,3 +3820,282 @@ unsigned char ovr_replace_or_add ( mm_appref_t *a, char *keybase, char *newvalue return ( 1 ); } + +void ui_manage_categories ( void ) { + unsigned char require_app_scan = 0; + + if ( ! mmcustom_setup() ) { + return; // error + } + + char *opts [ 20 ] = { + "List custom categories", + "List custom subcategories", + "Register custom category", + "Register custom subcategory", + "Unregister custom category", + "Unregister custom subcategory", + "Done" + }; + + while ( 1 ) { + + int sel = ui_modal_single_menu ( opts, 7, "Custom Categories", "B to select; other to cancel." ); + + switch ( sel ) { + + case 0: // list custom + if ( mmcustom_count ) { + ui_pick_custom_category(); + } else { + ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." ); + } + break; + + case 1: // list custom sub + if ( mmcustom_count ) { + + int maincat = ui_pick_custom_category(); + + if ( maincat >= 0 ) { + unsigned int subcount = mmcustom_count_subcats ( mmcustom_complete [ maincat ].cat ); + char titlebuf [ 201 ]; + + snprintf ( titlebuf, 200, "Category: %s", mmcustom_complete [ maincat ].cat ); + + if ( subcount == 0 ) { + ui_menu_oneby ( titlebuf, "B/Enter to accept", "Category has no subcategories." ); + } else { + + char **list = malloc ( subcount * sizeof(char*) ); + int i; + unsigned int counter = 0; + + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, mmcustom_complete [ maincat ].cat ) == 0 ) { + list [ counter++ ] = mmcustom_complete [ i ].cat; + } + } + + ui_modal_single_menu ( list, counter, titlebuf, "Any button to exit." ); + + free ( list ); + + } // more than 0 subcats? + + } // user picked a main cat? + + } else { + ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." ); + } + break; + + case 2: // register custom + { + unsigned char changed; + char namebuf [ 101 ] = ""; + + changed = ui_menu_get_text_line ( "Enter unique category name", "Use keyboard; Enter when done.", + "Pandora", namebuf, 30, 0 /* alphanumeric */ ); + + // did the user enter something? + if ( changed ) { + + // and if so, is it existant already or not? + if ( mmcustom_query ( namebuf, NULL ) ) { + ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a registered category." ); + } else if ( freedesktop_category_query ( namebuf, NULL ) ) { + ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a Standard category." ); + } else { + + char confirm [ 1001 ]; + snprintf ( confirm, 1000, "Confirm: %s", namebuf ); + + if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm new category", "Do not register" ) == 1 ) { + // register, save, recycle the current list + mmcustom_register ( namebuf, NULL ); + mmcustom_write ( NULL ); + mmcustom_shutdown(); + mmcustom_setup(); + } + + } // dupe? + + } // entered something? + + } + break; + + case 3: // register custom sub + if ( mmcustom_count ) { + + int maincat = ui_pick_custom_category(); + + if ( maincat >= 0 ) { + char titlebuf [ 201 ]; + + snprintf ( titlebuf, 200, "Subcat of: %s", mmcustom_complete [ maincat ].cat ); + + unsigned char changed; + char namebuf [ 101 ] = ""; + + changed = ui_menu_get_text_line ( titlebuf, "Use keyboard; Enter when done.", "Submarine", namebuf, 30, 0 /* alphanumeric */ ); + + // did the user enter something? + if ( changed ) { + + // and if so, is it existant already or not? + if ( mmcustom_query ( namebuf, mmcustom_complete [ maincat ].cat ) ) { + ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a subcategory." ); + } else if ( freedesktop_category_query ( namebuf, mmcustom_complete [ maincat ].cat ) ) { + ui_menu_oneby ( "Warning", "B/Enter to accept", "Already a Standard subcategory." ); + } else { + + char confirm [ 1001 ]; + snprintf ( confirm, 1000, "Confirm: %s [%s]", namebuf, mmcustom_complete [ maincat ].cat ); + + if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm new category", "Do not register" ) == 1 ) { + // register, save, recycle the current list + mmcustom_register ( namebuf, mmcustom_complete [ maincat ].cat ); + mmcustom_write ( NULL ); + mmcustom_shutdown(); + mmcustom_setup(); + } + + } // dupe? + + } // entered something? + + } // selected parent cat? + + } else { + ui_menu_oneby ( "Warning", "B/Enter to accept", "No categories registered." ); + } + break; + + case 4: // unreg custom + if ( mmcustom_count ) { + int maincat = ui_pick_custom_category(); + + if ( maincat >= 0 ) { + char confirm [ 1001 ]; + snprintf ( confirm, 1000, "Confirm remove: %s", mmcustom_complete [ maincat ].cat ); + + if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm unregister", "Do not unregister" ) == 1 ) { + // register, save, recycle the current list + mmcustom_unregister ( mmcustom_complete [ maincat ].cat, NULL ); + mmcustom_write ( NULL ); + mmcustom_shutdown(); + mmcustom_setup(); + } + + } // picked? + + } else { + ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." ); + } + break; + + case 5: // unreg custom sub + if ( mmcustom_count ) { + int maincat = ui_pick_custom_category(); + + if ( maincat >= 0 ) { + unsigned int subcount = mmcustom_count_subcats ( mmcustom_complete [ maincat ].cat ); + char titlebuf [ 201 ]; + + snprintf ( titlebuf, 200, "Category: %s", mmcustom_complete [ maincat ].cat ); + + if ( subcount == 0 ) { + ui_menu_oneby ( titlebuf, "B/Enter to accept", "Category has no subcategories." ); + } else { + + char **list = malloc ( subcount * sizeof(char*) ); + int i; + unsigned int counter = 0; + + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].parent_cat && strcasecmp ( mmcustom_complete [ i ].parent_cat, mmcustom_complete [ maincat ].cat ) == 0 ) { + list [ counter++ ] = mmcustom_complete [ i ].cat; + } + } + + int sel = ui_modal_single_menu ( list, counter, titlebuf, "B to selct; other to exit." ); + + if ( sel >= 0 ) { + char confirm [ 1001 ]; + snprintf ( confirm, 1000, "Confirm remove: %s", list [ sel ] ); + + if ( ui_menu_twoby ( confirm, "B/enter; other to cancel", "Confirm unregister", "Do not unregister" ) == 1 ) { + // register, save, recycle the current list + mmcustom_unregister ( list [ sel ], mmcustom_complete [ maincat ].cat ); + mmcustom_write ( NULL ); + mmcustom_shutdown(); + mmcustom_setup(); + } + + } // confirm kill? + + free ( list ); + + } // more than 0 subcats? + + } // user picked a main cat? + + } else { + ui_menu_oneby ( "Warning", "B/Enter to accept", "There are none registered." ); + } + break; + + } // switch + + // exeunt + if ( sel < 0 || sel > 5 ) { + break; + } + + } // while running the menu + + // shut down custom cats + mmcustom_shutdown(); + + // reload apps? + if ( require_app_scan ) { + applications_free(); + applications_scan(); + } + + // redraw + render_mask |= CHANGED_EVERYTHING; + + return; +} + +int ui_pick_custom_category ( void ) { + char **list = malloc ( mmcustom_count * sizeof(char*) ); + int i; + unsigned int counter = 0; + + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].parent_cat == NULL ) { + list [ counter++ ] = mmcustom_complete [ i ].cat; + } + } + + int sel = ui_modal_single_menu ( list, counter, "Custom Main Categories", "Any button to exit." ); + + counter = 0; + for ( i = 0; i < mmcustom_count; i++ ) { + if ( mmcustom_complete [ i ].parent_cat == NULL ) { + if ( counter == sel ) { + free ( list ); + return ( i ); + } + counter ++; + } + } + + free ( list ); + + return ( -1 ); +} diff --git a/minimenu/mmui.h b/minimenu/mmui.h index 7472294..65cdb71 100644 --- a/minimenu/mmui.h +++ b/minimenu/mmui.h @@ -74,6 +74,8 @@ void ui_post_scan ( void ); unsigned char ui_show_info ( char *pndrun, pnd_disco_t *p ); void ui_aboutscreen ( char *textpath ); void ui_revealscreen ( void ); +void ui_manage_categories ( void ); +int ui_pick_custom_category ( void ); /* internal functions follow */ @@ -120,6 +122,7 @@ unsigned int ui_callback_f ( unsigned int t ); // 'popup' 'context' menu void ui_menu_context ( mm_appref_t *a ); +unsigned char ui_menu_oneby ( char *title, char *footer, char *one ); // return 0 (nada) or 1 (one) for they actually picked it unsigned char ui_menu_twoby ( char *title, char *footer, char *one, char *two ); // return 0 (nada), 1 (one), 2 (two) unsigned char ui_menu_get_text_line ( char *title, char *footer, char *initialvalue, char *r_buffer, unsigned char maxlen, unsigned char numbersonlyp ); // populates r_buffer