static gchar *
gimp_plug_in_manager_get_pluginrc (GimpPlugInManager *manager)
{
  Gimp  *gimp = manager->gimp;
  gchar *pluginrc;

  if (gimp->config->plug_in_rc_path)
    {
      pluginrc = gimp_config_path_expand (gimp->config->plug_in_rc_path,
                                          TRUE, NULL);

      if (! g_path_is_absolute (pluginrc))
        {
          gchar *str = g_build_filename (gimp_directory (), pluginrc, NULL);

          g_free (pluginrc);
          pluginrc = str;
        }
    }
  else
    {
      pluginrc = gimp_personal_rc_file ("pluginrc");
    }

  return pluginrc;
}
Exemple #2
0
static gchar *
get_user_script_dir (void)
{
  return g_build_filename (gimp_directory (),
                           "scripts",
                           NULL);
}
static GFile *
gimp_plug_in_manager_get_pluginrc (GimpPlugInManager *manager)
{
  Gimp  *gimp = manager->gimp;
  GFile *pluginrc;

  if (gimp->config->plug_in_rc_path)
    {
      gchar *path;

      path = gimp_config_path_expand (gimp->config->plug_in_rc_path,
                                      TRUE, NULL);

      if (! g_path_is_absolute (path))
        {
          gchar *str = g_build_filename (gimp_directory (), path, NULL);

          g_free (path);
          path = str;
        }

      pluginrc = g_file_new_for_path (path);
      g_free (path);
    }
  else
    {
      pluginrc = gimp_personal_rc_gfile ("pluginrc");
    }

  return pluginrc;
}
Exemple #4
0
/* ----------------------------------
 * gap_ffpar_getPresetList
 * ----------------------------------
 * returns a list of all available encoder presets.
 * the list includes presets files found in user specific $GIMPDIR/video_encoder_presets
 * or in systemwide $GIMPDATADIR/video_encoder_presets.
 *
 * Note that Hardcoded presetes are not included in the list
 * but the presetId is generated as unique value > offset for hardcoded presets.
 */
GapGveFFMpegValues *
gap_ffpar_getPresetList()
{
   GapGveFFMpegValues *epp;
   GapGveFFMpegValues *eppPrev;
   char          *presetDir;

   eppPrev = eppRoot;
   for(epp = eppRoot; epp != NULL; epp = epp->next)
   {
     eppPrev = epp;
   }

   /* system wide data directory  example: /usr/local/share/gimp/2.0 */
   presetDir = g_build_filename(gimp_data_directory(), GAP_VIDEO_ENCODER_PRESET_DIR, NULL);
   p_add_presets_from_directory(eppPrev, presetDir);
   g_free(presetDir);

   /* user specific directory   example: /home/hof/.gimp-2.6 
    * (preset names that are already present in previous processed directory
    * will be overwritten. i.e. user specific variant is preferred)
    */
   presetDir = g_build_filename(gimp_directory(), GAP_VIDEO_ENCODER_PRESET_DIR, NULL);
   p_add_presets_from_directory(eppPrev, presetDir);
   g_free(presetDir);
   
   return(eppRoot);
  
}  /* end gap_ffpar_getPresetList */
static gboolean
create_custom_texture_pages (GtkNotebook *notebook, const gchar *texture_path)
{
  gboolean has_custom_texture = FALSE;

  const gchar *gimp_dir = gimp_directory ();
  const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
  GDir *dir = g_dir_open (texture_dir, 0, NULL);
  if (dir)
  {
    const gchar *dir_ent;
    while (dir_ent = g_dir_read_name (dir))
    {
      if (is_hidden (dir_ent))
        continue;

      gchar *filename = g_build_filename (texture_dir, dir_ent, NULL);
      if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
        create_custom_texture_page (GTK_NOTEBOOK (notebook), dir_ent, filename);
        has_custom_texture = TRUE;
      }
    }
  }

  return has_custom_texture;
}
Exemple #6
0
static gchar *
get_user_plugin_dir (void)
{
  return g_build_filename (gimp_directory (),
                           "plug-ins",
                           NULL);
}
Exemple #7
0
gchar *
gimp_lastval_desc_filename(void)
{
  gchar         *l_fname;

  l_fname = g_build_filename(gimp_directory (), "lastval_descriptions.txt", NULL);
  return(l_fname);
}       /* end gimp_lastval_desc_filename */
Exemple #8
0
static gchar *
cm_settings_filename (void)
{
  return g_build_filename (gimp_directory (),
                           "channel-mixer",
                           "settings",
                           NULL);
}
Exemple #9
0
/* ---------------------------------------
 * p_gap_build_enc_cancel_request_filename
 * ---------------------------------------
 * build the filename that is used to indicate cancel a running video encoder process.
 * (if this file exists cancel request is TRUE)
 */
