Merge pull request #89 from gergelypolonkai/gtk-icon-view

Move chart list from GdMainView to GtkIconView
This commit is contained in:
Gergely Polonkai 2014-09-26 23:57:29 +02:00
commit 39e58c7156
16 changed files with 1274 additions and 151 deletions

4
.gitignore vendored
View File

@ -40,8 +40,8 @@ Makefile.in
/data/astrognome.desktop.in /data/astrognome.desktop.in
# Generated files # Generated files
/src/ag-resources.c /src/ag-resources.[ch]
/src/ag-resources.h /src/ag-enumtypes.[ch]
# Geonames related things # Geonames related things
/data/geonames/*.txt /data/geonames/*.txt

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "libgd"]
path = libgd
url = git://git.gnome.org/libgd.git

View File

@ -1,5 +1,5 @@
ACLOCAL_AMFLAGS = -I m4 -I libgd ${ACLOCAL_FLAGS} ACLOCAL_AMFLAGS = -I m4 -I libgd ${ACLOCAL_FLAGS}
SUBDIRS = libgd src po data help SUBDIRS = src po data help
EXTRA_DIST = config.rpath ChangeLog EXTRA_DIST = config.rpath ChangeLog

View File

@ -40,14 +40,10 @@ PKG_CHECK_MODULES([GDA], [libgda-5.0 libgda-sqlite-5.0])
PKG_CHECK_MODULES([PIXBUF], [gdk-pixbuf-2.0]) PKG_CHECK_MODULES([PIXBUF], [gdk-pixbuf-2.0])
PKG_CHECK_MODULES([RSVG], [librsvg-2.0]) PKG_CHECK_MODULES([RSVG], [librsvg-2.0])
PKG_CHECK_MODULES([SWE_GLIB], [swe-glib >= 2.1.0]) PKG_CHECK_MODULES([SWE_GLIB], [swe-glib >= 2.1.0])
PKG_CHECK_MODULES([CAIRO], [cairo]);
LIBGD_INIT([
main-view
])
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
libgd/Makefile
src/Makefile src/Makefile
help/Makefile help/Makefile
po/Makefile.in po/Makefile.in

View File

@ -1,15 +1,27 @@
RESOURCE_DIR = $(srcdir)/resources RESOURCE_DIR = $(srcdir)/resources
resource_files = $(shell glib-compile-resources --sourcedir=$(RESOURCE_DIR) --generate-dependencies $(srcdir)/ag.gresource.xml) resource_files = $(shell glib-compile-resources --sourcedir=$(RESOURCE_DIR) --generate-dependencies $(srcdir)/ag.gresource.xml)
ag_enum_headers = ag-icon-view.h
ag-resources.c: ag.gresource.xml $(resource_files) ag-resources.c: ag.gresource.xml $(resource_files)
glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-source --c-name ag $(srcdir)/ag.gresource.xml glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-source --c-name ag $(srcdir)/ag.gresource.xml
ag-resources.h: ag.gresource.xml $(resource_files) ag-resources.h: ag.gresource.xml $(resource_files)
glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-header --c-name ag $(srcdir)/ag.gresource.xml glib-compile-resources --target=$@ --sourcedir=$(RESOURCE_DIR) --generate-header --c-name ag $(srcdir)/ag.gresource.xml
ag-enumtypes.h: $(ag_enum_headers) ag-enumtypes.h.template
$(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
ag-enumtypes.h.tmp && mv ag-enumtypes.h.tmp ag-enumtypes.h
ag-enumtypes.c: $(ag_enum_headers) ag-enumtypes.c.template
$(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
ag-enumtypes.c.tmp && mv ag-enumtypes.c.tmp ag-enumtypes.c
BUILT_SOURCES = \ BUILT_SOURCES = \
ag-resources.h \ ag-resources.h \
ag-resources.c \ ag-resources.c \
ag-enumtypes.h \
ag-enumtypes.c \
$(NULL) $(NULL)
astrognome_source_files = \ astrognome_source_files = \
@ -20,6 +32,8 @@ astrognome_source_files = \
ag-preferences.c \ ag-preferences.c \
ag-db.c \ ag-db.c \
ag-display-theme.c \ ag-display-theme.c \
ag-icon-view.c \
ag-chart-renderer.c \
astrognome.c \ astrognome.c \
$(NULL) $(NULL)
@ -28,13 +42,13 @@ EXTRA_DIST = \
ag.gresource.xml \ ag.gresource.xml \
$(NULL) $(NULL)
AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Astrognome\" -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -I$(top_srcdir)/libgd AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Astrognome\" -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\"
bin_PROGRAMS = astrognome bin_PROGRAMS = astrognome
astrognome_SOURCES = $(astrognome_source_files) $(BUILT_SOURCES) astrognome_SOURCES = $(astrognome_source_files) $(BUILT_SOURCES)
astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) $(GDA_LIBS) $(PIXBUF_LIBS) $(RSVG_LIBS) $(top_builddir)/libgd/libgd.la astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) $(GDA_LIBS) $(PIXBUF_LIBS) $(RSVG_LIBS) $(CAIRO_LIBS)
astrognome_LDFLAGS = -rdynamic astrognome_LDFLAGS = -rdynamic
astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) $(GDA_CFLAGS) $(PIXBUF_CFLAGS) $(RSVG_CFLAGS) -Wall astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) $(GDA_CFLAGS) $(PIXBUF_CFLAGS) $(RSVG_CFLAGS) $(CAIRO_CFLAGS) -Wall
# The following two lines generate a .dir-locals.el file, so # The following two lines generate a .dir-locals.el file, so
# company-mode wont die due to unknown includes # company-mode wont die due to unknown includes

396
src/ag-chart-renderer.c Normal file
View File

@ -0,0 +1,396 @@
#include <cairo.h>
#include "ag-chart-renderer.h"
typedef struct {
gchar *css_class;
gboolean checked;
gboolean toggle_visible;
} AgChartRendererPrivate;
enum {
PROP_0,
AG_CHART_RENDERER_PROP_CSS_CLASS,
AG_CHART_RENDERER_PROP_CHECKED,
AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE,
};
static void ag_chart_renderer_dispose(GObject *gobject);
static void ag_chart_renderer_finalize(GObject *gobject);
G_DEFINE_TYPE_WITH_PRIVATE(
AgChartRenderer,
ag_chart_renderer,
GTK_TYPE_CELL_RENDERER_PIXBUF
);
static void
ag_chart_renderer_render(GtkCellRenderer *renderer,
cairo_t *cr,
GtkWidget *widget,
const GdkRectangle *background_area,
const GdkRectangle *cell_area,
GtkCellRendererState flags)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
AG_CHART_RENDERER(renderer)
);
int margin;
GtkStyleContext *context = gtk_widget_get_style_context(widget);
GdkPixbuf *pixbuf;
gtk_style_context_save(context);
gtk_style_context_add_class(context, "ag-chart-renderer");
if (priv->css_class) {
gtk_style_context_add_class(context, priv->css_class);
}
cairo_save(cr);
gdk_cairo_rectangle(cr, cell_area);
cairo_clip(cr);
cairo_translate(cr, cell_area->x, cell_area->y);
margin = MAX(
AG_CHART_RENDERER_TILE_MARGIN,
(int)((cell_area->width - AG_CHART_RENDERER_TILE_SIZE) / 2)
);
g_object_get(renderer, "pixbuf", &pixbuf, NULL);
if (pixbuf != NULL) {
GdkRectangle area = {
margin,
margin,
AG_CHART_RENDERER_TILE_SIZE,
AG_CHART_RENDERER_TILE_SIZE
};
GTK_CELL_RENDERER_CLASS(ag_chart_renderer_parent_class)->render(
renderer,
cr,
widget,
&area,
&area,
flags
);
} else {
gtk_render_frame(
context,
cr,
margin,
margin,
AG_CHART_RENDERER_TILE_SIZE,
AG_CHART_RENDERER_TILE_SIZE
);
gtk_render_background(
context,
cr,
margin,
margin,
AG_CHART_RENDERER_TILE_SIZE,
AG_CHART_RENDERER_TILE_SIZE
);
}
gtk_style_context_restore(context);
if (priv->toggle_visible) {
gint xpad,
ypad,
x_offset,
check_x,
check_y;
gtk_cell_renderer_get_padding(
GTK_CELL_RENDERER(renderer),
&xpad, &ypad
);
if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) {
x_offset = xpad;
} else {
x_offset = cell_area->width
- AG_CHART_RENDERER_CHECK_ICON_SIZE
- xpad;
}
check_x = x_offset;
check_y = cell_area->height - AG_CHART_RENDERER_CHECK_ICON_SIZE - ypad;
gtk_style_context_save(context);
gtk_style_context_add_class(context, GTK_STYLE_CLASS_CHECK);
if (priv->checked) {
gtk_style_context_set_state(context, GTK_STATE_FLAG_CHECKED);
}
gtk_render_background(
context,
cr,
check_x,
check_y,
AG_CHART_RENDERER_CHECK_ICON_SIZE,
AG_CHART_RENDERER_CHECK_ICON_SIZE
);
gtk_render_frame(
context,
cr,
check_x,
check_y,
AG_CHART_RENDERER_CHECK_ICON_SIZE,
AG_CHART_RENDERER_CHECK_ICON_SIZE
);
gtk_render_check(
context,
cr,
check_x,
check_y,
AG_CHART_RENDERER_CHECK_ICON_SIZE,
AG_CHART_RENDERER_CHECK_ICON_SIZE
);
gtk_style_context_restore(context);
}
cairo_restore(cr);
}
void
ag_chart_renderer_set_css_class(AgChartRenderer *chart_renderer,
const gchar *css_class)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
g_free(priv->css_class);
priv->css_class = g_strdup(css_class);
}
const gchar *
ag_chart_renderer_get_css_class(AgChartRenderer *chart_renderer)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
return priv->css_class;
}
void
ag_chart_renderer_set_checked(AgChartRenderer *chart_renderer, gboolean checked)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
priv->checked = checked;
}
gboolean
ag_chart_renderer_get_checked(AgChartRenderer *chart_renderer)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
return priv->checked;
}
void
ag_chart_renderer_set_toggle_visible(AgChartRenderer *chart_renderer,
gboolean toggle_visible)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
priv->toggle_visible = toggle_visible;
}
gboolean
ag_chart_renderer_get_toggle_visible(AgChartRenderer *chart_renderer)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
return priv->toggle_visible;
}
static void
ag_chart_renderer_get_property(GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
AgChartRenderer *chart_renderer = AG_CHART_RENDERER(gobject);
switch (prop_id) {
case AG_CHART_RENDERER_PROP_CSS_CLASS:
g_value_set_string(
value,
ag_chart_renderer_get_css_class(chart_renderer)
);
break;
case AG_CHART_RENDERER_PROP_CHECKED:
g_value_set_boolean(
value,
ag_chart_renderer_get_checked(chart_renderer)
);
break;
case AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE:
g_value_set_boolean(
value,
ag_chart_renderer_get_toggle_visible(chart_renderer)
);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
break;
}
}
static void
ag_chart_renderer_set_property(GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
AgChartRenderer *chart_renderer = AG_CHART_RENDERER(gobject);
switch (prop_id) {
case AG_CHART_RENDERER_PROP_CSS_CLASS:
ag_chart_renderer_set_css_class(
chart_renderer,
g_value_get_string(value)
);
break;
case AG_CHART_RENDERER_PROP_CHECKED:
ag_chart_renderer_set_checked(
chart_renderer,
g_value_get_boolean(value)
);
break;
case AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE:
ag_chart_renderer_set_toggle_visible(
chart_renderer,
g_value_get_boolean(value)
);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
break;
}
}
static void
ag_chart_renderer_class_init(AgChartRendererClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *)klass;
GtkCellRendererClass *cell_renderer_class = (GtkCellRendererClass *)klass;
gobject_class->dispose = ag_chart_renderer_dispose;
gobject_class->finalize = ag_chart_renderer_finalize;
gobject_class->set_property = ag_chart_renderer_set_property;
gobject_class->get_property = ag_chart_renderer_get_property;
cell_renderer_class->render = ag_chart_renderer_render;
g_object_class_install_property(
G_OBJECT_CLASS(klass),
AG_CHART_RENDERER_PROP_CSS_CLASS,
g_param_spec_string(
"css-class",
"css-class",
"CSS Class",
NULL,
G_PARAM_STATIC_NAME
| G_PARAM_STATIC_NICK
| G_PARAM_STATIC_BLURB
| G_PARAM_READABLE
| G_PARAM_WRITABLE
)
);
g_object_class_install_property(
G_OBJECT_CLASS(klass),
AG_CHART_RENDERER_PROP_CHECKED,
g_param_spec_boolean(
"checked",
"checked",
"Checked",
FALSE,
G_PARAM_STATIC_NAME
| G_PARAM_STATIC_NICK
| G_PARAM_STATIC_BLURB
| G_PARAM_READABLE
| G_PARAM_WRITABLE
)
);
g_object_class_install_property(
G_OBJECT_CLASS(klass),
AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE,
g_param_spec_boolean(
"toggle-visible",
"toggle-visible",
"Toggle visible",
FALSE,
G_PARAM_STATIC_NAME
| G_PARAM_STATIC_NICK
| G_PARAM_STATIC_BLURB
| G_PARAM_READABLE
| G_PARAM_WRITABLE
)
);
}
static void
ag_chart_renderer_init(AgChartRenderer *chart_renderer)
{
AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(
chart_renderer
);
priv->checked = FALSE;
priv->toggle_visible = FALSE;
}
static void
ag_chart_renderer_dispose(GObject *gobject)
{
G_OBJECT_CLASS(ag_chart_renderer_parent_class)->dispose(gobject);
}
static void
ag_chart_renderer_finalize (GObject *gobject)
{
g_signal_handlers_destroy(gobject);
G_OBJECT_CLASS(ag_chart_renderer_parent_class)->finalize(gobject);
}
AgChartRenderer *
ag_chart_renderer_new(void)
{
AgChartRenderer *chart_renderer = NULL;
chart_renderer = g_object_new(AG_TYPE_CHART_RENDERER, NULL);
return chart_renderer;
}

58
src/ag-chart-renderer.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __AG_CHART_RENDERER_H__
#define __AG_CHART_RENDERER_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define AG_TYPE_CHART_RENDERER \
(ag_chart_renderer_get_type())
#define AG_CHART_RENDERER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
AG_TYPE_CHART_RENDERER, \
AgChartRenderer))
#define AG_CHART_RENDERER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
AG_TYPE_CHART_RENDERER, \
AgChartRendererClass))
#define IS_AG_CHART_RENDERER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
AG_TYPE_CHART_RENDERER))
#define IS_AG_CHART_RENDERER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
AG_TYPE_CHART_RENDERER))
#define AG_CHART_RENDERER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
AG_TYPE_CHART_RENDERER, \
AgChartRendererClass))
typedef struct _AgChartRenderer AgChartRenderer;
typedef struct _AgChartRendererClass AgChartRendererClass;
struct _AgChartRendererClass
{
GtkCellRendererPixbufClass parent_class;
};
struct _AgChartRenderer
{
GtkCellRendererPixbuf parent;
};
#define AG_CHART_RENDERER_TILE_SIZE 256
#define AG_CHART_RENDERER_CHECK_ICON_SIZE 40
#define AG_CHART_RENDERER_TILE_MARGIN AG_CHART_RENDERER_CHECK_ICON_SIZE / 4
#define AG_CHART_RENDERER_TILE_MARGIN_BOTTOM AG_CHART_RENDERER_CHECK_ICON_SIZE / 8
GType ag_chart_renderer_get_type (void) G_GNUC_CONST;
AgChartRenderer *ag_chart_renderer_new(void);
void ag_chart_renderer_set_toggle_visible(AgChartRenderer *chart_renderer, gboolean toggle_visible);
gboolean ag_chart_renderer_get_toggle_visible(AgChartRenderer *chart_renderer);
G_END_DECLS
#endif /* __AG_CHART_RENDERER_H__ */

View File

@ -1926,7 +1926,7 @@ ag_chart_get_db_save(AgChart *chart, gint db_id)
{ {
GsweCoordinates *coords; GsweCoordinates *coords;
AgChartPrivate *priv = ag_chart_get_instance_private(chart); AgChartPrivate *priv = ag_chart_get_instance_private(chart);
AgDbChartSave *save_data = g_new0(AgDbChartSave, 1); AgDbChartSave *save_data = ag_db_chart_save_new();
GsweTimestamp *timestamp = gswe_moment_get_timestamp(GSWE_MOMENT(chart)); GsweTimestamp *timestamp = gswe_moment_get_timestamp(GSWE_MOMENT(chart));
GEnumClass *house_system_class; GEnumClass *house_system_class;
GEnumValue *house_system_enum; GEnumValue *house_system_enum;

View File

@ -39,6 +39,12 @@ typedef struct _AgDbPrivate {
G_DEFINE_QUARK(ag_db_error_quark, ag_db_error); G_DEFINE_QUARK(ag_db_error_quark, ag_db_error);
G_DEFINE_TYPE_WITH_PRIVATE(AgDb, ag_db, G_TYPE_OBJECT); G_DEFINE_TYPE_WITH_PRIVATE(AgDb, ag_db, G_TYPE_OBJECT);
G_DEFINE_BOXED_TYPE(
AgDbChartSave,
ag_db_chart_save,
(GBoxedCopyFunc)ag_db_chart_save_ref,
(GBoxedFreeFunc)ag_db_chart_save_unref
);
enum { enum {
COLUMN_CHART_ID, COLUMN_CHART_ID,
@ -564,7 +570,7 @@ ag_db_get(void)
* *
* Frees @save_data and all its fields * Frees @save_data and all its fields
*/ */
void static void
ag_db_chart_save_free(AgDbChartSave *save_data) ag_db_chart_save_free(AgDbChartSave *save_data)
{ {
if (!save_data) { if (!save_data) {
@ -594,6 +600,30 @@ ag_db_chart_save_free(AgDbChartSave *save_data)
g_free(save_data); g_free(save_data);
} }
AgDbChartSave *
ag_db_chart_save_ref(AgDbChartSave *save_data)
{
if (save_data == NULL) {
return NULL;
}
save_data->refcount++;
return save_data;
}
void
ag_db_chart_save_unref(AgDbChartSave *save_data)
{
if (save_data == NULL) {
return;
}
if (--save_data->refcount == 0) {
ag_db_chart_save_free(save_data);
}
}
/** /**
* ag_db_chart_save: * ag_db_chart_save:
* @db: the #AgDb object to operate on * @db: the #AgDb object to operate on
@ -797,6 +827,17 @@ ag_db_chart_save(AgDb *db, AgDbChartSave *save_data, GError **err)
return save_success; return save_success;
} }
AgDbChartSave *
ag_db_chart_save_new(void)
{
AgDbChartSave *save_data;
save_data = g_new0(AgDbChartSave, 1);
save_data->refcount = 1;
return save_data;
}
/** /**
* ag_db_chart_get_list: * ag_db_chart_get_list:
* @db: the #AgDb object to operate on * @db: the #AgDb object to operate on
@ -833,7 +874,7 @@ ag_db_chart_get_list(AgDb *db, GError **err)
while (gda_data_model_iter_move_next(iter)) { while (gda_data_model_iter_move_next(iter)) {
const GValue *value; const GValue *value;
AgDbChartSave *save_data = g_new0(AgDbChartSave, 1); AgDbChartSave *save_data = ag_db_chart_save_new();
value = gda_data_model_iter_get_value_at(iter, 0); value = gda_data_model_iter_get_value_at(iter, 0);
save_data->db_id = g_value_get_int(value); save_data->db_id = g_value_get_int(value);
@ -910,7 +951,7 @@ ag_db_chart_get_data_by_id(AgDb *db, guint row_id, GError **err)
return NULL; return NULL;
} }
save_data = g_new0(AgDbChartSave, 1); save_data = ag_db_chart_save_new();
/* id */ /* id */
value = gda_data_model_get_value_at( value = gda_data_model_get_value_at(
@ -1082,8 +1123,8 @@ string_collate(const gchar *str1, const gchar *str2)
*/ */
gboolean gboolean
ag_db_chart_save_identical(const AgDbChartSave *a, ag_db_chart_save_identical(const AgDbChartSave *a,
const AgDbChartSave *b, const AgDbChartSave *b,
gboolean chart_only) gboolean chart_only)
{ {
if (a == b) { if (a == b) {
g_debug("identical: Equal"); g_debug("identical: Equal");

View File

@ -65,8 +65,12 @@ typedef struct _AgDbChartSave {
gdouble timezone; gdouble timezone;
gchar *house_system; gchar *house_system;
gchar *note; gchar *note;
gint refcount;
} AgDbChartSave; } AgDbChartSave;
GType ag_db_chart_save_get_type(void);
#define AG_TYPE_DB_CHART_SAVE (ag_db_chart_save_get_type())
typedef enum { typedef enum {
AG_DB_ERROR_NO_CHART, AG_DB_ERROR_NO_CHART,
AG_DB_ERROR_DATABASE_ERROR, AG_DB_ERROR_DATABASE_ERROR,
@ -76,12 +80,16 @@ GType ag_db_get_type(void) G_GNUC_CONST;
AgDb *ag_db_get(void); AgDb *ag_db_get(void);
void ag_db_chart_save_free(AgDbChartSave *save_data);
gboolean ag_db_chart_save(AgDb *db, gboolean ag_db_chart_save(AgDb *db,
AgDbChartSave *save_data, AgDbChartSave *save_data,
GError **err); GError **err);
AgDbChartSave *ag_db_chart_save_new(void);
AgDbChartSave *ag_db_chart_save_ref(AgDbChartSave *save_data);
void ag_db_chart_save_unref(AgDbChartSave *save_data);
GList *ag_db_chart_get_list(AgDb *db, GError **err); GList *ag_db_chart_get_list(AgDb *db, GError **err);
AgDbChartSave *ag_db_chart_get_data_by_id(AgDb *db, guint row_id, GError **err); AgDbChartSave *ag_db_chart_get_data_by_id(AgDb *db, guint row_id, GError **err);

View File

@ -0,0 +1,63 @@
/*** BEGIN file-header ***/
/* ag-enumtypes.c - Enumeration types for Astrognome
*
* Copyright © 2013 Gergely Polonkai
*
* Astrognome 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 3 of the License,
* or (at your option) any later version.
*
* Astrognome 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 library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "ag-enumtypes.h"
#include "@filename@"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type(void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter(&g_define_type_id__volatile)) {
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{
@VALUENAME@,
"@VALUENAME@",
"@valuenick@"
},
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_define_type_id = g_@type@_register_static(
g_intern_static_string("@EnumName@"),
values
);
g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
/*** END value-tail ***/

View File

@ -0,0 +1,42 @@
/*** BEGIN file-header ***/
/* ag-enumtypes.h - Enumeration types for Astrognome
*
* Copyright © 2013 Gergely Polonkai
*
* Astrognome 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 3 of the License,
* or (at your option) any later version.
*
* Astrognome 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 library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AG_ENUM_TYPES_H__
#define __AG_ENUM_TYPES_H__
#include <glib-object.h>
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
#include "@filename@"
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type(void);
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
/*** END value-header ***/
/*** BEGIN file-tail ***/
#endif /* __AG_ENUM_TYPES_H__ */
/*** END file-tail ***/

423
src/ag-icon-view.c Normal file
View File

@ -0,0 +1,423 @@
#include "ag-enumtypes.h"
#include "ag-icon-view.h"
#include "ag-db.h"
#include "ag-chart-renderer.h"
typedef struct _AgIconViewPrivate {
AgIconViewMode mode;
AgChartRenderer *thumb_renderer;
GtkCellRenderer *text_renderer;
GtkListStore *model;
} AgIconViewPrivate;
enum {
PROP_0,
PROP_MODE,
PROP_LAST
};
enum {
AG_ICON_VIEW_COLUMN_SELECTED,
AG_ICON_VIEW_COLUMN_ITEM,
AG_ICON_VIEW_COLUMN_COLUMNS
};
G_DEFINE_TYPE_WITH_PRIVATE(AgIconView, ag_icon_view, GTK_TYPE_ICON_VIEW);
static GParamSpec *properties[PROP_LAST];
void
ag_icon_view_set_mode(AgIconView *icon_view, AgIconViewMode mode)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
if (priv->mode != mode) {
priv->mode = mode;
if (mode != AG_ICON_VIEW_MODE_SELECTION) {
ag_icon_view_unselect_all(icon_view);
}
ag_chart_renderer_set_toggle_visible(priv->thumb_renderer, (mode == AG_ICON_VIEW_MODE_SELECTION));
gtk_widget_queue_draw(GTK_WIDGET(icon_view));
g_object_notify_by_pspec(
G_OBJECT(icon_view),
properties[PROP_MODE]
);
}
}
AgIconViewMode
ag_icon_view_get_mode(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
return priv->mode;
}
static void
ag_icon_view_set_property(GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *param_spec)
{
switch (prop_id) {
case PROP_MODE:
ag_icon_view_set_mode(
AG_ICON_VIEW(gobject),
g_value_get_enum(value)
);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
break;
}
}
static void
ag_icon_view_get_property(GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *param_spec)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(
AG_ICON_VIEW(gobject)
);
switch (prop_id) {
case PROP_MODE:
g_value_set_enum(value, priv->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
break;
}
}
static void
ag_icon_view_selection_changed(AgIconView *icon_view)
{
g_signal_emit_by_name(icon_view, "selection-changed");
}
static void
ag_icon_view_item_activated(AgIconView *icon_view, GtkTreePath *path)
{
g_signal_emit_by_name(icon_view, "item-activated", path);
}
static gboolean
ag_icon_view_button_press_event_cb(GtkWidget *widget,
GdkEventButton *event)
{
GtkTreePath *path;
GtkIconView *gtk_icon_view = GTK_ICON_VIEW(widget);
AgIconView *ag_icon_view = AG_ICON_VIEW(widget);
path = gtk_icon_view_get_path_at_pos(gtk_icon_view, ((GdkEventButton *)event)->x, ((GdkEventButton *)event)->y);
if (path != NULL) {
gboolean selected;
AgDbChartSave *chart_save;
GtkListStore *store = GTK_LIST_STORE(gtk_icon_view_get_model(gtk_icon_view));
if (event->button == GDK_BUTTON_SECONDARY) {
ag_icon_view_set_mode(ag_icon_view, AG_ICON_VIEW_MODE_SELECTION);
}
if (ag_icon_view_get_mode(ag_icon_view) == AG_ICON_VIEW_MODE_SELECTION) {
GtkTreeIter iter;
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) {
gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, AG_ICON_VIEW_COLUMN_SELECTED, &selected, AG_ICON_VIEW_COLUMN_ITEM, &chart_save, -1);
gtk_list_store_set(store, &iter, AG_ICON_VIEW_COLUMN_SELECTED, !selected, -1);
ag_icon_view_selection_changed(ag_icon_view);
}
} else {
ag_icon_view_item_activated(ag_icon_view, path);
}
}
return FALSE;
}
static void
ag_icon_view_class_init(AgIconViewClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
gobject_class->set_property = ag_icon_view_set_property;
gobject_class->get_property = ag_icon_view_get_property;
widget_class->button_press_event = ag_icon_view_button_press_event_cb;
properties[PROP_MODE] = g_param_spec_enum(
"mode",
"Mode",
"Mode",
AG_TYPE_ICON_VIEW_MODE,
AG_ICON_VIEW_MODE_NORMAL,
G_PARAM_STATIC_NAME
| G_PARAM_STATIC_NICK
| G_PARAM_STATIC_BLURB
| G_PARAM_READABLE
| G_PARAM_WRITABLE
);
g_object_class_install_property(
gobject_class,
PROP_MODE,
properties[PROP_MODE]
);
}
static void
ag_icon_view_chart_renderer_func(GtkCellLayout *layout,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
AgIconView *icon_view)
{
AgDbChartSave *chart_save;
gtk_tree_model_get(model, iter, AG_ICON_VIEW_COLUMN_ITEM, &chart_save, -1);
if (chart_save) {
g_object_set(renderer, "pixbuf", NULL, NULL);
}
}
static void
ag_icon_view_text_renderer_func(GtkCellLayout *layout,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
AgIconView *icon_view)
{
AgDbChartSave *chart_save;
gtk_tree_model_get(model, iter, AG_ICON_VIEW_COLUMN_ITEM, &chart_save, -1);
if (chart_save) {
gchar *text;
text = g_markup_escape_text(chart_save->name, -1);
g_object_set(renderer, "markup", text, NULL);
g_free(text);
}
}
static void
ag_icon_view_init(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
guint tile_width,
tile_height;
priv->model = gtk_list_store_new(
AG_ICON_VIEW_COLUMN_COLUMNS,
G_TYPE_BOOLEAN,
AG_TYPE_DB_CHART_SAVE
);
gtk_icon_view_set_model(
GTK_ICON_VIEW(icon_view),
GTK_TREE_MODEL(priv->model)
);
gtk_icon_view_set_selection_mode(
GTK_ICON_VIEW(icon_view),
GTK_SELECTION_NONE
);
priv->mode = AG_ICON_VIEW_MODE_NORMAL;
gtk_icon_view_set_item_padding(GTK_ICON_VIEW(icon_view), 0);
gtk_icon_view_set_margin(GTK_ICON_VIEW(icon_view), 12);
tile_width = AG_CHART_RENDERER_TILE_SIZE
+ 2 * AG_CHART_RENDERER_TILE_MARGIN;
tile_height = AG_CHART_RENDERER_TILE_SIZE
+ AG_CHART_RENDERER_TILE_MARGIN
+ AG_CHART_RENDERER_TILE_MARGIN_BOTTOM;
priv->thumb_renderer = ag_chart_renderer_new();
gtk_cell_renderer_set_alignment(
GTK_CELL_RENDERER(priv->thumb_renderer),
0.5, 0.5
);
gtk_cell_renderer_set_fixed_size(
GTK_CELL_RENDERER(priv->thumb_renderer),
tile_width, tile_height
);
gtk_cell_layout_pack_start(
GTK_CELL_LAYOUT(icon_view),
GTK_CELL_RENDERER(priv->thumb_renderer),
FALSE
);
gtk_cell_layout_add_attribute(
GTK_CELL_LAYOUT(icon_view),
GTK_CELL_RENDERER(priv->thumb_renderer),
"checked", AG_ICON_VIEW_COLUMN_SELECTED
);
gtk_cell_layout_set_cell_data_func(
GTK_CELL_LAYOUT(icon_view),
GTK_CELL_RENDERER(priv->thumb_renderer),
(GtkCellLayoutDataFunc)ag_icon_view_chart_renderer_func,
icon_view,
NULL
);
priv->text_renderer = gtk_cell_renderer_text_new();
gtk_cell_renderer_set_alignment(
GTK_CELL_RENDERER(priv->text_renderer),
0.5, 0.5
);
gtk_cell_layout_pack_start(
GTK_CELL_LAYOUT(icon_view),
priv->text_renderer,
TRUE
);
gtk_cell_layout_set_cell_data_func(
GTK_CELL_LAYOUT(icon_view),
GTK_CELL_RENDERER(priv->text_renderer),
(GtkCellLayoutDataFunc)ag_icon_view_text_renderer_func,
icon_view,
NULL
);
}
void
ag_icon_view_add_chart(AgIconView *icon_view, AgDbChartSave *chart_save)
{
GtkTreeIter iter;
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
g_debug("Adding chart for %s", chart_save->name);
gtk_list_store_append(priv->model, &iter);
gtk_list_store_set(
priv->model, &iter,
AG_ICON_VIEW_COLUMN_SELECTED, FALSE,
AG_ICON_VIEW_COLUMN_ITEM, chart_save,
-1
);
}
static gboolean
ag_icon_view_check_selected(GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
GList **list)
{
gboolean selected;
gtk_tree_model_get(model, iter, AG_ICON_VIEW_COLUMN_SELECTED, &selected, -1);
if (selected) {
*list = g_list_prepend(*list, path);
}
return FALSE;
}
GList *
ag_icon_view_get_selected_items(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
GList *items = NULL;
gtk_tree_model_foreach(GTK_TREE_MODEL(priv->model), (GtkTreeModelForeachFunc)ag_icon_view_check_selected, &items);
return g_list_reverse(items);
}
static gboolean
ag_icon_view_change_item_selection(GtkListStore *model,
GtkTreePath *path,
GtkTreeIter *iter,
gboolean *selected)
{
gtk_list_store_set(model, iter, AG_ICON_VIEW_COLUMN_SELECTED, *selected, -1);
return FALSE;
}
void
ag_icon_view_select_all(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
gboolean selected = TRUE;
gtk_tree_model_foreach(
GTK_TREE_MODEL(priv->model),
(GtkTreeModelForeachFunc)ag_icon_view_change_item_selection,
&selected
);
ag_icon_view_selection_changed(icon_view);
}
void
ag_icon_view_unselect_all(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
gboolean selected = FALSE;
gtk_tree_model_foreach(
GTK_TREE_MODEL(priv->model),
(GtkTreeModelForeachFunc)ag_icon_view_change_item_selection,
&selected
);
ag_icon_view_selection_changed(icon_view);
}
AgDbChartSave *
ag_icon_view_get_chart_save_at_path(AgIconView *icon_view,
const GtkTreePath *path)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
GtkTreeIter iter;
AgDbChartSave *save_data;
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(priv->model), &iter, (GtkTreePath *)path)) {
gtk_tree_model_get(
GTK_TREE_MODEL(priv->model), &iter,
AG_ICON_VIEW_COLUMN_ITEM, &save_data,
-1
);
} else {
g_warning("Invalid tree path");
save_data = NULL;
}
return save_data;
}
void
ag_icon_view_remove_selected(AgIconView *icon_view)
{
AgIconViewPrivate *priv = ag_icon_view_get_instance_private(icon_view);
GList *paths = g_list_reverse(ag_icon_view_get_selected_items(icon_view)),
*l;
for (l = paths; l; l = g_list_next(l)) {
GtkTreeIter iter;
GtkTreePath *path = l->data;
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(priv->model), &iter, path)) {
gtk_list_store_remove(priv->model, &iter);
}
}
ag_icon_view_selection_changed(icon_view);
}

69
src/ag-icon-view.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef __AG_ICON_VIEW_H__
#define __AG_ICON_VIEW_H__
#include <gtk/gtk.h>
#include "ag-db.h"
G_BEGIN_DECLS
#define AG_TYPE_ICON_VIEW \
(ag_icon_view_get_type())
#define AG_ICON_VIEW(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
AG_TYPE_ICON_VIEW, \
AgIconView))
#define AG_ICON_VIEW_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
AG_TYPE_ICON_VIEW, \
AgIconViewClass))
#define IS_AG_ICON_VIEW(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
AG_TYPE_ICON_VIEW))
#define IS_AG_ICON_VIEW_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
AG_TYPE_ICON_VIEW))
#define AG_ICON_VIEW_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
AG_TYPE_ICON_VIEW, \
AgIconViewClass))
typedef struct _AgIconView AgIconView;
typedef struct _AgIconViewClass AgIconViewClass;
struct _AgIconViewClass
{
GtkIconViewClass parent_class;
};
struct _AgIconView
{
GtkIconView parent;
};
typedef enum {
AG_ICON_VIEW_MODE_NORMAL,
AG_ICON_VIEW_MODE_SELECTION
} AgIconViewMode;
GType ag_icon_view_get_type (void) G_GNUC_CONST;
void ag_icon_view_set_mode(AgIconView *icon_view, AgIconViewMode mode);
AgIconViewMode ag_icon_view_get_mode(AgIconView *icon_view);
void ag_icon_view_add_chart(AgIconView *icon_view, AgDbChartSave *chart_save);
GList *ag_icon_view_get_selected_items(AgIconView *icon_view);
AgDbChartSave *ag_icon_view_get_chart_save_at_path(AgIconView *icon_view, const GtkTreePath *path);
void ag_icon_view_select_all(AgIconView *icon_view);
void ag_icon_view_unselect_all(AgIconView *icon_view);
void ag_icon_view_remove_selected(AgIconView *icon_view);
G_END_DECLS
#endif /* __AG_ICON_VIEW_H__ */

