From 1416ad27e9479633e17b631ce26a7056c188f60d Mon Sep 17 00:00:00 2001 From: jstebbins Date: Sun, 9 Nov 2008 19:12:00 +0000 Subject: [PATCH] LinGui: add update checking. shows a dialog similar to the macui when an update is available, but without the "install" option. git-svn-id: svn://localhost/HandBrake/trunk@1910 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- gtk/configure.ac | 2 +- gtk/src/Makefile.am | 2 + gtk/src/callbacks.c | 228 +++++++++++++++++++++++++++++++++++++- gtk/src/callbacks.h | 1 + gtk/src/ghb.ui | 161 +++++++++++++++++++++++++++ gtk/src/internal_defaults.xml | 2 + gtk/src/main.c | 8 +- gtk/src/resource_data.h | 250 ++++++++++++++++++++++++++++++++++++++++++ gtk/src/resources.plist | 163 +++++++++++++++++++++++++++ gtk/src/settings.h | 2 + 10 files changed, 808 insertions(+), 11 deletions(-) diff --git a/gtk/configure.ac b/gtk/configure.ac index 88e882b5..6b051ebd 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -70,7 +70,7 @@ PKG_CHECK_MODULES(GHBTOOLS, [glib-2.0 gobject-2.0 gdk-pixbuf-2.0]) AC_SUBST(GHBTOOLS_CFLAGS) AC_SUBST(GHBTOOLS_LIBS) -PKG_CHECK_MODULES(GHB, [gtk+-2.0 >= 2.8 gio-2.0 hal hal-storage]) +PKG_CHECK_MODULES(GHB, [gtk+-2.0 >= 2.8 gio-2.0 hal hal-storage libgtkhtml-3.14]) AC_SUBST(GHB_CFLAGS) AC_SUBST(GHB_LIBS) diff --git a/gtk/src/Makefile.am b/gtk/src/Makefile.am index 41881d09..4cae9d35 100644 --- a/gtk/src/Makefile.am +++ b/gtk/src/Makefile.am @@ -105,6 +105,8 @@ ghb_SOURCES = \ icon_tools.h \ values.c \ values.h \ + appcast.c \ + appcast.h \ plist.c \ plist.h \ hb-backend.c \ diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index 515acb5b..f7e55189 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -19,8 +19,11 @@ #include #include #include +#include +#include #include #include +#include #include #include #include @@ -34,6 +37,7 @@ #include "presets.h" #include "values.h" #include "plist.h" +#include "appcast.h" #include "hb-backend.h" #include "ghb-dvd.h" #include "ghbcellrenderertext.h" @@ -2013,12 +2017,13 @@ about_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud) gtk_widget_show (widget); } -void -guide_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud) +static void +browse_url(const gchar *url) { gboolean result; char *argv[] = - {"xdg-open","http://trac.handbrake.fr/wiki/HandBrakeGuide",NULL,NULL}; + {"xdg-open",NULL,NULL,NULL}; + argv[1] = (gchar*)url; result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); if (result) return; @@ -2040,7 +2045,12 @@ guide_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud) argv[2] = NULL; result = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); - if (result) return; +} + +void +guide_activate_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + browse_url("http://trac.handbrake.fr/wiki/HandBrakeGuide"); } void @@ -2728,3 +2738,213 @@ format_vquality_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud) return g_strdup_printf("%.1f", val); } } + +static void +html_link_cb(GtkHTML *html, const gchar *url, signal_user_data_t *ud) +{ + browse_url(url); +} + +static gboolean check_stable_update(signal_user_data_t *ud); +static gboolean stable_update_lock = FALSE; + +static void +process_appcast(signal_user_data_t *ud) +{ + gchar *description = NULL, *build = NULL, *version = NULL, *msg; + GtkWidget *html, *window, *dialog, *label; + gint response, ibuild = 0, skip; + + if (ud->appcast == NULL || ud->appcast_len < 15 || + strncmp(&(ud->appcast[9]), "200 OK", 6)) + { + if (!stable_update_lock && HB_BUILD % 100) + g_idle_add((GSourceFunc)check_stable_update, ud); + goto done; + } + ghb_appcast_parse(ud->appcast, &description, &build, &version); + if (build) + ibuild = g_strtod(build, NULL); + skip = ghb_settings_get_int(ud->settings, "update_skip_version"); + if (description == NULL || build == NULL || version == NULL + || ibuild <= HB_BUILD || skip == ibuild) + { + if (!stable_update_lock && HB_BUILD % 100) + g_idle_add((GSourceFunc)check_stable_update, ud); + goto done; + } + msg = g_strdup_printf("HandBrake %s/%s is now available (you have %s/%d).", + version, build, HB_VERSION, HB_BUILD); + label = GHB_WIDGET(ud->builder, "update_message"); + gtk_label_set_text(GTK_LABEL(label), msg); + html = gtk_html_new_from_string(description, -1); + g_signal_connect(html, "link_clicked", G_CALLBACK(html_link_cb), ud); + window = GHB_WIDGET(ud->builder, "update_scroll"); + gtk_container_add(GTK_CONTAINER(window), html); + // Show it + dialog = GHB_WIDGET(ud->builder, "update_dialog"); + gtk_widget_set_size_request(html, 420, 240); + gtk_widget_show(html); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + gtk_widget_destroy(html); + if (response == GTK_RESPONSE_OK) + { + // Skip + ghb_settings_set_int(ud->settings, "update_skip_version", ibuild); + ghb_pref_save(ud->settings, "update_skip_version"); + } + g_free(msg); + +done: + if (description) g_free(description); + if (build) g_free(build); + if (version) g_free(version); + g_free(ud->appcast); + ud->appcast_len = 0; + ud->appcast = NULL; +} + +void +ghb_net_close(GIOChannel *ioc) +{ + gint fd; + + g_debug("ghb_net_close"); + fd = g_io_channel_unix_get_fd(ioc); + close(fd); + g_io_channel_unref(ioc); +} + +gboolean +ghb_net_recv_cb(GIOChannel *ioc, GIOCondition cond, gpointer data) +{ + gchar buf[2048]; + gsize len; + GError *gerror = NULL; + GIOStatus status; + + g_debug("ghb_net_recv_cb"); + signal_user_data_t *ud = (signal_user_data_t*)data; + + status = g_io_channel_read_chars (ioc, buf, 2048, &len, &gerror); + if ((status == G_IO_STATUS_NORMAL || status == G_IO_STATUS_EOF) && + len > 0) + { + gint new_len = ud->appcast_len + len; + ud->appcast = g_realloc(ud->appcast, new_len + 1); + memcpy(&(ud->appcast[ud->appcast_len]), buf, len); + ud->appcast_len = new_len; + } + if (status == G_IO_STATUS_EOF) + { + ud->appcast[ud->appcast_len] = 0; + process_appcast(ud); + ghb_net_close(ioc); + return FALSE; + } + return TRUE; +} + +static gboolean +appcast_timeout_cb(GIOChannel *ioc) +{ + g_debug("appcast_timeout_cb"); + ghb_net_close(ioc); + return FALSE; +} + +GIOChannel* +ghb_net_open(signal_user_data_t *ud, gchar *address, gint port) +{ + GIOChannel *ioc; + gint fd; + + struct sockaddr_in sock; + struct hostent * host; + + g_debug("ghb_net_open"); + if( !( host = gethostbyname( address ) ) ) + { + g_warning( "gethostbyname failed (%s)", address ); + return NULL; + } + + memset( &sock, 0, sizeof( struct sockaddr_in ) ); + sock.sin_family = host->h_addrtype; + sock.sin_port = htons( port ); + memcpy( &sock.sin_addr, host->h_addr, host->h_length ); + + fd = socket(host->h_addrtype, SOCK_STREAM, 0); + if( fd < 0 ) + { + g_debug( "socket failed" ); + return NULL; + } + + if(connect(fd, (struct sockaddr*)&sock, sizeof(struct sockaddr_in )) < 0 ) + { + g_debug( "connect failed" ); + return NULL; + } + ioc = g_io_channel_unix_new(fd); + g_io_channel_set_encoding (ioc, NULL, NULL); + g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL); + g_io_add_watch (ioc, G_IO_IN, ghb_net_recv_cb, (gpointer)ud ); + g_timeout_add_seconds(20, (GSourceFunc)appcast_timeout_cb, ioc); + + return ioc; +} + +gboolean +ghb_check_update(signal_user_data_t *ud) +{ + gchar *query; + gsize len; + GIOChannel *ioc; + GError *gerror = NULL; + + g_debug("ghb_check_update"); + if (HB_BUILD % 100) + { + query = + "GET /appcast_unstable.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n"; + } + else + { + stable_update_lock = TRUE; + query = "GET /appcast.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n"; + } + ioc = ghb_net_open(ud, "handbrake.fr", 80); + if (ioc == NULL) + return FALSE; + + g_io_channel_write_chars(ioc, query, strlen(query), &len, &gerror); + g_io_channel_flush(ioc, &gerror); + // This function is initiated by g_idle_add. Must return false + // so that it is not called again + return FALSE; +} + +static gboolean +check_stable_update(signal_user_data_t *ud) +{ + gchar *query; + gsize len; + GIOChannel *ioc; + GError *gerror = NULL; + + g_debug("check_stable_update"); + stable_update_lock = TRUE; + query = "GET /appcast.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n"; + ioc = ghb_net_open(ud, "handbrake.fr", 80); + if (ioc == NULL) + return FALSE; + + g_io_channel_write_chars(ioc, query, strlen(query), &len, &gerror); + g_io_channel_flush(ioc, &gerror); + // This function is initiated by g_idle_add. Must return false + // so that it is not called again + return FALSE; +} + diff --git a/gtk/src/callbacks.h b/gtk/src/callbacks.h index 26c76861..7afaf9d1 100644 --- a/gtk/src/callbacks.h +++ b/gtk/src/callbacks.h @@ -46,6 +46,7 @@ GValue* ghb_start_next_job(signal_user_data_t *ud, gboolean find_first); void ghb_check_dependency(signal_user_data_t *ud, GtkWidget *widget); void ghb_do_scan(signal_user_data_t *ud, const gchar *filename, gboolean force); void ghb_log(gchar *log, ...); +gboolean ghb_check_update(signal_user_data_t *ud); #endif // _CALLBACKS_H_ diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 5dc1012c..c0fc2fcc 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -4752,4 +4752,165 @@ libxvidcore authors: + + 5 + True + center-on-parent + dialog + True + True + False + + + True + 2 + + + True + + + True + + + True + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK + False + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + hb-icon + 6 + + + + + False + 0 + + + + + + + + False + 0 + + + + + True + + + True + 0 + 10 + 5 + <b>A new version of HandBrake is available!</b> + True + + + False + 0 + + + + + True + 0 + 10 + 5 + HandBrake xxx is now available (you have yyy). + + + False + 1 + + + + + True + 0 + etched-out + + + True + 12 + + + True + True + automatic + automatic + + + + + + + + + + True + <b>Release Notes</b> + True + + + + + 2 + + + + + 1 + + + + + 1 + + + + + True + end + + + True + True + True + Skip This Version + + + 0 + + + + + True + True + True + Remind Me Later + + + 1 + + + + + False + end + 0 + + + + + + update_skip + update_remind + + diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 373f78a9..143223cf 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -108,6 +108,8 @@ use_source_name + update_skip_version + 0 version 0.1 diff --git a/gtk/src/main.c b/gtk/src/main.c index d7353847..08d7ff1a 100644 --- a/gtk/src/main.c +++ b/gtk/src/main.c @@ -515,15 +515,10 @@ main (int argc, char *argv[]) ghb_hal_init(); #endif - ud = g_malloc(sizeof(signal_user_data_t)); + ud = g_malloc0(sizeof(signal_user_data_t)); ud->debug = ghb_debug; - ud->cancel_encode = FALSE; g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, debug_log_handler, ud); ud->settings = ghb_settings_new(); - ud->queue = NULL; - ud->current_job = NULL; - ud->current_dvd_device = NULL; - ud->dont_clear_presets = FALSE; // Enable events that alert us to media change events watch_volumes (ud); ud->builder = create_builder_or_die (BUILDER_NAME); @@ -617,6 +612,7 @@ main (int argc, char *argv[]) } // Reload and check status of the last saved queue g_idle_add((GSourceFunc)ghb_reload_queue, ud); + g_idle_add((GSourceFunc)ghb_check_update, ud); // Start timer for monitoring libhb status, 500ms g_timeout_add (500, ghb_timer_cb, (gpointer)ud); // Everything should be go-to-go. Lets rock! diff --git a/gtk/src/resource_data.h b/gtk/src/resource_data.h index b61cc75d..9ffa3907 100644 --- a/gtk/src/resource_data.h +++ b/gtk/src/resource_data.h @@ -7654,6 +7654,254 @@ " </object>\n" " </child>\n" " </object>\n" +" <object class="GtkDialog" id="update_dialog"&g" +"t;\n" +" <property name="border_width">5</property>\n" +" <property name="modal">True</property>\n" +" <property name="window_position">center-on-parent&l" +"t;/property>\n" +" <property name="type_hint">dialog</property>\n" +" <property name="skip_taskbar_hint">True</propert" +"y>\n" +" <property name="skip_pager_hint">True</property&" +"gt;\n" +" <property name="has_separator">False</property&g" +"t;\n" +" <child internal-child="vbox">\n" +" <object class="GtkVBox" id="dialog-vbox6"&" +"gt;\n" +" <property name="visible">True</property>\n" +" <property name="spacing">2</property>\n" +" <child>\n" +" <object class="GtkHBox" id="hbox24">" +";\n" +" <property name="visible">True</property&" +"gt;\n" +" <child>\n" +" <object class="GtkVBox" id="vbox19"" +";>\n" +" <property name="visible">True</prope" +"rty>\n" +" <child>\n" +" <object class="GtkEventBox" id="eve" +"ntbox1">\n" +" <property name="visible">True</p" +"roperty>\n" +" <property name="events">GDK_BUTTON_" +"MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property&g" +"t;\n" +" <property name="visible_window">Fal" +"se</property>\n" +" <property name="above_child">True&l" +"t;/property>\n" +" <child>\n" +" <object class="GtkImage" id="im" +"age3">\n" +" <property name="visible">True&l" +"t;/property>\n" +" <property name="events">GDK_POI" +"NTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK" +" | GDK_BUTTON_RELEASE_MASK</property>\n" +" <property name="icon_name">hb-i" +"con</property>\n" +" <property name="icon-size">6<" +";/property>\n" +" </object>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="expand">False</p" +"roperty>\n" +" <property name="position">0</pro" +"perty>\n" +" </packing>\n" +" </child>\n" +" <child>\n" +" <placeholder/>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="expand">False</prope" +"rty>\n" +" <property name="position">0</propert" +"y>\n" +" </packing>\n" +" </child>\n" +" <child>\n" +" <object class="GtkVBox" id="vbox1"" +">\n" +" <property name="visible">True</prope" +"rty>\n" +" <child>\n" +" <object class="GtkLabel" id="label3" +"">\n" +" <property name="visible">True</p" +"roperty>\n" +" <property name="xalign">0</prope" +"rty>\n" +" <property name="xpad">10</proper" +"ty>\n" +" <property name="ypad">5</propert" +"y>\n" +" <property name="label" translatable=&q" +"uot;yes">&lt;b&gt;A new version of HandBrake is availab" +"le!&lt;/b&gt;</property>\n" +" <property name="use_markup">True<" +";/property>\n" +" </object>\n" +" <packing>\n" +" <property name="expand">False</p" +"roperty>\n" +" <property name="position">0</pro" +"perty>\n" +" </packing>\n" +" </child>\n" +" <child>\n" +" <object class="GtkLabel" id="update" +"_message">\n" +" <property name="visible">True</p" +"roperty>\n" +" <property name="xalign">0</prope" +"rty>\n" +" <property name="xpad">10</proper" +"ty>\n" +" <property name="ypad">5</propert" +"y>\n" +" <property name="label" translatable=&q" +"uot;yes">HandBrake xxx is now available (you have yyy).</pro" +"perty>\n" +" </object>\n" +" <packing>\n" +" <property name="expand">False</p" +"roperty>\n" +" <property name="position">1</pro" +"perty>\n" +" </packing>\n" +" </child>\n" +" <child>\n" +" <object class="GtkFrame" id="frame2" +"">\n" +" <property name="visible">True</p" +"roperty>\n" +" <property name="label_xalign">0<" +"/property>\n" +" <property name="shadow_type">etched" +"-out</property>\n" +" <child>\n" +" <object class="GtkAlignment" id=&quo" +"t;alignment2">\n" +" <property name="visible">True&l" +"t;/property>\n" +" <property name="left_padding">1" +"2</property>\n" +" <child>\n" +" <object class="GtkScrolledWindow"" +"; id="update_scroll">\n" +" <property name="visible">Tr" +"ue</property>\n" +" <property name="can_focus">" +"True</property>\n" +" <property name="hscrollbar_policy&q" +"uot;>automatic</property>\n" +" <property name="vscrollbar_policy&q" +"uot;>automatic</property>\n" +" <child>\n" +" <placeholder/>\n" +" </child>\n" +" </object>\n" +" </child>\n" +" </object>\n" +" </child>\n" +" <child type="label">\n" +" <object class="GtkLabel" id="la" +"bel88">\n" +" <property name="visible">True&l" +"t;/property>\n" +" <property name="label" translatabl" +"e="yes">&lt;b&gt;Release Notes&lt;/b&gt;&l" +"t;/property>\n" +" <property name="use_markup">Tru" +"e</property>\n" +" </object>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="position">2</pro" +"perty>\n" +" </packing>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="position">1</propert" +"y>\n" +" </packing>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="position">1</property>" +";\n" +" </packing>\n" +" </child>\n" +" <child internal-child="action_area">\n" +" <object class="GtkHButtonBox" id="dialog-ac" +"tion_area6">\n" +" <property name="visible">True</property&" +"gt;\n" +" <property name="layout_style">end</prope" +"rty>\n" +" <child>\n" +" <object class="GtkButton" id="update_sk" +"ip">\n" +" <property name="visible">True</prope" +"rty>\n" +" <property name="can_focus">True</pro" +"perty>\n" +" <property name="receives_default">True&" +"lt;/property>\n" +" <property name="label" translatable="" +"yes">Skip This Version</property>\n" +" </object>\n" +" <packing>\n" +" <property name="position">0</propert" +"y>\n" +" </packing>\n" +" </child>\n" +" <child>\n" +" <object class="GtkButton" id="update_re" +"mind">\n" +" <property name="visible">True</prope" +"rty>\n" +" <property name="can_focus">True</pro" +"perty>\n" +" <property name="receives_default">True&" +"lt;/property>\n" +" <property name="label" translatable="" +"yes">Remind Me Later</property>\n" +" </object>\n" +" <packing>\n" +" <property name="position">1</propert" +"y>\n" +" </packing>\n" +" </child>\n" +" </object>\n" +" <packing>\n" +" <property name="expand">False</property&" +"gt;\n" +" <property name="pack_type">end</property" +">\n" +" <property name="position">0</property>" +";\n" +" </packing>\n" +" </child>\n" +" </object>\n" +" </child>\n" +" <action-widgets>\n" +" <action-widget response="-5">update_skip</acti" +"on-widget>\n" +" <action-widget response="0">update_remind</act" +"ion-widget>\n" +" </action-widgets>\n" +" </object>\n" "</interface>\n" "\n" " icons\n" @@ -10169,6 +10417,8 @@ " \n" " show_presets\n" " \n" +" update_skip_version\n" +" 0\n" " use_source_name\n" " \n" " version\n" diff --git a/gtk/src/resources.plist b/gtk/src/resources.plist index ca929e5b..2bc58d60 100644 --- a/gtk/src/resources.plist +++ b/gtk/src/resources.plist @@ -4757,6 +4757,167 @@ libxvidcore authors: </object> </child> </object> + <object class="GtkDialog" id="update_dialog"> + <property name="border_width">5</property> + <property name="modal">True</property> + <property name="window_position">center-on-parent</property> + <property name="type_hint">dialog</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox6"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <object class="GtkHBox" id="hbox24"> + <property name="visible">True</property> + <child> + <object class="GtkVBox" id="vbox19"> + <property name="visible">True</property> + <child> + <object class="GtkEventBox" id="eventbox1"> + <property name="visible">True</property> + <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property> + <property name="visible_window">False</property> + <property name="above_child">True</property> + <child> + <object class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="icon_name">hb-icon</property> + <property name="icon-size">6</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">10</property> + <property name="ypad">5</property> + <property name="label" translatable="yes">&lt;b&gt;A new version of HandBrake is available!&lt;/b&gt;</property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="update_message"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">10</property> + <property name="ypad">5</property> + <property name="label" translatable="yes">HandBrake xxx is now available (you have yyy).</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">etched-out</property> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <object class="GtkScrolledWindow" id="update_scroll"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <placeholder/> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label88"> + <property name="visible">True</property> + <property name="label" translatable="yes">&lt;b&gt;Release Notes&lt;/b&gt;</property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area6"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="update_skip"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">Skip This Version</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="update_remind"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">Remind Me Later</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-5">update_skip</action-widget> + <action-widget response="0">update_remind</action-widget> + </action-widgets> + </object> </interface> icons @@ -4968,6 +5129,8 @@ R2RrUAAABBgBAQACAAAAQAAAABAAAAAQ////AP///wD///8A////AP///wD///8A////AP///wD///8A show_presets + update_skip_version + 0 use_source_name version diff --git a/gtk/src/settings.h b/gtk/src/settings.h index a089e0a7..bc4adc65 100644 --- a/gtk/src/settings.h +++ b/gtk/src/settings.h @@ -48,6 +48,8 @@ typedef struct GValue *current_job; GIOChannel *activity_log; GIOChannel *job_activity_log; + gchar *appcast; + gint appcast_len; } signal_user_data_t; enum -- 2.11.0