static char *
p_gap_build_enc_cancel_request_filename(gint32 master_encoder_id)
{
   char *filename;
   char *buf;
   
   buf = g_strdup_printf("gap_master_videoencoder_cancel_%d", master_encoder_id);
   
   filename = g_build_filename(gimp_directory(), buf, NULL);

   g_free(buf);
   return (filename);
}  /* end p_gap_build_enc_cancel_request_filename */
/* ------------------------------------
 * p_build_gvaidx_filename
 * ------------------------------------
 * internal variante using track numbers starting at 0
 */
static char *
p_build_gvaidx_filename(const char *filename, gint32 track, const char *decoder_name
  , const char *suffix)
{
  static gchar name[40];
  gchar *vindex_file;
  gchar *filename_part;
  gchar *uri;
  gchar *gvaindexes_dir;
  
  uri = GVA_filename_to_uri(filename);
  if(uri)
  {
    GVA_md5_string(name, uri);
  }
  else
  {
    return (NULL);
  }
  
  filename_part = g_strdup_printf("%s.%d.%s.%s"
        , name
        , (int)track
        , decoder_name
        , suffix
        );
  gvaindexes_dir = gimp_gimprc_query("video-index-dir");
  if(gvaindexes_dir)
  {
    vindex_file = g_build_filename(gvaindexes_dir, filename_part, NULL);
    g_free(gvaindexes_dir);  
  }
  else
  {
    /* nothing configured. in that case we use a default directory */
    //vindex_file = g_build_filename(g_get_home_dir(), "gvaindexes", filename_part, NULL);
    vindex_file = g_build_filename(gimp_directory(), "gvaindexes", filename_part, NULL);
  }


  if(gap_debug)
  {
    printf("VIDINDEX: filename_part: %s\n", filename_part);
    printf("VIDINDEX: vindex_file: %s\n", vindex_file);
  }

  g_free(filename_part);  

  return(vindex_file);
}  /* end p_build_gvaidx_filename */
Exemple #11
0
static gchar *
sanity_check_filename_encoding (void)
{
  gchar  *result;
  GError *error = NULL;

  result = g_filename_to_utf8 ("", -1, NULL, NULL, &error);

  if (! result)
    {
      gchar *msg =
        g_strdup_printf
        (_("The configured filename encoding cannot be converted to UTF-8: "
           "%s\n\n"
           "Please check the value of the environment variable "
           "G_FILENAME_ENCODING."),
         error->message);

      g_error_free (error);

      return msg;
    }

  g_free (result);

  result = g_filename_to_utf8 (gimp_directory (), -1, NULL, NULL, &error);

  if (! result)
    {
      gchar *msg =
        g_strdup_printf
        (_("The name of the directory holding the GIMP user configuration "
           "cannot be converted to UTF-8: "
           "%s\n\n"
           "Your filesystem probably stores files in an encoding "
           "other than UTF-8 and you didn't tell GLib about this. "
           "Please set the environment variable G_FILENAME_ENCODING."),
         error->message);

      g_error_free (error);

      return msg;
    }

  g_free (result);

  return NULL;
}
Exemple #12
0
static gboolean
can_delete_preset (const gchar *abs)
{
  gchar *user_data_dir;
  gboolean ret;

  user_data_dir = g_strconcat (gimp_directory (),
                               G_DIR_SEPARATOR_S,
                               NULL);


  ret = (!strncmp (abs, user_data_dir, strlen (user_data_dir)));

  g_free (user_data_dir);

  return ret;
}
Exemple #13
0
static GtkWidget *
gimp_operation_tool_get_settings_ui (GimpImageMapTool  *image_map_tool,
                                     GimpContainer     *settings,
                                     const gchar       *settings_filename,
                                     const gchar       *import_dialog_title,
                                     const gchar       *export_dialog_title,
                                     const gchar       *file_dialog_help_id,
                                     const gchar       *default_folder,
                                     GtkWidget        **settings_box)
{
  GimpOperationTool *tool = GIMP_OPERATION_TOOL (image_map_tool);
  GType              type = G_TYPE_FROM_INSTANCE (tool->config);
  GtkWidget         *widget;
  gchar             *basename;
  gchar             *filename;
  gchar             *import_title;
  gchar             *export_title;

  settings = gimp_gegl_get_config_container (type);
  if (! gimp_list_get_sort_func (GIMP_LIST (settings)))
    gimp_list_set_sort_func (GIMP_LIST (settings),
                             (GCompareFunc) gimp_image_map_config_compare);

  basename = g_strconcat (G_OBJECT_TYPE_NAME (tool->config), ".settings", NULL);
  filename = g_build_filename (gimp_directory (), "filters", basename, NULL);
  g_free (basename);

  import_title = g_strdup_printf (_("Import '%s' Settings"), tool->undo_desc);
  export_title = g_strdup_printf (_("Export '%s' Settings"), tool->undo_desc);

  widget =
    GIMP_IMAGE_MAP_TOOL_CLASS (parent_class)->get_settings_ui (image_map_tool,
                                                               settings,
                                                               filename,
                                                               import_title,
                                                               export_title,
                                                               "help-foo",
                                                               g_get_home_dir (),
                                                               settings_box);

  g_free (filename);
  g_free (import_title);
  g_free (export_title);

  return widget;
}
/* ----------------------------------
 * GVA_build_video_toc_filename
 * ----------------------------------
 */