View File

@ -22,8 +22,6 @@
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/tree.h> #include <libxml/tree.h>
#include <webkit2/webkit2.h> #include <webkit2/webkit2.h>
#include <libgd/gd-main-view.h>
#include <libgd/gd-main-view-generic.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <swe-glib.h> #include <swe-glib.h>
@ -35,6 +33,7 @@
#include "ag-settings.h" #include "ag-settings.h"
#include "ag-db.h" #include "ag-db.h"
#include "ag-display-theme.h" #include "ag-display-theme.h"
#include "ag-icon-view.h"
struct _AgWindowPrivate { struct _AgWindowPrivate {
GtkWidget *header_bar; GtkWidget *header_bar;
@ -72,12 +71,12 @@ struct _AgWindowPrivate {
GtkWidget *points_eq; GtkWidget *points_eq;
GtkAdjustment *year_adjust; GtkAdjustment *year_adjust;
GtkWidget *chart_list;
AgSettings *settings; AgSettings *settings;
AgChart *chart; AgChart *chart;
gboolean aspect_table_populated; gboolean aspect_table_populated;
GtkTextBuffer *note_buffer; GtkTextBuffer *note_buffer;
GtkListStore *house_system_model; GtkListStore *house_system_model;
GtkListStore *db_chart_data;
AgDbChartSave *saved_data; AgDbChartSave *saved_data;
GtkEntryCompletion *country_comp; GtkEntryCompletion *country_comp;
GtkEntryCompletion *city_comp; GtkEntryCompletion *city_comp;
@ -720,7 +719,7 @@ ag_window_recalculate_chart(AgWindow *window, gboolean set_everything)
gtk_spin_button_update(GTK_SPIN_BUTTON(current)); gtk_spin_button_update(GTK_SPIN_BUTTON(current));
} }
edit_data = g_new0(AgDbChartSave, 1); edit_data = ag_db_chart_save_new();
edit_data->db_id = db_id; edit_data->db_id = db_id;
@ -798,13 +797,13 @@ ag_window_recalculate_chart(AgWindow *window, gboolean set_everything)
if (ag_db_chart_save_identical(edit_data, chart_data, !set_everything)) { if (ag_db_chart_save_identical(edit_data, chart_data, !set_everything)) {
g_debug("No redrawing needed"); g_debug("No redrawing needed");
ag_db_chart_save_free(edit_data); ag_db_chart_save_unref(edit_data);
ag_db_chart_save_free(chart_data); ag_db_chart_save_unref(chart_data);
return; return;
} }
ag_db_chart_save_free(chart_data); ag_db_chart_save_unref(chart_data);
g_debug("Recalculating chart data"); g_debug("Recalculating chart data");
@ -846,7 +845,7 @@ ag_window_recalculate_chart(AgWindow *window, gboolean set_everything)
ag_chart_set_note(priv->chart, edit_data->note); ag_chart_set_note(priv->chart, edit_data->note);
} }
ag_db_chart_save_free(edit_data); ag_db_chart_save_unref(edit_data);
} }
static void static void
@ -1257,7 +1256,7 @@ ag_window_can_close(AgWindow *window, gboolean display_dialog)
} }
} }
ag_db_chart_save_free(save_data); ag_db_chart_save_unref(save_data);
return ret; return ret;
} }
@ -1289,7 +1288,7 @@ ag_window_save_action(GSimpleAction *action,
); );
} }
ag_db_chart_save_free(priv->saved_data); ag_db_chart_save_unref(priv->saved_data);
priv->saved_data = save_data; priv->saved_data = save_data;
} }
} }
@ -1644,7 +1643,7 @@ ag_window_back_action(GSimpleAction *action,
if (ag_window_can_close(window, TRUE)) { if (ag_window_can_close(window, TRUE)) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->toolbar_aspect), TRUE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->toolbar_aspect), TRUE);
g_clear_object(&(priv->chart)); g_clear_object(&(priv->chart));
ag_db_chart_save_free(priv->saved_data); ag_db_chart_save_unref(priv->saved_data);
priv->saved_data = NULL; priv->saved_data = NULL;
ag_window_load_chart_list(window); ag_window_load_chart_list(window);
@ -1662,30 +1661,23 @@ ag_window_refresh_action(GSimpleAction *action,
} }
static void static void
ag_window_selection_mode_action(GSimpleAction *action, ag_window_set_selection_mode(AgWindow *window, gboolean state)
GVariant *parameter,
gpointer user_data)
{ {
GVariant *state;
gboolean new_state;
GtkStyleContext *style; GtkStyleContext *style;
AgWindow *window = AG_WINDOW(user_data);
AgWindowPrivate *priv = ag_window_get_instance_private(window); AgWindowPrivate *priv = ag_window_get_instance_private(window);
state = g_action_get_state(G_ACTION(action));
new_state = !g_variant_get_boolean(state);
g_action_change_state(G_ACTION(action), g_variant_new_boolean(new_state));
g_variant_unref(state);
style = gtk_widget_get_style_context(priv->header_bar); style = gtk_widget_get_style_context(priv->header_bar);
if (new_state) { if (state) {
gtk_header_bar_set_show_close_button( gtk_header_bar_set_show_close_button(
GTK_HEADER_BAR(priv->header_bar), GTK_HEADER_BAR(priv->header_bar),
FALSE FALSE
); );
gtk_style_context_add_class(style, "selection-mode"); gtk_style_context_add_class(style, "selection-mode");
gd_main_view_set_selection_mode(GD_MAIN_VIEW(priv->tab_list), TRUE); ag_icon_view_set_mode(
AG_ICON_VIEW(priv->chart_list),
AG_ICON_VIEW_MODE_SELECTION
);
gtk_widget_hide(priv->new_back_stack); gtk_widget_hide(priv->new_back_stack);
gtk_stack_set_visible_child_name( gtk_stack_set_visible_child_name(
GTK_STACK(priv->menubutton_stack), GTK_STACK(priv->menubutton_stack),
@ -1697,7 +1689,10 @@ ag_window_selection_mode_action(GSimpleAction *action,
TRUE TRUE
); );
gtk_style_context_remove_class(style, "selection-mode"); gtk_style_context_remove_class(style, "selection-mode");
gd_main_view_set_selection_mode(GD_MAIN_VIEW(priv->tab_list), FALSE); ag_icon_view_set_mode(
AG_ICON_VIEW(priv->chart_list),
AG_ICON_VIEW_MODE_NORMAL
);
gtk_widget_show_all(priv->new_back_stack); gtk_widget_show_all(priv->new_back_stack);
gtk_stack_set_visible_child_name( gtk_stack_set_visible_child_name(
GTK_STACK(priv->menubutton_stack), GTK_STACK(priv->menubutton_stack),
@ -1706,6 +1701,42 @@ ag_window_selection_mode_action(GSimpleAction *action,
} }
} }
static void
ag_window_icon_view_mode_cb(AgIconView *icon_view,
GParamSpec *pspec,
AgWindow *window)
{
AgIconViewMode mode = ag_icon_view_get_mode(icon_view);
GVariant *state_var = g_variant_new_boolean(
(mode == AG_ICON_VIEW_MODE_SELECTION)
);
g_action_group_activate_action(
G_ACTION_GROUP(window),
"selection",
state_var
);
}
static void
ag_window_selection_mode_action(GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GVariant *state;
gboolean new_state;
AgWindow *window = AG_WINDOW(user_data);
state = g_action_get_state(G_ACTION(action));
new_state = !g_variant_get_boolean(state);
g_action_change_state(G_ACTION(action), g_variant_new_boolean(new_state));
g_variant_unref(state);
g_debug("Set selection mode: %d", new_state);
ag_window_set_selection_mode(window, new_state);
}
static void static void
ag_window_delete_action(GSimpleAction *action, ag_window_delete_action(GSimpleAction *action,
GVariant *parameter, GVariant *parameter,
@ -1713,31 +1744,20 @@ ag_window_delete_action(GSimpleAction *action,
{ {
GList *selection, GList *selection,
*item; *item;
GtkTreeModel *model;
AgWindow *window = AG_WINDOW(user_data); AgWindow *window = AG_WINDOW(user_data);
AgWindowPrivate *priv = ag_window_get_instance_private(window); AgWindowPrivate *priv = ag_window_get_instance_private(window);
AgDb *db = ag_db_get(); AgDb *db = ag_db_get();
selection = gd_main_view_get_selection(GD_MAIN_VIEW(priv->tab_list)); selection = ag_icon_view_get_selected_items(AG_ICON_VIEW(priv->chart_list));
model = gd_main_view_get_model(GD_MAIN_VIEW(priv->tab_list));
for (item = selection; item; item = g_list_next(item)) { for (item = selection; item; item = g_list_next(item)) {
GtkTreePath *path = item->data; GtkTreePath *path = item->data;
GtkTreeIter iter; GError *err = NULL;
gchar *id_str; AgDbChartSave *save_data;
gint id;
GError *err = NULL;
gtk_tree_model_get_iter(model, &iter, path); save_data = ag_icon_view_get_chart_save_at_path(AG_ICON_VIEW(priv->chart_list), path);
gtk_tree_model_get(
model, &iter,
GD_MAIN_COLUMN_ID, &id_str,
-1
);
id = atoi(id_str);
g_free(id_str);
if (!ag_db_chart_delete(db, id, &err)) { if (!ag_db_chart_delete(db, save_data->db_id, &err)) {
ag_app_message_dialog( ag_app_message_dialog(
GTK_WINDOW(window), GTK_WINDOW(window),
GTK_MESSAGE_ERROR, GTK_MESSAGE_ERROR,
@ -1749,6 +1769,8 @@ ag_window_delete_action(GSimpleAction *action,
} }
} }
ag_icon_view_remove_selected(AG_ICON_VIEW(priv->chart_list));
g_action_group_activate_action(G_ACTION_GROUP(window), "selection", NULL); g_action_group_activate_action(G_ACTION_GROUP(window), "selection", NULL);
g_action_group_activate_action(G_ACTION_GROUP(window), "refresh", NULL); g_action_group_activate_action(G_ACTION_GROUP(window), "refresh", NULL);
} }
@ -1827,7 +1849,7 @@ static GActionEntry win_entries[] = {
{ "new-chart", ag_window_new_chart_action, NULL, NULL, NULL }, { "new-chart", ag_window_new_chart_action, NULL, NULL, NULL },
{ "back", ag_window_back_action, NULL, NULL, NULL }, { "back", ag_window_back_action, NULL, NULL, NULL },
{ "refresh", ag_window_refresh_action, NULL, NULL, NULL }, { "refresh", ag_window_refresh_action, NULL, NULL, NULL },
{ "selection", ag_window_selection_mode_action, NULL, "false", NULL }, { "selection", ag_window_selection_mode_action, "b", "false", NULL },
{ "delete", ag_window_delete_action, NULL, NULL, NULL }, { "delete", ag_window_delete_action, NULL, NULL, NULL },
{ "connection", ag_window_connection_action, "s", "'aspects'", NULL }, { "connection", ag_window_connection_action, "s", "'aspects'", NULL },
}; };
@ -1878,15 +1900,14 @@ ag_window_add_display_theme(AgDisplayTheme *display_theme,
} }
static void static void
ag_window_list_item_activated_cb(GdMainView *view, ag_window_list_item_activated_cb(AgIconView *icon_view,
const gchar *id,
const GtkTreePath *path, const GtkTreePath *path,
AgWindow *window) AgWindow *window)
{ {
guint row_id = atoi(id);
AgWindowPrivate *priv = ag_window_get_instance_private(window); AgWindowPrivate *priv = ag_window_get_instance_private(window);
AgDb *db = ag_db_get(); AgDb *db = ag_db_get();
GError *err = NULL; GError *err = NULL;
AgDbChartSave *save_data;
if (priv->saved_data != NULL) { if (priv->saved_data != NULL) {
ag_app_message_dialog( ag_app_message_dialog(
@ -1902,11 +1923,17 @@ ag_window_list_item_activated_cb(GdMainView *view,
return; return;
} }
g_debug("Loading chart with ID %d", row_id); save_data = ag_icon_view_get_chart_save_at_path(icon_view, path);
if (save_data == NULL) {
return;
}
g_debug("Loading chart with ID %d", save_data->db_id);
if ((priv->saved_data = ag_db_chart_get_data_by_id( if ((priv->saved_data = ag_db_chart_get_data_by_id(
db, db,
row_id, save_data->db_id,
&err)) == NULL) { &err)) == NULL) {
ag_app_message_dialog( ag_app_message_dialog(
GTK_WINDOW(window), GTK_WINDOW(window),
@ -1931,7 +1958,7 @@ ag_window_list_item_activated_cb(GdMainView *view,
"Error: %s", "Error: %s",
err->message err->message
); );
ag_db_chart_save_free(priv->saved_data); ag_db_chart_save_unref(priv->saved_data);
priv->saved_data = NULL; priv->saved_data = NULL;
return; return;
@ -1943,13 +1970,13 @@ ag_window_list_item_activated_cb(GdMainView *view,
} }
static void static void
ag_window_list_selection_changed_cb(GdMainView *view, AgWindow *window) ag_window_list_selection_changed_cb(AgIconView *view, AgWindow *window)
{ {
GList *selection; GList *selection;
guint count; guint count;
AgWindowPrivate *priv = ag_window_get_instance_private(window); AgWindowPrivate *priv = ag_window_get_instance_private(window);
selection = gd_main_view_get_selection(view); selection = ag_icon_view_get_selected_items(view);
if ((count = g_list_length(selection)) > 0) { if ((count = g_list_length(selection)) > 0) {
gtk_revealer_set_reveal_child( gtk_revealer_set_reveal_child(
@ -2130,32 +2157,6 @@ ag_window_init(AgWindow *window)
NULL NULL
); );
priv->tab_list = GTK_WIDGET(gd_main_view_new(GD_MAIN_VIEW_ICON));
gtk_stack_add_titled(
GTK_STACK(priv->stack),
priv->tab_list,
"list",
"Chart list"
);
gd_main_view_set_selection_mode(GD_MAIN_VIEW(priv->tab_list), FALSE);
gd_main_view_set_model(
GD_MAIN_VIEW(priv->tab_list),
GTK_TREE_MODEL(priv->db_chart_data)
);
g_signal_connect(
priv->tab_list,
"item-activated",
G_CALLBACK(ag_window_list_item_activated_cb),
window
);
g_signal_connect(
priv->tab_list,
"view-selection-changed",
G_CALLBACK(ag_window_list_selection_changed_cb),
window
);
gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "list"); gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "list");
priv->current_tab = priv->tab_list; priv->current_tab = priv->tab_list;
@ -2402,12 +2403,35 @@ ag_window_display_theme_changed_cb(GtkComboBox *combo_box,
ag_window_set_theme(window, theme); ag_window_set_theme(window, theme);
} }
static void
ag_window_destroy(GtkWidget *widget)
{
AgWindowPrivate *priv = ag_window_get_instance_private(AG_WINDOW(widget));
// Destroy the signal handlers on priv->stack, as “tab” switching
// can cause trouble during destroy. However, this function might
// get called multiple times for the same object, in which case
// priv->stack is NULL.
if (priv->stack) {
g_signal_handlers_destroy(priv->stack);
}
GTK_WIDGET_CLASS(ag_window_parent_class)->destroy(widget);
}
static void
ag_window_selection_mode_cancel_cb(GtkButton *button, AgWindow *window)
{
ag_window_set_selection_mode(window, FALSE);
}
static void static void
ag_window_class_init(AgWindowClass *klass) ag_window_class_init(AgWindowClass *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass); GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
widget_class->destroy = ag_window_destroy;
gobject_class->dispose = ag_window_dispose; gobject_class->dispose = ag_window_dispose;
gtk_widget_class_set_template_from_resource( gtk_widget_class_set_template_from_resource(
@ -2429,11 +2453,6 @@ ag_window_class_init(AgWindowClass *klass)
AgWindow, AgWindow,
menubutton_stack menubutton_stack
); );
gtk_widget_class_bind_template_child_private(
widget_class,
AgWindow,
db_chart_data
);
gtk_widget_class_bind_template_child_private( gtk_widget_class_bind_template_child_private(
widget_class, widget_class,
AgWindow, AgWindow,
@ -2561,6 +2580,16 @@ ag_window_class_init(AgWindowClass *klass)
AgWindow, AgWindow,
toolbar_aspect toolbar_aspect
); );
gtk_widget_class_bind_template_child_private(
widget_class,
AgWindow,
tab_list
);
gtk_widget_class_bind_template_child_private(
widget_class,
AgWindow,
chart_list
);
gtk_widget_class_bind_template_callback( gtk_widget_class_bind_template_callback(
widget_class, widget_class,
@ -2586,6 +2615,22 @@ ag_window_class_init(AgWindowClass *klass)
widget_class, widget_class,
ag_window_display_theme_changed_cb ag_window_display_theme_changed_cb
); );
gtk_widget_class_bind_template_callback(
widget_class,
ag_window_list_item_activated_cb
);
gtk_widget_class_bind_template_callback(
widget_class,
ag_window_list_selection_changed_cb
);
gtk_widget_class_bind_template_callback(
widget_class,
ag_window_icon_view_mode_cb
);
gtk_widget_class_bind_template_callback(
widget_class,
ag_window_selection_mode_cancel_cb
);
} }
static gboolean static gboolean
@ -2657,7 +2702,7 @@ ag_window_set_chart(AgWindow *window, AgChart *chart)
g_clear_object(&(priv->chart)); g_clear_object(&(priv->chart));
} }
ag_db_chart_save_free(priv->saved_data); ag_db_chart_save_unref(priv->saved_data);
priv->chart = chart; priv->chart = chart;
g_signal_connect( g_signal_connect(
@ -2744,33 +2789,10 @@ ag_window_change_tab(AgWindow *window, const gchar *tab_name)
static void static void
ag_window_add_chart_to_list(AgDbChartSave *save_data, AgWindow *window) ag_window_add_chart_to_list(AgDbChartSave *save_data, AgWindow *window)
{
GtkTreeIter iter;
AgWindowPrivate *priv = ag_window_get_instance_private(window);
gchar *id = g_strdup_printf("%d", save_data->db_id);
gtk_list_store_append(priv->db_chart_data, &iter);
gtk_list_store_set(
priv->db_chart_data, &iter,
0, id, /* ID */
1, NULL, /* URI */
2, save_data->name, /* Primary text */
3, NULL, /* Secondary text */
4, NULL, /* Icon */
5, 0, /* mtime */
6, FALSE, /* Selected */
7, 0, /* Pulse */
-1
);
g_free(id);
}
static void
ag_window_clear_chart_list(AgWindow *window)
{ {
AgWindowPrivate *priv = ag_window_get_instance_private(window); AgWindowPrivate *priv = ag_window_get_instance_private(window);
gtk_list_store_clear(priv->db_chart_data); ag_icon_view_add_chart(AG_ICON_VIEW(priv->chart_list), save_data);
} }
gboolean gboolean
@ -2780,7 +2802,6 @@ ag_window_load_chart_list(AgWindow *window)
GError *err = NULL; GError *err = NULL;
GList *chart_list = ag_db_chart_get_list(db, &err); GList *chart_list = ag_db_chart_get_list(db, &err);
ag_window_clear_chart_list(window);
/* With only a few charts, this should be fine. Maybe implementing lazy /* With only a few charts, this should be fine. Maybe implementing lazy
* loading would be a better idea. See: * loading would be a better idea. See:
* http://blogs.gnome.org/ebassi/documentation/lazy-loading/ * http://blogs.gnome.org/ebassi/documentation/lazy-loading/

View File

@ -124,26 +124,6 @@
</object> </object>
<object class="GtkTextBuffer" id="note_buffer"> <object class="GtkTextBuffer" id="note_buffer">
</object> </object>
<object class="GtkListStore" id="db_chart_data">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name uri -->
<column type="gchararray"/>
<!-- column-name name -->
<column type="gchararray"/>
<!-- column-name secondary-text -->
<column type="gchararray"/>
<!-- column-name icon -->
<column type="GdkPixbuf"/>
<!-- column-name mtime -->
<column type="gint64"/>
<!-- column-name selected -->
<column type="gboolean"/>
<!-- column-name pulse -->
<column type="guint"/>
</columns>
</object>
<object class="GtkEntryCompletion" id="country_comp"> <object class="GtkEntryCompletion" id="country_comp">
<property name="inline_completion">True</property> <property name="inline_completion">True</property>
</object> </object>
@ -338,8 +318,8 @@
<object class="GtkButton"> <object class="GtkButton">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="action_name">win.selection</property>
<property name="label" translatable="yes">Cancel</property> <property name="label" translatable="yes">Cancel</property>
<signal name="clicked" handler="ag_window_selection_mode_cancel_cb" object="AgWindow" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@ -363,6 +343,21 @@
<property name="vexpand">True</property> <property name="vexpand">True</property>
<property name="hexpand">True</property> <property name="hexpand">True</property>
<signal name="notify::visible-child" handler="ag_window_tab_changed_cb" object="AgWindow" swapped="no"/> <signal name="notify::visible-child" handler="ag_window_tab_changed_cb" object="AgWindow" swapped="no"/>
<child>
<object class="GtkScrolledWindow" id="tab_list">
<child>
<object class="AgIconView" id="chart_list">
<signal name="item-activated" handler="ag_window_list_item_activated_cb" object="AgWindow" swapped="no"/>
<signal name="selection-changed" handler="ag_window_list_selection_changed_cb" object="AgWindow" swapped="no"/>
<signal name="notify::mode" handler="ag_window_icon_view_mode_cb" object="AgWindow" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="name">list</property>
<property name="title" translatable="yes">Chart list</property>
</packing>
</child>
<child> <child>
<object class="GtkGrid" id="tab_edit"> <object class="GtkGrid" id="tab_edit">
<property name="visible">True</property> <property name="visible">True</property>