Use the new MimeHandler API

This commit is contained in:
Pierre Pronchery 2017-12-09 01:08:26 +01:00
parent 027cb6a690
commit 1e87316fba

View File

@ -26,6 +26,7 @@
#include <errno.h> #include <errno.h>
#include <libintl.h> #include <libintl.h>
#include <System.h> #include <System.h>
#include <Desktop.h>
#include "Panel/applet.h" #include "Panel/applet.h"
#include "../../config.h" #include "../../config.h"
#define _(string) gettext(string) #define _(string) gettext(string)
@ -206,9 +207,9 @@ static void _menu_destroy(Menu * menu)
/* helpers */ /* helpers */
/* menu_applications */ /* menu_applications */
static void _applications_on_activate(gpointer data); static void _applications_on_activate(gpointer data);
static void _applications_on_activate_application(Config * config); static void _applications_on_activate_application(MimeHandler * handler);
static void _applications_on_activate_directory(Config * config); static void _applications_on_activate_directory(MimeHandler * handler);
static void _applications_on_activate_url(Config * config); static void _applications_on_activate_url(MimeHandler * handler);
static void _applications_categories(GtkWidget * menu, GtkWidget ** menus); static void _applications_categories(GtkWidget * menu, GtkWidget ** menus);
static GtkWidget * _menu_applications(Menu * menu) static GtkWidget * _menu_applications(Menu * menu)
@ -217,16 +218,16 @@ static GtkWidget * _menu_applications(Menu * menu)
GSList * p; GSList * p;
GtkWidget * menushell; GtkWidget * menushell;
GtkWidget * menuitem; GtkWidget * menuitem;
Config * config; MimeHandler * handler;
const char section[] = "Desktop Entry";
char const * name; char const * name;
#if GTK_CHECK_VERSION(2, 12, 0) #if GTK_CHECK_VERSION(2, 12, 0)
char const * comment; char const * comment;
#endif #endif
char const * q; char const * q;
char const * r; String const ** categories;
char const * path; String const * filename;
size_t i; size_t i;
size_t j;
if(menu->apps == NULL) if(menu->apps == NULL)
_menu_on_idle(menu); _menu_on_idle(menu);
@ -234,13 +235,13 @@ static GtkWidget * _menu_applications(Menu * menu)
menushell = gtk_menu_new(); menushell = gtk_menu_new();
for(p = menu->apps; p != NULL; p = p->next) for(p = menu->apps; p != NULL; p = p->next)
{ {
config = p->data; handler = p->data;
/* should not fail */ /* should not fail */
name = config_get(config, section, "Name"); name = mimehandler_get_name(handler);
#if GTK_CHECK_VERSION(2, 12, 0) #if GTK_CHECK_VERSION(2, 12, 0)
comment = config_get(config, section, "Comment"); comment = mimehandler_get_comment(handler);
#endif #endif
if((q = config_get(config, section, "GenericName")) != NULL) if((q = mimehandler_get_generic_name(handler)) != NULL)
{ {
#if GTK_CHECK_VERSION(2, 12, 0) #if GTK_CHECK_VERSION(2, 12, 0)
if(comment == NULL) if(comment == NULL)
@ -248,43 +249,47 @@ static GtkWidget * _menu_applications(Menu * menu)
#endif #endif
name = q; name = q;
} }
path = config_get(config, NULL, "path"); filename = mimehandler_get_filename(handler);
menuitem = _menu_menuitem(menu, path, name, menuitem = _menu_menuitem(menu, filename, name,
config_get(config, section, "Icon")); mimehandler_get_icon(handler));
#if GTK_CHECK_VERSION(2, 12, 0) #if GTK_CHECK_VERSION(2, 12, 0)
if(comment != NULL) if(comment != NULL)
gtk_widget_set_tooltip_text(menuitem, comment); gtk_widget_set_tooltip_text(menuitem, comment);
#endif #endif
if((q = config_get(config, section, "Type")) != NULL if(mimehandler_get_type(handler)
&& strcmp(q, "Application") == 0 == MIMEHANDLER_TYPE_APPLICATION
&& config_get(config, section, "Exec") == NULL) && mimehandler_can_execute(handler) == 0)
gtk_widget_set_sensitive(menuitem, FALSE); gtk_widget_set_sensitive(menuitem, FALSE);
else else
g_signal_connect_swapped(menuitem, "activate", g_signal_connect_swapped(menuitem, "activate",
G_CALLBACK(_applications_on_activate), G_CALLBACK(_applications_on_activate),
config); handler);
if((q = config_get(config, section, "Categories")) == NULL) if((categories = mimehandler_get_categories(handler)) == NULL
{ || categories[0] == NULL)
gtk_menu_shell_append(GTK_MENU_SHELL(menushell), menuitem);
continue;
}
for(i = 0; i < MENU_MENUS_COUNT; i++)
{
if((r = string_find(q, _menu_menus[i].category)) == NULL)
continue;
r += string_length(_menu_menus[i].category);
if(*r == '\0' || *r == ';')
break;
}
if(i == MENU_MENUS_COUNT)
{ {
gtk_menu_shell_append(GTK_MENU_SHELL(menushell), gtk_menu_shell_append(GTK_MENU_SHELL(menushell),
menuitem); menuitem);
continue; continue;
} }
if(menus[i] == NULL) for(i = 0; i < MENU_MENUS_COUNT; i++)
menus[i] = gtk_menu_new(); {
gtk_menu_shell_append(GTK_MENU_SHELL(menus[i]), menuitem); for(j = 0; categories[j] != NULL; j++)
if(string_compare(_menu_menus[i].category,
categories[j]) == 0)
break;
if(categories[j] != NULL)
break;
}
if(i == MENU_MENUS_COUNT)
gtk_menu_shell_append(GTK_MENU_SHELL(menushell),
menuitem);
else
{
if(menus[i] == NULL)
menus[i] = gtk_menu_new();
gtk_menu_shell_append(GTK_MENU_SHELL(menus[i]),
menuitem);
}
} }
_applications_categories(menushell, menus); _applications_categories(menushell, menus);
return menushell; return menushell;
@ -292,77 +297,39 @@ static GtkWidget * _menu_applications(Menu * menu)
static void _applications_on_activate(gpointer data) static void _applications_on_activate(gpointer data)
{ {
Config * config = data; MimeHandler * handler = data;
const char section[] = "Desktop Entry";
char const * q;
if((q = config_get(config, section, "Type")) == NULL) switch(mimehandler_get_type(handler))
return; {
else if(strcmp(q, "Application") == 0) case MIMEHANDLER_TYPE_APPLICATION:
_applications_on_activate_application(config); _applications_on_activate_application(handler);
else if(strcmp(q, "Directory") == 0) break;
_applications_on_activate_directory(config); case MIMEHANDLER_TYPE_DIRECTORY:
else if(strcmp(q, "URL") == 0) _applications_on_activate_directory(handler);
_applications_on_activate_url(config); break;
case MIMEHANDLER_TYPE_URL:
_applications_on_activate_url(handler);
break;
case MIMEHANDLER_TYPE_UNKNOWN:
break;
}
} }
static void _applications_on_activate_application(Config * config) static void _applications_on_activate_application(MimeHandler * handler)
{ {
const char section[] = "Desktop Entry"; mimehandler_execute(handler, NULL);
char * program;
char * p;
char const * q;
pid_t pid;
GError * error = NULL;
if((q = config_get(config, section, "Exec")) == NULL)
return;
if((program = strdup(q)) == NULL)
return; /* XXX report error */
/* XXX crude way to ignore %f, %F, %u and %U */
if((p = strchr(program, '%')) != NULL)
*p = '\0';
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() \"%s\"", __func__, program);
#endif
if((q = config_get(config, section, "Path")) == NULL)
{
/* execute the program directly */
if(g_spawn_command_line_async(program, &error) != TRUE)
{
fprintf(stderr, "%s: %s\n", program, error->message);
g_error_free(error);
}
}
else if((pid = fork()) == 0)
{
/* change the current working directory */
if(chdir(q) != 0)
fprintf(stderr, "%s: %s: %s\n", program, q,
strerror(errno));
else if(g_spawn_command_line_async(program, &error) != TRUE)
{
fprintf(stderr, "%s: %s\n", program, error->message);
g_error_free(error);
}
exit(0);
}
else if(pid < 0)
fprintf(stderr, "%s: %s\n", program, strerror(errno));
free(program);
} }
static void _applications_on_activate_directory(Config * config) static void _applications_on_activate_directory(MimeHandler * handler)
{ {
const char section[] = "Desktop Entry"; String const * directory;
char const * directory;
/* XXX open with the default file manager instead */ /* XXX open with the default file manager instead */
char * argv[] = { "browser", "--", NULL, NULL }; char * argv[] = { "browser", "--", NULL, NULL };
const unsigned int flags = G_SPAWN_SEARCH_PATH; const unsigned int flags = G_SPAWN_SEARCH_PATH;
GError * error = NULL; GError * error = NULL;
/* XXX this may not might the correct key */ /* XXX this may not might the correct key */
if((directory = config_get(config, section, "Path")) == NULL) if((directory = mimehandler_get_path(handler)) == NULL)
return; return;
if((argv[2] = strdup(directory)) == NULL) if((argv[2] = strdup(directory)) == NULL)
fprintf(stderr, "%s: %s\n", directory, strerror(errno)); fprintf(stderr, "%s: %s\n", directory, strerror(errno));
@ -375,16 +342,15 @@ static void _applications_on_activate_directory(Config * config)
free(argv[2]); free(argv[2]);
} }
static void _applications_on_activate_url(Config * config) static void _applications_on_activate_url(MimeHandler * handler)
{ {
const char section[] = "Desktop Entry"; String const * url;
char const * url;
/* XXX open with the default web browser instead */ /* XXX open with the default web browser instead */
char * argv[] = { BINDIR "/htmlapp", "--", NULL, NULL }; char * argv[] = { BINDIR "/htmlapp", "--", NULL, NULL };
unsigned int flags = 0; unsigned int flags = 0;
GError * error = NULL; GError * error = NULL;
if((url = config_get(config, section, "URL")) == NULL) if((url = mimehandler_get_url(handler)) == NULL)
return; return;
if((argv[2] = strdup(url)) == NULL) if((argv[2] = strdup(url)) == NULL)
fprintf(stderr, "%s: %s\n", url, strerror(errno)); fprintf(stderr, "%s: %s\n", url, strerror(errno));
@ -699,9 +665,6 @@ static void _clicked_position_menu(GtkMenu * widget, gint * x, gint * y,
/* menu_on_idle */ /* menu_on_idle */
static int _idle_access(Menu * menu, char const * path, int mode);
static int _idle_access_path(Menu * menu, char const * path,
char const * filename, int mode);
static gint _idle_apps_compare(gconstpointer a, gconstpointer b); static gint _idle_apps_compare(gconstpointer a, gconstpointer b);
static void _idle_path(Menu * menu, char const * path, char const * apppath); static void _idle_path(Menu * menu, char const * path, char const * apppath);
@ -720,73 +683,18 @@ static gboolean _menu_on_idle(gpointer data)
return FALSE; return FALSE;
} }
static int _idle_access(Menu * menu, char const * path, int mode)
{
int ret = -1;
char const * p;
char * q;
size_t i;
size_t j;
if(path[0] == '/')
return access(path, mode);
if((p = getenv("PATH")) == NULL)
return 0;
if((q = strdup(p)) == NULL)
{
menu->helper->error(NULL, path, 1);
return 0;
}
errno = ENOENT;
for(i = 0, j = 0;; i++)
if(q[i] == '\0')
{
ret = _idle_access_path(menu, &q[j], path, mode);
break;
}
else if(q[i] == ':')
{
q[i] = '\0';
if((ret = _idle_access_path(menu, &q[j], path, mode))
== 0)
break;
j = i + 1;
}
free(q);
return ret;
}
static int _idle_access_path(Menu * menu, char const * path,
char const * filename, int mode)
{
int ret;
char * p;
size_t len;
len = strlen(path) + 1 + strlen(filename) + 1;
if((p = malloc(len)) == NULL)
return -menu->helper->error(NULL, path, 1);
snprintf(p, len, "%s/%s", path, filename);
ret = access(p, mode);
free(p);
return ret;
}
static gint _idle_apps_compare(gconstpointer a, gconstpointer b) static gint _idle_apps_compare(gconstpointer a, gconstpointer b)
{ {
const char section[] = "Desktop Entry"; MimeHandler * mha = (MimeHandler *)a;
const char generic[] = "GenericName"; MimeHandler * mhb = (MimeHandler *)b;
const char name[] = "Name"; String const * mhas;
Config * ca = (Config *)a; String const * mhbs;
Config * cb = (Config *)b;
char const * cap;
char const * cbp;
if((cap = config_get(ca, section, generic)) == NULL) if((mhas = mimehandler_get_generic_name(mha)) == NULL)
cap = config_get(ca, section, name); mhas = mimehandler_get_name(mha);
if((cbp = config_get(cb, section, generic)) == NULL) if((mhbs = mimehandler_get_generic_name(mhb)) == NULL)
cbp = config_get(cb, section, name); mhbs = mimehandler_get_name(mhb);
return string_compare(cap, cbp); return string_compare(mhas, mhbs);
} }
static void _idle_path(Menu * menu, char const * path, char const * apppath) static void _idle_path(Menu * menu, char const * path, char const * apppath)
@ -797,11 +705,9 @@ static void _idle_path(Menu * menu, char const * path, char const * apppath)
struct dirent * de; struct dirent * de;
size_t len; size_t len;
const char ext[] = ".desktop"; const char ext[] = ".desktop";
const char section[] = "Desktop Entry";
char * name = NULL; char * name = NULL;
char * p; char * p;
Config * config = NULL; MimeHandler * handler;
String const * q;
#if defined(__sun) #if defined(__sun)
if((fd = open(apppath, O_RDONLY)) < 0 if((fd = open(apppath, O_RDONLY)) < 0
@ -842,48 +748,23 @@ static void _idle_path(Menu * menu, char const * path, char const * apppath)
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, name); fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, name);
#endif #endif
if(config == NULL) if((handler = mimehandler_new_open(name)) == NULL)
config = config_new();
else
config_reset(config);
if(config == NULL || config_load(config, name) != 0)
{ {
menu->helper->error(NULL, error_get(NULL), 1); menu->helper->error(NULL, error_get(NULL), 1);
continue; continue;
} }
/* skip this entry if it is deleted */ /* skip this entry if cannot be displayed or opened */
if((q = config_get(config, section, "Hidden")) != NULL if(mimehandler_can_display(handler) == 0
&& strcmp(q, "true") == 0) || mimehandler_can_open(handler) == 0)
{
mimehandler_delete(handler);
continue; continue;
/* skip this entry if it has an unknown type */ }
if((q = config_get(config, section, "Type")) == NULL) menu->apps = g_slist_insert_sorted(menu->apps, handler,
continue;
if(strcmp(q, "Application") != 0
&& strcmp(q, "Directory") != 0
&& strcmp(q, "URL") != 0)
continue;
/* skip this entry if there is no name defined */
if((q = config_get(config, section, "Name")) == NULL)
continue;
/* skip this entry if should not be displayed at all */
if((q = config_get(config, section, "NoDisplay")) != NULL
&& strcmp(q, "true") == 0)
continue;
/* skip this entry if the binary cannot be executed */
if((q = config_get(config, section, "TryExec")) != NULL
&& _idle_access(menu, q, X_OK) != 0
&& errno == ENOENT)
continue;
/* remember the path */
config_set(config, NULL, "path", path);
menu->apps = g_slist_insert_sorted(menu->apps, config,
_idle_apps_compare); _idle_apps_compare);
config = NULL;
} }
free(name); free(name);
closedir(dir); closedir(dir);
if(config != NULL)
config_delete(config);
} }