char *
GVA_build_video_toc_filename(const char *filename, const char *decoder_name)
{
  static gchar name[40];
  gchar *toc_file;
  gchar *filename_part;
  gchar *uri;
  gchar *gvaindexes_dir;
  
  uri = GVA_filename_to_uri(filename);
  if(uri)
  {
    GVA_md5_string(name, uri);
  }
  else
  {
    printf("TOC-NAME: uri is NULL filename:%s\n", filename);
    return (NULL);
  }
  
  filename_part = g_strdup_printf("%s.%s.toc", name, decoder_name);
  gvaindexes_dir = gimp_gimprc_query("video-index-dir");
  if(gvaindexes_dir)
  {
    toc_file = g_build_filename(gvaindexes_dir, filename_part, NULL);
    g_free(gvaindexes_dir);  
  }
  else
  {
    /* nothing configured. in that case we use a default directory */
    //toc_file = g_build_filename(g_get_home_dir(), "gvaindexes", filename_part, NULL);
    toc_file = g_build_filename(gimp_directory(), "gvaindexes", filename_part, NULL);
  }


  if(gap_debug)
  {
    printf("TOC-NAME: filename_part: %s\n", filename_part);
    printf("TOC-NAME: toc_file: %s\n", toc_file);
  }
  g_free(filename_part);  

  return(toc_file);
}  /* end GVA_build_video_toc_filename */
Exemple #15
0
/**
 * gimp_personal_rc_file:
 * @basename: The basename of a rc_file.
 *
 * Returns the name of a file in the user-specific GIMP settings directory.
 *
 * The returned string is allocated dynamically and *SHOULD* be freed
 * with g_free() after use. The returned string is in the encoding
 * used for filenames by GLib, which isn't necessarily
 * UTF-8. (On Windows it always is UTF-8.)
 *
 * Returns: The name of a file in the user-specific GIMP settings directory.
 **/
