...
 
Commits (87)
version 3.4.5
-------------
Bugs fixed:
* Fixed big memory leak and other minor memory leaks.
* Speed improvements:
* Make the preloader actually preload the images.
* Image overview: scale the image asynchronously.
* Faster execution for asynchronous tasks.
* Resize tool: fixed initial selection (Vaclav Brozek)
* Ensure the settings have been saved before exiting.
* Fixed possible crash when switching from the image viewer
to the video viewer.
New or updated application translations:
* Basque (Iñaki Larrañaga Murgoitio)
* Indonesian (Andika Triwidada)
version 3.4.4.1
---------------
Bugs fixed:
* gthumb 3.4.4 fails post build check 64bit-portability-issue
(#772739)
New or updated application translations:
* Croatian (gogo)
version 3.4.4
-------------
Bugs fixed:
* Sizing issues in gthumb preferences under gtk+ git master. (#770546)
* Hide the image frame when in fullscreen mode. (#767731)
* Fixed headerbar buttons not shown correctly after activating a tool.
* Orginaze files: fixed wrong catalog cardinality.
* Fixed scrollbars resetting their position when changing image.
* Find duplicates: faster.
* New folder: open the created folder.
* Print dialog: expand the options side to make the zoom slider visible.
* Fixed wrong image loaded after deleting an image from a catalog.
New or updated application translations:
* Croatian (gogo)
* Indonesian (Andika Triwidada)
version 3.4.3
-------------
Bugs fixed:
* Theme errors with gtk+ 3.20
* Viewer sidebar too wide
New or updated application translations:
* Serbian (Мирослав Николић)
* Serbian (Miroslav Nikolić)
version 3.4.2
-------------
User visible changes:
* Sort catalogs first by name then by date,
instead of doing the opposite.
Bugs fixed:
* Crash after pressing shift-arrow. (#760050)
* Stopping slideshow freezes entire program. (#759787)
* Crash if trying to delete image on sftp mounted. (#759727)
* Crash when deleting duplicate. (#759631)
* Crash after changing and renaming file. (#750142)
New or updated application translations:
* Brazilian Portuguese (Rafael Fontenelle)
* catalan (Robert Antoni Buj Gelonch)
* Deutsch (Christian Kirbach)
* Icelandic (Sveinn í Felli)
* Latvian (Rūdolfs Mazurs)
* Português (Pedro Albuquerque)
* Swedish (Josef Andersson)
* Русский (Yuri Myasoedov)
New or updated manual translations:
* Deutsch (Mario Blättermann)
* Español; Castellano (Daniel Mustieles)
* Swedish (Josef Andersson)
version 3.4.1
-------------
......
m4_define([gthumb_major_version], [3])
m4_define([gthumb_minor_version], [4])
m4_define([gthumb_micro_version], [1])
m4_define([gthumb_micro_version], [5])
m4_define([gthumb_version],
[gthumb_major_version.gthumb_minor_version.gthumb_micro_version])
m4_define([gthumb_api_version],
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkListStore" id="file_properties_position_liststore">
......@@ -59,6 +59,7 @@
<property name="can_focus">False</property>
<child>
<object class="GtkListBox" id="tabs_listbox">
<property name="width_request">180</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
......@@ -76,7 +77,7 @@
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="border_width">12</property>
<property name="show_tabs">False</property>
<property name="show_border">False</property>
<child>
......
......@@ -140,22 +140,26 @@ gth_image_svg_new (void)
}
static void
static gboolean
gth_image_svg_set_handle (GthImageSvg *self,
RsvgHandle *rsvg)
{
RsvgDimensionData dimension_data;
if (self->rsvg == rsvg)
return;
return TRUE;
self->rsvg = g_object_ref (rsvg);
rsvg_handle_get_dimensions (rsvg, &dimension_data);
if ((dimension_data.width == 0) || (dimension_data.height == 0))
return FALSE;
rsvg_handle_get_dimensions (self->rsvg, &dimension_data);
self->rsvg = g_object_ref (rsvg);
self->original_width = dimension_data.width;
self->original_height = dimension_data.height;
gth_image_svg_set_zoom (GTH_IMAGE (self), 1.0, NULL, NULL);
return TRUE;
}
......@@ -183,7 +187,11 @@ _cairo_image_surface_create_from_svg (GInputStream *istream,
cancellable,
error);
if (rsvg != NULL) {
gth_image_svg_set_handle (GTH_IMAGE_SVG (image), rsvg);
if (! gth_image_svg_set_handle (GTH_IMAGE_SVG (image), rsvg)) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Error");
g_object_unref (image);
image = NULL;
}
g_object_unref (rsvg);
}
......
......@@ -69,8 +69,8 @@ catalog_saved_cb (void **buffer,
gth_monitor_file_renamed (gth_main_get_default_monitor (),
data->original_file,
data->file_data->file);
}
gth_catalog_update_metadata (data->catalog, data->file_data);
gth_monitor_metadata_changed (gth_main_get_default_monitor (), data->file_data);
......
......@@ -694,16 +694,14 @@ update_standard_attributes (GFile *file,
if (gth_datetime_valid_date (date_time)) {
char *sort_order_s;
int sort_order;
sort_order_s = gth_datetime_strftime (date_time, "%Y%m%d");
sort_order = atoi (sort_order_s);
g_file_info_set_sort_order (info, sort_order);
_g_file_info_set_secondary_sort_order (info, atoi (sort_order_s));
g_free (sort_order_s);
}
else if (g_file_info_get_attribute_boolean (info, "gthumb::no-child"))
g_file_info_set_sort_order (info, 99999999);
else
g_file_info_remove_attribute (info, "gth::standard::secondary-sort-order");
display_name = get_display_name (file, name, date_time);
if (display_name != NULL) {
......@@ -745,7 +743,6 @@ gth_catalog_update_metadata (GthCatalog *catalog,
char *raw;
char *formatted;
char *sort_order_s;
int sort_order;
metadata = (GObject *) gth_metadata_new ();
raw = gth_datetime_to_exif_date (catalog->priv->date_time);
......@@ -758,15 +755,16 @@ gth_catalog_update_metadata (GthCatalog *catalog,
g_file_info_set_attribute_object (file_data->info, "general::event-date", metadata);
sort_order_s = gth_datetime_strftime (catalog->priv->date_time, "%Y%m%d");
sort_order = atoi (sort_order_s);
g_file_info_set_sort_order (file_data->info, sort_order);
_g_file_info_set_secondary_sort_order (file_data->info, atoi (sort_order_s));
g_free (formatted);
g_free (raw);
g_object_unref (metadata);
}
else
else {
g_file_info_remove_attribute (file_data->info, "general::event-date");
g_file_info_remove_attribute (file_data->info, "gth::standard::secondary-sort-order");
}
/* standard::display-name,standard::sort-order */
......@@ -779,6 +777,13 @@ gth_catalog_update_metadata (GthCatalog *catalog,
}
int
gth_catalog_get_size (GthCatalog *catalog)
{
return g_hash_table_size (catalog->priv->file_hash);
}
/* utils */
......
......@@ -109,6 +109,7 @@ void gth_catalog_list_async (GthCatalog *catalog,
void gth_catalog_cancel (GthCatalog *catalog);
void gth_catalog_update_metadata (GthCatalog *catalog,
GthFileData *file_data);
int gth_catalog_get_size (GthCatalog *catalog);
/* utils */
......
......@@ -165,20 +165,24 @@ done_func (GError *error,
CARDINALITY_COLUMN, &n,
-1);
if (n == 1) {
GthCatalog *catalog;
GList *file_list;
gtk_list_store_set (self->priv->results_liststore, &iter,
CREATE_CATALOG_COLUMN, FALSE,
-1);
singletons++;
catalog = g_hash_table_lookup (self->priv->catalogs, key);
file_list = gth_catalog_get_file_list (catalog);
gth_catalog_insert_file (self->priv->singletons_catalog, file_list->data, -1);
if (singletons == 1)
g_hash_table_insert (self->priv->catalogs,
g_strdup (gth_catalog_get_name (self->priv->singletons_catalog)),
g_object_ref (self->priv->singletons_catalog));
if (self->priv->singletons_catalog != NULL) {
GthCatalog *catalog;
GList *file_list;
catalog = g_hash_table_lookup (self->priv->catalogs, key);
file_list = gth_catalog_get_file_list (catalog);
gth_catalog_insert_file (self->priv->singletons_catalog, file_list->data, -1);
if (singletons == 1)
g_hash_table_insert (self->priv->catalogs,
g_strdup (gth_catalog_get_name (self->priv->singletons_catalog)),
g_object_ref (self->priv->singletons_catalog));
}
}
g_free (key);
......@@ -191,7 +195,7 @@ done_func (GError *error,
gtk_list_store_set (self->priv->results_liststore, &iter,
KEY_COLUMN, gth_catalog_get_name (self->priv->singletons_catalog),
NAME_COLUMN, gth_catalog_get_name (self->priv->singletons_catalog),
CARDINALITY_COLUMN, singletons,
CARDINALITY_COLUMN, gth_catalog_get_size (self->priv->singletons_catalog),
CREATE_CATALOG_COLUMN, TRUE,
ICON_COLUMN, self->priv->icon_pixbuf,
-1);
......@@ -417,6 +421,9 @@ add_file_to_catalog (GthOrganizeTask *self,
GtkTreeIter iter;
int n = 0;
if (! gth_catalog_insert_file (catalog, file_data->file, -1))
return;
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->results_liststore), &iter)) {
do {
char *k;
......@@ -427,11 +434,11 @@ add_file_to_catalog (GthOrganizeTask *self,
CARDINALITY_COLUMN, &n,
-1);
if (g_strcmp0 (k, catalog_key) == 0) {
self->priv->n_files++;
n += 1;
gtk_list_store_set (self->priv->results_liststore, &iter,
CARDINALITY_COLUMN, n + 1,
CARDINALITY_COLUMN, n,
-1);
self->priv->n_files++;
g_free (k);
break;
}
......@@ -440,8 +447,6 @@ add_file_to_catalog (GthOrganizeTask *self,
}
while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->results_liststore), &iter));
}
gth_catalog_insert_file (catalog, file_data->file, -1);
}
......@@ -802,7 +807,10 @@ gth_organize_task_init (GthOrganizeTask *self)
g_object_unref (icon);
self->priv->file_list = gth_file_list_new (gth_grid_view_new (), GTH_FILE_LIST_MODE_NORMAL, FALSE);
gth_file_list_set_filter (GTH_FILE_LIST (self->priv->file_list), NULL);
gth_file_list_set_caption (GTH_FILE_LIST (self->priv->file_list), "standard::display-name");
gth_file_list_set_thumb_size (GTH_FILE_LIST (self->priv->file_list), 128);
gth_file_list_set_ignore_hidden (GTH_FILE_LIST (self->priv->file_list), FALSE);
gtk_widget_show (self->priv->file_list);
gtk_box_pack_start (GTK_BOX (GET_WIDGET ("preview_box")), self->priv->file_list, TRUE, TRUE, 0);
......
......@@ -136,6 +136,7 @@ saver_completed_cb (GthTask *task,
close_dialog (data);
dialog_data_unref (data);
_g_object_unref (task);
}
......@@ -195,9 +196,6 @@ edit_metadata_dialog__response_cb (GtkDialog *dialog,
G_CALLBACK (saver_completed_cb),
data);
gth_browser_exec_task (data->browser, task, GTH_TASK_FLAGS_IGNORE_ERROR);
g_object_unref (task);
}
......
......@@ -804,6 +804,8 @@ upload_photo_file_buffer_ready_cb (void **buffer,
}
g_list_free (keys);
g_free (description);
g_free (title);
g_hash_table_unref (data_set);
}
......
......@@ -42,7 +42,7 @@ typedef struct {
static void
new_fodler_data_free (NewFolderData *data)
new_folder_data_free (NewFolderData *data)
{
g_object_unref (data->parent);
g_free (data);
......@@ -60,7 +60,7 @@ new_folder_dialog_response_cb (GtkWidget *dialog,
GError *error = NULL;
if (response_id != GTK_RESPONSE_OK) {
new_fodler_data_free (data);
new_folder_data_free (data);
gtk_widget_destroy (dialog);
return;
}
......@@ -112,7 +112,8 @@ new_folder_dialog_response_cb (GtkWidget *dialog,
g_clear_error (&error);
}
else {
new_fodler_data_free (data);
gth_browser_load_location (data->browser, folder);
new_folder_data_free (data);
gtk_widget_destroy (dialog);
}
......
......@@ -1064,6 +1064,8 @@ _gth_browser_update_open_menu (GthBrowser *browser)
else
g_menu_item_set_icon (item, icon);
g_menu_append_item (data->open_with_menu, item);
g_object_unref (item);
}
gth_window_enable_action (GTH_WINDOW (browser), "open-with-application", data->applications != NULL);
......@@ -1155,7 +1157,7 @@ fm__gth_browser_file_list_key_press_cb (GthBrowser *browser,
* for example: when viewing a catalog removes
* the files from the catalog; when viewing a
* folder removes the files from the folder. */
source = gth_browser_get_location_source (browser);
source = _g_object_ref (gth_browser_get_location_source (browser));
location = gth_browser_get_location_data (browser);
}
else {
......@@ -1183,6 +1185,7 @@ fm__gth_browser_file_list_key_press_cb (GthBrowser *browser,
_g_object_list_unref (file_data_list);
_gtk_tree_path_list_free (items);
_g_object_unref (source);
}
break;
}
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkAdjustment" id="crop_height_adjustment">
......@@ -91,10 +91,10 @@
<object class="GtkLabel" id="brightness_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">B_rightness:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -110,10 +110,10 @@
<object class="GtkLabel" id="contrast_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">Con_trast:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -129,10 +129,10 @@
<object class="GtkLabel" id="saturation_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">_Saturation:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -210,10 +210,10 @@
<object class="GtkLabel" id="gamma_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">G_amma:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -227,10 +227,10 @@
<object class="GtkLabel" id="cyan_red_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">Cyan-_Red:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -246,10 +246,10 @@
<object class="GtkLabel" id="magenta_green_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">_Magenta-Green:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......@@ -265,10 +265,10 @@
<object class="GtkLabel" id="yellow_blue_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">_Yellow-Blue:</property>
<property name="use_underline">True</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<attributes>
<attribute name="size" value="8000"/>
</attributes>
......
......@@ -393,6 +393,8 @@ ratio_combobox_changed_cb (GtkComboBox *combobox,
self->priv->fixed_aspect_ratio = use_ratio;
self->priv->aspect_ratio = (double) w / h;
selection_width_value_changed_cb (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), self);
if (! use_ratio)
selection_height_value_changed_cb (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), self);
}
......
......@@ -371,6 +371,7 @@ duplicates_list_view_selection_changed_cb (GthFileView *fileview,
GList *file_data_list;
GHashTable *selected_files;
GtkTreeModel *files_treemodel;
GtkTreeModel *files_treemodelfilter;
GtkTreeIter iter;
GList *scan;
......@@ -394,6 +395,11 @@ duplicates_list_view_selection_changed_cb (GthFileView *fileview,
}
files_treemodel = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
files_treemodelfilter = GTK_TREE_MODEL (GET_WIDGET ("files_treemodelfilter"));
g_object_ref (files_treemodelfilter);
gtk_tree_view_set_model (GTK_TREE_VIEW (GET_WIDGET ("files_treeview")), NULL); /* to avoid excessive recomputation */
if (gtk_tree_model_get_iter_first (files_treemodel, &iter)) {
do {
GthFileData *file_data;
......@@ -410,6 +416,9 @@ duplicates_list_view_selection_changed_cb (GthFileView *fileview,
while (gtk_tree_model_iter_next (files_treemodel, &iter));
}
gtk_tree_view_set_model (GTK_TREE_VIEW (GET_WIDGET ("files_treeview")), files_treemodelfilter);
g_object_unref (files_treemodelfilter);
update_file_list_sensitivity (self);
update_file_list_selection_info (self);
......@@ -457,9 +466,6 @@ files_tree_view_selection_changed_cb (GtkTreeSelection *tree_selection,
}
static void start_next_checksum (GthFindDuplicates *self);
static void
update_total_duplicates_label (GthFindDuplicates *self)
{
......@@ -475,6 +481,89 @@ update_total_duplicates_label (GthFindDuplicates *self)
}
static void
folder_changed_cb (GthMonitor *monitor,
GFile *parent,
GList *list,
int position,
GthMonitorEvent event,
gpointer user_data)
{
GthFindDuplicates *self = user_data;
GList *file_scan;
if (event != GTH_MONITOR_EVENT_DELETED)
return;
for (file_scan = list; file_scan; file_scan = file_scan->next) {
GFile *file = file_scan->data;
GList *values;
GList *scan;
values = g_hash_table_get_values (self->priv->duplicated);
for (scan = values; scan; scan = scan->next) {
DuplicatedData *d_data = scan->data;
GList *link;
char *text;
GList *singleton;
link = gth_file_data_list_find_file (d_data->files, file);
if (link == NULL)
continue;
d_data->files = g_list_remove_link (d_data->files, link);
d_data->n_files -= 1;
d_data->total_size -= g_file_info_get_size (d_data->file_data->info);
text = g_strdup_printf (g_dngettext (NULL, "%d duplicate", "%d duplicates", d_data->n_files - 1), d_data->n_files - 1);
g_file_info_set_attribute_string (d_data->file_data->info,
"find-duplicates::n-duplicates",
text);
g_free (text);
singleton = g_list_append (NULL, d_data->file_data);
if (d_data->n_files <= 1)
gth_file_list_delete_files (GTH_FILE_LIST (self->priv->duplicates_list), singleton);
else
gth_file_list_update_files (GTH_FILE_LIST (self->priv->duplicates_list), singleton);
g_list_free (singleton);
self->priv->n_duplicates -= 1;
self->priv->duplicates_size -= g_file_info_get_size (d_data->file_data->info);
update_total_duplicates_label (self);
_g_object_list_unref (link);
}
g_list_free (values);
}
duplicates_list_view_selection_changed_cb (NULL, self);
update_file_list_sensitivity (self);
update_file_list_selection_info (self);
}
static void
after_checksums (GthFindDuplicates *self)
{
self->priv->folder_changed_id = g_signal_connect (gth_main_get_default_monitor (),
"folder-changed",
G_CALLBACK (folder_changed_cb),
self);
gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("pages_notebook")), (self->priv->n_duplicates > 0) ? 0 : 1);
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("progress_label")), _("Search completed"));
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("search_details_label")), "");
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (GET_WIDGET ("search_progressbar")), 1.0);
gtk_widget_set_sensitive (GET_WIDGET ("stop_button"), FALSE);
duplicates_list_view_selection_changed_cb (NULL, self);
}
static void start_next_checksum (GthFindDuplicates *self);
static void
_file_list_add_file (GthFindDuplicates *self,
GthFileData *file_data)
......@@ -579,7 +668,6 @@ file_input_stream_read_ready_cb (GObject *source,
}
duplicates_list_view_selection_changed_cb (NULL, self);
start_next_checksum (self);
return;
......@@ -631,69 +719,6 @@ read_current_file_ready_cb (GObject *source,
}
static void
folder_changed_cb (GthMonitor *monitor,
GFile *parent,
GList *list,
int position,
GthMonitorEvent event,
gpointer user_data)
{
GthFindDuplicates *self = user_data;
GList *file_scan;
if (event != GTH_MONITOR_EVENT_DELETED)
return;
for (file_scan = list; file_scan; file_scan = file_scan->next) {
GFile *file = file_scan->data;
GList *values;
GList *scan;
values = g_hash_table_get_values (self->priv->duplicated);
for (scan = values; scan; scan = scan->next) {
DuplicatedData *d_data = scan->data;
GList *link;
char *text;
GList *singleton;
link = gth_file_data_list_find_file (d_data->files, file);
if (link == NULL)
continue;
d_data->files = g_list_remove_link (d_data->files, link);
d_data->n_files -= 1;
d_data->total_size -= g_file_info_get_size (d_data->file_data->info);
text = g_strdup_printf (g_dngettext (NULL, "%d duplicate", "%d duplicates", d_data->n_files - 1), d_data->n_files - 1);
g_file_info_set_attribute_string (d_data->file_data->info,
"find-duplicates::n-duplicates",
text);
g_free (text);
singleton = g_list_append (NULL, d_data->file_data);
if (d_data->n_files <= 1)
gth_file_list_delete_files (GTH_FILE_LIST (self->priv->duplicates_list), singleton);
else
gth_file_list_update_files (GTH_FILE_LIST (self->priv->duplicates_list), singleton);
g_list_free (singleton);
self->priv->n_duplicates -= 1;
self->priv->duplicates_size -= g_file_info_get_size (d_data->file_data->info);
update_total_duplicates_label (self);
_g_object_list_unref (link);
}
g_list_free (values);
}
duplicates_list_view_selection_changed_cb (NULL, self);
update_file_list_sensitivity (self);
update_file_list_selection_info (self);
}
static void
start_next_checksum (GthFindDuplicates *self)
{
......@@ -703,17 +728,7 @@ start_next_checksum (GthFindDuplicates *self)
link = self->priv->files;
if (link == NULL) {
self->priv->folder_changed_id = g_signal_connect (gth_main_get_default_monitor (),
"folder-changed",
G_CALLBACK (folder_changed_cb),
self);
gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("pages_notebook")), (self->priv->n_duplicates > 0) ? 0 : 1);
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("progress_label")), _("Search completed"));
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("search_details_label")), "");
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (GET_WIDGET ("search_progressbar")), 1.0);
gtk_widget_set_sensitive (GET_WIDGET ("stop_button"), FALSE);
duplicates_list_view_selection_changed_cb (NULL, self);
after_checksums (self);
return;
}
......@@ -746,12 +761,18 @@ start_next_checksum (GthFindDuplicates *self)
}
/* -- search_directory -- */
static void
done_func (GObject *object,
GError *error,
gpointer user_data)
{
GthFindDuplicates *self = user_data;
GList *scan;
GHashTable *file_sizes;
GList *possible_duplicates;
g_source_remove (self->priv->pulse_event_id);
self->priv->pulse_event_id = 0;
......@@ -768,7 +789,45 @@ done_func (GObject *object,
return;
}
self->priv->files = g_list_reverse (self->priv->files);
/* ignore files with an unique size */
file_sizes = g_hash_table_new_full (g_int64_hash, g_int64_equal, NULL, NULL);
for (scan = self->priv->files; scan; scan = scan->next) {
GthFileData *file_data = scan->data;
gpointer value;
int n_files;
gint64 size;
size = g_file_info_get_size (file_data->info);
value = g_hash_table_lookup (file_sizes, &size);
n_files = (value == NULL) ? 0 : GPOINTER_TO_INT (value);
n_files += 1;
g_hash_table_insert (file_sizes, &size, GINT_TO_POINTER (n_files));
}
possible_duplicates = NULL;
for (scan = self->priv->files; scan; scan = scan->next) {
GthFileData *file_data = scan->data;
gint64 size;
gpointer value;
int n_files;
size = g_file_info_get_size (file_data->info);
value = g_hash_table_lookup (file_sizes, &size);
if (value == NULL)
continue;
n_files = GPOINTER_TO_INT (value);
if (n_files > 1)
possible_duplicates = g_list_prepend (possible_duplicates, g_object_ref (file_data));
}
g_hash_table_destroy (file_sizes);
/* start computing checksums */
_g_object_list_unref (self->priv->files);
self->priv->files = possible_duplicates;
self->priv->n_files = g_list_length (self->priv->files);
self->priv->n_file = 0;
start_next_checksum (self);
......@@ -954,6 +1013,7 @@ position_treeviewcolumn_clicked_cb (GtkTreeViewColumn *treeviewcolumn,
_file_list_set_sort_column_id (self, treeviewcolumn, FILE_LIST_COLUMN_POSITION);
}
static GList *
get_selected_files (GthFindDuplicates *self)
{
......
......@@ -1363,6 +1363,8 @@ post_photo_file_buffer_ready_cb (void **buffer,
g_free (tags);
g_list_free (keys);
g_free (description);
g_free (title);
g_hash_table_unref (data_set);
}
......
......@@ -162,7 +162,6 @@ screenshot_ready_cb (GdkPixbuf *pixbuf,
G_CALLBACK (save_screenshot_task_completed_cb),
save_data);
gth_browser_exec_task (GTH_BROWSER (save_data->browser), task, GTH_TASK_FLAGS_IGNORE_ERROR);
}
......
......@@ -35,6 +35,8 @@
#define OVERLAY_MARGIN 10
#define APPLY_ICC_PROFILE_BUTTON 4
#undef ALWAYS_LOAD_ORIGINAL_SIZE
#define N_FORWARD_PRELOADERS 2
#define N_BACKWARD_PRELOADERS 2
static void gth_viewer_page_interface_init (GthViewerPageInterface *iface);
......@@ -100,6 +102,8 @@ struct _GthImageViewerPagePrivate {
gboolean pointer_on_overview;
guint hide_overview_id;
gboolean apply_icc_profile;
GthFileData *next_file_data[N_FORWARD_PRELOADERS];
GthFileData *prev_file_data[N_BACKWARD_PRELOADERS];
};
......@@ -191,6 +195,44 @@ _gth_image_preloader_get_requested_size_for_current_image (GthImageViewerPage *s
}
static void
_gth_image_viewer_page_load_with_preloader (GthImageViewerPage *self,
GthFileData *file_data,
int requested_size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
if (self->priv->apply_icc_profile)
gth_image_preloader_set_out_profile (self->priv->preloader, gth_browser_get_screen_profile (self->priv->browser));
else
gth_image_preloader_set_out_profile (self->priv->preloader, NULL);
g_object_ref (self);
gth_image_preloader_load (self->priv->preloader,
file_data,
requested_size,
cancellable,
callback,
user_data,
N_FORWARD_PRELOADERS + N_BACKWARD_PRELOADERS,
self->priv->next_file_data[0],
self->priv->next_file_data[1],
self->priv->prev_file_data[0],
self->priv->prev_file_data[1]);
}
static gboolean
_gth_image_viewer_page_load_with_preloader_finish (GthImageViewerPage *self)
{
gboolean active = self->priv->active;
g_object_unref (self);
return active;
}
static void
different_quality_ready_cb (GObject *source_object,
GAsyncResult *result,
......@@ -208,6 +250,9 @@ different_quality_ready_cb (GObject *source_object,
int w1, h1, w2, h2;
gboolean got_better_quality;
if (! _gth_image_viewer_page_load_with_preloader_finish (self))
return;
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
&requested,
......@@ -288,16 +333,6 @@ _g_mime_type_can_load_different_quality (const char *mime_type)
}
static void
_gth_image_preloader_init_preloader (GthImageViewerPage *self)
{
if (self->priv->apply_icc_profile)
gth_image_preloader_set_out_profile (self->priv->preloader, gth_browser_get_screen_profile (self->priv->browser));
else
gth_image_preloader_set_out_profile (self->priv->preloader, NULL);
}
static gboolean
update_quality_cb (gpointer user_data)
{
......@@ -308,21 +343,24 @@ update_quality_cb (gpointer user_data)
self->priv->update_quality_id = 0;
}
if (! self->priv->active)
return FALSE;
if (self->priv->viewer == NULL)
return FALSE;
if (self->priv->loading_image)
return FALSE;
if (! self->priv->image_changed && ! _g_mime_type_can_load_different_quality (gth_file_data_get_mime_type (self->priv->file_data)))
return FALSE;
_gth_image_preloader_init_preloader (self);
gth_image_preloader_load (self->priv->preloader,
self->priv->image_changed ? GTH_MODIFIED_IMAGE : self->priv->file_data,
_gth_image_preloader_get_requested_size_for_current_image (self),
NULL,
different_quality_ready_cb,
self,
GTH_NO_PRELOADERS,
NULL);
_gth_image_viewer_page_load_with_preloader (self,
self->priv->image_changed ? GTH_MODIFIED_IMAGE : self->priv->file_data,
_gth_image_preloader_get_requested_size_for_current_image (self),
NULL,
different_quality_ready_cb,
self);
return FALSE;
}
......@@ -547,7 +585,7 @@ viewer_realize_cb (GtkWidget *widget,
GthImageViewerPage *self = user_data;
GtkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (self->priv->viewer, GDK_SELECTION_CLIPBOARD);
clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
g_signal_connect (clipboard,
"owner_change",
G_CALLBACK (clipboard_owner_change_cb),
......@@ -562,7 +600,7 @@ viewer_unrealize_cb (GtkWidget *widget,
GthImageViewerPage *self = user_data;
GtkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (self->priv->viewer, GDK_SELECTION_CLIPBOARD);
clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
g_signal_handlers_disconnect_by_func (clipboard,
G_CALLBACK (clipboard_owner_change_cb),
self);
......@@ -635,6 +673,9 @@ pref_zoom_quality_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
if (! self->priv->active || (self->priv->viewer == NULL))
return;
gth_image_viewer_set_zoom_quality (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_enum (self->priv->settings, PREF_IMAGE_VIEWER_ZOOM_QUALITY));
gtk_widget_queue_draw (self->priv->viewer);
......@@ -648,6 +689,9 @@ pref_zoom_change_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
if (! self->priv->active || (self->priv->viewer == NULL))
return;
gth_image_viewer_set_zoom_change (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_enum (self->priv->settings, PREF_IMAGE_VIEWER_ZOOM_CHANGE));
gtk_widget_queue_draw (self->priv->viewer);
......@@ -661,6 +705,9 @@ pref_reset_scrollbars_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
if (! self->priv->active || (self->priv->viewer == NULL))
return;
gth_image_viewer_set_reset_scrollbars (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_boolean (self->priv->settings, PREF_IMAGE_VIEWER_RESET_SCROLLBARS));
}
......@@ -868,6 +915,7 @@ gth_image_viewer_page_real_activate (GthViewerPage *base,
self->priv->preloader = gth_browser_get_image_preloader (browser);
self->priv->viewer = gth_image_viewer_new ();
g_object_add_weak_pointer (G_OBJECT (self->priv->viewer), &self->priv->viewer);
gtk_widget_add_events (self->priv->viewer, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
gth_image_viewer_page_reset_viewer_tool (self);
gtk_widget_show (self->priv->viewer);
......@@ -1025,6 +1073,8 @@ preloader_load_ready_cb (GObject *source_object,
GError *error = NULL;
self->priv->loading_image = FALSE;
if (! _gth_image_viewer_page_load_with_preloader_finish (self))
return;
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
......@@ -1090,10 +1140,6 @@ clear_data:
}
#define N_FORWARD_PRELOADERS 2
#define N_BACKWARD_PRELOADERS 2
static void
_gth_image_viewer_page_load (GthImageViewerPage *self,
GthFileData *file_data)
......@@ -1101,8 +1147,6 @@ _gth_image_viewer_page_load (GthImageViewerPage *self,
GthFileStore *file_store;
GtkTreeIter iter;
int i;
GthFileData *next_file_data[N_FORWARD_PRELOADERS];
GthFileData *prev_file_data[N_BACKWARD_PRELOADERS];
if (self->priv->file_data != file_data) {
_g_object_unref (self->priv->file_data);
......@@ -1112,9 +1156,9 @@ _gth_image_viewer_page_load (GthImageViewerPage *self,
self->priv->loading_image = TRUE;
for (i = 0; i < N_FORWARD_PRELOADERS; i++)
next_file_data[i] = NULL;
_g_clear_object (&self->priv->next_file_data[i]);
for (i = 0; i < N_BACKWARD_PRELOADERS; i++)
prev_file_data[i] = NULL;
_g_clear_object (&self->priv->prev_file_data[i]);
file_store = gth_browser_get_file_store (self->priv->browser);
if (gth_file_store_find_visible (file_store, self->priv->file_data->file, &iter)) {
......@@ -1124,36 +1168,29 @@ _gth_image_viewer_page_load (GthImageViewerPage *self,
for (i = 0; i < N_FORWARD_PRELOADERS; i++) {
if (! gth_file_store_get_next_visible (file_store, &next_iter))
break;
next_file_data[i] = gth_file_store_get_file (file_store, &next_iter);
self->priv->next_file_data[i] = g_object_ref (gth_file_store_get_file (file_store, &next_iter));
}
next_iter = iter;
for (i = 0; i < N_BACKWARD_PRELOADERS; i++) {
if (! gth_file_store_get_prev_visible (file_store, &next_iter))
break;
prev_file_data[i] = gth_file_store_get_file (file_store, &next_iter);
self->priv->prev_file_data[i] = g_object_ref (gth_file_store_get_file (file_store, &next_iter));
}
gth_image_viewer_set_void (GTH_IMAGE_VIEWER (self->priv->viewer));
}
_gth_image_preloader_init_preloader (self);
gth_image_preloader_load (self->priv->preloader,
self->priv->file_data,
_gth_image_viewer_page_load_with_preloader (self,
self->priv->file_data,
#ifdef ALWAYS_LOAD_ORIGINAL_SIZE
GTH_ORIGINAL_SIZE,
GTH_ORIGINAL_SIZE,
#else
_gth_image_preloader_get_requested_size_for_next_images (self),
_gth_image_preloader_get_requested_size_for_next_images (self),
#endif
NULL,
preloader_load_ready_cb,
self,
N_FORWARD_PRELOADERS + N_BACKWARD_PRELOADERS,
next_file_data[0],
next_file_data[1],
prev_file_data[0],
prev_file_data[1]);
NULL,
preloader_load_ready_cb,
self);
}
......@@ -1198,7 +1235,16 @@ static void
gth_image_viewer_page_real_fullscreen (GthViewerPage *base,
gboolean active)
{
/* void */
GthImageViewerPage *self;
GthImageViewerTool *tool;
self = (GthImageViewerPage *) base;
tool = gth_image_viewer_get_tool (GTH_IMAGE_VIEWER (self->priv->viewer));
if (! GTH_IS_IMAGE_DRAGGER (tool))
return;
g_object_set (tool, "show-frame", ! active, NULL);
}
......@@ -1314,6 +1360,7 @@ save_image_task_completed_cb (GthTask *task,
}
save_data_free (data);
_g_object_unref (task);
}
......@@ -1375,8 +1422,6 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
G_CALLBACK (save_image_task_completed_cb),
data);
gth_browser_exec_task (GTH_BROWSER (self->priv->browser), task, GTH_TASK_FLAGS_DEFAULT);
_g_object_unref (task);
}
......@@ -1607,6 +1652,7 @@ static void
gth_image_viewer_page_finalize (GObject *obj)
{
GthImageViewerPage *self;
int i;
self = GTH_IMAGE_VIEWER_PAGE (obj);
......@@ -1628,6 +1674,11 @@ gth_image_viewer_page_finalize (GObject *obj)
_g_object_unref (self->priv->file_data);
_g_object_unref (self->priv->last_loaded);
for (i = 0; i < N_FORWARD_PRELOADERS; i++)
_g_clear_object (&self->priv->next_file_data[i]);
for (i = 0; i < N_BACKWARD_PRELOADERS; i++)
_g_clear_object (&self->priv->prev_file_data[i]);
G_OBJECT_CLASS (gth_image_viewer_page_parent_class)->finalize (obj);
}
......@@ -1687,6 +1738,11 @@ gth_image_viewer_page_init (GthImageViewerPage *self)
self->priv->pointer_on_viewer = FALSE;
self->priv->hide_overview_id = 0;
self->priv->apply_icc_profile = TRUE;
for (i = 0; i < N_FORWARD_PRELOADERS; i++)
self->priv->next_file_data[i] = NULL;
for (i = 0; i < N_BACKWARD_PRELOADERS; i++)
self->priv->prev_file_data[i] = NULL;
}
......@@ -1914,6 +1970,7 @@ get_original_data_free (OriginalImageData *data)
if (data == NULL)
return;
_g_object_unref (data->viewer_page);
_g_object_unref (data->cancellable);
_g_object_unref (data->result);
g_free (data);
......@@ -1926,8 +1983,13 @@ original_image_ready_cb (GObject *source_object,
gpointer user_data)
{
OriginalImageData *data = user_data;
GthImage *image = NULL;
GError *error = NULL;
GthImage *image = NULL;
GError *error = NULL;
if (! _gth_image_viewer_page_load_with_preloader_finish (data->viewer_page)) {
get_original_data_free (data);
return;
}
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
......@@ -1959,22 +2021,32 @@ gth_image_viewer_page_get_original (GthImageViewerPage *self,
OriginalImageData *data;
data = get_original_data_new ();
data->viewer_page = self;
data->viewer_page = g_object_ref (self);
data->result = g_simple_async_result_new (G_OBJECT (self),
ready_callback,
user_data,
gth_image_viewer_page_get_original);
data->cancellable = (cancellable != NULL) ? g_object_ref (cancellable) : g_cancellable_new ();
_gth_image_preloader_init_preloader (self);
gth_image_preloader_load (self->priv->preloader,
self->priv->image_changed ? GTH_MODIFIED_IMAGE : self->priv->file_data,
GTH_ORIGINAL_SIZE,
data->cancellable,
original_image_ready_cb,
data,
GTH_NO_PRELOADERS,
NULL);
if (gth_image_viewer_is_animation (GTH_IMAGE_VIEWER (self->priv->viewer))) {
GthImage