From: skeezix Date: Fri, 28 Jan 2011 04:35:39 +0000 (-0500) Subject: Stricter freedesktop categry enforcement; no more letting crummy or StUdLy-caps or... X-Git-Tag: sz_beta3~99 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29680fa01e21a304104ffb160d32dad5e62d5dc8;p=pandora-libraries.git Stricter freedesktop categry enforcement; no more letting crummy or StUdLy-caps or bogus categories through into tabs. Also, order subcat-folders (if active) to front of applications. --- diff --git a/minimenu/freedesktop_cats.c b/minimenu/freedesktop_cats.c index b90341f..27b6276 100644 --- a/minimenu/freedesktop_cats.c +++ b/minimenu/freedesktop_cats.c @@ -8,167 +8,169 @@ // http://standards.freedesktop.org/menu-spec/latest/apa.html // -char *freedesktop_approved_cats[] = { - "AudioVideo", - "Audio", - "Video", - "Development", - "Education", - "Game", - "Graphics", - "Network", - "Office", - "Settings", - "System", - "Utility", - "Building", - "Debugger", - "IDE", - "GUIDesigner", - "Profiling", - "RevisionControl", - "Translation", - "Calendar", - "ContactManagement", - "Database", - "Dictionary", - "Chart", - "Email", - "Finance", - "FlowChart", - "PDA", - "ProjectManagement", - "Presentation", - "Spreadsheet", - "WordProcessor", - "2DGraphics", - "VectorGraphics", - "RasterGraphics", - "3DGraphics", - "Scanning", - "OCR", - "Photography", - "Publishing", - "Viewer", - "TextTools", - "DesktopSettings", - "HardwareSettings", - "Printing", - "PackageManager", - "Dialup", - "InstantMessaging", - "Chat", - "IRCClient", - "FileTransfer", - "HamRadio", - "News", - "P2P", - "RemoteAccess", - "Telephony", - "TelephonyTools", - "VideoConference", - "WebBrowser", - "WebDevelopment", - "Midi", - "Mixer", - "Sequencer", - "Tuner", - "TV", - "AudioVideoEditing", - "Player", - "Recorder", - "DiscBurning", - "ActionGame", - "AdventureGame", - "ArcadeGame", - "BoardGame", - "BlocksGame", - "CardGame", - "KidsGame", - "LogicGame", - "RolePlaying", - "Simulation", - "SportsGame", - "StrategyGame", - "Art", - "Construction", - "Music", - "Languages", - "Science", - "ArtificialIntelligence", - "Astronomy", - "Biology", - "Chemistry", - "ComputerScience", - "DataVisualization", - "Economy", - "Electricity", - "Geography", - "Geology", - "Geoscience", - "History", - "ImageProcessing", - "Literature", - "Math", - "NumericalAnalysis", - "MedicalSoftware", - "Physics", - "Robotics", - "Sports", - "ParallelComputing", - "Amusement", - "Archiving", - "Compression", - "Electronics", - "Emulator", - "Engineering", - "FileTools", - "FileManager", - "TerminalEmulator", - "Filesystem", - "Monitor", - "Security", - "Accessibility", - "Calculator", - "Clock", - "TextEditor", - "Documentation", - "Core", - "KDE", - "GNOME", - "GTK", - "Qt", - "Motif", - "Java", - "ConsoleOnly", - "Screensaver", - "TrayIcon", - "Applet", - "Shell", - NULL +freedesktop_cat_t freedesktop_complete[] = { + + // HACK + { BADCATNAME, NULL, "Lazy PXML dev is lazy." }, + // HACK + + { "AudioVideo", NULL, "A multimedia (audio/video) application" }, + { "Audio", NULL, "An audio application" }, + { "Video", NULL, "A video application" }, + { "Development", NULL, "An application for development" }, + { "Education", NULL, "Educational software" }, + { "Game", NULL, "A game" }, + { "Graphics", NULL, "Graphical application" }, + { "Network", NULL, "Network application such as a web browser" }, + { "Office", NULL, "An office type application" }, + { "Settings", NULL, "Settings applications" }, + { "System", NULL, "System application" }, + { "Utility", NULL, "Small utility application" }, + + { "Building", "Development", "A tool to build applications " }, + { "Debugger", "Development", "A tool to debug applications" }, + { "IDE", "Development", "IDE application " }, + { "GUIDesigner", "Development", "A GUI designer application " }, + { "Profiling", "Development", "A profiling tool " }, + { "RevisionControl", "Development", "Applications like cvs or subversion " }, + { "Translation", "Development", "A translation tool " }, + { "Calendar", "Office", "Calendar application " }, + { "ContactManagement", "Office", "E.g. an address book " }, + { "Database", "Office", "Application to manage a database " }, + { "Dictionary", "Office", "A dictionary " }, + { "Chart", "Office", "Chart application" }, + { "Email", "Office", "Email application" }, + { "Finance", "Office", "Application to manage your finance " }, + { "FlowChart", "Office", "A flowchart application " }, + { "PDA", "Office", "Tool to manage your PDA " }, + { "ProjectManagement", "Office", "Project management application " }, + { "Presentation", "Office", "Presentation software " }, + { "Spreadsheet", "Office", "A spreadsheet " }, + { "WordProcessor", "Office", "A word processor " }, + { "2DGraphics", "Graphics", "2D based graphical application " }, + { "VectorGraphics", "Graphics", "Vector based graphical application " }, + { "RasterGraphics", "Graphics", "Raster based graphical application " }, + { "3DGraphics", "Graphics", "3D based graphical application " }, + { "Scanning", "Graphics", "Tool to scan a file/text " }, + { "OCR", "Graphics", "Optical character recognition application " }, + { "Photography", "Graphics", "Camera tools, etc. " }, + { "Publishing", "Graphics", "Desktop Publishing applications and Color Management tools " }, + { "Viewer", "Graphics", "Tool to view e.g. a graphic or pdf file " }, + { "TextTools", "Utility", "A text tool utiliy " }, + { "DesktopSettings", "Settings", "Configuration tool for the GUI " }, + { "HardwareSettings", "Settings", "A tool to manage hardware components, like sound cards, video cards or printers " }, + { "Printing", "Settings", "A tool to manage printers " }, + { "PackageManager", "Settings", "A package manager application " }, + { "Dialup", "Network", "A dial-up program " }, + { "InstantMessaging", "Network", "An instant messaging client " }, + { "Chat", "Network", "A chat client" }, + { "IRCClient", "Network", "An IRC client" }, + { "FileTransfer", "Network", "Tools like FTP or P2P programs " }, + { "HamRadio", "Network", "HAM radio software " }, + { "News", "Network", "A news reader or a news ticker " }, + { "P2P", "Network", "A P2P program " }, + { "RemoteAccess", "Network", "A tool to remotely manage your PC " }, + { "Telephony", "Network", "Telephony via PC " }, + { "TelephonyTools", "Utility", "Telephony tools, to dial a number, manage PBX, ... " }, + { "VideoConference", "Network", "Video Conference software " }, + { "WebBrowser", "Network", "A web browser " }, + { "WebDevelopment", "Network", "A tool for web developers " }, + { "Midi", "AudioVideo", "An app related to MIDI " }, + { "Mixer", "AudioVideo", "Just a mixer " }, + { "Sequencer", "AudioVideo", "A sequencer " }, + { "Tuner", "AudioVideo", "A tuner " }, + { "TV", "AudioVideo", "A TV application" }, + { "AudioVideoEditing", "Audio", "Application to edit audio/video files " }, + { "Player", "Audio", "Application to play audio/video files " }, + { "Recorder", "Audio", "Application to record audio/video files " }, + { "DiscBurning", "AudioVideo", "Application to burn a disc " }, + { "ActionGame", "Game", "An action game " }, + { "AdventureGame", "Game", "Adventure style game" }, + { "ArcadeGame", "Game", "Arcade style game" }, + { "BoardGame", "Game", "A board game" }, + { "BlocksGame", "Game", "Falling blocks game" }, + { "CardGame", "Game", "A card game " }, + { "KidsGame", "Game", "A game for kids" }, + { "LogicGame", "Game", "Logic games like puzzles, etc " }, + { "RolePlaying", "Game", "A role playing game " }, + { "Simulation", "Game", "A simulation game " }, + { "SportsGame", "Game", "A sports game " }, + { "StrategyGame", "Game", "A strategy game " }, + { "Art", "Education", "Software to teach arts " }, + { "Construction", "Education", NULL }, + { "Music", "Audio", "Musical software" }, + { "Languages", "Education", "Software to learn foreign languages " }, + { "Science", "Education", "Scientific software " }, + { "ArtificialIntelligence", "Education", "Artificial Intelligence software " }, + { "Astronomy", "Education", "Astronomy software " }, + { "Biology", "Education", "Biology software " }, + { "Chemistry", "Education", "Chemistry software " }, + { "ComputerScience", "Education", "ComputerSience software " }, + { "DataVisualization", "Education", "Data visualization software " }, + { "Economy", "Education", "Economy software " }, + { "Electricity", "Education", "Electricity software" }, + { "Geography", "Education", "Geography software" }, + { "Geology", "Education", "Geology software" }, + { "Geoscience", "Education", "Geoscience software" }, + { "History", "Education", "History software" }, + { "ImageProcessing", "Education", "Image Processing software " }, + { "Literature", "Education", "Literature software " }, + { "Math", "Education", "Math software " }, + { "NumericalAnalysis", "Education", "Numerical analysis software " }, + { "MedicalSoftware", "Education", "Medical software " }, + { "Physics", "Education", "Physics software " }, + { "Robotics", "Education", "Robotics software " }, + { "Sports", "Education", "Sports software " }, + { "ParallelComputing", "Education", "Parallel computing software " }, + { "Amusement", NULL, "A simple amusement " }, + { "Archiving", "Utility", "A tool to archive/backup data " }, + { "Compression", "Utility", "A tool to manage compressed data/archives " }, + { "Electronics", NULL, "Electronics software, e.g. a circuit designer" }, + { "Emulator", "Game", "Emulator of another platform, such as a DOS emulator " }, + { "Engineering", NULL, "Engineering software, e.g. CAD programs " }, + { "FileTools", "Utility", "A file tool utility " }, + { "FileManager", "System", "A file manager " }, + { "TerminalEmulator", "System", "A terminal emulator application " }, + { "Filesystem", "System", "A file system tool " }, + { "Monitor", "System", "Monitor application/applet that monitors some resource or activity " }, + { "Security", "System", "A security tool " }, + { "Accessibility", "System", "Accessibility " }, + { "Calculator", "Utility", "A calculator " }, + { "Clock", "Utility", "A clock application/applet " }, + { "TextEditor", "Utility", "A text editor " }, + { "Documentation", NULL, "Help or documentation " }, + { "Core", NULL, "Important application, core to the desktop such as a file manager or a help browser " }, + { "KDE", "QT", "Application based on KDE libraries " }, + { "GNOME", "GTK", "Application based on GNOME libraries " }, + { "GTK", NULL, "Application based on GTK+ libraries" }, + { "Qt", NULL, "Application based on Qt libraries" }, + { "Motif", NULL, "Application based on Motif libraries" }, + { "Java", NULL, "Application based on Java GUI libraries, such as AWT or Swing" }, + { "ConsoleOnly", NULL, "Application that only works inside a terminal (text-based or command line application)" }, + { NULL, NULL, NULL } }; -unsigned char freedesktop_check_cat ( char *name ) { - char **p = freedesktop_approved_cats; +freedesktop_cat_t *freedesktop_category_query ( char *name ) { + freedesktop_cat_t *p = freedesktop_complete; - while ( *p ) { + while ( p -> cat ) { - if ( strcasecmp ( *p, name ) == 0 ) { - return ( 1 ); + if ( strcasecmp ( p -> cat, name ) == 0 ) { + return ( p ); } p++; } - return ( 0 ); + return ( NULL ); } #if 0 int main ( void ) { - printf ( "check Applet (should be 1) -> %d\n", freedesktop_check_cat ( "Applet" ) ); - printf ( "check Education (should be 1) -> %d\n", freedesktop_check_cat ( "Education" ) ); - printf ( "check Mofo (should be 0) -> %d\n", freedesktop_check_cat ( "Mofo" ) ); + printf ( "check Applet (should be 1) -> %d\n", freedesktop_category_query ( "Applet" ) ); + printf ( "check Education (should be 1) -> %d\n", freedesktop_category_query ( "Education" ) ); + printf ( "check Mofo (should be 0) -> %d\n", freedesktop_category_query ( "Mofo" ) ); return ( 0 ); } diff --git a/minimenu/freedesktop_cats.h b/minimenu/freedesktop_cats.h index 54bdae2..6caf511 100644 --- a/minimenu/freedesktop_cats.h +++ b/minimenu/freedesktop_cats.h @@ -2,9 +2,14 @@ #ifndef h_freedesktop_cats_h #define h_freedesktop_cats_h -unsigned char freedesktop_check_cat ( char *name ); +typedef struct { + char *cat; + char *parent_cat; + char *desc; +} freedesktop_cat_t; -extern char *freedesktop_approved_cats[]; +// return NULL on error, otherwise a category entry +freedesktop_cat_t *freedesktop_category_query ( char *name ); #define BADCATNAME "Other" /* irony: Other is itself not a freedesktop category */ diff --git a/minimenu/mmcat.c b/minimenu/mmcat.c index 5efff6f..ba030a4 100644 --- a/minimenu/mmcat.c +++ b/minimenu/mmcat.c @@ -154,6 +154,7 @@ int cat_sort_score ( mm_category_t *cat, mm_appref_t *s1, mm_appref_t *s2 ) { // are we in a directory browser, or looking at pnd-files? if ( cat -> fspath ) { + // directory browser mode if ( s1 == s2 ) { return ( 0 ); // equal @@ -178,6 +179,29 @@ int cat_sort_score ( mm_category_t *cat, mm_appref_t *s1, mm_appref_t *s2 ) { } + // pnd tab + // + + // if this is comparing subcat folder to subcat folder, or pnd to pnd, or pnd to subcat folder? + unsigned char s1sub = 0; + unsigned char s2sub = 0; + if ( s1 -> ref -> object_type == pnd_object_type_directory ) { + s1sub = 1; + } + if ( s2 -> ref -> object_type == pnd_object_type_directory ) { + s2sub = 1; + } + + if ( ( s1sub ) && ( s2sub ) ) { + return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) ); + } else if ( ( s1sub ) && ( ! s2sub ) ) { + return ( -1 ); + } else if ( ( ! s1sub ) && ( s2sub ) ) { + return ( 1 ); + } else if ( ( ! s1sub ) && ( ! s2sub ) ) { + return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) ); + } + return ( strcasecmp ( s1 -> ref -> title_en, s2 -> ref -> title_en ) ); } @@ -300,14 +324,124 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco char catnamebuffer [ 512 ] = ""; #endif + //fprintf ( stderr, "meta push: '%s'\n", catname ); + if ( ! catname ) { return ( 1 ); // fine, just nada } - //fprintf ( stderr, "meta push: '%s'\n", catname ); + // we don't screw with "All" category that mmenu.c generates on the fly + if ( strncmp ( catname, "All ", 4 ) == 0 ) { + goto category_done_audit; + } + + // category cleansing; lets.. + // - ensure we only let good freedesktop categories through + // - we fix case.. no more UtIliTy (a good cat, studlycaps) + // - no more good cats but swapped ancestry; Utility as child of something? + // - if bogus, we just ship it off to BAD_CAT + + unsigned char cat_is_clean = 1; + freedesktop_cat_t *fdcat = NULL, *fdpcat = NULL; + fdcat = freedesktop_category_query ( catname ); + if ( parentcatname ) { + fdpcat = freedesktop_category_query ( parentcatname ); + } + + // ensure requested cat is good + 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" ); + + // do the Other substitution right away, so remaining code has something to look at in fdcat + fdcat = freedesktop_category_query ( BADCATNAME ); + catname = fdcat -> cat; + fdpcat = NULL; + parentcatname = NULL; + + } else { + // use canonicle entry, so our Case is now correct! + catname = fdcat -> cat; + } + + // ensure parent is good, if specified + if ( parentcatname ) { + 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" ); + // fix immediately so code doesn't explode + parentcatname = NULL; + } else { + // use canonicle entry, so our Case is now correct! + parentcatname = fdpcat -> cat; + } + } + + // ensure ancestry is good + // - if cat request is for child, ensure its a child + // - if parent specified, ensure its a parent + // - if child specified, ensure its parent is the right parent(?!) + // + if ( parentcatname ) { + // implies catname request is for child, with parent parentcatname + + 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" ); + } + 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" ); + } + + } else { + // implies request is for a parent cat - itself has no parent + + 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" ); + } + + } + + // ensure that if this is a child cat, its parent is the right parent + if ( parentcatname ) { + if ( ( ! fdcat -> parent_cat ) || + ( ! fdpcat ) ) + { + // 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" ); + } 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" ); + } + } + + // did testing fail? if so, bump to Other! + // + if ( ! cat_is_clean ) { + // set Other visibility + visiblep = cat_is_visible ( g_conf, BADCATNAME ); + // fix cat request + fdcat = freedesktop_category_query ( BADCATNAME ); + catname = fdcat -> cat; + // nullify parent cat request (if any) + fdpcat = NULL; + parentcatname = NULL; + } else { + //printf ( "PXML Category Pass: Cat request %s (parent %s)\n", catname, parentcatname ? parentcatname : "n/a" ); + } // push bad categories into Other (if we're not targeting All right now) - if ( pnd_conf_get_as_int_d ( g_conf, "categories.good_cats_only", 1 ) ) { +#if 0 + if ( 1 /*pnd_conf_get_as_int_d ( g_conf, "categories.good_cats_only", 1 )*/ ) { // don't audit All if ( strncmp ( catname, "All ", 4 ) != 0 ) { @@ -342,6 +476,9 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco } // not All } // good cats only? +#endif + + category_done_audit: // if invisible, and a parent category name is known, prepend it for ease of use #if 0 // prepending @@ -373,6 +510,14 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco } // cat map is desired? + // 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, 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 ); + return ( 1 ); // success, already there! + } + } + // not default, just do it category_push ( catname, parentcatname /* parent cat */, app, ovrh, NULL /* fspath */, visiblep ); @@ -670,3 +815,29 @@ int category_index ( char *catname ) { return ( -1 ); } + +unsigned char category_contains_app ( char *catname, char *unique_id ) { + + mm_category_t *c = pnd_box_find_by_key ( m_categories, catname ); + + if ( ! c ) { + return ( 0 ); // wtf? + } + + if ( ! c -> refs ) { + return ( 0 ); // no apps at all + } + + mm_appref_t *iter = c -> refs; + + while ( iter ) { + + if ( strcmp ( iter -> ref -> unique_id, unique_id ) == 0 ) { + return ( 1 ); + } + + iter = iter -> next; + } + + return ( 0 ); +} diff --git a/minimenu/mmcat.h b/minimenu/mmcat.h index d367a2f..0b15ba2 100644 --- a/minimenu/mmcat.h +++ b/minimenu/mmcat.h @@ -62,6 +62,9 @@ unsigned char category_meta_push ( char *catname, char *parentcatname, pnd_disco // filesystem browser unsigned char category_fs_restock ( mm_category_t *cat ); +// apps within cats +unsigned char category_contains_app ( char *catname, char *unique_id ); + // advertising to rest of the system // extern mm_category_t *g_categories [ MAX_CATS ]; diff --git a/minimenu/mmconf.c b/minimenu/mmconf.c index 8a69ef1..c77bc11 100644 --- a/minimenu/mmconf.c +++ b/minimenu/mmconf.c @@ -34,7 +34,8 @@ confitem_t page_general[] = { { "Sub-categories as folders?", "If no, uses tabs instead of folders within tabs.", "1", "tabs.subcat_as_folders", ct_boolean }, { "Start with app selected", "Whethor selection is placed by default or not", "0", "minimenu.start_selected", ct_boolean }, { "Auto discover pnd apps?", "If no, turn on diectory browser to manually find apps", "1", "filesystem.do_pnd_disco", ct_boolean }, - { "Keep bad categories in Other?", "Lazy dev! Put broken categories into Other to keep clean", "1", "categories.good_cats_only", ct_boolean }, + // dropped option -- we now strictly enforce free desktop categories (or user defined, but no more bogus PXML categories) + // { "Keep bad categories in Other?", "Lazy dev! Put broken categories into Other to keep clean", "1", "categories.good_cats_only", ct_boolean }, { "Set CPU speed when leaving", "Whether the next setting is applied or not", "0", "minimenu.use_run_speed", ct_boolean }, { "CPU speed when leaving", "Before running app, set this speed; app may override.", "500", "minimenu.run_speed", ct_cpu_speed }, { "Wrap tab change", "Changing tab left or right, does it wrap around?", "0", "tabs.wraparound", ct_boolean },