gchar *
gimp_personal_rc_file (const gchar *basename)
{
  return g_build_filename (gimp_directory (), basename, NULL);
}
Exemple #16
0
void
app_run (const gchar         *full_prog_name,
         const gchar        **filenames,
         const gchar         *alternate_system_gimprc,
         const gchar         *alternate_gimprc,
         const gchar         *session_name,
         const gchar         *batch_interpreter,
         const gchar        **batch_commands,
         gboolean             as_new,
         gboolean             no_interface,
         gboolean             no_data,
         gboolean             no_fonts,
         gboolean             no_splash,
         gboolean             be_verbose,
         gboolean             use_shm,
         gboolean             use_cpu_accel,
         gboolean             console_messages,
         gboolean             use_debug_handler,
         GimpStackTraceMode   stack_trace_mode,
         GimpPDBCompatMode    pdb_compat_mode)
{
  GimpInitStatusFunc  update_status_func = NULL;
  Gimp               *gimp;
  GMainLoop          *loop;
  GMainLoop          *run_loop;
  gchar              *default_folder = NULL;

  if (filenames && filenames[0] && ! filenames[1] &&
      g_file_test (filenames[0], G_FILE_TEST_IS_DIR))
    {
      if (g_path_is_absolute (filenames[0]))
        {
          default_folder = g_filename_to_uri (filenames[0], NULL, NULL);
        }
      else
        {
          gchar *absolute = g_build_path (G_DIR_SEPARATOR_S,
                                          g_get_current_dir (),
                                          filenames[0],
                                          NULL);
          default_folder = g_filename_to_uri (absolute, NULL, NULL);
          g_free (absolute);
        }

      filenames = NULL;
    }

  /*  Create an instance of the "Gimp" object which is the root of the
   *  core object system
   */
  gimp = gimp_new (full_prog_name,
                   session_name,
                   default_folder,
                   be_verbose,
                   no_data,
                   no_fonts,
                   no_interface,
                   use_shm,
                   use_cpu_accel,
                   console_messages,
                   stack_trace_mode,
                   pdb_compat_mode);

  gimp_cpu_accel_set_use (use_cpu_accel);

  errors_init (gimp, full_prog_name, use_debug_handler, stack_trace_mode);

  units_init (gimp);

  /*  Check if the user's gimp_directory exists
   */
  if (! g_file_test (gimp_directory (), G_FILE_TEST_IS_DIR))
    {
      GimpUserInstall *install = gimp_user_install_new (be_verbose);

#ifdef GIMP_CONSOLE_COMPILATION
      gimp_user_install_run (install);
#else
      if (! (no_interface ?
	     gimp_user_install_run (install) :
	     user_install_dialog_run (install)))
	exit (EXIT_FAILURE);
#endif

      gimp_user_install_free (install);
    }

  gimp_load_config (gimp, alternate_system_gimprc, alternate_gimprc);

  /*  change the locale if a language if specified  */
  language_init (gimp->config->language);

  /*  initialize lowlevel stuff  */
  gimp_gegl_init (gimp);

#ifndef GIMP_CONSOLE_COMPILATION
  if (! no_interface)
    update_status_func = gui_init (gimp, no_splash);
#endif

  if (! update_status_func)
    update_status_func = app_init_update_noop;

  /*  Create all members of the global Gimp instance which need an already
   *  parsed gimprc, e.g. the data factories
   */
  gimp_initialize (gimp, update_status_func);

  /*  Load all data files
   */
  gimp_restore (gimp, update_status_func);

  /*  enable autosave late so we don't autosave when the
   *  monitor resolution is set in gui_init()
   */
  gimp_rc_set_autosave (GIMP_RC (gimp->edit_config), TRUE);

  loop = run_loop = g_main_loop_new (NULL, FALSE);

  g_signal_connect_after (gimp, "exit",
                          G_CALLBACK (app_exit_after_callback),
                          &run_loop);

  /*  Load the images given on the command-line.
   */
  if (filenames)
    {
      gint i;

      for (i = 0; filenames[i] != NULL; i++)
        {
          if (run_loop)
            file_open_from_command_line (gimp, filenames[i], as_new);
        }
    }

  if (run_loop)
    batch_run (gimp, batch_interpreter, batch_commands);

  if (run_loop)
    {
      gimp_threads_leave (gimp);
      g_main_loop_run (loop);
      gimp_threads_enter (gimp);
    }

  g_main_loop_unref (loop);

  g_object_unref (gimp);

  gimp_debug_instances ();

  errors_exit ();
  gegl_exit ();
}
Exemple #17
0
void
app_run (const gchar         *full_prog_name,
         const gchar        **filenames,
         const gchar         *alternate_system_gimprc,
         const gchar         *alternate_gimprc,
         const gchar         *session_name,
         const gchar         *batch_interpreter,
         const gchar        **batch_commands,
         gboolean             as_new,
         gboolean             no_interface,
         gboolean             no_data,
         gboolean             no_fonts,
         gboolean             no_splash,
         gboolean             be_verbose,
         gboolean             use_shm,
         gboolean             use_cpu_accel,
         gboolean             console_messages,
         gboolean             use_debug_handler,
         GimpStackTraceMode   stack_trace_mode,
         GimpPDBCompatMode    pdb_compat_mode)
{
  GimpInitStatusFunc  update_status_func = NULL;
  Gimp               *gimp;
  GimpGeglConfig     *config;
  GMainLoop          *loop;
  gboolean            swap_is_ok;

  /*  Create an instance of the "Gimp" object which is the root of the
   *  core object system
   */
  gimp = gimp_new (full_prog_name,
                   session_name,
                   be_verbose,
                   no_data,
                   no_fonts,
                   no_interface,
                   use_shm,
                   console_messages,
                   stack_trace_mode,
                   pdb_compat_mode);

  errors_init (gimp, full_prog_name, use_debug_handler, stack_trace_mode);

  units_init (gimp);

  /*  Check if the user's gimp_directory exists
   */
  if (! g_file_test (gimp_directory (), G_FILE_TEST_IS_DIR))
    {
      GimpUserInstall *install = gimp_user_install_new (be_verbose);

#ifdef GIMP_CONSOLE_COMPILATION
      gimp_user_install_run (install);
#else
      if (! (no_interface ?
	     gimp_user_install_run (install) :
	     user_install_dialog_run (install)))
	exit (EXIT_FAILURE);
#endif

      gimp_user_install_free (install);
    }

  gimp_load_config (gimp, alternate_system_gimprc, alternate_gimprc);

  config = GIMP_GEGL_CONFIG (gimp->config);

  /*  change the locale if a language if specified  */
  language_init (gimp->config->language);

  /*  initialize lowlevel stuff  */
  swap_is_ok = base_init (config, be_verbose, use_cpu_accel);

  gimp_gegl_init (gimp);

#ifndef GIMP_CONSOLE_COMPILATION
  if (! no_interface)
    update_status_func = gui_init (gimp, no_splash);
#endif

  if (! update_status_func)
    update_status_func = app_init_update_noop;

  /*  Create all members of the global Gimp instance which need an already
   *  parsed gimprc, e.g. the data factories
   */
  gimp_initialize (gimp, update_status_func);

  /*  Load all data files
   */
  gimp_restore (gimp, update_status_func);

  /* display a warning when no test swap file could be generated */
  if (! swap_is_ok)
    {
      gchar *path = gimp_config_path_expand (config->swap_path, FALSE, NULL);

      g_message (_("Unable to open a test swap file.\n\n"
		   "To avoid data loss, please check the location "
		   "and permissions of the swap directory defined in "
		   "your Preferences (currently \"%s\")."), path);

      g_free (path);
    }

  /*  enable autosave late so we don't autosave when the
   *  monitor resolution is set in gui_init()
   */
  gimp_rc_set_autosave (GIMP_RC (gimp->edit_config), TRUE);

  /*  Load the images given on the command-line.
   */
  if (filenames)
    {
      gint i;

      for (i = 0; filenames[i] != NULL; i++)
        file_open_from_command_line (gimp, filenames[i], as_new);
    }

  batch_run (gimp, batch_interpreter, batch_commands);

  loop = g_main_loop_new (NULL, FALSE);

  g_signal_connect_after (gimp, "exit",
                          G_CALLBACK (app_exit_after_callback),
                          loop);

  gimp_threads_leave (gimp);
  g_main_loop_run (loop);
  gimp_threads_enter (gimp);

  g_main_loop_unref (loop);

  g_object_unref (gimp);

  gimp_debug_instances ();

  errors_exit ();
  gegl_exit ();
  base_exit ();
}
Exemple #18
0
/* -----------------------------------------------
 * p_gap_delete_old_communication_files
 * -----------------------------------------------
 * delete older communication files (if there are any)
 * this kind of cleanup tries to remove old comminication files
 * that may be still there
 * if a previous call to the master video encoder crashed or was killed.
 */
static void
p_gap_delete_old_communication_files()
{
   GDir          *l_dirp;
   const gchar   *l_entry;
   const char    *l_directory;

#define SECONDS_OF_ONE_HOUR 3600

   l_directory  = gimp_directory();
   l_dirp = g_dir_open( l_directory, 0, NULL );
   if(l_dirp)
   {
     time_t  l_ref_mtime;

     l_ref_mtime = gap_base_get_current_time();
     
     while ( (l_entry = g_dir_read_name( l_dirp )) != NULL )
     {
        if(gap_debug)
        {
          printf("delete_old_communication_files: l_entry:%s\n", l_entry);
        }
        if (strncmp(l_entry, "gap_master_videoencoder_", strlen("gap_master_videoencoder_")) == 0)
        {
           char *l_filename;
           time_t  l_mtime;
           time_t  l_diff_time;
           gint32  l_pid;
           gint32  l_delete_flag;
           
           l_delete_flag = FALSE;
           l_filename = g_build_filename(l_directory, l_entry, NULL);
           l_pid = p_get_number_at_end_of_string(l_entry);
           l_mtime = gap_file_get_mtime(l_filename);
           l_diff_time = l_ref_mtime - l_mtime;
           
           if(l_pid >= 0)
           {
             /* note: detection of a not-running process works only on unix systems */
             if(!gap_base_is_pid_alive(l_pid))
             {
               l_delete_flag = TRUE;   /* delete commounication files immediate when refered process is not running */
             }
             else
             {
               /* assume old communication file when it did not change in the last hour
                * (for NON unix operating systems)
                */
               if (l_diff_time > SECONDS_OF_ONE_HOUR)
               {
                 l_delete_flag = TRUE;   /* delete commounication files immediate when refered process is not running */
               }
             }
           }
           
           if (l_delete_flag == TRUE)
           {
             if(gap_debug)
             {
               printf("DELETE file: %s  l_ref_mtime:%d l_mtime:%d  diff:%d  l_pid:%d\n"
                   , l_filename
                   , (int)l_ref_mtime
                   , (int)l_mtime
                   , (int)l_diff_time
                   , (int)l_pid
                   );
             }
             g_remove(l_filename);
           }
           g_free(l_filename);
           
        }
     }
     g_dir_close( l_dirp );
     
   }
   
}  /* end p_gap_delete_old_communication_files */
Exemple #19
0
gboolean
gimp_tags_user_install (void)
{
  gchar             *filename;
  GMarkupParser      markup_parser;
  GimpXmlParser     *xml_parser;
  const char        *tags_locale;
  GimpTagsInstaller  tags_installer = { 0, };
  GError            *error          = NULL;
  gboolean           result         = TRUE;

  /* This is a special string to specify the language identifier to
   * look for in the gimp-tags-default.xml file. Please translate the
   * C in it according to the name of the po file used for
   * gimp-tags-default.xml. E.g. lithuanian for the translation,
   * that would be "tags-locale:lt".
   */
  tags_locale = _("tags-locale:C");

  if (g_str_has_prefix (tags_locale, "tags-locale:"))
    {
      tags_locale += strlen ("tags-locale:");

      if (*tags_locale && *tags_locale != 'C')
        tags_installer.locale = tags_locale;
    }
  else
    {
      g_warning ("Wrong translation for 'tags-locale:', fix the translation!");
    }

  tags_installer.buf = g_string_new (NULL);

  g_string_append (tags_installer.buf, "<?xml version='1.0' encoding='UTF-8'?>\n");
  g_string_append (tags_installer.buf, "<tags>\n");

  filename = g_build_filename (gimp_data_directory (), "tags",
                               "gimp-tags-default.xml", NULL);

  markup_parser.start_element = gimp_tags_installer_load_start_element;
  markup_parser.end_element   = gimp_tags_installer_load_end_element;
  markup_parser.text          = gimp_tags_installer_load_text;
  markup_parser.passthrough   = NULL;
  markup_parser.error         = NULL;

  xml_parser = gimp_xml_parser_new (&markup_parser, &tags_installer);

  result = gimp_xml_parser_parse_file (xml_parser, filename, &error);

  g_free (filename);
  gimp_xml_parser_free (xml_parser);

  if (! result)
    {
      g_string_free (tags_installer.buf, TRUE);
      return FALSE;
    }

  g_string_append (tags_installer.buf, "\n</tags>\n");

  filename = g_build_filename (gimp_directory (), GIMP_TAGS_FILE, NULL);

  result = g_file_set_contents (filename, tags_installer.buf->str,
                                tags_installer.buf->len, &error);

  g_free (filename);
  g_string_free (tags_installer.buf, TRUE);

  if (! result)
    {
      g_warning ("Error while creating tags.xml: %s\n", error->message);
      g_error_free (error);
      return FALSE;
    }

  return TRUE;
}
static void
textures_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, const gchar *texture_path)
{
  if (page_num == 0 || g_array_index (textures_timestamps, time_t, page_num) > 0)
    return;

  // fix gtk2
  page = gtk_notebook_get_nth_page (notebook, page_num);

  gtk_container_set_border_width (GTK_CONTAINER (page), 0);
  gtk_widget_set_size_request (page, -1, 480);

  const gchar *category = gtk_notebook_get_tab_label_text(notebook, page);

  /* scrolled window */
  GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX (page), scrolled_window, TRUE, TRUE, 0);
  gtk_widget_show (scrolled_window);

  /* table */
  gint rows = 5;
  gint cols = 3;
  GtkWidget *table = gtk_table_new (rows, cols, FALSE);
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  gtk_container_set_border_width (GTK_CONTAINER (table), 10);
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
  gtk_widget_show (table);

  gint row = 1;
  gint col = 1;

  const gchar *gimp_dir = gimp_directory ();
  const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
  const gchar *path = g_build_filename (texture_dir, category, NULL);

  GDir *dir = g_dir_open (path, 0, NULL);
  if (dir)
  {
    const gchar *dir_ent;
    while (dir_ent = g_dir_read_name (dir))
    {
      if (is_hidden (dir_ent))
        continue;

      gchar *filename = g_build_filename (path, dir_ent, NULL);
      GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
      pixbuf = gdk_pixbuf_scale_simple (pixbuf, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GDK_INTERP_BILINEAR);
      GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
      GtkWidget *event_box = gtk_event_box_new ();
      gtk_container_add (GTK_CONTAINER (event_box), image);
      gtk_widget_show (image);
      gtk_table_attach_defaults (GTK_TABLE (table), event_box, col - 1, col, row - 1, row);
      gtk_widget_show (event_box);

      col++;
      if (col > cols)
      {
        row++;
        col = 1;
      }

      g_signal_connect (event_box, "button_press_event", G_CALLBACK (custom_texture_press), filename);
    }
  }

  g_array_index (textures_timestamps, time_t, page_num) = time (NULL);
}