00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "config.h"
00032
00033 #include <gconf/gconf-client.h>
00034 #include <gdk/gdk.h>
00035 #include <glib.h>
00036 #include <string.h>
00037
00038 #include "ctb_log.h"
00039 #include "filetypes.h"
00040 #include "i18n.h"
00041
00042
00043
00044
00045
00046
00047
00048 typedef struct
00049 {
00050 gchar *extension;
00051 gchar *reference_ext;
00052 gboolean is_directory;
00053 gchar *icon_name;
00054 gchar *description;
00055 gchar *viewer_cmd;
00056 GdkPixbuf *pixbuf_icon [N_FILEMODEL_THUMB_SIZES];
00057 gboolean generate_thumbnail;
00058 } filetype_info_t;
00059
00060
00061
00062
00063
00064
00065 static const gchar *ICONS_DIRECTORY = DATADIR;
00066 static const gchar *ICONFILE_PREFIX = "icon-";
00067 static const gchar *ICONFILE_POSTFIX[ N_FILEMODEL_THUMB_SIZES ] =
00068 {
00069 "-mini.png",
00070 "-small.png",
00071 "-medium.png",
00072 "-large.png"
00073 };
00074
00075 static const gchar *ICONNAME_APPLICATION = "application";
00076 static const gchar *ICONNAME_LIBRARY = "sdcard";
00077
00078 #define CTB_GCONF_PATH "/apps/er/sys/ctb"
00079 #define REGKEY_SHOW_SDCARD "show_sdcard"
00080 static const gchar *REGKEY_FILETYPE_DIR = CTB_GCONF_PATH "/filetypes";
00081
00082
00083 static filetype_info_t g_hardcoded_filetypes[] =
00084 {
00085
00086 { "" , NULL, TRUE , "folder", N_("Folder"), NULL, {}, FALSE },
00087 { "" , NULL, FALSE, "unknown", N_("Unknown"), NULL, {}, FALSE },
00088 { FILE_EXT_SHORTCUT , NULL, FALSE, "unknown", N_("Shortcut"), NULL, {}, FALSE },
00089 { FILE_EXT_SHORTCUT_TO_DIR, NULL, FALSE, "folder", N_("Shortcut"), NULL, {}, FALSE },
00090 { NULL, NULL, FALSE, NULL, NULL, NULL, {}, FALSE },
00091 };
00092
00093 #define GCONF_BUFFER_SIZE 128
00094
00095
00096
00097
00098
00099 static GArray *g_filetype_info = NULL;
00100 static GTree *g_icon_cache = NULL;
00101 static GConfClient *g_gconfclient = NULL;
00102 static gboolean g_showdir = FALSE;
00103
00104
00105
00106
00107
00108
00109 static filetype_info_t* find_filetype_info(const gchar *file_ext,
00110 const gboolean is_directory,
00111 const gboolean with_default );
00112
00113
00114
00115
00116
00117 static gchar *read_gconf_value(const gchar *dir,
00118 const gchar *key,
00119 GConfClient *client)
00120 {
00121 gchar buffer[GCONF_BUFFER_SIZE];
00122 gchar* value;
00123 g_assert(strlen(dir) + 1 + strlen(key) < GCONF_BUFFER_SIZE);
00124 snprintf(buffer, GCONF_BUFFER_SIZE-1, "%s/%s", dir, key);
00125 value = gconf_client_get_string(client, buffer, NULL);
00126 if (value == NULL) {
00127 ERRORPRINTF("gconf: cannot read %s", buffer);
00128 }
00129 return value;
00130 }
00131
00132
00133 static gboolean read_gconf_boolean(const gchar *dir,
00134 const gchar *key,
00135 GConfClient *client)
00136 {
00137 gboolean value = FALSE;
00138 gchar buffer[GCONF_BUFFER_SIZE];
00139 g_assert(strlen(dir) + 1 + strlen(key) < GCONF_BUFFER_SIZE);
00140 snprintf(buffer, GCONF_BUFFER_SIZE-1, "%s/%s", dir, key);
00141
00142 value = gconf_client_get_bool(client, buffer, NULL);
00143 return value;
00144 }
00145
00146
00147 static void add_filetype_from_gconf(const gchar *dir,
00148 GConfClient *client)
00149 {
00150 gchar buffer[GCONF_BUFFER_SIZE];
00151 gchar *descr = NULL;
00152 gchar *viewer_cmd = NULL;
00153 gchar *icon_name = NULL;
00154 gchar *reference_ext = NULL;
00155 GSList *ext = NULL;
00156 gboolean generate_thumbnail = FALSE;
00157
00158 descr = read_gconf_value(dir, "descr", client);
00159 if (!descr) goto out_error;
00160
00161 viewer_cmd = read_gconf_value(dir, "viewer_cmd", client);
00162 if (!viewer_cmd) goto out_error;
00163
00164 icon_name = read_gconf_value(dir, "icon_name", client);
00165 if (!icon_name) goto out_error;
00166
00167 generate_thumbnail = read_gconf_boolean(dir, "generate_thumbnail", client);
00168
00169 g_assert(strlen(dir) + strlen("/extensions") < GCONF_BUFFER_SIZE);
00170 snprintf(buffer, GCONF_BUFFER_SIZE-1, "%s/extensions", dir);
00171 GSList *extensions = gconf_client_get_list(client, buffer, GCONF_VALUE_STRING, NULL);
00172 if (extensions == NULL) {
00173 ERRORPRINTF("gconf: cannot read %s", buffer);
00174 goto out_error;
00175 }
00176
00177 for (ext = extensions; ext; ext = g_slist_next(ext)) {
00178 if (find_filetype_info(ext->data, FALSE, FALSE) != NULL) {
00179 ERRORPRINTF("gconf: ext %s is already registered, skipping", (gchar*)ext->data);
00180 continue;
00181 }
00182
00183 filetype_info_t newtype;
00184 memset(&newtype, 0x00, sizeof(newtype));
00185 newtype.extension = g_strdup(ext->data);
00186 newtype.reference_ext = g_strdup(reference_ext);
00187 newtype.is_directory = FALSE;
00188 newtype.icon_name = g_strdup(icon_name);
00189 newtype.description = g_strdup(descr);
00190 newtype.viewer_cmd = g_strdup(viewer_cmd);
00191 newtype.generate_thumbnail = generate_thumbnail;
00192 g_array_append_val(g_filetype_info, newtype);
00193
00194 if (reference_ext == NULL) reference_ext = ext->data;
00195 }
00196 g_slist_foreach (extensions, (GFunc)g_free, NULL);
00197 g_slist_free(extensions);
00198 out_error:
00199 g_free(icon_name);
00200 g_free(viewer_cmd);
00201 g_free(descr);
00202 }
00203
00204
00205 static void add_filetypes_from_gconf()
00206 {
00207 GSList *types = NULL;
00208 GConfClient *client = gconf_client_get_default();
00209
00210 gboolean exists = gconf_client_dir_exists(client, REGKEY_FILETYPE_DIR, NULL);
00211 if (exists == FALSE) {
00212 ERRORPRINTF("gconf: %s does not exist", REGKEY_FILETYPE_DIR);
00213 goto unref;
00214 }
00215
00216 types = gconf_client_all_dirs(client, REGKEY_FILETYPE_DIR, NULL);
00217 if (types == NULL) {
00218 ERRORPRINTF("gconf: cannot read dir entries of %s", REGKEY_FILETYPE_DIR);
00219 goto unref;
00220 }
00221
00222 g_slist_foreach (types, (GFunc)add_filetype_from_gconf, client);
00223 g_slist_foreach (types, (GFunc)g_free, NULL);
00224 g_slist_free(types);
00225 unref:
00226 g_object_unref(client);
00227 }
00228
00229
00230 static void add_hardcoded_filetypes()
00231 {
00232 filetype_info_t *known_type = NULL;
00233 filetype_info_t details;
00234
00235
00236 for ( known_type = g_hardcoded_filetypes ; known_type->extension ; known_type++ )
00237 {
00238
00239 memset(&details, 0x00, sizeof(details));
00240 details.extension = g_strdup(known_type->extension );
00241 details.reference_ext = g_strdup(known_type->reference_ext );
00242 details.is_directory = known_type->is_directory;
00243 details.icon_name = g_strdup(known_type->icon_name );
00244 details.description = g_strdup(known_type->description );
00245 details.viewer_cmd = g_strdup(known_type->viewer_cmd );
00246
00247
00248 g_array_append_val(g_filetype_info, details);
00249 }
00250 }
00251
00252
00253 static void on_gconf_key_changed(GConfClient *client,
00254 guint cnxn_id,
00255 GConfEntry *entry,
00256 gpointer user_data)
00257 {
00258 const gchar* key = gconf_entry_get_key(entry);
00259 if (strcmp(key, CTB_GCONF_PATH"/"REGKEY_SHOW_SDCARD) == 0) {
00260 const GConfValue* value = gconf_entry_get_value(entry);
00261 gboolean show = gconf_value_get_bool(value);
00262 g_showdir = show;
00263 }
00264 }
00265
00266
00267 void filetypes_init ( gboolean watch )
00268 {
00269 g_filetype_info = g_array_new( TRUE, TRUE, sizeof(filetype_info_t) );
00270 g_assert(g_filetype_info);
00271
00272 add_hardcoded_filetypes();
00273 add_filetypes_from_gconf();
00274
00275 if (watch) {
00276 g_gconfclient = gconf_client_get_default();
00277 g_assert(g_gconfclient);
00278 g_showdir = read_gconf_boolean(CTB_GCONF_PATH, REGKEY_SHOW_SDCARD, g_gconfclient);
00279
00280 gconf_client_add_dir(g_gconfclient,
00281 CTB_GCONF_PATH,
00282 GCONF_CLIENT_PRELOAD_NONE,
00283 NULL);
00284
00285 gconf_client_notify_add(g_gconfclient,
00286 CTB_GCONF_PATH,
00287 on_gconf_key_changed,
00288 NULL,
00289 NULL,
00290 NULL);
00291 }
00292 }
00293
00294
00295 gboolean filetypes_showdir()
00296 {
00297 return g_showdir;
00298 }
00299
00300
00301 static filetype_info_t* find_filetype_info (const gchar *file_ext,
00302 const gboolean is_directory,
00303 const gboolean with_default )
00304 {
00305
00306 g_assert(g_filetype_info);
00307
00308
00309 if (file_ext == NULL)
00310 {
00311 file_ext = "";
00312 }
00313
00314 gboolean done = FALSE;
00315 gboolean found = FALSE;
00316 filetype_info_t *ret = NULL;
00317 while ( !done )
00318 {
00319 filetype_info_t *details = (filetype_info_t*) g_filetype_info->data;
00320 while (details->extension)
00321 {
00322 if (details->is_directory == is_directory
00323 && g_ascii_strcasecmp( details->extension, file_ext ) == 0 )
00324 {
00325 ret = details;
00326 found = TRUE;
00327 break;
00328 }
00329 else
00330 {
00331 details++;
00332 }
00333 }
00334
00335 if ( found )
00336 {
00337 gchar *ref_ext = details->reference_ext;
00338
00339
00340 if (ref_ext)
00341 {
00342 return find_filetype_info( ref_ext, is_directory, with_default );
00343 }
00344 done = TRUE;
00345 }
00346 else if (*file_ext)
00347 {
00348 LOGPRINTF("unkown filetype [%s] is_dir [%d]", file_ext, is_directory);
00349 if (with_default)
00350 {
00351 file_ext = "";
00352 }
00353 else
00354 {
00355 done = TRUE;
00356 }
00357 }
00358 else
00359 {
00360 ERRORPRINTF("no default fileinfo for is_dir [%d]", is_directory);
00361 done = TRUE;
00362 }
00363 }
00364
00365 return ret;
00366 }
00367
00368
00369 GdkPixbuf* get_icon_from_file_extension (const gchar *file_ext,
00370 const gboolean is_directory,
00371 const filemodel_thumbsize_t icon_size )
00372 {
00373 GdkPixbuf *icon = NULL;
00374
00375 filetype_info_t *details = find_filetype_info(file_ext, is_directory, TRUE);
00376 if (details)
00377 {
00378
00379 GdkPixbuf **p_pixbuf_icon = &(details->pixbuf_icon[icon_size]);
00380 icon = *p_pixbuf_icon;
00381 if (icon == NULL)
00382 {
00383
00384 gchar* icon_file = g_strdup_printf( "%s/%s%s%s",
00385 ICONS_DIRECTORY,
00386 ICONFILE_PREFIX,
00387 details->icon_name,
00388 ICONFILE_POSTFIX[icon_size] );
00389 GError *err = NULL;
00390 icon = gdk_pixbuf_new_from_file( icon_file, &err );
00391 if (icon) *p_pixbuf_icon = icon;
00392 else
00393 {
00394 ERRORPRINTF("cannot load iconfile [%s] error [%s]", icon_file, err->message);
00395 g_clear_error(&err);
00396 }
00397 g_free(icon_file);
00398 }
00399 }
00400 return icon;
00401 }
00402
00403
00404 GdkPixbuf* get_icon_application ( const filemodel_thumbsize_t icon_size)
00405 {
00406 return get_icon_from_file(ICONNAME_APPLICATION, icon_size);
00407 }
00408
00409
00410 GdkPixbuf* get_icon_library ( const filemodel_thumbsize_t icon_size)
00411 {
00412 return get_icon_from_file(ICONNAME_LIBRARY, icon_size);
00413 }
00414
00415
00416 GdkPixbuf* get_icon_delete_toggle(gboolean toggled, filemodel_thumbsize_t icon_size)
00417 {
00418 if (toggled) {
00419 return get_icon_from_file("delete-toggled", icon_size);
00420 } else {
00421 return get_icon_from_file("delete-untoggled", icon_size);
00422 }
00423 }
00424
00425 gint compareString(gconstpointer a, gconstpointer b) {
00426 return strcmp((const gchar*)a, (const gchar*)b);
00427 }
00428
00429
00430 GdkPixbuf* get_icon_from_file(const gchar* icon_name, filemodel_thumbsize_t icon_size)
00431 {
00432 if (g_icon_cache == NULL) g_icon_cache = g_tree_new(compareString);
00433
00434 g_assert(icon_name && *icon_name);
00435 gchar icon_file[256];
00436 snprintf(icon_file, 255, "%s/%s%s%s",
00437 ICONS_DIRECTORY,
00438 ICONFILE_PREFIX,
00439 icon_name,
00440 ICONFILE_POSTFIX[icon_size]);
00441 int len = strlen(ICONS_DIRECTORY) + strlen(ICONFILE_PREFIX) + 1;
00442 gchar* short_name = icon_file + len;
00443 gpointer cache = g_tree_lookup(g_icon_cache, short_name);
00444 GdkPixbuf *icon = NULL;
00445 if (cache) {
00446 icon = (GdkPixbuf *)cache;
00447 } else {
00448 GError *err = NULL;
00449 icon = gdk_pixbuf_new_from_file(icon_file, &err);
00450 if (icon) {
00451 g_tree_insert(g_icon_cache, g_strdup(short_name), icon);
00452 } else {
00453 ERRORPRINTF("cannot load iconfile [%s] error [%s]", icon_file, err->message);
00454 g_clear_error(&err);
00455 }
00456 }
00457 return icon;
00458 }
00459
00460
00461 static void apply_icon_overlay ( const filemodel_thumbsize_t icon_size,
00462 GdkPixbuf *icon,
00463 const gchar *overlay_name)
00464 {
00465 if (icon == NULL) return;
00466
00467 GdkPixbuf *overlay = get_icon_from_file(overlay_name, icon_size);
00468
00469
00470 if (overlay)
00471 {
00472 gdk_pixbuf_composite( overlay,
00473 icon,
00474 0, 0,
00475 gdk_pixbuf_get_width(icon),
00476 gdk_pixbuf_get_height(icon),
00477 0.0, 0.0,
00478 1.0, 1.0,
00479 GDK_INTERP_NEAREST,
00480 0xFF );
00481 }
00482 }
00483
00484
00485 void apply_icon_overlay_shortcut ( const filemodel_thumbsize_t icon_size,
00486 GdkPixbuf *icon )
00487 {
00488 apply_icon_overlay( icon_size, icon, "overlay-shortcut");
00489 }
00490
00491
00492 void apply_icon_overlay_delete ( const filemodel_thumbsize_t icon_size,
00493 GdkPixbuf *icon,
00494 gboolean toggled)
00495 {
00496 if (toggled)
00497 apply_icon_overlay( icon_size, icon, "overlay-delete-toggled");
00498 else
00499 apply_icon_overlay( icon_size, icon, "overlay-delete-untoggled");
00500 }
00501
00502
00503 const gchar* get_type_descr_from_file_extension ( const gchar *file_ext,
00504 const gboolean is_directory)
00505 {
00506 filetype_info_t *details = find_filetype_info(file_ext, is_directory, TRUE);
00507
00508 const gchar *description = "";
00509 if (details)
00510 {
00511 if (details->description)
00512 {
00513 description = _( details->description );
00514 }
00515 else
00516 {
00517 ERRORPRINTF( "filetype [%s] is_dir [%d] has no description",
00518 details->description, is_directory);
00519 }
00520 }
00521
00522 return description;
00523 }
00524
00525
00526 gboolean is_drz_file_extension(const gchar *file_ext)
00527 {
00528 if ( strcmp( file_ext, FILE_EXT_DRZ ) == 0 )
00529 {
00530 return TRUE;
00531 }
00532 return FALSE;
00533 }
00534
00535
00536 gboolean is_shortcut_file_extension(const gchar *file_ext)
00537 {
00538 if ( strcmp( file_ext, FILE_EXT_SHORTCUT ) == 0
00539 || strcmp( file_ext, FILE_EXT_SHORTCUT_TO_DIR) == 0 )
00540 {
00541 return TRUE;
00542 }
00543 return FALSE;
00544 }
00545
00546
00547 gboolean is_shortcut_file(const char* filename)
00548 {
00549 const char* ext = g_extension_pointer(filename);
00550 return is_shortcut_file_extension(ext);
00551 }
00552
00553
00554
00555 const gchar* get_viewer_from_file_extension ( const gchar *file_ext )
00556 {
00557 filetype_info_t *details = find_filetype_info(file_ext, FALSE, FALSE);
00558
00559 const gchar *viewer_cmd = (details) ? details->viewer_cmd : NULL;
00560 return viewer_cmd;
00561 }
00562
00563
00564 gboolean get_generate_thumbnail ( const gchar *file_ext )
00565 {
00566 filetype_info_t *details = find_filetype_info(file_ext, FALSE, FALSE);
00567 return details->generate_thumbnail;
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 const char *
00585 g_extension_pointer (const char * path)
00586 {
00587 char * s;
00588
00589 g_return_val_if_fail(path != NULL, NULL);
00590
00591
00592 char *t = strrchr(path, G_DIR_SEPARATOR);
00593 if (t != NULL)
00594 s = strrchr(t, '.');
00595 else
00596 s = strrchr(path, '.');
00597
00598 if (s == NULL)
00599 return path + strlen(path);
00600 else {
00601 ++s;
00602 return s;
00603 }
00604 }