mirror of
https://github.com/csete/gpredict
synced 2026-08-13 17:39:46 -04:00
git-svn-id: https://gpredict.svn.sourceforge.net/svnroot/gpredict/trunk@697 ab6734ba-2843-0410-b83b-99c217ef6c0f
329 lines
10 KiB
C
329 lines
10 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
Gpredict: Real-time satellite tracking and orbit prediction program
|
|
|
|
Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC.
|
|
|
|
Authors: Alexandru Csete <oz9aec@gmail.com>
|
|
|
|
Comments, questions and bugreports should be submitted via
|
|
http://sourceforge.net/projects/gpredict/
|
|
More details can be found at the project home page:
|
|
|
|
http://gpredict.oz9aec.net/
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, visit http://www.fsf.org/
|
|
*/
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
#include <glib/gstdio.h>
|
|
#include <sys/stat.h> /*** FIXME: ok for win32? see thunar-vfs-io-local.c */
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <build-config.h>
|
|
#endif
|
|
#include "sat-log.h"
|
|
#include "map-selector.h"
|
|
#include "compat.h"
|
|
|
|
|
|
|
|
static GtkWidget *create_preview_widget (const gchar *selection);
|
|
static void update_preview_widget (GtkFileChooser *chooser, gpointer data);
|
|
static gchar *get_map_humanize_size (gint64 size, gchar *buffer, gsize buflen);
|
|
|
|
|
|
/** \brief Execute map selector.
|
|
* \param curmap The name of the current map.
|
|
* \return A newly allocated string with filename of the selected map
|
|
* or NULL if action was cancelled.
|
|
*
|
|
* This function creates and executes a file chooser dialog
|
|
* and selects the currently selected map curmap. The file chooser dialogue
|
|
* has a custom map preview widget showing the scaled down copty of
|
|
* the selected map as well as the size of the map.
|
|
*
|
|
*/
|
|
gchar *
|
|
select_map (const gchar *curmap)
|
|
{
|
|
GtkWidget *chooser; /* file chooser dialogue */
|
|
GtkFileFilter *filter; /* file filter object */
|
|
gchar *selection; /* full path of selected file */
|
|
gchar *mapsdir; /* stock maps directory */
|
|
gchar *ret = NULL;
|
|
GtkWidget *preview;
|
|
|
|
|
|
/* we are going to need this as a shortcut folder
|
|
and to find out whether selected map is stock
|
|
or user specific
|
|
*/
|
|
mapsdir = get_maps_dir ();
|
|
|
|
|
|
/* create a new file chooser dialogue in "open file" mode */
|
|
chooser = gtk_file_chooser_dialog_new (_("Select Map"),
|
|
NULL,
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
|
|
|
|
/* single selection only */
|
|
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), FALSE);
|
|
|
|
/* add shortcut */
|
|
gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (chooser), mapsdir, NULL);
|
|
|
|
/* create filter */
|
|
filter = gtk_file_filter_new ();
|
|
gtk_file_filter_set_name (filter, _("Image files"));
|
|
gtk_file_filter_add_pixbuf_formats (filter);
|
|
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
|
|
|
|
/* select current map file */
|
|
if (g_path_is_absolute (curmap)) {
|
|
/* map is user specific, ie. in USER_CONF_DIR/maps/ */
|
|
selection = g_strdup (curmap);
|
|
}
|
|
else {
|
|
/* build complete path */
|
|
selection = map_file_name (curmap);
|
|
}
|
|
gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (chooser), selection);
|
|
|
|
/* preview widget */
|
|
preview = create_preview_widget (selection);
|
|
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (chooser), preview);
|
|
gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (chooser), TRUE);
|
|
/* sig connect */
|
|
g_signal_connect (G_OBJECT (chooser), "update-preview",
|
|
G_CALLBACK (update_preview_widget), preview);
|
|
|
|
/* we don't need this anymore */
|
|
g_free (selection);
|
|
|
|
/* run the dialogue */
|
|
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) {
|
|
char *filename;
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
|
|
|
|
/* find out whether selected file is a
|
|
stock map or user map */
|
|
if (g_str_has_prefix (filename, mapsdir)) {
|
|
/* selected map is a stock map */
|
|
|
|
/* get file name without dir component */
|
|
ret = g_path_get_basename (filename);
|
|
|
|
}
|
|
else {
|
|
ret = g_strdup (filename);
|
|
}
|
|
|
|
|
|
/* clean up */
|
|
g_free (filename);
|
|
}
|
|
|
|
gtk_widget_destroy (chooser);
|
|
|
|
g_free (mapsdir);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/** \brief Create the preview widget and load the current map */
|
|
static GtkWidget *
|
|
create_preview_widget (const gchar *selection)
|
|
{
|
|
GtkWidget *vbox;
|
|
GtkWidget *img;
|
|
GtkWidget *label;
|
|
GdkPixbuf *obuf,*sbuf;
|
|
gchar *buff;
|
|
gint w,h;
|
|
gint64 size;
|
|
struct stat sb;
|
|
gchar *bf = NULL;
|
|
|
|
|
|
label = gtk_label_new (NULL);
|
|
img = gtk_image_new ();
|
|
|
|
vbox = gtk_vbox_new (FALSE, 5);
|
|
g_object_set_data (G_OBJECT (vbox), "image", img);
|
|
g_object_set_data (G_OBJECT (vbox), "label", label);
|
|
gtk_box_pack_start (GTK_BOX (vbox), img, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
|
gtk_widget_show_all (vbox);
|
|
|
|
/* load current map into preview widget */
|
|
obuf = gdk_pixbuf_new_from_file (selection, NULL);
|
|
|
|
if (G_LIKELY (obuf != NULL)) {
|
|
|
|
/* store data */
|
|
w = gdk_pixbuf_get_width (obuf);
|
|
h = gdk_pixbuf_get_height (obuf);
|
|
|
|
/* try to stat the file */
|
|
if (G_UNLIKELY (g_stat (selection, &sb) < 0)) {
|
|
sat_log_log (SAT_LOG_LEVEL_ERROR,
|
|
_("%s:%d: Could not stat %s"),
|
|
__FILE__, __LINE__, selection);
|
|
|
|
size = 0;
|
|
}
|
|
else {
|
|
size = sb.st_size;
|
|
}
|
|
|
|
bf = get_map_humanize_size (size, bf, 0);
|
|
|
|
buff = g_strdup_printf ("%dx%d pixels\n%s", w, h, bf);
|
|
gtk_label_set_text (GTK_LABEL (label), buff);
|
|
g_free (buff);
|
|
g_free (bf);
|
|
|
|
/* scale the pixbuf */
|
|
sbuf = gdk_pixbuf_scale_simple (obuf, 160, 80, GDK_INTERP_HYPER);
|
|
g_object_unref (obuf);
|
|
|
|
/* update the GtkImage from the pixbuf */
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (img), sbuf);
|
|
g_object_unref (sbuf);
|
|
}
|
|
else {
|
|
gtk_image_set_from_stock (GTK_IMAGE (img),
|
|
GTK_STOCK_MISSING_IMAGE,
|
|
GTK_ICON_SIZE_LARGE_TOOLBAR);
|
|
}
|
|
|
|
return vbox;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
update_preview_widget (GtkFileChooser *chooser, gpointer data)
|
|
{
|
|
GtkWidget *box = GTK_WIDGET (data);
|
|
GtkImage *img = GTK_IMAGE (g_object_get_data (G_OBJECT (box), "image"));
|
|
GtkLabel *lab = GTK_LABEL (g_object_get_data (G_OBJECT (box), "label"));
|
|
gchar *sel = NULL;
|
|
GdkPixbuf *obuf,*sbuf;
|
|
gint w,h;
|
|
gint64 size;
|
|
struct stat sb;
|
|
gchar *buff = NULL;
|
|
|
|
|
|
sel = gtk_file_chooser_get_preview_filename (chooser);
|
|
|
|
if (G_LIKELY (sel != NULL)) {
|
|
|
|
obuf = gdk_pixbuf_new_from_file (sel, NULL);
|
|
|
|
/* try to stat the file */
|
|
if (G_UNLIKELY (g_stat (sel, &sb) < 0)) {
|
|
sat_log_log (SAT_LOG_LEVEL_ERROR,
|
|
_("%s:%d: Could not stat %s"),
|
|
__FILE__, __LINE__, sel);
|
|
|
|
size = 0;
|
|
}
|
|
else {
|
|
size = sb.st_size;
|
|
}
|
|
|
|
g_free (sel);
|
|
|
|
if (G_LIKELY (obuf != NULL)) {
|
|
|
|
/* store data */
|
|
w = gdk_pixbuf_get_width (obuf);
|
|
h = gdk_pixbuf_get_height (obuf);
|
|
|
|
buff = get_map_humanize_size (size, buff, 0);
|
|
|
|
sel = g_strdup_printf ("%dx%d pixels\n%s", w, h, buff);
|
|
gtk_label_set_text (lab, sel);
|
|
g_free (sel);
|
|
g_free (buff);
|
|
|
|
/* scale the pixbuf */
|
|
sbuf = gdk_pixbuf_scale_simple (obuf, 160, 80, GDK_INTERP_HYPER);
|
|
g_object_unref (obuf);
|
|
|
|
/* update the GtkImage from the pixbuf */
|
|
gtk_image_clear (img);
|
|
gtk_image_set_from_pixbuf (img, sbuf);
|
|
g_object_unref (sbuf);
|
|
|
|
/* report success */
|
|
gtk_file_chooser_set_preview_widget_active (chooser, TRUE);
|
|
}
|
|
else {
|
|
gtk_image_clear (img);
|
|
gtk_image_set_from_stock (GTK_IMAGE (img),
|
|
GTK_STOCK_MISSING_IMAGE,
|
|
GTK_ICON_SIZE_LARGE_TOOLBAR);
|
|
|
|
/* report failure */
|
|
gtk_file_chooser_set_preview_widget_active (chooser, FALSE);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/** \brief Convert map filesize into a human readable format
|
|
* \param size Size in bytes.
|
|
* \param buffer Destination buffer or NULL to dynamically allocate a buffer.
|
|
* \param buflen Length of @buffer in bytes.
|
|
* \return A string containing a human readable description of size.
|
|
*
|
|
* The caller is responsible to free the returned string using g_free()
|
|
* if you pass NULL for buffer. Else the returned string will be a
|
|
* pointer to buffer.
|
|
*
|
|
* Credits: Thunar (XFCE file manager).
|
|
*
|
|
**/
|
|
static gchar*
|
|
get_map_humanize_size (gint64 size,
|
|
gchar *buffer,
|
|
gsize buflen)
|
|
{
|
|
/* allocate buffer if necessary */
|
|
if (buffer == NULL) {
|
|
buffer = g_new (gchar, 32);
|
|
buflen = 32;
|
|
}
|
|
|
|
if (G_UNLIKELY (size > 1024ul * 1024ul * 1024ul))
|
|
g_snprintf (buffer, buflen, "%0.1f GB", size / (1024.0 * 1024.0 * 1024.0));
|
|
else if (size > 1024ul * 1024ul)
|
|
g_snprintf (buffer, buflen, "%0.1f MB", size / (1024.0 * 1024.0));
|
|
else if (size > 1024ul)
|
|
g_snprintf (buffer, buflen, "%0.1f kB", size / 1024.0);
|
|
else
|
|
g_snprintf (buffer, buflen, "%lu B", (gulong) size);
|
|
|
|
return buffer;
|
|
}
|
|
|