/****f* pekwm-menu/clean_exec * FUNCTION * Remove %f, %F, %u, %U, %i, %c, %k from exec field. * None of theses codes are interesting to manage here. * %i, %c and %k codes are implemented but don't ask why we need them. :) * * OUTPUT * A gchar that needs to be freed. * * NOTES * %d, %D, %n, %N, %v and %m are deprecated and should be removed. * * SEE ALSO * http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html ****/ gchar * clean_exec (MenuCacheApp *app) { gchar *filepath = NULL; const char *exec = menu_cache_app_get_exec (MENU_CACHE_APP(app)); GString *cmd = g_string_sized_new (64); for (;*exec; ++exec) { if (*exec == '%') { ++exec; switch (*exec) { /* useless and commonly used codes */ case 'u': case 'U': case 'f': case 'F': break; /* deprecated codes */ case 'd': case 'D': case 'm': case 'n': case 'N': case 'v': break; /* Other codes, more or less pointless to implement */ case 'c': g_string_append (cmd, menu_cache_item_get_name (MENU_CACHE_ITEM(app))); break; #if WITH_ICONS case 'i': if (get_item_icon_path (MENU_CACHE_ITEM(app))) { g_string_append_printf (cmd, "--icon %s", get_item_icon_path (MENU_CACHE_ITEM(app))); } break; #endif case 'k': filepath = menu_cache_item_get_file_path (MENU_CACHE_ITEM(app)); if (filepath) { g_string_append (cmd, filepath); g_free (filepath); } break; /* It was not in the freedesktop specification. */ default: g_string_append_c (cmd, '%'); g_string_append_c (cmd, *exec); break; } } else g_string_append_c (cmd, *exec); } return g_strchomp (g_string_free (cmd, FALSE)); }
void AppLinkProvider::update() { emit aboutToBeChanged(); QHash<QString, AppLinkItem*> newItems; #ifdef HAVE_MENU_CACHE // libmenu-cache is available, use it to get cached app list GSList* apps = menu_cache_list_all_apps(mMenuCache); for(GSList* l = apps; l; l = l->next) { MenuCacheApp* app = MENU_CACHE_APP(l->data); AppLinkItem *item = new AppLinkItem(app); AppLinkItem *prevItem = newItems[item->command()]; if(prevItem) delete prevItem; // delete previous item; newItems.insert(item->command(), item); menu_cache_item_unref(MENU_CACHE_ITEM(app)); } g_slist_free(apps); #else // use libqtxdg XdgMenu to get installed apps doUpdate(mXdgMenu->xml().documentElement(), newItems); #endif { QMutableListIterator<CommandProviderItem*> i(*this); while (i.hasNext()) { AppLinkItem *item = static_cast<AppLinkItem*>(i.next()); AppLinkItem *newItem = newItems.take(item->command()); if (newItem) { *(item) = *newItem; // Copy by value, not pointer! // After the item is copied, the original "updateIcon" call queued // on the newItem object is never called since the object iss going to // be deleted. Hence we need to call it on the copied item manually. // Otherwise the copied item will have no icon. // FIXME: this is a dirty hack and it should be made cleaner later. if(item->icon().isNull()) QMetaObject::invokeMethod(item, "updateIcon", Qt::QueuedConnection); delete newItem; } else { i.remove(); delete item; } } } { QHashIterator<QString, AppLinkItem*> i(newItems); while (i.hasNext()) { append(i.next().value()); } } emit changed(); }
guint app_is_visible(MenuCacheApp *app, guint32 de_flag) { gint32 flags = menu_cache_app_get_show_flags (app); if (flags < 0) return !(- flags & de_flag); else return menu_cache_app_get_is_visible(MENU_CACHE_APP(app), de_flag); }
/****f* pekwm-menu/generate_pekwm_menu * FUNCTION * main routine of menu creation. * * NOTES * It calls itself when 'dir' type is MENU_CACHE_TYPE_DIR. ****/ void generate_pekwm_menu (MenuCacheDir *dir, OB_Menu *context) { GSList *l = NULL; for (l = menu_cache_dir_get_children (dir); l; l = l->next) switch ((guint) menu_cache_item_get_type (MENU_CACHE_ITEM(l->data))) { case MENU_CACHE_TYPE_DIR: menu_directory (l->data, context); generate_pekwm_menu (MENU_CACHE_DIR(l->data), context); g_string_append (context->builder, "}\n"); break; case MENU_CACHE_TYPE_SEP: g_string_append (context->builder, "Separator {}\n"); break; case MENU_CACHE_TYPE_APP: if (app_is_visible (MENU_CACHE_APP(l->data), 0)) menu_application (l->data, context); } }
/** * fm_app_chooser_dlg_dup_selected_app * @dlg: a widget * @set_default: location to get value that was used for fm_app_chooser_dlg_new() * * Retrieves a currently selected application from @dlg. * * Before 1.0.0 this call had name fm_app_chooser_dlg_get_selected_app. * * Returns: (transfer full): selected application. * * Since: 0.1.0 */ GAppInfo* fm_app_chooser_dlg_dup_selected_app(GtkDialog* dlg, gboolean* set_default) { GAppInfo* app = NULL; AppChooserData* data = (AppChooserData*)g_object_get_qdata(G_OBJECT(dlg), fm_qdata_id); switch( gtk_notebook_get_current_page(data->notebook) ) { case 0: /* all applications */ app = fm_app_menu_view_dup_selected_app(data->apps_view); break; case 1: /* custom cmd line */ { const char* cmdline = gtk_entry_get_text(data->cmdline); const char* app_name = gtk_entry_get_text(data->app_name); if(cmdline && cmdline[0]) { char* _cmdline = NULL; gboolean arg_found = FALSE; char* bin1 = get_binary(cmdline, &arg_found); g_debug("bin1 = %s", bin1); /* see if command line contains %f, %F, %u, or %U. */ if(!arg_found) /* append %f if no %f, %F, %u, or %U was found. */ cmdline = _cmdline = g_strconcat(cmdline, " %f", NULL); /* FIXME: is there any better way to do this? */ /* We need to ensure that no duplicated items are added */ if(data->mime_type) { MenuCache* menu_cache; /* see if the command is already in the list of known apps for this mime-type */ GList* apps = g_app_info_get_all_for_type(fm_mime_type_get_type(data->mime_type)); GList* l; for(l=apps;l;l=l->next) { GAppInfo* app2 = G_APP_INFO(l->data); const char* cmd = g_app_info_get_commandline(app2); char* bin2 = get_binary(cmd, NULL); if(g_strcmp0(bin1, bin2) == 0) { app = G_APP_INFO(g_object_ref(app2)); g_debug("found in app list"); g_free(bin2); break; } g_free(bin2); } g_list_foreach(apps, (GFunc)g_object_unref, NULL); g_list_free(apps); if(app) goto _out; /* see if this command can be found in menu cache */ menu_cache = menu_cache_lookup("applications.menu"); if(menu_cache) { #if MENU_CACHE_CHECK_VERSION(0, 4, 0) MenuCacheDir *root_dir = menu_cache_dup_root_dir(menu_cache); if(root_dir) #else if(menu_cache_get_root_dir(menu_cache)) #endif { GSList* all_apps = menu_cache_list_all_apps(menu_cache); GSList* l; for(l=all_apps;l;l=l->next) { MenuCacheApp* ma = MENU_CACHE_APP(l->data); const char *exec = menu_cache_app_get_exec(ma); char* bin2; if (exec == NULL) { g_warning("application %s has no Exec statement", menu_cache_item_get_id(MENU_CACHE_ITEM(ma))); continue; } bin2 = get_binary(exec, NULL); if(g_strcmp0(bin1, bin2) == 0) { app = G_APP_INFO(g_desktop_app_info_new(menu_cache_item_get_id(MENU_CACHE_ITEM(ma)))); g_debug("found in menu cache"); menu_cache_item_unref(MENU_CACHE_ITEM(ma)); g_free(bin2); break; } menu_cache_item_unref(MENU_CACHE_ITEM(ma)); g_free(bin2); } g_slist_free(all_apps); #if MENU_CACHE_CHECK_VERSION(0, 4, 0) menu_cache_item_unref(MENU_CACHE_ITEM(root_dir)); #endif } menu_cache_unref(menu_cache); } if(app) goto _out; } /* FIXME: g_app_info_create_from_commandline force the use of %f or %u, so this is not we need */ app = app_info_create_from_commandline(cmdline, app_name ? app_name : "", bin1, data->mime_type ? fm_mime_type_get_type(data->mime_type) : NULL, gtk_toggle_button_get_active(data->use_terminal), data->keep_open && gtk_toggle_button_get_active(data->keep_open)); _out: g_free(bin1); g_free(_cmdline); } } break; } if(set_default) *set_default = gtk_toggle_button_get_active(data->set_default); return app; }
static MenuCacheApp* match_app_by_exec(const char* exec) { GSList* l; MenuCacheApp* ret = NULL; char* exec_path = g_find_program_in_path(exec); const char* pexec; int path_len, exec_len, len; if( ! exec_path ) return NULL; path_len = strlen(exec_path); exec_len = strlen(exec); for( l = app_list; l; l = l->next ) { MenuCacheApp* app = MENU_CACHE_APP(l->data); const char* app_exec = menu_cache_app_get_exec(app); if ( ! app_exec) continue; #if 0 /* This is useless and incorrect. */ /* Dirty hacks to skip sudo programs. This can be a little bit buggy */ if( g_str_has_prefix(app_exec, "gksu") ) { app_exec += 4; if( app_exec[0] == '\0' ) /* "gksu" itself */ app_exec -= 4; else if( app_exec[0] == ' ' ) /* "gksu something..." */ ++app_exec; else if( g_str_has_prefix(app_exec, "do ") ) /* "gksudo something" */ app_exec += 3; } else if( g_str_has_prefix(app_exec, "kdesu ") ) /* kdesu */ app_exec += 6; #endif if( g_path_is_absolute(app_exec) ) { pexec = exec_path; len = path_len; } else { pexec = exec; len = exec_len; } if( strncmp(app_exec, pexec, len) == 0 ) { /* exact match has the highest priority */ if( app_exec[len] == '\0' ) { ret = app; break; } /* those matches the pattern: exe_name %F|%f|%U|%u have higher priority */ if( app_exec[len] == ' ' ) { if( app_exec[len + 1] == '%' ) { if( strchr( "FfUu", app_exec[len + 2] ) ) { ret = app; break; } } ret = app; } } } /* if this is a symlink */ if( ! ret && g_file_test(exec_path, G_FILE_TEST_IS_SYMLINK) ) { char target[512]; /* FIXME: is this enough? */ len = readlink( exec_path, target, sizeof(target) - 1); if( len > 0 ) { target[len] = '\0'; ret = match_app_by_exec(target); if( ! ret ) { /* FIXME: Actually, target could be relative paths. * So, actually path resolution is needed here. */ char* basename = g_path_get_basename(target); char* locate = g_find_program_in_path(basename); if( locate && strcmp(locate, target) == 0 ) { ret = match_app_by_exec(basename); g_free(locate); } g_free(basename); } } } g_free(exec_path); return ret; }