Commit 5c89099f authored by Jehan's avatar Jehan

Issue #4777: "New version available" after update.

The About dialog refreshes the release information relatively to
currently running version before being displayed. No check of the remote
JSON file is done, it only verifies whether any stored released
version/revision is not same (or even lower) than the actually running
version. Indeed existence of a stored release means that a newer version
exists at check time only. On later run, this stored information may
have become deprecated.
parent 534e0a49
Pipeline #221874 passed with stages
in 59 minutes and 10 seconds
......@@ -52,7 +52,8 @@ typedef struct
{
GtkWidget *dialog;
GtkWidget *update_frame;
GtkWidget *update_frame;
GimpCoreConfig *config;
GtkWidget *anim_area;
PangoLayout *layout;
......@@ -112,6 +113,7 @@ about_dialog_create (GimpCoreConfig *config)
gchar *version;
dialog.n_authors = G_N_ELEMENTS (authors) - 1;
dialog.config = config;
pixbuf = about_dialog_load_logo ();
......@@ -193,6 +195,8 @@ static void
about_dialog_map (GtkWidget *widget,
GimpAboutDialog *dialog)
{
gimp_update_refresh (dialog->config);
if (dialog->layout && dialog->timer == 0)
{
dialog->state = 0;
......@@ -287,6 +291,12 @@ about_dialog_add_update (GimpAboutDialog *dialog,
gchar *date;
gchar *text;
if (dialog->update_frame)
{
gtk_widget_destroy (dialog->update_frame);
dialog->update_frame = NULL;
}
/* Get the dialog vbox. */
container = gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog));
children = gtk_container_get_children (GTK_CONTAINER (container));
......@@ -452,6 +462,7 @@ about_dialog_add_update (GimpAboutDialog *dialog,
gtk_widget_show (frame);
dialog->update_frame = frame;
g_object_add_weak_pointer (G_OBJECT (frame), (gpointer) &dialog->update_frame);
/* Reconstruct the dialog when release info changes. */
g_signal_connect (config, "notify::last-known-release",
......@@ -763,12 +774,6 @@ about_dialog_last_release_changed (GimpCoreConfig *config,
if (! dialog->dialog)
return;
if (dialog->update_frame)
{
gtk_widget_destroy (dialog->update_frame);
dialog->update_frame = NULL;
}
about_dialog_add_update (dialog, config);
}
......
......@@ -42,6 +42,130 @@
#include "gimp-update.h"
#include "gimp-version.h"
static gboolean gimp_update_known (GimpCoreConfig *config,
const gchar *last_version,
gint64 release_timestamp,
gint build_revision,
const gchar *comment);
static gboolean gimp_version_break (const gchar *v,
gint *major,
gint *minor,
gint *micro);
static void gimp_check_updates_callback (GObject *source,
GAsyncResult *result,
gpointer user_data);
static void gimp_update_about_dialog (GimpCoreConfig *config,
const GParamSpec *pspec,
gpointer user_data);
/* Private Functions */
/**
* gimp_update_known:
* @config:
* @last_version:
* @release_timestamp: must be non-zero is @last_version is not %NULL.
* @build_revision:
* @build_comment:
*
* Compare @last_version with currently running version. If the checked
* version is more recent than running version, then @config properties
* are updated appropriately (which may trigger a dialog depending on
* update policy settings).
* If @last_version is %NULL, the currently stored "last known release"
* is compared. Even if we haven't made any new remote checks, it is
* important to always compare again stored last release, otherwise we
* might warn of the same current version, or worse an older version.
*
* Returns: %TRUE is @last_version (or stored last known release if
* @last_version was %NULL) is newer than running version.
*/
static gboolean
gimp_update_known (GimpCoreConfig *config,
const gchar *last_version,
gint64 release_timestamp,
gint build_revision,
const gchar *build_comment)
{
gboolean new_check = (last_version != NULL);
gint major;
gint minor;
gint micro;
if (last_version && release_timestamp == 0)
{
/* I don't exit with a g_return_val_if_fail() assert because this
* is not necessarily a code bug. It may be data issues. So let's
* just return with an error printed on stderr.
*/
g_printerr ("%s: version %s with no release dates.\n",
G_STRFUNC, last_version);
return FALSE;
}
if (last_version == NULL)
{
last_version = config->last_known_release;
release_timestamp = config->last_release_timestamp;
build_revision = config->last_revision;
build_comment = config->last_release_comment;
}
if (last_version)
{
if (gimp_version_break (last_version, &major, &minor, &micro))
{
if (/* We are using a newer version than last check. This could
* happen if updating the config files without having
* re-checked the remote JSON file.
*/
(major < GIMP_MAJOR_VERSION ||
(major == GIMP_MAJOR_VERSION && minor < GIMP_MINOR_VERSION) ||
(major == GIMP_MAJOR_VERSION && minor == GIMP_MINOR_VERSION && micro < GIMP_MICRO_VERSION)) ||
/* Already using the last officially released
* revision. */
(major == GIMP_MAJOR_VERSION &&
minor == GIMP_MINOR_VERSION &&
micro == GIMP_MICRO_VERSION &&
build_revision <= gimp_version_get_revision ()))
{
last_version = NULL;
}
}
else
{
/* If version is not properly parsed, something is wrong with
* upstream version number or parsing. This should not happen.
*/
g_printerr ("%s: version not properly formatted: %s\n",
G_STRFUNC, last_version);
return FALSE;
}
}
if (last_version == NULL)
{
release_timestamp = 0;
build_revision = 0;
build_comment = NULL;
}
if (new_check)
g_object_set (config,
"check-update-timestamp", g_get_real_time() / G_USEC_PER_SEC,
NULL);
g_object_set (config,
"last-release-timestamp", release_timestamp,
"last-known-release", last_version,
"last-revision", build_revision,
"last-release-comment", build_comment,
NULL);
/* Are we running an old GIMP? */
return (last_version != NULL);
}
static gboolean
gimp_version_break (const gchar *v,
......@@ -92,17 +216,15 @@ gimp_check_updates_callback (GObject *source,
NULL, &error))
{
const gchar *platform;
const gchar *last_version = NULL;
const gchar *release_date = NULL;
const gchar *last_version = NULL;
const gchar *release_date = NULL;
const gchar *build_comment = NULL;
gint64 release_timestamp = 0;
gint build_revision = 0;
JsonParser *parser;
JsonPath *path;
JsonNode *result;
JsonArray *versions;
JsonArray *builds;
gint build_revision = 0;
gint major;
gint minor;
gint micro;
gint i;
/* For Windows and macOS, let's look if installers are available.
......@@ -117,8 +239,8 @@ gimp_check_updates_callback (GObject *source,
parser = json_parser_new ();
if (! json_parser_load_from_data (parser, file_contents, file_length, &error))
{
g_printerr("%s: parsing of %s failed: %s\n", G_STRFUNC,
g_file_get_uri (G_FILE (source)), error->message);
g_printerr ("%s: parsing of %s failed: %s\n", G_STRFUNC,
g_file_get_uri (G_FILE (source)), error->message);
g_free (file_contents);
g_clear_object (&parser);
g_clear_error (&error);
......@@ -157,80 +279,82 @@ gimp_check_updates_callback (GObject *source,
/* Note that we don't actually look for the highest version,
* but for the highest version for which a build for your
* platform is available.
* platform (and optional build-id) is available.
*
* So we loop through the version list then the build array
* and break at first compatible release, since JSON arrays
* are ordered.
*/
version = json_array_get_object_element (versions, i);
if (json_object_has_member (version, platform))
{
last_version = json_object_get_string_member (version, "version");
release_date = json_object_get_string_member (version, "date");
builds = json_object_get_array_member (version, platform);
break;
}
}
JsonArray *builds;
gint j;
/* If version is not properly parsed, something is wrong with
* upstream version number or parsing. This should not happen.
*/
if (gimp_version_break (last_version, &major, &minor, &micro))
{
const gchar *build_date = NULL;
const gchar *build_comment = NULL;
GDateTime *datetime;
gchar *str;
if (major < GIMP_MAJOR_VERSION ||
(major == GIMP_MAJOR_VERSION && minor < GIMP_MINOR_VERSION) ||
(major == GIMP_MAJOR_VERSION && minor == GIMP_MINOR_VERSION && micro < GIMP_MICRO_VERSION))
{
/* We are using a newer version than last one (somehow). */
last_version = NULL;
}
else if (major == GIMP_MAJOR_VERSION &&
minor == GIMP_MINOR_VERSION &&
micro == GIMP_MICRO_VERSION)
{
for (i = 0; i < (gint) json_array_get_length (builds); i++)
builds = json_object_get_array_member (version, platform);
for (j = 0; j < (gint) json_array_get_length (builds); j++)
{
const gchar *build_id = NULL;
JsonObject *build;
build = json_array_get_object_element (builds, i);
build = json_array_get_object_element (builds, j);
if (json_object_has_member (build, "build-id"))
build_id = json_object_get_string_member (build, "build-id");
if (g_strcmp0 (build_id, GIMP_BUILD_ID) == 0)
{
/* Release date is the build date if any set,
* otherwise the main version release date.
*/
if (json_object_has_member (build, "date"))
release_date = json_object_get_string_member (build, "date");
else
release_date = json_object_get_string_member (version, "date");
/* These are optional data. */
if (json_object_has_member (build, "revision"))
build_revision = json_object_get_int_member (build, "revision");
if (json_object_has_member (build, "date"))
build_date = json_object_get_string_member (build, "date");
if (json_object_has_member (build, "comment"))
build_comment = json_object_get_string_member (build, "comment");
break;
}
}
if (build_revision <= gimp_version_get_revision ())
if (release_date)
{
/* Already using the last officially released
* revision. */
last_version = NULL;
last_version = json_object_get_string_member (version, "version");
break;
}
}
str = g_strdup_printf ("%s 00:00:00Z", build_date ? build_date : release_date);
}
if (last_version && release_date)
{
GDateTime *datetime;
gchar *str;
str = g_strdup_printf ("%s 00:00:00Z", release_date);
datetime = g_date_time_new_from_iso8601 (str, NULL);
g_free (str);
if (datetime)
{
g_object_set (config,
"check-update-timestamp", g_get_real_time() / G_USEC_PER_SEC,
"last-release-timestamp", g_date_time_to_unix (datetime),
"last-known-release", last_version,
"last-revision", build_revision,
"last-release-comment", build_comment,
NULL);
release_timestamp = g_date_time_to_unix (datetime);
g_date_time_unref (datetime);
}
else
{
/* JSON file data bug. */
g_printerr ("%s: release date for version %s not properly formatted: %s\n",
G_STRFUNC, last_version, release_date);
last_version = NULL;
release_date = NULL;
build_revision = 0;
build_comment = NULL;
}
}
gimp_update_known (config, last_version, release_timestamp, build_revision, build_comment);
g_object_unref (path);
g_object_unref (parser);
......@@ -265,11 +389,15 @@ gimp_update_about_dialog (GimpCoreConfig *config,
}
}
/* Public Functions */
/*
* gimp_update_auto_check:
* @config:
*
* Run the check for newer versions of GIMP if conditions are right.
*
* Returns: %TRUE if a check was actually run.
*/
gboolean
gimp_update_auto_check (GimpCoreConfig *config)
......@@ -302,7 +430,9 @@ gimp_update_auto_check (GimpCoreConfig *config)
(GCallback) gimp_update_about_dialog,
NULL);
return gimp_update_check (config);
gimp_update_check (config);
return TRUE;
}
/*
......@@ -311,7 +441,7 @@ gimp_update_auto_check (GimpCoreConfig *config)
*
* Run the check for newer versions of GIMP inconditionnally.
*/
gboolean
void
gimp_update_check (GimpCoreConfig *config)
{
GFile *gimp_versions;
......@@ -326,6 +456,17 @@ gimp_update_check (GimpCoreConfig *config)
#endif
g_file_load_contents_async (gimp_versions, NULL, gimp_check_updates_callback, config);
g_object_unref (gimp_versions);
}
return TRUE;
/*
* gimp_update_refresh:
* @config:
*
* Do not execute a remote check, but refresh the known release data as
* it may be outdated.
*/
void
gimp_update_refresh (GimpCoreConfig *config)
{
gimp_update_known (config, NULL, 0, 0, NULL);
}
......@@ -23,7 +23,8 @@
gboolean gimp_update_auto_check (GimpCoreConfig *config);
gboolean gimp_update_check (GimpCoreConfig *config);
void gimp_update_check (GimpCoreConfig *config);
void gimp_update_refresh (GimpCoreConfig *config);
#endif /* __APP_GIMP_UPDATE_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment