00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00026 #include <errno.h>
00027 #include <fcntl.h>
00028 #include <glib.h>
00029 #include <glib/gstdio.h>
00030 #include <gtk/gtk.h>
00031 #include <libtar.h>
00032
00033 #include "application-data.h"
00034 #include "frame-common.h"
00035 #include "frame-private.h"
00036 #include "frame-saving.h"
00037 #include "frame-utilities.h"
00038 #include "machine.h"
00039 #include "notebook.h"
00040 #include "time-period.h"
00041
00042
00043
00045 static void frame_save_private (frame_t *frame, GKeyFile *file)
00046 {
00047
00048 if (frame->save_private)
00049 frame->save_private (frame, file);
00050 else
00051 g_warning ("frame_save_private: No save_private function in frame %u, deprecated plugin (%s) format (0.3.1)", frame->id, frame->type);
00052 }
00053
00054
00055
00057 static void frame_restore_private (frame_t *frame, GKeyFile *file)
00058 {
00059
00060 if (frame->restore_private)
00061 frame->restore_private (frame, file);
00062 else
00063 g_warning ("frame_restore_private: No restore_private function in frame %u, deprecated plugin (%s) format (0.3.1)", frame->id, frame->type);
00064 }
00065
00066
00067
00068 GKeyFile *frame_to_key_file (frame_t *frame, guint left, guint top)
00069 {
00070 gchar *size_label = NULL;
00071 GKeyFile *keyfile = g_key_file_new ();
00072 gint *list_buffer = g_malloc (sizeof (gint) * 2);
00073
00074
00075 g_key_file_set_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_TYPE, frame->type);
00076
00077 switch (frame->size) {
00078 case LARGE:
00079 size_label = g_strdup ("LARGE");
00080 break;
00081 case NORMAL:
00082 size_label = g_strdup ("NORMAL");
00083 break;
00084 case FULL:
00085 size_label = g_strdup ("FULL");
00086 break;
00087 default:
00088 size_label = g_strdup ("INVALID");
00089 break;
00090 }
00091 g_key_file_set_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_SIZE, size_label);
00092 g_free (size_label);
00093
00094 g_key_file_set_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_MACHINE,
00095 machine_get_folder_name (frame->display_machine));
00096
00097 list_buffer[0] = frame->display_period.type;
00098 list_buffer[1] = frame->display_period.value;
00099 g_key_file_set_integer_list (keyfile, FTGKF_GROUP_FRAME, FTGKF_PERIOD, list_buffer, 2);
00100
00101
00102
00103 list_buffer[0] = left;
00104 list_buffer[1] = top;
00105 g_key_file_set_integer_list (keyfile, FTGKF_GROUP_POSITION, FTGKF_POSITION, list_buffer, 2);
00106
00107
00108
00109 frame_save_private (frame, keyfile);
00110
00111 g_free (list_buffer);
00112 return keyfile;
00113 }
00114
00115
00116
00117 int frame_table_save_to_files (const char *savedirpath, frame_table_t *tab)
00118 {
00119 synema_instance_t *inst = synema_instance ();
00120 const gchar *tablabel = notebook_get_tab_label (GTK_NOTEBOOK (gtk_builder_get_object (inst->builder, "notebook")), tab->table_box);
00121 gchar *buffer = NULL;
00122 gchar *framepath = NULL;
00123 gchar *path = NULL;
00124 GError *err = NULL;
00125 gint nbindex = gtk_notebook_page_num (GTK_NOTEBOOK (gtk_builder_get_object (inst->builder, "notebook")), tab->table_box);
00126 GFile *file = NULL;
00127 GFileOutputStream *stream = NULL;
00128 GKeyFile *keyfile = NULL;
00129 guint left, top, index = 0;
00130 gsize len = 0;
00131 GList *iter = tab->frames_list;
00132
00133 path = g_strdup_printf ("%s/%i__%s", savedirpath, nbindex, tablabel);
00134
00135 if (g_mkdir_with_parents (path, 0777)) {
00136 g_warning ("frame_table_save_to_file: Could not make the saved frames directory (%s)", g_strerror (errno));
00137 g_free (path);
00138 return -1;
00139 }
00140
00141 if (iter) {
00142 do {
00143 if (!frame_get_coordinates (iter->data, tab->table, &left, &top)) {
00144 g_warning ("frame_table_save_to_file: A frame could not be saved (not in the table) (err0)");
00145 } else {
00146 keyfile = frame_to_key_file (iter->data, left, top);
00147 buffer = g_key_file_to_data (keyfile, &len, &err);
00148 if (err) {
00149 g_warning ("frame_table_save_to_file: A frame could not be saved (%s) (err1)", err->message);
00150 g_clear_error (&err);
00151 } else {
00152 framepath = g_strdup_printf ("%s/%03d"FRAME_SAVE_SUFFIX, path, index);
00153 index++;
00154 file = g_file_new_for_path (framepath);
00155 g_free (framepath);
00156
00157 stream = g_file_replace (file, NULL, TRUE, G_FILE_CREATE_NONE, NULL, &err);
00158 if (err) {
00159 g_warning ("frame_table_save_to_file: A frame could not be saved (%s) (err2)", err->message);
00160 g_clear_error (&err);
00161 } else {
00162 if (g_output_stream_write (G_OUTPUT_STREAM (stream), FRAME_HEADER, g_utf8_strlen (FRAME_HEADER, -1), NULL, &err) == -1) {
00163 g_warning ("frame_table_save_to_file: A frame could not be saved (%s) (err3)", err->message);
00164 g_clear_error (&err);
00165 }
00166 if (g_output_stream_write (G_OUTPUT_STREAM (stream), buffer, len, NULL, &err) == -1) {
00167 g_warning ("frame_table_save_to_file: A frame could not be saved (%s) (err4)", err->message);
00168 g_clear_error (&err);
00169 }
00170 g_object_unref (stream);
00171 }
00172
00173 g_object_unref (file);
00174 }
00175
00176 g_key_file_free (keyfile);
00177 g_free (buffer);
00178 }
00179 } while ((iter = g_list_next (iter)) != NULL);
00180 }
00181
00182 g_free (path);
00183 return 0;
00184 }
00185
00186
00187
00188 frame_t *file_to_frame (const char *path, guint *left, guint *top)
00189 {
00190 synema_instance_t *inst = synema_instance ();
00191 frame_t *frame = NULL;
00192 gchar *plugin_type = NULL;
00193 gchar *buffer = NULL;
00194 GError *err = NULL;
00195 gint *list_buffer = NULL;
00196 GKeyFile *keyfile = g_key_file_new ();
00197 gsize list_len = 0;
00198 machine_t *machine = NULL;
00199 size_ratio_t size;
00200 time_period_t period = {0,0};
00201
00202
00203
00204 g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &err);
00205 if (err) {
00206 g_warning ("file_to_frame: Opening file %s failed (%s)", path, err->message);
00207 g_clear_error (&err);
00208 return NULL;
00209 }
00210
00211
00212
00213 plugin_type = g_key_file_get_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_TYPE, &err);
00214 if (err) {
00215 g_warning ("file_to_frame: Could not read plugin type (%s)", err->message);
00216 g_clear_error (&err);
00217 g_key_file_free (keyfile);
00218 return NULL;
00219 }
00220 if ((frame = frame_new (plugin_type)) == NULL) {
00221 g_warning ("file_to_frame: Unsupported plugin type %s", plugin_type);
00222 g_key_file_free (keyfile);
00223 g_free (plugin_type);
00224 return NULL;
00225 }
00226 g_free (plugin_type);
00227
00228
00229
00230 buffer = g_key_file_get_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_SIZE, &err);
00231 if (err) {
00232 g_warning ("file_to_frame: Could not read size ratio (%s)", err->message);
00233 g_clear_error (&err);
00234 g_key_file_free (keyfile);
00235 frame_free_uninitialised (frame);
00236 return NULL;
00237 }
00238
00239 if (g_strcmp0 (buffer, "LARGE") == 0)
00240 size = LARGE;
00241 else if (g_strcmp0 (buffer, "NORMAL") == 0)
00242 size = NORMAL;
00243 else if (g_strcmp0 (buffer, "FULL") == 0)
00244 size = FULL;
00245 else {
00246 g_warning ("file_to_frame: Unsupported size ratio %s", buffer);
00247 g_key_file_free (keyfile);
00248 frame_free_uninitialised (frame);
00249 g_free (buffer);
00250 return NULL;
00251 }
00252 g_free (buffer);
00253
00254
00255
00256 buffer = g_key_file_get_string (keyfile, FTGKF_GROUP_FRAME, FTGKF_MACHINE, &err);
00257 if (err) {
00258 g_warning ("file_to_frame: Could not read machine name (%s)", err->message);
00259 g_clear_error (&err);
00260 g_key_file_free (keyfile);
00261 frame_free_uninitialised (frame);
00262 return NULL;
00263 }
00264 if ((machine = machine_list_find_by_name (inst->machines_list, buffer)) == NULL) {
00265 g_warning ("file_to_frame: Could not find machine %s", buffer);
00266 g_key_file_free (keyfile);
00267 frame_free_uninitialised (frame);
00268 g_free (buffer);
00269 return NULL;
00270 }
00271 g_free (buffer);
00272
00273
00274
00275 list_buffer = g_key_file_get_integer_list (keyfile, FTGKF_GROUP_FRAME, FTGKF_PERIOD, &list_len, &err);
00276 if (err) {
00277 g_warning ("file_to_frame: Could not read time period (%s)", err->message);
00278 g_clear_error (&err);
00279 g_key_file_free (keyfile);
00280 frame_free_uninitialised (frame);
00281 return NULL;
00282 }
00283 if (list_len == 2) {
00284 period.type = list_buffer[0];
00285 period.value = list_buffer[1];
00286 } else {
00287 g_warning ("file_to_frame: Invalid time period setting");
00288 g_key_file_free (keyfile);
00289 frame_free_uninitialised (frame);
00290 g_free (list_buffer);
00291 return NULL;
00292 }
00293 g_free (list_buffer);
00294
00295
00296
00297 if (left || top) {
00298 list_buffer = g_key_file_get_integer_list (keyfile, FTGKF_GROUP_POSITION, FTGKF_POSITION, &list_len, &err);
00299 if (err) {
00300 g_warning ("file_to_frame: Could not read table coordinates (%s)", err->message);
00301 g_clear_error (&err);
00302 g_key_file_free (keyfile);
00303 frame_free_uninitialised (frame);
00304 return NULL;
00305 }
00306
00307 if (list_len == 2) {
00308 *left = list_buffer[0];
00309 *top = list_buffer[1];
00310 } else {
00311 g_warning ("file_to_frame: Invalid table coordinate setting");
00312 g_key_file_free (keyfile);
00313 frame_free_uninitialised (frame);
00314 g_free (list_buffer);
00315 return NULL;
00316 }
00317 g_free (list_buffer);
00318 }
00319
00320
00321
00322 if (frame_initialise (frame, size, machine, &period) != 0) {
00323 frame_free (frame);
00324 g_key_file_free (keyfile);
00325 g_warning ("file_to_frame: Frame could not be initialised");
00326 return NULL;
00327 }
00328
00329
00330
00331 frame_restore_private (frame, keyfile);
00332
00333 g_key_file_free (keyfile);
00334 return frame;
00335 }
00336
00337
00338
00339 int frame_table_load_from_files (const char *subdirpath, frame_table_t *tab)
00340 {
00341 gchar *framepath = NULL;
00342 GError *err = NULL;
00343 GFile *dirfile = NULL;
00344 GFileEnumerator *direnum = NULL;
00345 GFileInfo *dirinfo = NULL;
00346 GFileInfo *current = NULL;
00347 guint left = 0, top = 0;
00348
00349 dirfile = g_file_new_for_path (subdirpath);
00350
00351 tab->position = g_ascii_strtod (g_strrstr (subdirpath, "/") + 1, NULL);
00352
00353 dirinfo = g_file_query_info (dirfile, "standard::type", G_FILE_QUERY_INFO_NONE, NULL, &err);
00354 if (err) {
00355
00356
00357 g_clear_error (&err);
00358 g_object_unref (dirfile);
00359 return -1;
00360 }
00361 if (g_file_info_get_file_type (dirinfo) != G_FILE_TYPE_DIRECTORY) {
00362
00363 return -1;
00364 }
00365 g_object_unref (dirinfo);
00366
00367 direnum = g_file_enumerate_children (dirfile, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, &err);
00368 if (err) {
00369 g_warning ("frame_table_load_from_files: Error while reading the saved frames directory (%s)", err->message);
00370 g_clear_error (&err);
00371 g_object_unref (dirfile);
00372 return -1;
00373 }
00374
00375
00376 while ((current = g_file_enumerator_next_file (direnum, NULL, &err)) != NULL) {
00377 if (err) {
00378 g_warning ("frame_table_load_from_files: Error while reading a file of the saved frames (%s)", err->message);
00379 g_clear_error (&err);
00380 } else {
00381 if (g_str_has_suffix (g_file_info_get_name (current), FRAME_SAVE_SUFFIX)) {
00382 framepath = g_strdup_printf ("%s/%s", subdirpath, g_file_info_get_name (current));
00383 frame_t *frame = file_to_frame (framepath, &left, &top);
00384 g_free (framepath);
00385 if (frame) {
00386 frame_table_add_with_coords (tab, frame, left, top);
00387 }
00388 }
00389 g_object_unref (current);
00390 }
00391 }
00392
00393 g_object_unref (direnum);
00394 g_object_unref (dirfile);
00395 return 0;
00396 }
00397
00398
00399
00400 void save_frames_dialog_show (GtkToolButton *button, gpointer user_data)
00401 {
00402 synema_instance_t *inst = synema_instance ();
00403 gchar *path = NULL;
00404 gchar *tarpath = NULL;
00405 gchar *taruri = NULL;
00406 gchar *dlg_objects[] = {"save_frames_dialog", NULL};
00407 GError *err = NULL;
00408 GFile *tmp = NULL;
00409 GList *iter = NULL;
00410 GtkRecentManager *manager = NULL;
00411 GtkWidget *dialog = NULL;
00412 TAR *tarhandle = NULL;
00413
00414
00415
00416 path = g_strdup_printf ("%s/window.ui", inst->data_dir);
00417 gtk_builder_add_objects_from_file (inst->builder, path, dlg_objects, &err);
00418 g_free (path);
00419 if (err) {
00420 g_warning ("frame_on_new: %s", err->message);
00421 g_clear_error (&err);
00422 return;
00423 }
00424
00425
00426
00427 dialog = (GtkWidget *) gtk_builder_get_object (inst->builder, "save_frames_dialog");
00428 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
00429
00430
00431
00432 switch (result) {
00433 case GTK_RESPONSE_OK:
00434 gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
00435 path = g_strdup_printf ("%s/"FRAME_SAVING_DIR, inst->tmp_dir);
00436 if (g_mkdir_with_parents (path, 0777)) {
00437 g_warning ("save_frames_dialog_show: Could not create a temporary directory in which frames could be written (%s)", g_strerror (errno));
00438 error_dialog ("<b>Failed to save file</b>\n\nCould not create a temporary directory in which frames could be written (%s)", g_strerror (errno));
00439 recursive_remove (path);
00440 g_free (path);
00441 break;
00442 }
00443
00444
00445 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (inst->builder, "save_frames_all_tabs")))) {
00446 iter = inst->tables_list;
00447 if (iter) {
00448 do {
00449 frame_table_save_to_files (path, iter->data);
00450 } while ((iter = g_list_next (iter)) != NULL);
00451 }
00452 }
00453
00454 else {
00455 frame_table_save_to_files (path, inst->current_table);
00456 }
00457
00458 tarpath = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
00459 if (!g_str_has_suffix (tarpath, TAB_SAVE_SUFFIX)) {
00460 char *tmp = g_strdup_printf ("%s"TAB_SAVE_SUFFIX, tarpath);
00461 g_free (tarpath);
00462 tarpath = tmp;
00463 }
00464
00465 if (tar_open (&tarhandle, tarpath, NULL, O_CREAT | O_TRUNC | O_WRONLY, 0666, 0)) {
00466 g_warning ("save_frames_dialog_show: Could not create a tar archive to save the frames (%s)", g_strerror (errno));
00467 error_dialog ("<b>Failed to save file</b>\n\nCould not create a tar archive to save the frames (%s)", g_strerror (errno));
00468 g_free (tarpath);
00469 recursive_remove (path);
00470 g_free (path);
00471 break;
00472 }
00473
00474 if (tar_append_tree (tarhandle, path, SAVED_FRAMES_DIR)) {
00475 g_warning ("save_frames_dialog_show: Could not put frames into the tar archive (%s)", g_strerror (errno));
00476 error_dialog ("<b>Failed to save file</b>\n\nCould not put frames into the tar archive (%s)", g_strerror (errno));
00477 tar_close (tarhandle);
00478 g_free (tarpath);
00479 g_free (path);
00480 break;
00481 }
00482 recursive_remove (path);
00483 g_free (path);
00484
00485 if (tar_append_eof (tarhandle)) {
00486 g_warning ("save_frames_dialog_show: Could not set the EOF of the tar archive (%s)", g_strerror (errno));
00487 error_dialog ("<b>Failed to save file</b>\n\nCould not set the EOF of the tar archive (%s)\nThis is most likely a libtar bug", g_strerror (errno));
00488 tar_close (tarhandle);
00489 g_free (tarpath);
00490 break;
00491 }
00492
00493 if (tar_close (tarhandle)) {
00494 g_warning ("save_frames_dialog_show: Error on closing the tar archive (%s)", g_strerror (errno));
00495 error_dialog ("<b>Failed to save file</b>\n\nError on closing the tar archive (%s)\nThis is most likely a libtar bug", g_strerror (errno));
00496 g_free (tarpath);
00497 break;
00498 }
00499 manager = gtk_recent_manager_get_default ();
00500 tmp = g_file_new_for_path (tarpath);
00501 taruri = g_file_get_uri (tmp);
00502 gtk_recent_manager_add_item (manager, taruri);
00503 g_free (tarpath);
00504 g_free (taruri);
00505 g_object_unref (tmp);
00506 default:
00507 break;
00508 }
00509
00510 gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
00511 gtk_widget_destroy (dialog);
00512 }