diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 50 | ||||
-rw-r--r-- | src/app-menu.ui | 19 | ||||
-rw-r--r-- | src/gears-menu.ui | 16 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/org.sigxcpu.uplanfahr.gschema.xml | 20 | ||||
-rw-r--r-- | src/prefs.ui | 78 | ||||
-rw-r--r-- | src/tripview.ui | 103 | ||||
-rw-r--r-- | src/uplanfahr.c | 117 | ||||
-rw-r--r-- | src/uplanfahr.gresource.xml | 10 | ||||
-rw-r--r-- | src/uplanfahr.h | 19 | ||||
-rw-r--r-- | src/uplanfahrprefs.c | 79 | ||||
-rw-r--r-- | src/uplanfahrprefs.h | 20 | ||||
-rw-r--r-- | src/uplanfahrtripview.c | 149 | ||||
-rw-r--r-- | src/uplanfahrtripview.h | 17 | ||||
-rw-r--r-- | src/uplanfahrwin.c | 688 | ||||
-rw-r--r-- | src/uplanfahrwin.h | 23 | ||||
-rw-r--r-- | src/window.ui | 150 |
17 files changed, 1566 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..2dbeadc --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,50 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(WARN_CFLAGS) \ + $(GTK_CFLAGS) \ + $(LIBPLANFAHR_CFLAGS) + $(NULL) + +LDFLAGS = \ + $(GTK_LIBS) \ + $(LIBPLANFAHR_LIBS) \ + $(NULL) + +noinst_PROGRAMS = uplanfahr + +uplanfahr_SOURCES = \ + main.c \ + uplanfahr.c uplanfahr.h \ + uplanfahrwin.c uplanfahrwin.h \ + uplanfahrprefs.c uplanfahrprefs.h \ + uplanfahrtripview.c uplanfahrtripview.h \ + resources.c + +BUILT_SOURCES = \ + resources.c \ + gschemas.compiled + +resources.c: uplanfahr.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/uplanfahr.gresource.xml) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/uplanfahr.gresource.xml \ + --target=$@ --sourcedir=$(srcdir) --generate-source + +gsettings_SCHEMAS = \ + org.sigxcpu.uplanfahr.gschema.xml + +@GSETTINGS_RULES@ + +gschemas.compiled: org.sigxcpu.uplanfahr.gschema.xml + $(GLIB_COMPILE_SCHEMAS) . + +EXTRA_DIST = \ + window.ui \ + app-menu.ui \ + prefs.ui \ + gears-menu.ui \ + tripview.ui \ + uplanfahr.gresource.xml \ + org.sigxcpu.uplanfahr.gschema.xml + +CLEANFILES = \ + gschemas.compiled + diff --git a/src/app-menu.ui b/src/app-menu.ui new file mode 100644 index 0000000..b0eddb6 --- /dev/null +++ b/src/app-menu.ui @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <menu id="appmenu"> + <section> + <item> + <attribute name="label" translatable="yes">_Preferences</attribute> + <attribute name="action">app.preferences</attribute> + </item> + </section> + <section> + <item> + <attribute name="label" translatable="yes">_Quit</attribute> + <attribute name="action">app.quit</attribute> + <attribute name="accel"><![CDATA[<Ctrl>Q]]></attribute> + </item> + </section> + </menu> +</interface> diff --git a/src/gears-menu.ui b/src/gears-menu.ui new file mode 100644 index 0000000..fb0e929 --- /dev/null +++ b/src/gears-menu.ui @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <menu id="menu"> + <section> + <item> + <attribute name="label" translatable="yes">_Words</attribute> + <attribute name="action">win.show-words</attribute> + </item> + <item> + <attribute name="label" translatable="yes">_Lines</attribute> + <attribute name="action">win.show-lines</attribute> + </item> + </section> + </menu> +</interface> diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..be59b2d --- /dev/null +++ b/src/main.c @@ -0,0 +1,8 @@ +#include <gtk/gtk.h> +#include <uplanfahr.h> + +int +main (int argc, char *argv[]) +{ + return g_application_run (G_APPLICATION (u_plan_fahr_new ()), argc, argv); +} diff --git a/src/org.sigxcpu.uplanfahr.gschema.xml b/src/org.sigxcpu.uplanfahr.gschema.xml new file mode 100644 index 0000000..ca6af26 --- /dev/null +++ b/src/org.sigxcpu.uplanfahr.gschema.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<schemalist> + <schema path="/org/sigxcpu/uplanfahr/" id="org.sigxcpu.uplanfahr"> + <key name="font" type="s"> + <default>'Monospace 12'</default> + <summary>Font</summary> + <description>The font to be used for content.</description> + </key> + <key name="fullscreen" type="b"> + <default>false</default> + <summary>Fullscreen</summary> + <description>Whether to display the app fullscreen.</description> + </key> + <key name="show-words" type="b"> + <default>false</default> + <summary>Show words</summary> + <description>Whether to show a word list in the sidebar</description> + </key> + </schema> +</schemalist> diff --git a/src/prefs.ui b/src/prefs.ui new file mode 100644 index 0000000..833eb36 --- /dev/null +++ b/src/prefs.ui @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.8 --> + <template class="UPlanFahrPrefs" parent="GtkDialog"> + <property name="title" translatable="yes">Preferences</property> + <property name="resizable">False</property> + <property name="modal">True</property> + <child internal-child="vbox"> + <object class="GtkBox" id="vbox"> + <child> + <object class="GtkGrid" id="grid"> + <property name="visible">True</property> + <property name="margin">6</property> + <property name="row-spacing">12</property> + <property name="column-spacing">6</property> + <child> + <object class="GtkLabel" id="fontlabel"> + <property name="visible">True</property> + <property name="label">_Font:</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">font</property> + <property name="xalign">1</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkFontButton" id="font"> + <property name="visible">True</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="fullscreenlabel"> + <property name="visible">True</property> + <property name="label">_Fullscreen:</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">fullscreen</property> + <property name="xalign">1</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">1</property> + </packing> + </child> + <child> + <object class="GtkSwitch" id="fullscreen"> + <property name="visible">True</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">1</property> + </packing> + </child> + </object> + </child> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="action_area"> + <property name="visible">True</property> + <child> + <object class="GtkButton" id="close"> + <signal name="clicked" handler="preferences_closed"/> + <property name="visible">True</property> + <property name="label">_Close</property> + <property name="use-underline">True</property> + </object> + </child> + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/src/tripview.ui b/src/tripview.ui new file mode 100644 index 0000000..f4542ec --- /dev/null +++ b/src/tripview.ui @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.16.1 --> +<interface> + <requires lib="gtk+" version="3.10"/> + <object class="GtkListStore" id="liststore"> + <columns> + <!-- column-name start --> + <column type="LpfStop"/> + <!-- column-name end --> + <column type="LpfStop"/> + <!-- column-name departure_time --> + <column type="gchararray"/> + <!-- column-name arrival_time --> + <column type="gchararray"/> + <!-- column-name switches --> + <column type="gint"/> + <!-- column-name departure_delay --> + <column type="gchararray"/> + <!-- column-name arrival_delay --> + <column type="gchararray"/> + </columns> + </object> + <template class="UPlanFahrTripView" parent="GtkTreeView"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="model">liststore</property> + <property name="headers_clickable">False</property> + <property name="enable_search">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection1"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_departure_time"> + <property name="title" translatable="yes">Departure_time</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererText" id="cr_departure_time"/> + <attributes> + <attribute name="markup">2</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_departure_delay"> + <property name="title" translatable="yes">Delay</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererText" id="cr_departure_delay"/> + <attributes> + <attribute name="markup">5</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_arrival_time"> + <property name="title" translatable="yes">Arrival_time</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererText" id="cr_arrival_time"/> + <attributes> + <attribute name="markup">3</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_arrival_delay"> + <property name="title" translatable="yes">Delay</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererText" id="cr_arrivaL_delay"/> + <attributes> + <attribute name="markup">6</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_switches"> + <property name="title" translatable="yes">Switches</property> + <property name="alignment">0.5</property> + <child> + <object class="GtkCellRendererText" id="cr_switches"/> + <attributes> + <attribute name="markup">4</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="col_status"> + <property name="title" translatable="yes">Status</property> + <property name="alignment">0.5</property> + <property name="reorderable">True</property> + <child> + <object class="GtkCellRendererPixbuf" id="cr_status"/> + </child> + </object> + </child> + </template> +</interface> diff --git a/src/uplanfahr.c b/src/uplanfahr.c new file mode 100644 index 0000000..e87d25e --- /dev/null +++ b/src/uplanfahr.c @@ -0,0 +1,117 @@ +#include <gtk/gtk.h> + +#include "uplanfahr.h" +#include "uplanfahrwin.h" +#include "uplanfahrprefs.h" + +struct _UPlanFahr +{ + GtkApplication parent; +}; + +struct _UPlanFahrClass +{ + GtkApplicationClass parent_class; +}; + +G_DEFINE_TYPE(UPlanFahr, u_plan_fahr, GTK_TYPE_APPLICATION); + +static void +u_plan_fahr_init (UPlanFahr *app) +{ +} + +static void +preferences_activated (GSimpleAction *action, + GVariant *parameter, + gpointer app) +{ + UPlanFahrPrefs *prefs; + GtkWindow *win; + + win = gtk_application_get_active_window (GTK_APPLICATION (app)); + prefs = u_plan_fahr_prefs_new (U_PLAN_FAHR_WINDOW (win)); + gtk_window_present (GTK_WINDOW (prefs)); +} + +static void +quit_activated (GSimpleAction *action, + GVariant *parameter, + gpointer app) +{ + g_application_quit (G_APPLICATION (app)); +} + +static GActionEntry app_entries[] = +{ + { "preferences", preferences_activated, NULL, NULL, NULL, {0, 0, 0} }, + { "quit", quit_activated, NULL, NULL, NULL, {0, 0, 0} } +}; + +static void +u_plan_fahr_startup (GApplication *app) +{ + GtkBuilder *builder; + GMenuModel *app_menu; + + G_APPLICATION_CLASS (u_plan_fahr_parent_class)->startup (app); + + g_action_map_add_action_entries (G_ACTION_MAP (app), + app_entries, G_N_ELEMENTS (app_entries), + app); + + builder = gtk_builder_new_from_resource ("/org/sigxcpu/uplanfahr/app-menu.ui"); + app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu")); + gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu); + g_object_unref (builder); +} + +static void +u_plan_fahr_activate (GApplication *app) +{ + UPlanFahrWindow *win; + + win = u_plan_fahr_window_new (U_PLAN_FAHR (app)); + gtk_window_present (GTK_WINDOW (win)); +} + +static void +u_plan_fahr_open (GApplication *app, + GFile **args, + gint n_files, + const gchar *hint) +{ + GList *windows; + UPlanFahrWindow *win; + int i; + + windows = gtk_application_get_windows (GTK_APPLICATION (app)); + if (windows) + win = U_PLAN_FAHR_WINDOW (windows->data); + else + win = u_plan_fahr_window_new (U_PLAN_FAHR (app)); + + if (n_files % 2 == 0) { + for (i = 0; i < n_files; i+=2) + u_plan_fahr_window_open (win, args[i], args[i+1]); + } + + gtk_window_present (GTK_WINDOW (win)); +} + +static void +u_plan_fahr_class_init (UPlanFahrClass *class) +{ + G_APPLICATION_CLASS (class)->startup = u_plan_fahr_startup; + G_APPLICATION_CLASS (class)->activate = u_plan_fahr_activate; + G_APPLICATION_CLASS (class)->open = u_plan_fahr_open; +} + +UPlanFahr * +u_plan_fahr_new (void) +{ + return g_object_new (U_PLAN_FAHR_TYPE, + "application-id", "org.sigxcpu.org.uplanfahr", + "flags", G_APPLICATION_HANDLES_OPEN, + NULL); +} diff --git a/src/uplanfahr.gresource.xml b/src/uplanfahr.gresource.xml new file mode 100644 index 0000000..0248133 --- /dev/null +++ b/src/uplanfahr.gresource.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/sigxcpu/uplanfahr"> + <file preprocess="xml-stripblanks">window.ui</file> + <file preprocess="xml-stripblanks">app-menu.ui</file> + <file preprocess="xml-stripblanks">gears-menu.ui</file> + <file preprocess="xml-stripblanks">tripview.ui</file> + <file preprocess="xml-stripblanks">prefs.ui</file> + </gresource> +</gresources> diff --git a/src/uplanfahr.h b/src/uplanfahr.h new file mode 100644 index 0000000..5ce2c5a --- /dev/null +++ b/src/uplanfahr.h @@ -0,0 +1,19 @@ +#ifndef __UPLANFAHR_H +#define __UPLANFAHR_H + +#include <gtk/gtk.h> + + +#define U_PLAN_FAHR_TYPE (u_plan_fahr_get_type ()) +#define U_PLAN_FAHR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), U_PLAN_FAHR_TYPE, UPlanFahr)) + + +typedef struct _UPlanFahr UPlanFahr; +typedef struct _UPlanFahrClass UPlanFahrClass; + + +GType u_plan_fahr_get_type (void); +UPlanFahr *u_plan_fahr_new (void); + + +#endif /* __UPLANFAHR_H */ diff --git a/src/uplanfahrprefs.c b/src/uplanfahrprefs.c new file mode 100644 index 0000000..49b5f05 --- /dev/null +++ b/src/uplanfahrprefs.c @@ -0,0 +1,79 @@ +#include <gtk/gtk.h> + +#include "uplanfahr.h" +#include "uplanfahrwin.h" +#include "uplanfahrprefs.h" + +struct _UPlanFahrPrefs +{ + GtkDialog parent; +}; + +struct _UPlanFahrPrefsClass +{ + GtkDialogClass parent_class; +}; + +typedef struct _UPlanFahrPrefsPrivate UPlanFahrPrefsPrivate; + +struct _UPlanFahrPrefsPrivate +{ + GSettings *settings; + GtkWidget *font; + GtkWidget *fullscreen; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(UPlanFahrPrefs, u_plan_fahr_prefs, GTK_TYPE_DIALOG) + +static void +preferences_closed (GtkWidget *button) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (button)); +} + +static void +u_plan_fahr_prefs_init (UPlanFahrPrefs *prefs) +{ + UPlanFahrPrefsPrivate *priv; + + priv = u_plan_fahr_prefs_get_instance_private (prefs); + gtk_widget_init_template (GTK_WIDGET (prefs)); + priv->settings = g_settings_new ("org.sigxcpu.uplanfahr"); + + g_settings_bind (priv->settings, "font", + priv->font, "font", + G_SETTINGS_BIND_DEFAULT); + g_settings_bind (priv->settings, "fullscreen", + priv->fullscreen, "active", + G_SETTINGS_BIND_DEFAULT); +} + +static void +u_plan_fahr_prefs_dispose (GObject *object) +{ + UPlanFahrPrefsPrivate *priv; + + priv = u_plan_fahr_prefs_get_instance_private (U_PLAN_FAHR_PREFS (object)); + g_clear_object (&priv->settings); + + G_OBJECT_CLASS (u_plan_fahr_prefs_parent_class)->dispose (object); +} + +static void +u_plan_fahr_prefs_class_init (UPlanFahrPrefsClass *class) +{ + G_OBJECT_CLASS (class)->dispose = u_plan_fahr_prefs_dispose; + + gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class), + "/org/sigxcpu/uplanfahr/prefs.ui"); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrPrefs, font); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrPrefs, fullscreen); + + gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), preferences_closed); +} + +UPlanFahrPrefs * +u_plan_fahr_prefs_new (UPlanFahrWindow *win) +{ + return g_object_new (U_PLAN_FAHR_PREFS_TYPE, "transient-for", win, NULL); +} diff --git a/src/uplanfahrprefs.h b/src/uplanfahrprefs.h new file mode 100644 index 0000000..3e8a302 --- /dev/null +++ b/src/uplanfahrprefs.h @@ -0,0 +1,20 @@ +#ifndef __UPLANFAHRPREFS_H +#define __UPLANFAHRPREFS_H + +#include <gtk/gtk.h> +#include "uplanfahrwin.h" + + +#define U_PLAN_FAHR_PREFS_TYPE (u_plan_fahr_prefs_get_type ()) +#define U_PLAN_FAHR_PREFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), U_PLAN_FAHR_PREFS_TYPE, UPlanFahrPrefs)) + + +typedef struct _UPlanFahrPrefs UPlanFahrPrefs; +typedef struct _UPlanFahrPrefsClass UPlanFahrPrefsClass; + + +GType u_plan_fahr_prefs_get_type (void); +UPlanFahrPrefs *u_plan_fahr_prefs_new (UPlanFahrWindow *win); + + +#endif /* __UPLANFAHRPREFS_H */ diff --git a/src/uplanfahrtripview.c b/src/uplanfahrtripview.c new file mode 100644 index 0000000..d36673a --- /dev/null +++ b/src/uplanfahrtripview.c @@ -0,0 +1,149 @@ +#include <gtk/gtk.h> + +#include <libplanfahr/libplanfahr.h> + +#include "uplanfahr.h" +#include "uplanfahrtripview.h" + +#define COL_START 0 +#define COL_END 1 +#define COL_DEPARTURE_TIME 2 +#define COL_ARRIVAL_TIME 3 +#define COL_PARTS 4 +#define COL_DEPARTURE_DELAY 5 +#define COL_ARRIVAL_DELAY 6 + +struct _UPlanFahrTripView +{ + GtkTreeView parent; +}; + +struct _UPlanFahrTripViewClass +{ + GtkTreeViewClass parent_class; +}; + +typedef struct _UPlanFahrTripViewPrivate UPlanFahrTripViewPrivate; + +struct _UPlanFahrTripViewPrivate +{ + GtkListStore *liststore; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(UPlanFahrTripView, u_plan_fahr_trip_view, GTK_TYPE_TREE_VIEW) + +static void +u_plan_fahr_trip_view_init (UPlanFahrTripView *trip_view) +{ + gtk_widget_init_template (GTK_WIDGET (trip_view)); +} + +static void +u_plan_fahr_trip_view_dispose (GObject *object) +{ + G_OBJECT_CLASS (u_plan_fahr_trip_view_parent_class)->dispose (object); +} + +static void +u_plan_fahr_trip_view_class_init (UPlanFahrTripViewClass *class) +{ + G_OBJECT_CLASS (class)->dispose = u_plan_fahr_trip_view_dispose; + + gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class), + "/org/sigxcpu/uplanfahr/tripview.ui"); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrTripView, liststore); +} + +GtkWidget * +u_plan_fahr_trip_view_new (void) +{ + return g_object_new (U_PLAN_FAHR_TRIP_VIEW_TYPE, NULL); +} + +static gchar * +delay_str (GDateTime *dt, gint delay) +{ + gchar sign, *str = NULL; + + if (dt) { + if (delay > 0) { + sign = '+'; + } else if (delay < 0) { + sign = '-'; + } else { + sign = ' '; + } + str = g_strdup_printf("%c%d", sign, delay); + } + + return str; +} + +void +u_plan_fahr_trip_view_store_trips (UPlanFahrTripView *self, GSList *trips) +{ + UPlanFahrTripViewPrivate *priv; + GtkTreeIter iter; + + GSList *parts; + LpfTrip *tripobj; + LpfTripPart *firstpart, *lastpart; + LpfStop *start, *end; + GDateTime *arrival, *departure, *rt_departure, *rt_arrival; + gchar *deptime, *arrtime, *dep_delay, *arr_delay; + gint ddelay, adelay; + + priv = u_plan_fahr_trip_view_get_instance_private (U_PLAN_FAHR_TRIP_VIEW (self)); + + gtk_list_store_clear (priv->liststore); + for (; trips; trips = g_slist_next (trips)) { + tripobj = trips->data; + g_object_get(tripobj, "parts", &parts, NULL); + + firstpart = LPF_TRIP_PART(parts->data); + lastpart = LPF_TRIP_PART(g_slist_last (parts)->data); + + g_object_get (firstpart, "start", &start, NULL); + g_object_get (start, + "departure", &departure, + "departure_delay", &ddelay, + "rt_departure", &rt_departure, + NULL); + deptime = g_date_time_format (departure, "%H:%M"); + + g_object_get (lastpart, "end", &end, NULL); + g_object_get (end, + "arrival", &arrival, + "arrival_delay", &adelay, + "rt_arrival", &rt_arrival, + NULL); + arrtime = g_date_time_format (arrival, "%H:%M"); + + dep_delay = delay_str (rt_departure, ddelay); + arr_delay = delay_str (rt_arrival, adelay); + + gtk_list_store_append (priv->liststore, &iter); + gtk_list_store_set (priv->liststore, &iter, + COL_START, start, + COL_END, end, + COL_DEPARTURE_TIME, deptime, + COL_ARRIVAL_TIME, arrtime, + COL_PARTS, g_slist_length(parts) - 1, + COL_DEPARTURE_DELAY, dep_delay, + COL_ARRIVAL_DELAY, arr_delay, + -1); + + g_date_time_unref (departure); + g_date_time_unref (arrival); + g_object_unref (start); + g_object_unref (end); + if (rt_departure) + g_date_time_unref (rt_departure); + if (rt_arrival) + g_date_time_unref (rt_arrival); + g_free (deptime); + g_free (arrtime); + g_free (dep_delay); + g_free (arr_delay); + } +} diff --git a/src/uplanfahrtripview.h b/src/uplanfahrtripview.h new file mode 100644 index 0000000..828d99c --- /dev/null +++ b/src/uplanfahrtripview.h @@ -0,0 +1,17 @@ +#ifndef __UPLANFAHRTRIPVIEW_H +#define __UPLANFAHRTRIPVIEW_H + +#include <gtk/gtk.h> +#include "uplanfahrwin.h" + +#define U_PLAN_FAHR_TRIP_VIEW_TYPE (u_plan_fahr_trip_view_get_type ()) +#define U_PLAN_FAHR_TRIP_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), U_PLAN_FAHR_TRIP_VIEW_TYPE, UPlanFahrTripView)) + +typedef struct _UPlanFahrTripView UPlanFahrTripView; +typedef struct _UPlanFahrTripViewClass UPlanFahrTripViewClass; + +GType u_plan_fahr_trip_view_get_type (void); +GtkWidget *u_plan_fahr_trip_view_new (void); +void u_plan_fahr_trip_view_store_trips (UPlanFahrTripView *self, GSList *trips); + +#endif /* __UPLANFAHRTRIPVIEW_H */ diff --git a/src/uplanfahrwin.c b/src/uplanfahrwin.c new file mode 100644 index 0000000..1e4301d --- /dev/null +++ b/src/uplanfahrwin.c @@ -0,0 +1,688 @@ +#include "config.h" + +#include <string.h> + +#include <gtk/gtk.h> +#include <libplanfahr/libplanfahr.h> + +#include "uplanfahr.h" +#include "uplanfahrwin.h" +#include "uplanfahrtripview.h" + +LpfProvider *provider; +LpfManager *manager; + +struct _UPlanFahrWindow +{ + GtkApplicationWindow parent; +}; + +struct _UPlanFahrWindowClass +{ + GtkApplicationWindowClass parent_class; +}; + +typedef struct _UPlanFahrWindowPrivate UPlanFahrWindowPrivate; + +struct _UPlanFahrWindowPrivate +{ + GSettings *settings; + GtkWidget *stack; + GtkWidget *search; + GtkWidget *searchbar; + GtkWidget *searchentry; + GtkWidget *gears; + GtkWidget *sidebar; + GtkWidget *words; + GtkWidget *lines; + GtkWidget *lines_label; + GtkWidget *popover; + GtkWidget *listbox; + GtkWidget *start_radiobutton; + GtkWidget *tripview; + + gboolean fullscreen; + guint searchentry_pulse_id; +}; + +enum { + LPF_STOP_PROP_0 = 0, + U_PLAN_FAHR_WINDOW_PROP_FULLSCREEN, +}; + +G_DEFINE_TYPE_WITH_PRIVATE(UPlanFahrWindow, u_plan_fahr_window, GTK_TYPE_APPLICATION_WINDOW); + + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UPlanFahrWindow *self = U_PLAN_FAHR_WINDOW (object); + UPlanFahrWindowPrivate *priv; + + priv = u_plan_fahr_window_get_instance_private (self); + + switch (property_id) { + case U_PLAN_FAHR_WINDOW_PROP_FULLSCREEN: + priv->fullscreen = g_value_get_boolean (value); + if (priv->fullscreen) + gtk_window_fullscreen (GTK_WINDOW(self)); + else + gtk_window_unfullscreen (GTK_WINDOW(self)); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UPlanFahrWindow *self = U_PLAN_FAHR_WINDOW (object); + UPlanFahrWindowPrivate *priv; + + priv = u_plan_fahr_window_get_instance_private (self); + + switch (property_id) { + case U_PLAN_FAHR_WINDOW_PROP_FULLSCREEN: + g_value_set_boolean (value, priv->fullscreen); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +static gboolean +window_key_press_event_cb (GtkWidget *win, + GdkEvent *event, + GtkSearchBar *searchbar) +{ + return gtk_search_bar_handle_event (searchbar, event); +} + + +static void +got_trips (GSList *trips, gpointer user_data, GError *err) +{ + GtkWidget *view = user_data; + + if (err) { + g_warning ("%s", err->message); + return; + } + + g_message ("Found %d trips", g_slist_length (trips)); + + u_plan_fahr_trip_view_store_trips (U_PLAN_FAHR_TRIP_VIEW(view), trips); +} + + +static gboolean +u_planfahr_get_trips_cb (gpointer user_data) +{ + LpfLoc *start, *end; + GDateTime *when; + GtkWidget *view = GTK_WIDGET(user_data); + + start = g_object_get_data (G_OBJECT(view), "start"); + end = g_object_get_data (G_OBJECT(view), "end"); + when = g_date_time_new_now_local (); + + if (start && end && when) { + g_message ("Looking for trip from %s to %s", lpf_loc_get_name (start), lpf_loc_get_name (end)); + lpf_provider_get_trips (provider, start, end, when, 0, got_trips, view); + } else { + g_message("Missing info"); + } + return G_SOURCE_CONTINUE; +} + + +static void +u_planfahr_get_trips (GtkWidget *view) +{ + u_planfahr_get_trips_cb (view); + g_timeout_add_seconds (30, u_planfahr_get_trips_cb, view); +} + + +static void +set_loc (LpfLoc *loc, GtkWidget *view, gboolean is_start) +{ + const char *type = is_start ? "start" : "end"; + + g_object_set_data (G_OBJECT(view), type, loc); +} + + +static LpfLoc* +get_loc (GtkWidget *view, gboolean is_start) +{ + const char *type = is_start ? "start" : "end"; + + return LPF_LOC(g_object_get_data (G_OBJECT(view), type)); +} + + +static void +update_title (UPlanFahrWindowPrivate *priv) +{ + GtkWidget *tab, *view; + LpfLoc *start, *end; + gchar *title; + + tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); + view = gtk_bin_get_child (GTK_BIN (tab)); + + start = get_loc (view, TRUE); + end = get_loc (view, FALSE); + + title = g_strdup_printf ("%s ⇨ %s", lpf_loc_get_name(start), lpf_loc_get_name(end)); + + gtk_container_child_set(GTK_CONTAINER(priv->stack), tab, "title", title, NULL); + + g_free (title); +} + + +static void +row_activated (GtkListBox *listbox G_GNUC_UNUSED, GtkListBoxRow *row, gpointer user_data) +{ + UPlanFahrWindowPrivate *priv = user_data; + LpfLoc *loc; + gchar *name; + GtkWidget *tab, *view; + gboolean is_start; + + if (row == NULL) + return; + + is_start = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(priv->start_radiobutton)); + + loc = LPF_LOC(g_object_get_data (G_OBJECT(row), "loc")); + g_return_if_fail (loc != NULL); + + g_object_get (loc, "name", &name, NULL); + g_message ("Row activated %s", name); + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR(priv->searchbar), FALSE); + + tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); + view = gtk_bin_get_child (GTK_BIN (tab)); + + set_loc (loc, view, is_start); + update_title (priv); + + u_planfahr_get_trips (view); + + gtk_widget_hide (GTK_WIDGET(priv->popover)); + g_free (name); +} + + +static void +clear_search_popover(UPlanFahrWindowPrivate *priv) +{ + GList *iter, *children; + + children = gtk_container_get_children(GTK_CONTAINER(priv->listbox)); + for(iter = children; iter != NULL; iter = g_list_next(iter)) + gtk_container_remove(GTK_CONTAINER(priv->listbox), GTK_WIDGET(iter->data)); + g_list_free(children); +} + + +static void +popover_closed (GtkPopover *popover, UPlanFahrWindowPrivate *priv) +{ + /* popup closed without selection, back to searchentry */ + gtk_widget_grab_focus (priv->searchentry); + gtk_editable_set_position (GTK_EDITABLE(priv->searchentry), -1); +} + +static gboolean +searchentry_pulse_step(GtkEntry *entry) +{ + gtk_entry_progress_pulse (entry); + return TRUE; +} + + +static void +searchentry_start_progressbar (UPlanFahrWindowPrivate *priv) +{ + gtk_entry_set_progress_pulse_step (GTK_ENTRY(priv->searchentry), 0.25); + searchentry_pulse_step (GTK_ENTRY (priv->searchentry)); + if (!priv->searchentry_pulse_id) + priv->searchentry_pulse_id = g_timeout_add_seconds (1, (GSourceFunc)searchentry_pulse_step, GTK_ENTRY(priv->searchentry)); +} + + +static void +searchentry_stop_progressbar (UPlanFahrWindowPrivate *priv) +{ + if (priv->searchentry_pulse_id) + g_source_remove (priv->searchentry_pulse_id); + gtk_entry_set_progress_pulse_step (GTK_ENTRY(priv->searchentry), 0); + priv->searchentry_pulse_id = 0; +} + + +static void +populate_search_popover(GSList *locs, gpointer user_data, GError *err) +{ + UPlanFahrWindow *win; + UPlanFahrWindowPrivate *priv; + GtkEntry *entry = GTK_ENTRY(user_data); + GtkWidget *label, *row; + LpfLoc *loc; + GSList *iter; + gchar *name; + + win = U_PLAN_FAHR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (entry))); + priv = u_plan_fahr_window_get_instance_private (win); + + if (err) { + g_warning ("%s", err->message); + return; + } + + g_message("Found %d locs", g_slist_length(locs)); + for (iter = locs; iter; iter = g_slist_next (iter)) { + loc = iter->data; + g_object_get (loc, "name", &name, NULL); + label = gtk_label_new(name); + row = gtk_list_box_row_new (); + g_object_set_data (G_OBJECT(row), "loc", loc); + gtk_container_add (GTK_CONTAINER(row), label); + gtk_list_box_insert (GTK_LIST_BOX(priv->listbox), row, -1); + } + + row = GTK_WIDGET (gtk_list_box_get_row_at_index (GTK_LIST_BOX(priv->listbox), 0)); + gtk_list_box_select_row ( GTK_LIST_BOX(priv->listbox), GTK_LIST_BOX_ROW(row)); + + searchentry_stop_progressbar (priv); + + gtk_widget_show_all (priv->popover); +} + + +static void +trigger_populate_search_popover(UPlanFahrWindowPrivate *priv, const gchar *text) +{ + g_message ("Searching for %s", text); + lpf_provider_get_locs (provider, text, 0, populate_search_popover, priv->searchentry); + searchentry_start_progressbar (priv); +} + + +static void +searchentry_text_changed (GtkEntry *entry) +{ + UPlanFahrWindow *win; + UPlanFahrWindowPrivate *priv; + const gchar *text; + + win = U_PLAN_FAHR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (entry))); + priv = u_plan_fahr_window_get_instance_private (win); + + clear_search_popover(priv); + text = gtk_entry_get_text (entry); + + if (text[0] == '\0') { + gtk_widget_hide (priv->popover); + return; + } + + searchentry_start_progressbar (priv); + + trigger_populate_search_popover (priv, text); +} + + +static void +update_words (UPlanFahrWindow *win) +{ +#if 0 + UPlanFahrWindowPrivate *priv; + GHashTable *strings; + GHashTableIter iter; + GtkWidget *tab, *view, *row; + GtkTextBuffer *buffer; + GtkTextIter start, end; + GList *children, *l; + gchar *word, *key; + + priv = u_plan_fahr_window_get_instance_private (win); + + tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); + + if (tab == NULL) + return; + + view = gtk_bin_get_child (GTK_BIN (tab)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + gtk_text_buffer_get_start_iter (buffer, &start); + while (!gtk_text_iter_is_end (&start)) + { + while (!gtk_text_iter_starts_word (&start)) + { + if (!gtk_text_iter_forward_char (&start)) + goto done; + } + end = start; + if (!gtk_text_iter_forward_word_end (&end)) + goto done; + word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); + g_hash_table_add (strings, g_utf8_strdown (word, -1)); + g_free (word); + start = end; + } + + done: + children = gtk_container_get_children (GTK_CONTAINER (priv->words)); + for (l = children; l; l = l->next) + gtk_container_remove (GTK_CONTAINER (priv->words), GTK_WIDGET (l->data)); + g_list_free (children); + + g_hash_table_iter_init (&iter, strings); + while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL)) + { + row = gtk_button_new_with_label (key); + g_signal_connect (row, "clicked", + G_CALLBACK (find_word), win); + gtk_widget_show (row); + gtk_container_add (GTK_CONTAINER (priv->words), row); + } + + g_hash_table_unref (strings); +#endif +} + + +static void +update_lines (UPlanFahrWindow *win) +{ +#if 0 + UPlanFahrWindowPrivate *priv; + GtkWidget *tab, *view; + GtkTextBuffer *buffer; + GtkTextIter iter; + int count; + gchar *lines; + + priv = u_plan_fahr_window_get_instance_private (win); + + tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); + + if (tab == NULL) + return; + + view = gtk_bin_get_child (GTK_BIN (tab)); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + count = 0; + + gtk_text_buffer_get_start_iter (buffer, &iter); + while (!gtk_text_iter_is_end (&iter)) + { + count++; + if (!gtk_text_iter_forward_line (&iter)) + break; + } + + lines = g_strdup_printf ("%d", count); + gtk_label_set_text (GTK_LABEL (priv->lines), lines); + g_free (lines); +#endif +} + + +static void +visible_child_changed (GObject *stack, + GParamSpec *pspec) +{ +#if 0 + UPlanFahrWindow *win; + UPlanFahrWindowPrivate *priv; + + if (gtk_widget_in_destruction (GTK_WIDGET (stack))) + return; + + win = U_PLAN_FAHR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (stack))); + priv = u_plan_fahr_window_get_instance_private (win); + gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->searchbar), FALSE); + update_words (win); + update_lines (win); +#endif +} + + +static void +words_changed (GObject *sidebar, + GParamSpec *pspec, + UPlanFahrWindow *win) +{ + update_words (win); +} + + +static void +u_plan_fahr_window_init (UPlanFahrWindow *win) +{ + UPlanFahrWindowPrivate *priv; + GtkBuilder *builder; + GMenuModel *menu; + GAction *action; + + priv = u_plan_fahr_window_get_instance_private (win); + gtk_widget_init_template (GTK_WIDGET (win)); + priv->settings = g_settings_new ("org.sigxcpu.uplanfahr"); + + g_settings_bind (priv->settings, "fullscreen", + win, "fullscreen", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind (priv->settings, "show-words", + priv->sidebar, "reveal-child", + G_SETTINGS_BIND_DEFAULT); + + g_object_bind_property (priv->search, "active", + priv->searchbar, "search-mode-enabled", + G_BINDING_BIDIRECTIONAL); + + g_signal_connect (priv->sidebar, "notify::reveal-child", + G_CALLBACK (words_changed), win); + + builder = gtk_builder_new_from_resource ("/org/sigxcpu/uplanfahr/gears-menu.ui"); + menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu")); + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gears), menu); + g_object_unref (builder); + + action = g_settings_create_action (priv->settings, "show-words"); + g_action_map_add_action (G_ACTION_MAP (win), action); + g_object_unref (action); + + action = (GAction*) g_property_action_new ("show-lines", priv->lines, "visible"); + g_action_map_add_action (G_ACTION_MAP (win), action); + g_object_unref (action); + + g_object_bind_property (priv->lines, "visible", + priv->lines_label, "visible", + G_BINDING_DEFAULT); + + gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE); + + /* search bar and popup */ + priv->listbox = gtk_list_box_new (); + + priv->popover = gtk_popover_new (GTK_WIDGET (priv->searchentry)); + gtk_style_context_add_class (gtk_widget_get_style_context (priv->popover), + GTK_STYLE_CLASS_OSD); + gtk_popover_set_position (GTK_POPOVER(priv->popover), GTK_POS_BOTTOM); + gtk_popover_set_modal (GTK_POPOVER (priv->popover), FALSE); + gtk_container_add (GTK_CONTAINER (priv->popover), + priv->listbox); + gtk_container_set_border_width (GTK_CONTAINER (priv->popover), 4); + + g_signal_connect (priv->popover, "closed", + G_CALLBACK (popover_closed), priv); + + g_signal_connect (priv->listbox, "row-activated", + G_CALLBACK (row_activated), priv); + + g_signal_connect (win, "key-press-event", + G_CALLBACK (window_key_press_event_cb), priv->searchbar); + + gtk_widget_show (priv->listbox); +} + + +static void +u_plan_fahr_window_dispose (GObject *object) +{ + UPlanFahrWindow *win; + UPlanFahrWindowPrivate *priv; + + win = U_PLAN_FAHR_WINDOW (object); + priv = u_plan_fahr_window_get_instance_private (win); + + g_clear_object (&priv->settings); + + G_OBJECT_CLASS (u_plan_fahr_window_parent_class)->dispose (object); +} + + +static void +u_plan_fahr_window_class_init (UPlanFahrWindowClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = u_plan_fahr_window_dispose; + + gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class), + "/org/sigxcpu/uplanfahr/window.ui"); + + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, stack); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, search); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, searchbar); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, searchentry); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, gears); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, words); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, sidebar); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, lines); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, lines_label); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), UPlanFahrWindow, start_radiobutton); + + gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), searchentry_text_changed); + gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed); + + object_class->set_property = set_property; + object_class->get_property = get_property; + + g_object_class_install_property (object_class, + U_PLAN_FAHR_WINDOW_PROP_FULLSCREEN, + g_param_spec_boolean ("fullscreen", + "Fullscreen", + "Fullscreen window", + FALSE, + G_PARAM_READWRITE)); +} + +UPlanFahrWindow * +u_plan_fahr_window_new (UPlanFahr *app) +{ + UPlanFahrWindow *win; + + win = g_object_new (U_PLAN_FAHR_WINDOW_TYPE, "application", app, NULL); + + return win; +} + + + + +static void +initial_got_start (GSList *locs, gpointer user_data, GError *err) +{ + GtkWidget *view = GTK_WIDGET(user_data); + + if (err) { + g_warning ("%s", err->message); + return; + } + + set_loc (locs->data, view, TRUE); +} + + +static void +initial_got_end (GSList *locs, gpointer user_data, GError *err) +{ + GtkWidget *view = GTK_WIDGET(user_data); + + if (err) { + g_warning ("%s", err->message); + return; + } + + set_loc (locs->data, view, FALSE); + u_planfahr_get_trips (view); +} + + +void +u_plan_fahr_window_open (UPlanFahrWindow *win, + GFile *from, + GFile *to) +{ + UPlanFahrWindowPrivate *priv; + GtkWidget *scrolled, *view; + gchar *fromname, *toname, *title; + + priv = u_plan_fahr_window_get_instance_private (win); + + /* use the first two args as from and to */ + fromname = g_file_get_basename(from); + toname = g_file_get_basename(to); + + title = g_strdup_printf ("%s ⇨ %s", fromname, toname); + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolled); + gtk_widget_set_hexpand (scrolled, TRUE); + gtk_widget_set_vexpand (scrolled, TRUE); + view = u_plan_fahr_trip_view_new (); + gtk_widget_show (view); + + gtk_container_add (GTK_CONTAINER (scrolled), view); + gtk_stack_add_titled (GTK_STACK (priv->stack), scrolled, title, title); + g_free (title); + + /* FIXME: move out and fill initial data */ + manager = lpf_manager_new(); + provider = lpf_manager_activate_provider(manager, "de-db", NULL); + lpf_provider_get_locs(provider, fromname, 0, initial_got_start, view); + lpf_provider_get_locs(provider, toname, 0, initial_got_end, view); + + gtk_widget_set_sensitive (priv->search, TRUE); + + update_words (win); + update_lines (win); + + g_free (title); +} diff --git a/src/uplanfahrwin.h b/src/uplanfahrwin.h new file mode 100644 index 0000000..9decaf7 --- /dev/null +++ b/src/uplanfahrwin.h @@ -0,0 +1,23 @@ +#ifndef __UPLANFAHRWIN_H +#define __UPLANFAHRWIN_H + +#include <gtk/gtk.h> +#include "uplanfahr.h" + + +#define U_PLAN_FAHR_WINDOW_TYPE (u_plan_fahr_window_get_type ()) +#define U_PLAN_FAHR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), U_PLAN_FAHR_WINDOW_TYPE, UPlanFahrWindow)) + + +typedef struct _UPlanFahrWindow UPlanFahrWindow; +typedef struct _UPlanFahrWindowClass UPlanFahrWindowClass; + + +GType u_plan_fahr_window_get_type (void); +UPlanFahrWindow *u_plan_fahr_window_new (UPlanFahr *app); +void u_plan_fahr_window_open (UPlanFahrWindow *win, + GFile *from, + GFile *to); + + +#endif /* __UPLANFAHRWIN_H */ diff --git a/src/window.ui b/src/window.ui new file mode 100644 index 0000000..c6c7d1f --- /dev/null +++ b/src/window.ui @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.8 --> + <template class="UPlanFahrWindow" parent="GtkApplicationWindow"> + <property name="title" translatable="yes">UPlanFahr</property> + <property name="default-width">600</property> + <property name="default-height">400</property> + <child type="titlebar"> + <object class="GtkHeaderBar" id="header"> + <property name="visible">True</property> + <property name="show-close-button">True</property> + <child> + <object class="GtkLabel" id="lines_label"> + <property name="visible">False</property> + <property name="label" translatable="yes">Lines:</property> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="lines"> + <property name="visible">False</property> + </object> + <packing> + <property name="pack-type">start</property> + </packing> + </child> + <child type="title"> + <object class="GtkStackSwitcher" id="tabs"> + <property name="visible">True</property> + <property name="stack">stack</property> + </object> + </child> + <child> + <object class="GtkToggleButton" id="search"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <child> + <object class="GtkImage" id="search-icon"> + <property name="visible">True</property> + <property name="icon-name">edit-find-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="gears"> + <property name="visible">True</property> + <child> + <object class="GtkImage" id="gears-icon"> + <property name="visible">True</property> + <property name="icon-name">emblem-system-symbolic</property> + <property name="icon-size">1</property> + </object> + </child> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + </object> + </child> + <child> + <object class="GtkBox" id="content_box"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkSearchBar" id="searchbar"> + <property name="visible">True</property> + + <child> + <object class="GtkSearchEntry" id="searchentry"> + <signal name="search-changed" handler="searchentry_text_changed"/> + <property name="visible">True</property> + </object> + </child> + + <child> + <object class="GtkBox" id="box1"> + <property name="visible">True</property> + + <child> + <object class="GtkRadioButton" id="start_radiobutton"> + <property name="label" translatable="yes">Start</property> + <property name="visible">True</property> + <property name="active">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="stop_radiobutton"> + <property name="label" translatable="yes">End</property> + <property name="visible">True</property> + <property name="group">start_radiobutton</property> + <property name="active">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + + </object> + </child> + <child> + <object class="GtkBox" id="hbox"> + <property name="visible">True</property> + <child> + <object class="GtkRevealer" id="sidebar"> + <property name="visible">True</property> + <property name="transition-type">slide-right</property> + <child> + <object class="GtkScrolledWindow" id="sidebar-sw"> + <property name="visible">True</property> + <property name="hscrollbar-policy">never</property> + <property name="vscrollbar-policy">automatic</property> + <child> + <object class="GtkListBox" id="words"> + <property name="visible">True</property> + <property name="selection-mode">none</property> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkStack" id="stack"> + <signal name="notify::visible-child" handler="visible_child_changed"/> + <property name="visible">True</property> + </object> + </child> + </object> + </child> + </object> + </child> + </template> +</interface> |