Merge branch 'khorben/desktophandler'
This commit is contained in:
commit
8b2f86384a
|
@ -35,12 +35,21 @@
|
|||
/* Desktop */
|
||||
/* public */
|
||||
/* types */
|
||||
typedef struct _Desktop Desktop;
|
||||
|
||||
typedef enum _DesktopAlignment
|
||||
{
|
||||
DESKTOP_ALIGNMENT_VERTICAL = 0,
|
||||
DESKTOP_ALIGNMENT_HORIZONTAL
|
||||
} DesktopAlignment;
|
||||
|
||||
typedef struct _DesktopHandler DesktopHandler;
|
||||
|
||||
typedef struct _DesktopHandlerHelper
|
||||
{
|
||||
Desktop * desktop;
|
||||
} DesktopHandlerHelper;
|
||||
|
||||
typedef enum _DesktopIcons
|
||||
{
|
||||
DESKTOP_ICONS_NONE = 0,
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
|
||||
/* types */
|
||||
typedef struct _Desktop Desktop;
|
||||
typedef struct _DesktopIcon DesktopIcon;
|
||||
typedef struct _DesktopIconWindow DesktopIconWindow;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2011-2018 Pierre Pronchery <khorben@defora.org> */
|
||||
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
|
@ -30,7 +30,7 @@
|
|||
|
||||
# include <gtk/gtk.h>
|
||||
# include <Desktop.h>
|
||||
# include "../../include/Browser.h"
|
||||
# include "Browser/desktop.h"
|
||||
# include "../common.h"
|
||||
|
||||
|
||||
|
@ -55,11 +55,14 @@ void desktop_delete(Desktop * desktop);
|
|||
int desktop_get_drag_data(Desktop * desktop, GtkSelectionData * seldata);
|
||||
GdkPixbuf * desktop_get_file(Desktop * desktop);
|
||||
GdkPixbuf * desktop_get_folder(Desktop * desktop);
|
||||
DesktopHandler * desktop_get_handler(Desktop * desktop);
|
||||
String const * desktop_get_home(Desktop * desktop);
|
||||
void desktop_get_icon_size(Desktop * desktop, unsigned int * width,
|
||||
unsigned int * height, unsigned int * size);
|
||||
DesktopIcon ** desktop_get_icons_selected(Desktop * desktop);
|
||||
Mime * desktop_get_mime(Desktop * desktop);
|
||||
GtkIconTheme * desktop_get_theme(Desktop * desktop);
|
||||
GtkWidget * desktop_get_window(Desktop * desktop);
|
||||
|
||||
void desktop_set_alignment(Desktop * desktop, DesktopAlignment alignment);
|
||||
void desktop_set_icons(Desktop * desktop, DesktopIcons icons);
|
||||
|
@ -68,14 +71,19 @@ int desktop_set_layout(Desktop * desktop, DesktopLayout layout);
|
|||
/* useful */
|
||||
int desktop_error(Desktop * desktop, char const * message, char const * error,
|
||||
int ret);
|
||||
int desktop_perror(Desktop * desktop, char const * message, int ret);
|
||||
int desktop_serror(Desktop * desktop, char const * message, int ret);
|
||||
|
||||
void desktop_refresh(Desktop * desktop);
|
||||
void desktop_reset(Desktop * desktop);
|
||||
|
||||
void desktop_icon_add(Desktop * desktop, DesktopIcon * icon);
|
||||
void desktop_icon_remove(Desktop * desktop, DesktopIcon * icon);
|
||||
void desktop_icon_add(Desktop * desktop, DesktopIcon * icon, gboolean align);
|
||||
int desktop_icon_remove(Desktop * desktop, DesktopIcon * icon, gboolean align);
|
||||
|
||||
void desktop_icons_align(Desktop * desktop);
|
||||
void desktop_icons_cleanup(Desktop * desktop, gboolean align);
|
||||
DesktopIcon * desktop_icons_lookup(Desktop * desktop, String const * name);
|
||||
void desktop_icons_remove_all(Desktop * desktop);
|
||||
void desktop_icons_sort(Desktop * desktop);
|
||||
|
||||
void desktop_select_all(Desktop * desktop);
|
||||
|
@ -83,4 +91,6 @@ void desktop_select_above(Desktop * desktop, DesktopIcon * icon);
|
|||
void desktop_select_under(Desktop * desktop, DesktopIcon * icon);
|
||||
void desktop_unselect_all(Desktop * desktop);
|
||||
|
||||
void desktop_show_preferences(Desktop * desktop);
|
||||
|
||||
#endif /* !BROWSER_DESKTOP_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2010-2018 Pierre Pronchery <khorben@defora.org> */
|
||||
/* Copyright (c) 2010-2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
|
@ -29,6 +29,7 @@
|
|||
# define BROWSER_DESKTOPICON_H
|
||||
|
||||
# include <gtk/gtk.h>
|
||||
# include "Browser/desktop.h"
|
||||
# include "../common.h"
|
||||
|
||||
|
||||
|
|
245
src/desktop/handler.c
Normal file
245
src/desktop/handler.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <System.h>
|
||||
#include "Browser/vfs.h"
|
||||
#include "desktop.h"
|
||||
#include "desktopicon.h"
|
||||
#include "desktopiconwindow.h"
|
||||
#include "handler.h"
|
||||
#define _(string) gettext(string)
|
||||
#define N_(string) string
|
||||
|
||||
#define COMMON_SYMLINK
|
||||
#include "../common.c"
|
||||
|
||||
|
||||
/* DesktopHandler */
|
||||
/* private */
|
||||
/* types */
|
||||
typedef struct _DesktopCategory
|
||||
{
|
||||
gboolean show;
|
||||
char const * category;
|
||||
char const * name;
|
||||
char const * icon;
|
||||
} DesktopCategory;
|
||||
|
||||
typedef struct _DesktopHandlerApplications
|
||||
{
|
||||
DIR * refresh_dir;
|
||||
time_t refresh_mtime;
|
||||
guint refresh_source;
|
||||
GSList * apps;
|
||||
DesktopCategory * category;
|
||||
} DesktopHandlerApplications;
|
||||
|
||||
typedef struct _DesktopHandlerCategories
|
||||
{
|
||||
DIR * refresh_dir;
|
||||
time_t refresh_mtime;
|
||||
guint refresh_source;
|
||||
GSList * apps;
|
||||
} DesktopHandlerCategories;
|
||||
|
||||
typedef struct _DesktopHandlerFiles
|
||||
{
|
||||
char * path;
|
||||
DIR * refresh_dir;
|
||||
time_t refresh_mtime;
|
||||
guint refresh_source;
|
||||
gboolean show_hidden;
|
||||
GtkWidget * menu;
|
||||
} DesktopHandlerFiles;
|
||||
|
||||
struct _DesktopHandler
|
||||
{
|
||||
Desktop * desktop;
|
||||
DesktopIcons icons;
|
||||
union
|
||||
{
|
||||
DesktopHandlerApplications applications;
|
||||
DesktopHandlerCategories categories;
|
||||
DesktopHandlerFiles files;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
/* constants */
|
||||
#ifndef PREFIX
|
||||
# define PREFIX "/usr/local"
|
||||
#endif
|
||||
#ifndef DATADIR
|
||||
# define DATADIR PREFIX "/share"
|
||||
#endif
|
||||
|
||||
#define DESKTOP ".desktop"
|
||||
|
||||
#define IDLE_LOOP_ICON_CNT 16 /* number of icons added in a loop */
|
||||
|
||||
|
||||
#include "handler/applications.c"
|
||||
#include "handler/categories.c"
|
||||
#include "handler/files.c"
|
||||
#include "handler/homescreen.c"
|
||||
|
||||
|
||||
/* protected */
|
||||
/* functions */
|
||||
/* desktophandler_new */
|
||||
DesktopHandler * desktophandler_new(Desktop * desktop, DesktopIcons icons)
|
||||
{
|
||||
DesktopHandler * handler;
|
||||
|
||||
if((handler = object_new(sizeof(*handler))) == NULL)
|
||||
return NULL;
|
||||
handler->desktop = desktop;
|
||||
handler->icons = DESKTOP_ICONS_NONE;
|
||||
desktophandler_set_icons(handler, icons);
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_delete */
|
||||
void desktophandler_delete(DesktopHandler * handler)
|
||||
{
|
||||
desktophandler_set_icons(handler, DESKTOP_ICONS_NONE);
|
||||
object_delete(handler);
|
||||
}
|
||||
|
||||
|
||||
/* accessors */
|
||||
static void _set_icons_destroy(DesktopHandler * handler);
|
||||
static void _set_icons_init(DesktopHandler * handler);
|
||||
|
||||
void desktophandler_set_icons(DesktopHandler * handler, DesktopIcons icons)
|
||||
{
|
||||
if(handler->icons != icons)
|
||||
{
|
||||
desktop_icons_remove_all(handler->desktop);
|
||||
_set_icons_destroy(handler);
|
||||
handler->icons = icons;
|
||||
_set_icons_init(handler);
|
||||
}
|
||||
}
|
||||
|
||||
static void _set_icons_destroy(DesktopHandler * handler)
|
||||
{
|
||||
switch(handler->icons)
|
||||
{
|
||||
case DESKTOP_ICONS_APPLICATIONS:
|
||||
_desktophandler_applications_destroy(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_CATEGORIES:
|
||||
_desktophandler_categories_destroy(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_FILES:
|
||||
_desktophandler_files_destroy(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_HOMESCREEN:
|
||||
_desktophandler_homescreen_destroy(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _set_icons_init(DesktopHandler * handler)
|
||||
{
|
||||
switch(handler->icons)
|
||||
{
|
||||
case DESKTOP_ICONS_APPLICATIONS:
|
||||
_desktophandler_applications_init(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_CATEGORIES:
|
||||
_desktophandler_categories_init(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_FILES:
|
||||
_desktophandler_files_init(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_HOMESCREEN:
|
||||
_desktophandler_homescreen_init(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_popup */
|
||||
void desktophandler_popup(DesktopHandler * handler, XButtonEvent * xbev)
|
||||
{
|
||||
switch(handler->icons)
|
||||
{
|
||||
case DESKTOP_ICONS_APPLICATIONS:
|
||||
_desktophandler_applications_popup(handler, xbev);
|
||||
break;
|
||||
case DESKTOP_ICONS_CATEGORIES:
|
||||
_desktophandler_categories_popup(handler, xbev);
|
||||
break;
|
||||
case DESKTOP_ICONS_FILES:
|
||||
_desktophandler_files_popup(handler, xbev);
|
||||
break;
|
||||
case DESKTOP_ICONS_HOMESCREEN:
|
||||
_desktophandler_homescreen_popup(handler, xbev);
|
||||
break;
|
||||
case DESKTOP_ICONS_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_refresh */
|
||||
void desktophandler_refresh(DesktopHandler * handler)
|
||||
{
|
||||
switch(handler->icons)
|
||||
{
|
||||
case DESKTOP_ICONS_APPLICATIONS:
|
||||
_desktophandler_applications_refresh(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_CATEGORIES:
|
||||
_desktophandler_categories_refresh(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_FILES:
|
||||
_desktophandler_files_refresh(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_HOMESCREEN:
|
||||
_desktophandler_homescreen_refresh(handler);
|
||||
break;
|
||||
case DESKTOP_ICONS_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
48
src/desktop/handler.h
Normal file
48
src/desktop/handler.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
#ifndef BROWSER_DESKTOPHANDLER_H
|
||||
# define BROWSER_DESKTOPHANDLER_H
|
||||
|
||||
# include <X11/Xlib.h>
|
||||
# include "Browser/desktop.h"
|
||||
|
||||
|
||||
/* DesktopHandler */
|
||||
/* types */
|
||||
/* functions */
|
||||
DesktopHandler * desktophandler_new(Desktop * desktop, DesktopIcons icons);
|
||||
void desktophandler_delete(DesktopHandler * handler);
|
||||
|
||||
/* accessors */
|
||||
void desktophandler_set_icons(DesktopHandler * handler, DesktopIcons icons);
|
||||
|
||||
/* useful */
|
||||
void desktophandler_popup(DesktopHandler * handler, XButtonEvent * xbev);
|
||||
void desktophandler_refresh(DesktopHandler * handler);
|
||||
|
||||
#endif /* !BROWSER_DESKTOPHANDLER_H */
|
356
src/desktop/handler/applications.c
Normal file
356
src/desktop/handler/applications.c
Normal file
|
@ -0,0 +1,356 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
/* DesktopHandlerApplications */
|
||||
/* private */
|
||||
/* prototypes */
|
||||
static void _desktophandler_applications_init(DesktopHandler * handler);
|
||||
static void _desktophandler_applications_destroy(DesktopHandler * handler);
|
||||
static void _desktophandler_applications_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev);
|
||||
static void _desktophandler_applications_refresh(DesktopHandler * handler);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* desktophandler_applications_init */
|
||||
static void _applications_init_on_back(Desktop * desktop, gpointer data);
|
||||
|
||||
static void _desktophandler_applications_init(DesktopHandler * handler)
|
||||
{
|
||||
DesktopIcon * desktopicon;
|
||||
GdkPixbuf * icon;
|
||||
unsigned int size;
|
||||
|
||||
handler->u.applications.refresh_dir = NULL;
|
||||
handler->u.applications.refresh_mtime = 0;
|
||||
handler->u.applications.refresh_source = 0;
|
||||
handler->u.applications.apps = NULL;
|
||||
handler->u.applications.category = NULL;
|
||||
desktop_set_alignment(handler->desktop, DESKTOP_ALIGNMENT_HORIZONTAL);
|
||||
if((desktopicon = desktopicon_new(handler->desktop, _("Back"), NULL))
|
||||
== NULL)
|
||||
{
|
||||
desktop_serror(handler->desktop, _("Back"), 1);
|
||||
return;
|
||||
}
|
||||
desktopicon_set_callback(desktopicon, _applications_init_on_back,
|
||||
handler);
|
||||
desktopicon_set_first(desktopicon, TRUE);
|
||||
desktopicon_set_immutable(desktopicon, TRUE);
|
||||
desktop_get_icon_size(handler->desktop, NULL, NULL, &size);
|
||||
icon = gtk_icon_theme_load_icon(desktop_get_theme(handler->desktop),
|
||||
"back", size, 0, NULL);
|
||||
if(icon != NULL)
|
||||
desktopicon_set_icon(desktopicon, icon);
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
}
|
||||
|
||||
static void _applications_init_on_back(Desktop * desktop, gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
desktop_set_icons(desktop, (handler->u.applications.category != NULL)
|
||||
? DESKTOP_ICONS_CATEGORIES : DESKTOP_ICONS_HOMESCREEN);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_applications_destroy */
|
||||
static void _desktophandler_applications_destroy(DesktopHandler * handler)
|
||||
{
|
||||
if(handler->u.applications.refresh_source != 0)
|
||||
g_source_remove(handler->u.applications.refresh_source);
|
||||
if(handler->u.applications.refresh_dir != NULL)
|
||||
browser_vfs_closedir(handler->u.applications.refresh_dir);
|
||||
g_slist_foreach(handler->u.applications.apps, (GFunc)mimehandler_delete,
|
||||
NULL);
|
||||
g_slist_free(handler->u.applications.apps);
|
||||
handler->u.applications.apps = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_applications_popup */
|
||||
static void _desktophandler_applications_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev)
|
||||
{
|
||||
(void) handler;
|
||||
(void) xbev;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_applications_refresh */
|
||||
static gboolean _desktophandler_applications_on_refresh(gpointer data);
|
||||
static gboolean _applications_on_refresh_done(DesktopHandler * handler);
|
||||
static void _applications_on_refresh_done_applications(
|
||||
DesktopHandler * handler);
|
||||
static int _applications_on_refresh_loop(DesktopHandler * handler);
|
||||
static void _applications_on_refresh_loop_path(DesktopHandler * handler,
|
||||
char const * path, char const * apppath);
|
||||
static void _applications_on_refresh_loop_xdg(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath));
|
||||
static void _applications_on_refresh_loop_xdg_home(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath));
|
||||
static void _applications_on_refresh_loop_xdg_path(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath), char const * path);
|
||||
static gint _applications_apps_compare(gconstpointer a, gconstpointer b);
|
||||
|
||||
static void _desktophandler_applications_refresh(DesktopHandler * handler)
|
||||
{
|
||||
g_slist_foreach(handler->u.applications.apps, (GFunc)mimehandler_delete,
|
||||
NULL);
|
||||
g_slist_free(handler->u.applications.apps);
|
||||
handler->u.applications.apps = NULL;
|
||||
handler->u.applications.refresh_source = g_idle_add(
|
||||
_desktophandler_applications_on_refresh, handler);
|
||||
}
|
||||
|
||||
static gboolean _desktophandler_applications_on_refresh(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
/* FIXME upon deletion one icon too many is removed */
|
||||
for(i = 0; i < IDLE_LOOP_ICON_CNT
|
||||
&& _applications_on_refresh_loop(handler) == 0; i++);
|
||||
if(i == IDLE_LOOP_ICON_CNT)
|
||||
return TRUE;
|
||||
return _applications_on_refresh_done(handler);
|
||||
}
|
||||
|
||||
static gboolean _applications_on_refresh_done(DesktopHandler * handler)
|
||||
{
|
||||
handler->u.applications.refresh_source = 0;
|
||||
_applications_on_refresh_done_applications(handler);
|
||||
desktop_icons_cleanup(handler->desktop, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _applications_on_refresh_done_applications(DesktopHandler * handler)
|
||||
{
|
||||
GSList * p;
|
||||
MimeHandler * mime;
|
||||
DesktopCategory * dc = handler->u.applications.category;
|
||||
String const ** categories;
|
||||
size_t i;
|
||||
String const * filename;
|
||||
DesktopIcon * icon;
|
||||
|
||||
for(p = handler->u.applications.apps; p != NULL; p = p->next)
|
||||
{
|
||||
mime = p->data;
|
||||
if(dc != NULL)
|
||||
{
|
||||
if((categories = mimehandler_get_categories(mime))
|
||||
== NULL || categories[0] == NULL)
|
||||
continue;
|
||||
for(i = 0; categories[i] != NULL; i++)
|
||||
if(string_compare(categories[i], dc->category)
|
||||
== 0)
|
||||
break;
|
||||
if(categories[i] == NULL)
|
||||
continue;
|
||||
}
|
||||
filename = mimehandler_get_filename(mime);
|
||||
/* FIXME keep track of the datadir */
|
||||
if((icon = desktopicon_new_application(handler->desktop,
|
||||
filename, NULL)) == NULL)
|
||||
continue;
|
||||
desktop_icon_add(handler->desktop, icon, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static int _applications_on_refresh_loop(DesktopHandler * handler)
|
||||
{
|
||||
_applications_on_refresh_loop_xdg(handler,
|
||||
_applications_on_refresh_loop_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _applications_on_refresh_loop_path(DesktopHandler * handler,
|
||||
char const * path, char const * apppath)
|
||||
{
|
||||
DIR * dir;
|
||||
struct stat st;
|
||||
size_t alen;
|
||||
struct dirent * de;
|
||||
size_t len;
|
||||
const char ext[] = ".desktop";
|
||||
char * name = NULL;
|
||||
char * p;
|
||||
MimeHandler * mime;
|
||||
(void) path;
|
||||
|
||||
if((dir = browser_vfs_opendir(apppath, &st)) == NULL)
|
||||
{
|
||||
if(errno != ENOENT)
|
||||
desktop_perror(NULL, apppath, 1);
|
||||
return;
|
||||
}
|
||||
if(st.st_mtime > handler->u.applications.refresh_mtime)
|
||||
handler->u.applications.refresh_mtime = st.st_mtime;
|
||||
alen = strlen(apppath);
|
||||
while((de = browser_vfs_readdir(dir)) != NULL)
|
||||
{
|
||||
if(de->d_name[0] == '.')
|
||||
if(de->d_name[1] == '\0' || (de->d_name[1] == '.'
|
||||
&& de->d_name[2] == '\0'))
|
||||
continue;
|
||||
len = strlen(de->d_name);
|
||||
if(len < sizeof(ext))
|
||||
continue;
|
||||
if(strncmp(&de->d_name[len - sizeof(ext) + 1], ext,
|
||||
sizeof(ext)) != 0)
|
||||
continue;
|
||||
if((p = realloc(name, alen + len + 2)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, apppath, 1);
|
||||
continue;
|
||||
}
|
||||
name = p;
|
||||
snprintf(name, alen + len + 2, "%s/%s", apppath, de->d_name);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() name=\"%s\" path=\"%s\"\n",
|
||||
__func__, name, path);
|
||||
#endif
|
||||
if((mime = mimehandler_new_load(name)) == NULL
|
||||
|| mimehandler_can_display(mime) == 0)
|
||||
{
|
||||
if(mime != NULL)
|
||||
mimehandler_delete(mime);
|
||||
else
|
||||
desktop_serror(NULL, NULL, 1);
|
||||
continue;
|
||||
}
|
||||
handler->u.applications.apps = g_slist_insert_sorted(
|
||||
handler->u.applications.apps, mime,
|
||||
_applications_apps_compare);
|
||||
}
|
||||
free(name);
|
||||
browser_vfs_closedir(dir);
|
||||
}
|
||||
|
||||
static void _applications_on_refresh_loop_xdg(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath))
|
||||
{
|
||||
char const * path;
|
||||
char * p;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if((path = getenv("XDG_DATA_DIRS")) == NULL || strlen(path) == 0)
|
||||
/* XXX check this at build-time instead */
|
||||
path = (strcmp(DATADIR, "/usr/local/share") == 0)
|
||||
? DATADIR ":/usr/share"
|
||||
: "/usr/local/share:" DATADIR ":/usr/share";
|
||||
if((p = strdup(path)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, NULL, 1);
|
||||
return;
|
||||
}
|
||||
for(i = 0, j = 0;; i++)
|
||||
if(p[i] == '\0')
|
||||
{
|
||||
_applications_on_refresh_loop_xdg_path(handler, callback,
|
||||
&p[j]);
|
||||
break;
|
||||
}
|
||||
else if(p[i] == ':')
|
||||
{
|
||||
p[i] = '\0';
|
||||
_applications_on_refresh_loop_xdg_path(handler, callback,
|
||||
&p[j]);
|
||||
j = i + 1;
|
||||
}
|
||||
free(p);
|
||||
_applications_on_refresh_loop_xdg_home(handler, callback);
|
||||
}
|
||||
|
||||
static void _applications_on_refresh_loop_xdg_home(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath))
|
||||
{
|
||||
char const fallback[] = ".local/share";
|
||||
char const * path;
|
||||
char const * homedir;
|
||||
size_t len;
|
||||
char * p;
|
||||
|
||||
/* use $XDG_DATA_HOME if set and not empty */
|
||||
if((path = getenv("XDG_DATA_HOME")) != NULL && strlen(path) > 0)
|
||||
{
|
||||
_applications_on_refresh_loop_xdg_path(handler, callback, path);
|
||||
return;
|
||||
}
|
||||
/* fallback to "$HOME/.local/share" */
|
||||
if((homedir = getenv("HOME")) == NULL)
|
||||
homedir = g_get_home_dir();
|
||||
len = strlen(homedir) + 1 + sizeof(fallback);
|
||||
if((p = malloc(len)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, homedir, 1);
|
||||
return;
|
||||
}
|
||||
snprintf(p, len, "%s/%s", homedir, fallback);
|
||||
_applications_on_refresh_loop_xdg_path(handler, callback, p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void _applications_on_refresh_loop_xdg_path(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath), char const * path)
|
||||
{
|
||||
const char applications[] = "/applications";
|
||||
char * apppath;
|
||||
|
||||
if((apppath = string_new_append(path, applications, NULL)) == NULL)
|
||||
desktop_serror(NULL, path, 1);
|
||||
callback(handler, path, apppath);
|
||||
string_delete(apppath);
|
||||
}
|
||||
|
||||
static gint _applications_apps_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
MimeHandler * mha = (MimeHandler *)a;
|
||||
MimeHandler * mhb = (MimeHandler *)b;
|
||||
String const * mhas;
|
||||
String const * mhbs;
|
||||
|
||||
if((mhas = mimehandler_get_generic_name(mha, 1)) == NULL)
|
||||
mhas = mimehandler_get_name(mha, 1);
|
||||
if((mhbs = mimehandler_get_generic_name(mhb, 1)) == NULL)
|
||||
mhbs = mimehandler_get_name(mhb, 1);
|
||||
return string_compare(mhas, mhbs);
|
||||
}
|
416
src/desktop/handler/categories.c
Normal file
416
src/desktop/handler/categories.c
Normal file
|
@ -0,0 +1,416 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
/* DesktopHandlerCategories */
|
||||
/* private */
|
||||
/* variables */
|
||||
static DesktopCategory _desktop_categories[] =
|
||||
{
|
||||
{ FALSE, "Audio", N_("Audio"), "gnome-mime-audio", },
|
||||
{ FALSE, "Development", N_("Development"),"applications-development"},
|
||||
{ FALSE, "Education", N_("Education"),"applications-science" },
|
||||
{ FALSE, "Game", N_("Games"), "applications-games" },
|
||||
{ FALSE, "Graphics", N_("Graphics"), "applications-graphics" },
|
||||
{ FALSE, "AudioVideo", N_("Multimedia"),"applications-multimedia"},
|
||||
{ FALSE, "Network", N_("Network"), "applications-internet" },
|
||||
{ FALSE, "Office", N_("Office"), "applications-office" },
|
||||
{ FALSE, "Settings", N_("Settings"), "gnome-settings" },
|
||||
{ FALSE, "System", N_("System"), "applications-system" },
|
||||
{ FALSE, "Utility", N_("Utilities"),"applications-utilities"},
|
||||
{ FALSE, "Video", N_("Video"), "video" }
|
||||
};
|
||||
static const size_t _desktop_categories_cnt = sizeof(_desktop_categories)
|
||||
/ sizeof(*_desktop_categories);
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static void _desktophandler_categories_init(DesktopHandler * handler);
|
||||
static void _desktophandler_categories_destroy(DesktopHandler * handler);
|
||||
static void _desktophandler_categories_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev);
|
||||
static void _desktophandler_categories_refresh(DesktopHandler * handler);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* desktophandler_categories_init */
|
||||
static void _categories_init_on_back(Desktop * desktop, gpointer data);
|
||||
|
||||
static void _desktophandler_categories_init(DesktopHandler * handler)
|
||||
{
|
||||
DesktopIcon * desktopicon;
|
||||
GdkPixbuf * icon;
|
||||
unsigned int size;
|
||||
|
||||
handler->u.categories.refresh_dir = NULL;
|
||||
handler->u.categories.refresh_mtime = 0;
|
||||
handler->u.categories.refresh_source = 0;
|
||||
handler->u.categories.apps = NULL;
|
||||
desktop_set_alignment(handler->desktop, DESKTOP_ALIGNMENT_HORIZONTAL);
|
||||
if((desktopicon = desktopicon_new(handler->desktop, _("Back"), NULL))
|
||||
== NULL)
|
||||
{
|
||||
desktop_serror(handler->desktop, _("Back"), 1);
|
||||
return;
|
||||
}
|
||||
desktopicon_set_callback(desktopicon, _categories_init_on_back, NULL);
|
||||
desktopicon_set_first(desktopicon, TRUE);
|
||||
desktopicon_set_immutable(desktopicon, TRUE);
|
||||
desktop_get_icon_size(handler->desktop, NULL, NULL, &size);
|
||||
icon = gtk_icon_theme_load_icon(desktop_get_theme(handler->desktop),
|
||||
"back", size, 0, NULL);
|
||||
if(icon != NULL)
|
||||
desktopicon_set_icon(desktopicon, icon);
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
}
|
||||
|
||||
static void _categories_init_on_back(Desktop * desktop, gpointer data)
|
||||
{
|
||||
(void) data;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
desktop_set_icons(desktop, DESKTOP_ICONS_HOMESCREEN);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_categories_destroy */
|
||||
static void _desktophandler_categories_destroy(DesktopHandler * handler)
|
||||
{
|
||||
if(handler->u.categories.refresh_source != 0)
|
||||
g_source_remove(handler->u.categories.refresh_source);
|
||||
if(handler->u.categories.refresh_dir != NULL)
|
||||
browser_vfs_closedir(handler->u.categories.refresh_dir);
|
||||
g_slist_foreach(handler->u.categories.apps, (GFunc)mimehandler_delete,
|
||||
NULL);
|
||||
g_slist_free(handler->u.categories.apps);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_categories_popup */
|
||||
static void _desktophandler_categories_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev)
|
||||
{
|
||||
(void) handler;
|
||||
(void) xbev;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_categories_refresh */
|
||||
static gboolean _desktophandler_categories_on_refresh(gpointer data);
|
||||
static gboolean _categories_on_refresh_done(DesktopHandler * handler);
|
||||
static void _categories_on_refresh_done_categories(DesktopHandler * handler);
|
||||
static void _categories_on_refresh_done_categories_open(Desktop * desktop,
|
||||
gpointer data);
|
||||
static int _categories_on_refresh_loop(DesktopHandler * handler);
|
||||
static void _categories_on_refresh_loop_path(DesktopHandler * handler,
|
||||
char const * path, char const * apppath);
|
||||
static void _categories_on_refresh_loop_xdg(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath));
|
||||
static void _categories_on_refresh_loop_xdg_home(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath));
|
||||
static void _categories_on_refresh_loop_xdg_path(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath), char const * path);
|
||||
static gint _categories_apps_compare(gconstpointer a, gconstpointer b);
|
||||
|
||||
static void _desktophandler_categories_refresh(DesktopHandler * handler)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < _desktop_categories_cnt; i++)
|
||||
_desktop_categories[i].show = FALSE;
|
||||
g_slist_foreach(handler->u.categories.apps, (GFunc)mimehandler_delete,
|
||||
NULL);
|
||||
g_slist_free(handler->u.categories.apps);
|
||||
handler->u.categories.apps = NULL;
|
||||
handler->u.categories.refresh_source = g_idle_add(
|
||||
_desktophandler_categories_on_refresh, handler);
|
||||
}
|
||||
|
||||
static gboolean _desktophandler_categories_on_refresh(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
/* FIXME upon deletion one icon too many is removed */
|
||||
for(i = 0; i < IDLE_LOOP_ICON_CNT
|
||||
&& _categories_on_refresh_loop(handler) == 0; i++);
|
||||
if(i == IDLE_LOOP_ICON_CNT)
|
||||
return TRUE;
|
||||
return _categories_on_refresh_done(handler);
|
||||
}
|
||||
|
||||
static gboolean _categories_on_refresh_done(DesktopHandler * handler)
|
||||
{
|
||||
handler->u.categories.refresh_source = 0;
|
||||
_categories_on_refresh_done_categories(handler);
|
||||
desktop_icons_cleanup(handler->desktop, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_done_categories(DesktopHandler * handler)
|
||||
{
|
||||
GSList * p;
|
||||
MimeHandler * mime;
|
||||
DesktopCategory * dc;
|
||||
String const ** categories;
|
||||
size_t i;
|
||||
size_t j;
|
||||
String const * filename;
|
||||
DesktopIcon * icon;
|
||||
|
||||
for(p = handler->u.categories.apps; p != NULL; p = p->next)
|
||||
{
|
||||
mime = p->data;
|
||||
filename = mimehandler_get_filename(mime);
|
||||
if((categories = mimehandler_get_categories(mime)) == NULL
|
||||
|| categories[0] == NULL)
|
||||
{
|
||||
/* FIXME keep track of the datadir */
|
||||
if((icon = desktopicon_new_application(handler->desktop,
|
||||
filename, NULL))
|
||||
!= NULL)
|
||||
desktop_icon_add(handler->desktop, icon, FALSE);
|
||||
continue;
|
||||
}
|
||||
for(i = 0; i < _desktop_categories_cnt; i++)
|
||||
{
|
||||
dc = &_desktop_categories[i];
|
||||
for(j = 0; categories[j] != NULL; j++)
|
||||
if(string_compare(categories[j], dc->category)
|
||||
== 0)
|
||||
break;
|
||||
if(categories[j] != NULL)
|
||||
break;
|
||||
}
|
||||
if(i == _desktop_categories_cnt)
|
||||
{
|
||||
/* FIXME keep track of the datadir */
|
||||
if((icon = desktopicon_new_application(handler->desktop,
|
||||
filename, NULL))
|
||||
!= NULL)
|
||||
desktop_icon_add(handler->desktop, icon, FALSE);
|
||||
continue;
|
||||
}
|
||||
if(dc->show == TRUE)
|
||||
continue;
|
||||
dc->show = TRUE;
|
||||
if((icon = desktopicon_new_category(handler->desktop,
|
||||
_(dc->name), dc->icon)) == NULL)
|
||||
continue;
|
||||
desktopicon_set_callback(icon,
|
||||
_categories_on_refresh_done_categories_open,
|
||||
dc);
|
||||
desktop_icon_add(handler->desktop, icon, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_done_categories_open(Desktop * desktop,
|
||||
gpointer data)
|
||||
{
|
||||
DesktopCategory * dc = data;
|
||||
DesktopHandler * handler;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, _(dc->name));
|
||||
#endif
|
||||
handler = desktop_get_handler(desktop);
|
||||
desktophandler_set_icons(handler, DESKTOP_ICONS_APPLICATIONS);
|
||||
/* FIXME really need an extra argument for applications (category) */
|
||||
handler->u.applications.category = dc;
|
||||
desktop_refresh(desktop);
|
||||
}
|
||||
|
||||
static int _categories_on_refresh_loop(DesktopHandler * handler)
|
||||
{
|
||||
_categories_on_refresh_loop_xdg(handler,
|
||||
_categories_on_refresh_loop_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_loop_path(DesktopHandler * handler,
|
||||
char const * path, char const * apppath)
|
||||
{
|
||||
DIR * dir;
|
||||
struct stat st;
|
||||
size_t alen;
|
||||
struct dirent * de;
|
||||
size_t len;
|
||||
const char ext[] = ".desktop";
|
||||
char * name = NULL;
|
||||
char * p;
|
||||
MimeHandler * mime;
|
||||
(void) path;
|
||||
|
||||
if((dir = browser_vfs_opendir(apppath, &st)) == NULL)
|
||||
{
|
||||
if(errno != ENOENT)
|
||||
desktop_perror(NULL, apppath, 1);
|
||||
return;
|
||||
}
|
||||
if(st.st_mtime > handler->u.categories.refresh_mtime)
|
||||
handler->u.categories.refresh_mtime = st.st_mtime;
|
||||
alen = strlen(apppath);
|
||||
while((de = browser_vfs_readdir(dir)) != NULL)
|
||||
{
|
||||
if(de->d_name[0] == '.')
|
||||
if(de->d_name[1] == '\0' || (de->d_name[1] == '.'
|
||||
&& de->d_name[2] == '\0'))
|
||||
continue;
|
||||
len = strlen(de->d_name);
|
||||
if(len < sizeof(ext))
|
||||
continue;
|
||||
if(strncmp(&de->d_name[len - sizeof(ext) + 1], ext,
|
||||
sizeof(ext)) != 0)
|
||||
continue;
|
||||
if((p = realloc(name, alen + len + 2)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, apppath, 1);
|
||||
continue;
|
||||
}
|
||||
name = p;
|
||||
snprintf(name, alen + len + 2, "%s/%s", apppath, de->d_name);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() name=\"%s\" path=\"%s\"\n",
|
||||
__func__, name, path);
|
||||
#endif
|
||||
if((mime = mimehandler_new_load(name)) == NULL
|
||||
|| mimehandler_can_display(mime) == 0)
|
||||
{
|
||||
if(mime != NULL)
|
||||
mimehandler_delete(mime);
|
||||
else
|
||||
desktop_serror(NULL, NULL, 1);
|
||||
continue;
|
||||
}
|
||||
handler->u.categories.apps = g_slist_insert_sorted(
|
||||
handler->u.categories.apps, mime,
|
||||
_categories_apps_compare);
|
||||
}
|
||||
free(name);
|
||||
browser_vfs_closedir(dir);
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_loop_xdg(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath))
|
||||
{
|
||||
char const * path;
|
||||
char * p;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if((path = getenv("XDG_DATA_DIRS")) == NULL || strlen(path) == 0)
|
||||
/* XXX check this at build-time instead */
|
||||
path = (strcmp(DATADIR, "/usr/local/share") == 0)
|
||||
? DATADIR ":/usr/share"
|
||||
: "/usr/local/share:" DATADIR ":/usr/share";
|
||||
if((p = strdup(path)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, NULL, 1);
|
||||
return;
|
||||
}
|
||||
for(i = 0, j = 0;; i++)
|
||||
if(p[i] == '\0')
|
||||
{
|
||||
_categories_on_refresh_loop_xdg_path(handler, callback,
|
||||
&p[j]);
|
||||
break;
|
||||
}
|
||||
else if(p[i] == ':')
|
||||
{
|
||||
p[i] = '\0';
|
||||
_categories_on_refresh_loop_xdg_path(handler, callback,
|
||||
&p[j]);
|
||||
j = i + 1;
|
||||
}
|
||||
free(p);
|
||||
_categories_on_refresh_loop_xdg_home(handler, callback);
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_loop_xdg_home(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath))
|
||||
{
|
||||
char const fallback[] = ".local/share";
|
||||
char const * path;
|
||||
char const * homedir;
|
||||
size_t len;
|
||||
char * p;
|
||||
|
||||
/* use $XDG_DATA_HOME if set and not empty */
|
||||
if((path = getenv("XDG_DATA_HOME")) != NULL && strlen(path) > 0)
|
||||
{
|
||||
_categories_on_refresh_loop_xdg_path(handler, callback, path);
|
||||
return;
|
||||
}
|
||||
/* fallback to "$HOME/.local/share" */
|
||||
if((homedir = getenv("HOME")) == NULL)
|
||||
homedir = g_get_home_dir();
|
||||
len = strlen(homedir) + 1 + sizeof(fallback);
|
||||
if((p = malloc(len)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, homedir, 1);
|
||||
return;
|
||||
}
|
||||
snprintf(p, len, "%s/%s", homedir, fallback);
|
||||
_categories_on_refresh_loop_xdg_path(handler, callback, p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void _categories_on_refresh_loop_xdg_path(DesktopHandler * handler,
|
||||
void (*callback)(DesktopHandler * handler, char const * path,
|
||||
char const * apppath), char const * path)
|
||||
{
|
||||
const char applications[] = "/applications";
|
||||
char * apppath;
|
||||
|
||||
if((apppath = string_new_append(path, applications, NULL)) == NULL)
|
||||
desktop_serror(NULL, path, 1);
|
||||
callback(handler, path, apppath);
|
||||
string_delete(apppath);
|
||||
}
|
||||
|
||||
static gint _categories_apps_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
MimeHandler * mha = (MimeHandler *)a;
|
||||
MimeHandler * mhb = (MimeHandler *)b;
|
||||
String const * mhas;
|
||||
String const * mhbs;
|
||||
|
||||
if((mhas = mimehandler_get_generic_name(mha, 1)) == NULL)
|
||||
mhas = mimehandler_get_name(mha, 1);
|
||||
if((mhbs = mimehandler_get_generic_name(mhb, 1)) == NULL)
|
||||
mhbs = mimehandler_get_name(mhb, 1);
|
||||
return string_compare(mhas, mhbs);
|
||||
}
|
421
src/desktop/handler/files.c
Normal file
421
src/desktop/handler/files.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
/* DesktopHandlerFiles */
|
||||
/* private */
|
||||
/* prototypes */
|
||||
static void _desktophandler_files_init(DesktopHandler * handler);
|
||||
static void _desktophandler_files_destroy(DesktopHandler * handler);
|
||||
static void _desktophandler_files_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev);
|
||||
static void _desktophandler_files_refresh(DesktopHandler * handler);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* desktophandler_files_init */
|
||||
static int _files_init_add_home(DesktopHandler * handler);
|
||||
|
||||
static void _desktophandler_files_init(DesktopHandler * handler)
|
||||
{
|
||||
char const * path;
|
||||
struct stat st;
|
||||
|
||||
if((path = getenv("XDG_DESKTOP_DIR")) != NULL)
|
||||
handler->u.files.path = string_new(path);
|
||||
else
|
||||
handler->u.files.path = string_new_append(
|
||||
desktop_get_home(handler->desktop), "/",
|
||||
DESKTOP, NULL);
|
||||
handler->u.files.refresh_dir = NULL;
|
||||
handler->u.files.refresh_mtime = 0;
|
||||
handler->u.files.refresh_source = 0;
|
||||
handler->u.files.menu = NULL;
|
||||
desktop_set_alignment(handler->desktop, DESKTOP_ALIGNMENT_VERTICAL);
|
||||
/* FIXME let it be configured again */
|
||||
handler->u.files.show_hidden = FALSE;
|
||||
/* check for errors */
|
||||
if(handler->u.files.path == NULL)
|
||||
{
|
||||
desktop_error(handler->desktop, NULL, error_get(NULL), 1);
|
||||
return;
|
||||
}
|
||||
_files_init_add_home(handler);
|
||||
if(browser_vfs_stat(handler->u.files.path, &st) == 0)
|
||||
{
|
||||
if(!S_ISDIR(st.st_mode))
|
||||
{
|
||||
desktop_error(NULL, handler->u.files.path,
|
||||
strerror(ENOTDIR), 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(errno != ENOENT)
|
||||
desktop_perror(NULL, handler->u.files.path, 1);
|
||||
}
|
||||
|
||||
static int _files_init_add_home(DesktopHandler * handler)
|
||||
{
|
||||
DesktopIcon * desktopicon;
|
||||
GdkPixbuf * icon;
|
||||
unsigned int size;
|
||||
|
||||
if((desktopicon = desktopicon_new(handler->desktop, _("Home"),
|
||||
desktop_get_home(handler->desktop)))
|
||||
== NULL)
|
||||
return -desktop_serror(handler->desktop, _("Home"), 1);
|
||||
desktopicon_set_first(desktopicon, TRUE);
|
||||
desktopicon_set_immutable(desktopicon, TRUE);
|
||||
desktop_get_icon_size(handler->desktop, NULL, NULL, &size);
|
||||
icon = gtk_icon_theme_load_icon(desktop_get_theme(handler->desktop),
|
||||
"gnome-home", size, 0, NULL);
|
||||
if(icon == NULL)
|
||||
icon = gtk_icon_theme_load_icon(desktop_get_theme(
|
||||
handler->desktop), "gnome-fs-home",
|
||||
size, 0, NULL);
|
||||
if(icon != NULL)
|
||||
desktopicon_set_icon(desktopicon, icon);
|
||||
/* XXX report errors */
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_files_destroy */
|
||||
static void _desktophandler_files_destroy(DesktopHandler * handler)
|
||||
{
|
||||
if(handler->u.files.refresh_source != 0)
|
||||
g_source_remove(handler->u.files.refresh_source);
|
||||
if(handler->u.files.refresh_dir != NULL)
|
||||
browser_vfs_closedir(handler->u.files.refresh_dir);
|
||||
if(handler->u.files.menu != NULL)
|
||||
gtk_widget_destroy(handler->u.files.menu);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_files_popup */
|
||||
static void _on_popup_new_folder(gpointer data);
|
||||
static void _on_popup_new_text_file(gpointer data);
|
||||
static void _on_popup_paste(gpointer data);
|
||||
static void _on_popup_preferences(gpointer data);
|
||||
static void _on_popup_symlink(gpointer data);
|
||||
|
||||
static void _desktophandler_files_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev)
|
||||
{
|
||||
GtkWidget * menuitem;
|
||||
GtkWidget * submenu;
|
||||
GtkWidget * image;
|
||||
|
||||
if((xbev == NULL || xbev->button != 3) && handler->u.files.menu != NULL)
|
||||
{
|
||||
gtk_widget_destroy(handler->u.files.menu);
|
||||
handler->u.files.menu = NULL;
|
||||
}
|
||||
handler->u.files.menu = gtk_menu_new();
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_New"));
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
|
||||
gtk_image_new_from_icon_name("document-new",
|
||||
GTK_ICON_SIZE_MENU));
|
||||
submenu = gtk_menu_new();
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(handler->u.files.menu), menuitem);
|
||||
/* submenu for new documents */
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Folder"));
|
||||
image = gtk_image_new_from_icon_name("folder-new", GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
|
||||
g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
|
||||
_on_popup_new_folder), handler);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
|
||||
menuitem = gtk_separator_menu_item_new();
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Symbolic link..."));
|
||||
g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
|
||||
_on_popup_symlink), handler);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Text file"));
|
||||
image = gtk_image_new_from_icon_name("stock_new-text",
|
||||
GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
|
||||
g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
|
||||
_on_popup_new_text_file), handler);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
|
||||
/* edition */
|
||||
menuitem = gtk_separator_menu_item_new();
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(handler->u.files.menu), menuitem);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Paste"));
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
|
||||
gtk_image_new_from_icon_name("edit-paste",
|
||||
GTK_ICON_SIZE_MENU));
|
||||
g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
|
||||
_on_popup_paste), handler);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(handler->u.files.menu), menuitem);
|
||||
/* preferences */
|
||||
menuitem = gtk_separator_menu_item_new();
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(handler->u.files.menu), menuitem);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Preferences"));
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
|
||||
gtk_image_new_from_icon_name("gtk-preferences",
|
||||
GTK_ICON_SIZE_MENU));
|
||||
g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
|
||||
_on_popup_preferences), handler);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(handler->u.files.menu), menuitem);
|
||||
gtk_widget_show_all(handler->u.files.menu);
|
||||
gtk_menu_popup(GTK_MENU(handler->u.files.menu), NULL, NULL, NULL, NULL,
|
||||
3, (xbev != NULL)
|
||||
? xbev->time : gtk_get_current_event_time());
|
||||
}
|
||||
|
||||
static void _on_popup_new_folder(gpointer data)
|
||||
{
|
||||
static char const newfolder[] = N_("New folder");
|
||||
DesktopHandler * handler = data;
|
||||
String * path;
|
||||
|
||||
gtk_widget_destroy(handler->u.files.menu);
|
||||
handler->u.files.menu = NULL;
|
||||
if((path = string_new_append(handler->u.files.path, "/", newfolder,
|
||||
NULL)) == NULL)
|
||||
{
|
||||
desktop_serror(handler->desktop, newfolder, 0);
|
||||
return;
|
||||
}
|
||||
if(browser_vfs_mkdir(path, 0777) != 0)
|
||||
desktop_perror(handler->desktop, path, 0);
|
||||
string_delete(path);
|
||||
}
|
||||
|
||||
static void _on_popup_new_text_file(gpointer data)
|
||||
{
|
||||
static char const newtext[] = N_("New text file.txt");
|
||||
DesktopHandler * handler = data;
|
||||
String * path;
|
||||
int fd;
|
||||
|
||||
gtk_widget_destroy(handler->u.files.menu);
|
||||
handler->u.files.menu = NULL;
|
||||
if((path = string_new_append(handler->u.files.path, "/", _(newtext),
|
||||
NULL)) == NULL)
|
||||
{
|
||||
desktop_serror(handler->desktop, _(newtext), 0);
|
||||
return;
|
||||
}
|
||||
if((fd = creat(path, 0666)) < 0)
|
||||
desktop_perror(handler->desktop, path, 0);
|
||||
else
|
||||
close(fd);
|
||||
string_delete(path);
|
||||
}
|
||||
|
||||
static void _on_popup_paste(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
|
||||
/* FIXME implement */
|
||||
gtk_widget_destroy(handler->u.files.menu);
|
||||
handler->u.files.menu = NULL;
|
||||
}
|
||||
|
||||
static void _on_popup_preferences(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
|
||||
desktop_show_preferences(handler->desktop);
|
||||
}
|
||||
|
||||
static void _on_popup_symlink(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
|
||||
if(_common_symlink(desktop_get_window(handler->desktop),
|
||||
handler->u.files.path) != 0)
|
||||
desktop_perror(handler->desktop, handler->u.files.path, 0);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_files_refresh */
|
||||
static gboolean _desktophandler_files_on_refresh(gpointer data);
|
||||
static gboolean _files_on_refresh_done(DesktopHandler * handler);
|
||||
static gboolean _files_on_refresh_done_timeout(gpointer data);
|
||||
static gboolean _files_on_refresh_loop(DesktopHandler * handler);
|
||||
static int _files_on_refresh_loop_lookup(DesktopHandler * handler,
|
||||
char const * name);
|
||||
static int _files_on_refresh_loop_opendir(DesktopHandler * handler);
|
||||
|
||||
static void _desktophandler_files_refresh(DesktopHandler * handler)
|
||||
{
|
||||
if(handler->u.files.refresh_source != 0)
|
||||
g_source_remove(handler->u.files.refresh_source);
|
||||
if(handler->u.files.refresh_dir != NULL)
|
||||
browser_vfs_closedir(handler->u.files.refresh_dir);
|
||||
handler->u.files.refresh_dir = NULL;
|
||||
if(handler->u.files.path == NULL)
|
||||
return;
|
||||
handler->u.files.refresh_source = g_idle_add(
|
||||
_desktophandler_files_on_refresh, handler);
|
||||
}
|
||||
|
||||
static gboolean _desktophandler_files_on_refresh(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
unsigned int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
/* FIXME upon deletion one icon too many is removed */
|
||||
for(i = 0; i < IDLE_LOOP_ICON_CNT
|
||||
&& _files_on_refresh_loop(handler) == 0; i++);
|
||||
if(i == IDLE_LOOP_ICON_CNT)
|
||||
return TRUE;
|
||||
return _files_on_refresh_done(handler);
|
||||
}
|
||||
|
||||
static gboolean _files_on_refresh_done(DesktopHandler * handler)
|
||||
{
|
||||
if(handler->u.files.refresh_dir != NULL)
|
||||
browser_vfs_closedir(handler->u.files.refresh_dir);
|
||||
handler->u.files.refresh_dir = NULL;
|
||||
desktop_icons_cleanup(handler->desktop, TRUE);
|
||||
handler->u.files.refresh_source = g_timeout_add(1000,
|
||||
_files_on_refresh_done_timeout, handler);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean _files_on_refresh_done_timeout(gpointer data)
|
||||
{
|
||||
DesktopHandler * handler = data;
|
||||
struct stat st;
|
||||
|
||||
if(handler->u.files.path == NULL)
|
||||
{
|
||||
handler->u.files.refresh_source = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if(browser_vfs_stat(handler->u.files.path, &st) != 0)
|
||||
{
|
||||
handler->u.files.refresh_source = 0;
|
||||
return desktop_perror(NULL, handler->u.files.path, FALSE);
|
||||
}
|
||||
if(st.st_mtime == handler->u.files.refresh_mtime)
|
||||
return TRUE;
|
||||
handler->u.files.refresh_source = 0;
|
||||
desktop_refresh(handler->desktop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int _files_on_refresh_loop(DesktopHandler * handler)
|
||||
{
|
||||
const char ext[] = ".desktop";
|
||||
struct dirent * de;
|
||||
String * p;
|
||||
size_t len;
|
||||
gchar * q;
|
||||
DesktopIcon * desktopicon;
|
||||
GError * error = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
if(handler->u.files.refresh_dir == NULL
|
||||
&& _files_on_refresh_loop_opendir(handler) != 0)
|
||||
return -1;
|
||||
while((de = browser_vfs_readdir(handler->u.files.refresh_dir)) != NULL)
|
||||
{
|
||||
if(de->d_name[0] == '.')
|
||||
{
|
||||
if(de->d_name[1] == '\0')
|
||||
continue;
|
||||
if(de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||
continue;
|
||||
if(handler->u.files.show_hidden == 0)
|
||||
continue;
|
||||
}
|
||||
if(_files_on_refresh_loop_lookup(handler, de->d_name) == 1)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(de == NULL)
|
||||
return -1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, de->d_name);
|
||||
#endif
|
||||
if((p = string_new_append(handler->u.files.path, "/", de->d_name, NULL))
|
||||
== NULL)
|
||||
return -desktop_serror(handler->desktop, de->d_name, 1);
|
||||
/* detect desktop entries */
|
||||
if((len = strlen(de->d_name)) > sizeof(ext)
|
||||
&& strcmp(&de->d_name[len - sizeof(ext) + 1], ext) == 0)
|
||||
desktopicon = desktopicon_new_application(handler->desktop, p,
|
||||
handler->u.files.path);
|
||||
/* XXX not relative to the current folder */
|
||||
else if((q = g_filename_to_utf8(de->d_name, -1, NULL, NULL, &error))
|
||||
!= NULL)
|
||||
{
|
||||
desktopicon = desktopicon_new(handler->desktop, q, p);
|
||||
g_free(q);
|
||||
}
|
||||
else
|
||||
{
|
||||
desktop_error(NULL, NULL, error->message, 1);
|
||||
g_error_free(error);
|
||||
desktopicon = desktopicon_new(handler->desktop, de->d_name, p);
|
||||
}
|
||||
if(desktopicon != NULL)
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
string_delete(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _files_on_refresh_loop_lookup(DesktopHandler * handler,
|
||||
char const * name)
|
||||
{
|
||||
DesktopIcon * icon;
|
||||
|
||||
if((icon = desktop_icons_lookup(handler->desktop, name)) == NULL)
|
||||
return 0;
|
||||
desktopicon_set_updated(icon, TRUE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _files_on_refresh_loop_opendir(DesktopHandler * handler)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__,
|
||||
handler->u.files.path);
|
||||
#endif
|
||||
if((handler->u.files.refresh_dir = browser_vfs_opendir(
|
||||
handler->u.files.path, &st)) == NULL)
|
||||
{
|
||||
desktop_perror(NULL, handler->u.files.path, 1);
|
||||
handler->u.files.refresh_source = 0;
|
||||
return -1;
|
||||
}
|
||||
handler->u.files.refresh_mtime = st.st_mtime;
|
||||
return 0;
|
||||
}
|
127
src/desktop/handler/homescreen.c
Normal file
127
src/desktop/handler/homescreen.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2020 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Desktop Browser */
|
||||
/* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
|
||||
|
||||
/* DesktopHandlerHomescreen */
|
||||
/* private */
|
||||
/* prototypes */
|
||||
static void _desktophandler_homescreen_init(DesktopHandler * handler);
|
||||
static void _desktophandler_homescreen_destroy(DesktopHandler * handler);
|
||||
static void _desktophandler_homescreen_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev);
|
||||
static void _desktophandler_homescreen_refresh(DesktopHandler * handler);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* desktophandler_homescreen_init */
|
||||
static int _homescreen_init_subdir(DesktopHandler * handler,
|
||||
char const * subdir, char const * name);
|
||||
static void _homescreen_init_on_applications(Desktop * desktop, gpointer data);
|
||||
|
||||
static void _desktophandler_homescreen_init(DesktopHandler * handler)
|
||||
{
|
||||
DesktopIcon * desktopicon;
|
||||
GdkPixbuf * icon;
|
||||
char const * paths[] =
|
||||
{
|
||||
#ifdef EMBEDDED
|
||||
/* FIXME let this be configurable */
|
||||
"deforaos-phone-contacts",
|
||||
"deforaos-phone-dialer",
|
||||
"deforaos-phone-messages",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
char const ** p;
|
||||
unsigned int size;
|
||||
|
||||
if((desktopicon = desktopicon_new(handler->desktop, _("Applications"),
|
||||
NULL)) == NULL)
|
||||
{
|
||||
desktop_serror(handler->desktop, _("Applications"), 1);
|
||||
return;
|
||||
}
|
||||
desktopicon_set_callback(desktopicon, _homescreen_init_on_applications,
|
||||
NULL);
|
||||
desktopicon_set_immutable(desktopicon, TRUE);
|
||||
desktop_get_icon_size(handler->desktop, NULL, NULL, &size);
|
||||
icon = gtk_icon_theme_load_icon(desktop_get_theme(handler->desktop),
|
||||
"gnome-applications", size, 0, NULL);
|
||||
if(icon != NULL)
|
||||
desktopicon_set_icon(desktopicon, icon);
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
for(p = paths; *p != NULL; p++)
|
||||
_homescreen_init_subdir(handler, DATADIR "/applications", *p);
|
||||
}
|
||||
|
||||
static int _homescreen_init_subdir(DesktopHandler * handler,
|
||||
char const * subdir, char const * name)
|
||||
{
|
||||
DesktopIcon * desktopicon;
|
||||
String * q;
|
||||
|
||||
if((q = string_new_append(subdir, "/", name, ".desktop", NULL)) == NULL)
|
||||
return -desktop_error(NULL, name, error_get(NULL), 1);
|
||||
if(access(q, R_OK) == 0
|
||||
&& (desktopicon = desktopicon_new_application(
|
||||
handler->desktop, q, DATADIR)) != NULL)
|
||||
desktop_icon_add(handler->desktop, desktopicon, FALSE);
|
||||
string_delete(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _homescreen_init_on_applications(Desktop * desktop, gpointer data)
|
||||
{
|
||||
(void) data;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
#endif
|
||||
desktop_set_icons(desktop, DESKTOP_ICONS_CATEGORIES);
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_homescreen_destroy */
|
||||
static void _desktophandler_homescreen_destroy(DesktopHandler * handler)
|
||||
{
|
||||
(void) handler;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_homescreen_popup */
|
||||
static void _desktophandler_homescreen_popup(DesktopHandler * handler,
|
||||
XButtonEvent * xbev)
|
||||
{
|
||||
(void) handler;
|
||||
(void) xbev;
|
||||
}
|
||||
|
||||
|
||||
/* desktophandler_homescreen_refresh */
|
||||
static void _desktophandler_homescreen_refresh(DesktopHandler * handler)
|
||||
{
|
||||
(void) handler;
|
||||
}
|
|
@ -5,13 +5,13 @@ cflags_force=`pkg-config --cflags libDesktop`
|
|||
cflags=-W -Wall -g -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
|
||||
ldflags_force=`pkg-config --libs libDesktop` -lintl
|
||||
ldflags=-pie -Wl,-z,relro -Wl,-z,now
|
||||
dist=Makefile,desktop.h,desktopicon.h,desktopiconwindow.h
|
||||
dist=Makefile,desktop.h,desktopicon.h,desktopiconwindow.h,handler.h,handler/applications.c,handler/categories.c,handler/files.c,handler/homescreen.c
|
||||
|
||||
#targets
|
||||
[desktop]
|
||||
type=binary
|
||||
depends=$(OBJDIR)../lib/libBrowser.a
|
||||
sources=desktop.c,desktopicon.c,desktopiconwindow.c,main.c
|
||||
sources=desktop.c,desktopicon.c,desktopiconwindow.c,handler.c,main.c
|
||||
cflags=`pkg-config --cflags x11 xrandr`
|
||||
ldflags=`pkg-config --libs x11 xrandr` -L$(OBJDIR)../lib -Wl,-rpath,$(LIBDIR) -lBrowser
|
||||
install=$(BINDIR)
|
||||
|
@ -36,5 +36,8 @@ cppflags=-D PREFIX=\"$(PREFIX)\"
|
|||
[desktopiconwindow.c]
|
||||
depends=../common.h,desktop.h,desktopicon.h,desktopiconwindow.h
|
||||
|
||||
[handler.c]
|
||||
depends=desktop.h,desktopicon.h,desktopiconwindow.h,handler.h,handler/applications.c,handler/categories.c,handler/files.c,handler/homescreen.c
|
||||
|
||||
[main.c]
|
||||
depends=desktop.h,../../config.h
|
||||
|
|
Loading…
Reference in New Issue
Block a user