1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD et Damien
3 CALISTE, laboratoire L_Sim, (2001-2005)
4
5 Adresse mèl :
6 BILLARD, non joignable par mèl ;
7 CALISTE, damien P caliste AT cea P fr.
8
9 Ce logiciel est un programme informatique servant à visualiser des
10 structures atomiques dans un rendu pseudo-3D.
11
12 Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 respectant les principes de diffusion des logiciels libres. Vous pouvez
14 utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 sur le site "http://www.cecill.info".
17
18 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22
23 /* LICENCE SUM UP
24 Copyright CEA, contributors : Luc BILLARD et Damien
25 CALISTE, laboratoire L_Sim, (2001-2005)
26
27 E-mail address:
28 BILLARD, not reachable any more ;
29 CALISTE, damien P caliste AT cea P fr.
30
31 This software is a computer program whose purpose is to visualize atomic
32 configurations in 3D.
33
34 This software is governed by the CeCILL license under French law and
35 abiding by the rules of distribution of free software. You can use,
36 modify and/ or redistribute the software under the terms of the CeCILL
37 license as circulated by CEA, CNRS and INRIA at the following URL
38 "http://www.cecill.info".
39
40 The fact that you are presently reading this means that you have had
41 knowledge of the CeCILL license and that you accept its terms. You can
42 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 #include "panelBrowser.h"
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <math.h>
50 #include <time.h>
51
52 #include <glib/gstdio.h>
53 #include <gtk/gtk.h>
54
55 #include <visu_gtk.h>
56 #include <visu_tools.h>
57 #include <visu_basic.h>
58 #include <visu_configFile.h>
59 #include <visu_dataatomic.h>
60 #include <visu_dataspin.h>
61
62 #include <support.h>
63 #include <gtk_main.h>
64 #include <extraGtkFunctions/gtk_dumpDialogWidget.h>
65 #include <gtk_openGLWidget.h>
66 #include <gtk_renderingWindowWidget.h>
67
68 /**
69 * SECTION: panelBrowser
70 * @short_description: A tab to view a list of files and quickly
71 * change from one to another.
72 *
73 * <para>One can display a message about the file list by calling
74 * visu_ui_panel_browser_setMessage(). It is possible also to change
75 * the browser directory or directories with
76 * visu_ui_panel_browser_setCurrentDirectory().</para>
77 */
78
79 static GtkWidget *panelBrowser, *vbox1;
80 static GtkTreeStore *treeStoreFiles;
81 static GtkTreeModel *treeStoreFilesFilter;
82 enum
83 {
84 COLUMN_BOOLEAN, /* Rendered or not. */
85 COLUMN_NAME, /* File name in locale of the file system. */
86 COLUMN_NAME_UTF8, /* File name in UTF8 (to view it in GTK). */
87 COLUMN_DATE, /* The modified time for the file. */
88 COLUMN_DATA, /* File info (size / date). */
89 COLUMN_ACTIVE, /* A boolean to set if this file is filtered or not. */
90 COLUMN_FILE_KIND, /* An integer that correspond to the file type. */
91 COLUMN_FILE_VALID, /* TRUE if the file is parsable. */
92 COLUMN_FILE_ERROR_ID, /* a stock icon id. */
93 N_COLUMNS
94 };
95 static gboolean dirDirty;
_toSpherical(void)96 static GtkWidget *fileTree;
97 static GtkWidget *scrolledwindow1, *infoBar, *labelInfo;
98 static GtkWidget *labelDirectory;
99 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 17
100 static GtkWidget *infoImg;
101 #endif
102 /* A list of array of directory names and the current position in the list. */
103 static GList *historyBrowseredDirectory, *currentHistory;
104 /* A NULL terminated array of directories names, currently printed. */
105 static gchar **currentBrowseredDirectory;
106 /* The string common to all paths in currentBrowseredDirectory. */
107 static gchar *commonBrowseredDirectory;
108 #define HISTORY_TOOLTIP_PREV "Go to previously visited directories in history."
_fromSpherical(void)109 #define HISTORY_TOOLTIP_NEXT "Go to next visited directories in history."
110
111 static GtkWidget *entryFilterBrowser;
112 enum
113 {
114 PANEL_BROWSER_COLUMN_FILTER_LABEL,
115 PANEL_BROWSER_COLUMN_FILTER_ID,
116 PANEL_BROWSER_N_COLUMN_FILTER
117 };
118 static GtkWidget *comboFilter;
119 struct TimerInfo_
120 {
121 GtkWidget *bt;
122 guint timer, label, nbFiles;
123 gboolean abort;
124 };
125
126 static GtkWidget *imagePlay;
127 static GtkWidget *imageStop;
128 static GtkWidget *buttonPlayStop;
129 static GtkWidget *spinDelay;
130
gtk_spin_create_direction()131 static GtkWidget *buttonPrevious;
132 static GtkWidget *buttonNext;
133 static GtkWidget *buttonDirPrev;
134 static GtkWidget *buttonDirNext;
135 static GtkWidget *buttonSelectAll;
136 static GtkWidget *buttonUnselectAll;
137 static GtkWidget *buttonDirectory;
138 static GtkWidget *buttonRecurse;
139 static GtkWidget *radioGoAround, *radioGoOnce, *radioGoAndBack;
140 static int currentBrowseDirection;
141 static GtkTreePath *startBrowsePath;
142 static GtkWidget *buttonDumpAll;
143 /* GtkProgressBar *progressBarDump; */
144
145 static GtkWidget *createInteriorBrowser();
146 static void browseDirectory();
147 static void addParsedDirectory(int commonPathLen, const gchar *root,
148 GDir *gdir, gboolean recurse,
149 GList *atFmt, gint atKind, GList *spFmt, gint spKind,
150 struct TimerInfo_ *timer);
151 static gboolean showProgressBar(gpointer data);
152 static void hideProgressBar(struct TimerInfo_ *timer);
153 /* Load and render the given file. The iter is given in the filter
154 model. */
155 static gboolean browserLoad(gchar *filename, gchar* fileUTF8,
156 GtkTreeIter *iter, int nSet);
157 /* For the given iter load it. The iter must be given
158 in the filter model. */
159 static gboolean navigateInFiles(GtkTreePath *path, GtkTreeIter *iterSelected);
160 static void selectFile(GtkTreePath *path, GtkTreeIter *iter);
161
162 gboolean gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *last, GtkTreePath **path);
163 void panelBrowserSet_labelCurrentDir();
164
165 /* Callbacks */
166 static void onCheckFile(GtkCellRendererToggle *cell_renderer, gchar *path,
167 gpointer user_data);
168 static void onTreeviewActivated(GtkTreeView *treeview, GtkTreePath *path,
169 GtkTreeViewColumn *col, gpointer user_data);
170 static void navigateClicked(GtkButton *button, gpointer data);
171 static void checkFiles(GtkButton *button, gpointer data);
172 static void onDirectoryClicked(GtkButton *button, gpointer data);
173 static void onPlayStopClicked(GtkToggleButton *button _U_, gpointer data _U_);
174 static void stopPlayStop(gpointer data);
175 static void onSpinDelayChangeValue(GtkSpinButton *spinbutton, gpointer user_data);
176 void onDumpButtonClicked(GtkButton *button, gpointer user_data);
177 static void onFilterChanged(GtkEditable *entry, gpointer user_data);
178 void abortDumpAll(GtkButton *button, gpointer data);
179 void updateDumpAllProgressBar(gpointer data);
180 static gboolean panelBrowserIsIterVisible(GtkTreeModel *model,
181 GtkTreeIter *iter, gpointer data);
182 static void onRefreshDir(GtkButton *button, gpointer data);
183 static void onEnter(VisuUiPanel *visu_ui_panel, gpointer data);
184 static gboolean checkFile(GtkTreeModel *model, GtkTreePath *path,
185 GtkTreeIter *iter, gpointer data);
186 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 17
187 static void onParseAbortClicked(GtkButton *button, gpointer data);
188 #else
189 static void onParseAbortClicked(GtkInfoBar *infoBar, gint response, gpointer data);
190 #endif
191 static void onRecurseToggled(GtkToggleButton *toggle, gpointer data);
192 static void onNewDir(GObject *obj, VisuUiDirectoryType type, gpointer userData);
193 static void onPrevClicked(GtkButton *button, gpointer data);
194 static void onNextClicked(GtkButton *button, gpointer data);
195 static gint onSortNames(GtkTreeModel *model, GtkTreeIter *a,
196 GtkTreeIter *b, gpointer user_data);
197 static void onNextPrevFile(VisuUiRenderingWindow *window, gpointer data);
198
199 static void updateHistory();
200 static void updateDirectionalTooltips();
201
202 /* Parameters customising the dialog. */
203 #define FLAG_PARAMETER_BROWSER_HEADERS "browser_headersVisibility"
204 #define DESC_PARAMETER_BROWSER_HEADERS "Show or hide the headers in the treeview ; boolean 0 or 1"
205 static gboolean showHeaders;
206 #define FLAG_PARAMETER_BROWSER_DATE "browser_dateVisibility"
207 #define DESC_PARAMETER_BROWSER_DATE "Show or hide the date column in the treeview ; boolean 0 or 1"
208 static gboolean showDate;
209 static void exportParameters(GString *data, VisuData *dataObj);
210
gtk_spin_create_color_wheel()211 VisuUiPanel* visu_ui_panel_browser_init(VisuUiMain *ui)
212 {
213 char *cl = _("Browser");
214 char *tl = _("Browser");
215 VisuConfigFileEntry *entry;
216
217 panelBrowser = visu_ui_panel_newWithIconFromPath("Panel_browser", cl, tl,
218 "stock-browser_20.png");
219 if (!panelBrowser)
220 return (VisuUiPanel*)0;
221 vbox1 = gtk_vbox_new(FALSE, 0);
222 fileTree = (GtkWidget*)0;
223 buttonDirPrev = (GtkWidget*)0;
224 buttonDirNext = (GtkWidget*)0;
225 gtk_container_add(GTK_CONTAINER(panelBrowser), vbox1);
226 gtk_container_set_border_width(GTK_CONTAINER(panelBrowser), 5);
227 visu_ui_panel_setDockable(VISU_UI_PANEL(panelBrowser), TRUE);
228
229 /* Create the configuration file entries. */
230 entry = visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
231 FLAG_PARAMETER_BROWSER_HEADERS,
232 DESC_PARAMETER_BROWSER_HEADERS,
233 &showHeaders, FALSE);
234 visu_config_file_entry_setVersion(entry, 3.5f);
235 entry = visu_config_file_addBooleanEntry(VISU_CONFIG_FILE_PARAMETER,
236 FLAG_PARAMETER_BROWSER_DATE,
237 DESC_PARAMETER_BROWSER_DATE,
238 &showDate, FALSE);
239 visu_config_file_entry_setVersion(entry, 3.5f);
240 visu_config_file_addExportFunction(VISU_CONFIG_FILE_PARAMETER,
241 exportParameters);
242
243 /* Create the tree structure. */
244 treeStoreFiles = gtk_tree_store_new(N_COLUMNS,
245 G_TYPE_BOOLEAN,
246 G_TYPE_STRING,
247 G_TYPE_STRING,
248 G_TYPE_UINT,
249 G_TYPE_STRING,
250 G_TYPE_BOOLEAN,
251 G_TYPE_INT,
252 G_TYPE_BOOLEAN,
253 G_TYPE_STRING);
254 /* Use the COLUMN_ACTIVE as a flag to hide or not the rows that
255 don't match the filter value. */
256 treeStoreFilesFilter = gtk_tree_model_filter_new(GTK_TREE_MODEL(treeStoreFiles), NULL);
257 gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(treeStoreFilesFilter),
258 panelBrowserIsIterVisible, (gpointer)0,
259 (GDestroyNotify)0);
260 /* gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(treeStoreFilesFilter), COLUMN_ACTIVE); */
261
262 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(treeStoreFiles),
263 COLUMN_NAME_UTF8, onSortNames,
264 (gpointer)0, (GDestroyNotify)0);
265
266 /* Add a new row to the model */
267 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(treeStoreFiles),
268 COLUMN_NAME_UTF8, GTK_SORT_ASCENDING);
269
270 /* Initialise the values. */
271 currentBrowseredDirectory = (gchar**)0;
272 commonBrowseredDirectory = (gchar*)0;
273 historyBrowseredDirectory = (GList*)0;
274 currentHistory = (GList*)0;
275 currentBrowseDirection = VISU_UI_PANEL_BROWSER_NEXT;
276 showHeaders = FALSE;
277 showDate = FALSE;
278 dirDirty = FALSE;
279
280 /* Create the callbacks of all the sensitive widgets. */
281 g_signal_connect(G_OBJECT(panelBrowser), "page-entered",
282 G_CALLBACK(onEnter), (gpointer)0);
283 g_signal_connect(ui, "DirectoryChanged",
284 G_CALLBACK(onNewDir), (gpointer)0);
285 g_signal_connect(G_OBJECT(visu_ui_main_class_getDefaultRendering()), "load-next-file",
286 G_CALLBACK(onNextPrevFile), GINT_TO_POINTER(VISU_UI_PANEL_BROWSER_NEXT));
287 g_signal_connect(G_OBJECT(visu_ui_main_class_getDefaultRendering()), "load-prev-file",
288 G_CALLBACK(onNextPrevFile), GINT_TO_POINTER(VISU_UI_PANEL_BROWSER_PREVIOUS));
289
290 return VISU_UI_PANEL(panelBrowser);
291 }
292
293 static GtkWidget *createInteriorBrowser()
294 {
295 /* include from glade */
296 GtkWidget *image2;
_setModel(VisuMethodSpin * spin)297 GtkWidget *image3;
298 GtkWidget *image1;
299 GtkWidget *hbox2;
300 GtkWidget *label4;
301 GtkWidget *label1;
302 GtkWidget *hbox5;
303 GtkWidget *image4;
304 GtkWidget *refreshDirButton;
305 GtkCellRenderer *renderer;
306 GtkTreeViewColumn *column;
307
308 GtkWidget *label;
309 GtkWidget *hbox, *vbox;
310
311 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
312 GtkTooltips *tooltips;
313
314 tooltips = gtk_tooltips_new ();
315 #endif
316
317 GSList *radiobuttonCycle_group;
318
319 hbox = gtk_hbox_new(FALSE, 0);
320 gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
321 /* This is a label in the browser panel to introduce the
322 entry that allows to enter a filter for files shown. */
323 label = gtk_label_new(_("Filter: "));
324 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
325 entryFilterBrowser = gtk_entry_new();
326 gtk_editable_set_editable(GTK_EDITABLE(entryFilterBrowser), TRUE);
327 gtk_entry_set_text(GTK_ENTRY(entryFilterBrowser), "*");
328 gtk_box_pack_start(GTK_BOX(hbox), entryFilterBrowser, TRUE, TRUE, 0);
329 comboFilter = gtk_combo_box_text_new();
330 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(comboFilter),
331 "atomic", _("atomic rendering"));
332 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(comboFilter),
333 "spin", _("spin rendering"));
334 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(comboFilter),
335 "spin_at", _("atomic part"));
336 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(comboFilter),
337 "spin_sp", _("spin part"));
338 gtk_box_pack_start(GTK_BOX(hbox), comboFilter, FALSE, FALSE, 2);
339 gtk_combo_box_set_active(GTK_COMBO_BOX(comboFilter), 0);
340
341 /*******************/
342 /* File lists part */
343 /*******************/
344 hbox = gtk_hbox_new(FALSE, 0);
345 gtk_box_pack_start(GTK_BOX(vbox1), hbox, TRUE, TRUE, 0);
346
347 vbox = gtk_vbox_new (FALSE, 0);
348 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 2);
349
350 buttonDirectory = gtk_button_new ();
351 gtk_box_pack_start (GTK_BOX (vbox), buttonDirectory, FALSE, FALSE, 1);
352 gtk_widget_set_tooltip_text(buttonDirectory,
353 _("Choose a different directory."));
354
355 image3 = gtk_image_new_from_icon_name("document-open", GTK_ICON_SIZE_BUTTON);
356 gtk_container_add (GTK_CONTAINER (buttonDirectory), image3);
357
358 refreshDirButton = gtk_button_new ();
359 gtk_widget_set_tooltip_text(refreshDirButton,
360 _("Rescan current directory."));
361 gtk_box_pack_start(GTK_BOX(vbox), refreshDirButton, FALSE, FALSE, 1);
362 image3 = gtk_image_new_from_icon_name("view-refresh", GTK_ICON_SIZE_BUTTON);
363 gtk_container_add(GTK_CONTAINER(refreshDirButton), image3);
364 g_signal_connect(G_OBJECT(refreshDirButton), "clicked",
365 G_CALLBACK(onRefreshDir), (gpointer)entryFilterBrowser);
366
367 buttonRecurse = gtk_toggle_button_new();
368 gtk_widget_set_tooltip_text(buttonRecurse,
visu_ui_panel_method_spin_create(VisuGlNodeScene * scene _U_)369 _("Read directories recursively."));
370 gtk_box_pack_start(GTK_BOX(vbox), buttonRecurse, FALSE, FALSE, 1);
371 image3 = gtk_image_new_from_icon_name("zoom-in", GTK_ICON_SIZE_BUTTON);
372 gtk_container_add(GTK_CONTAINER(buttonRecurse), image3);
373 g_signal_connect(G_OBJECT(buttonRecurse), "toggled",
374 G_CALLBACK(onRecurseToggled), (gpointer)entryFilterBrowser);
375
376 buttonDirPrev = gtk_button_new();
377 gtk_widget_set_sensitive(buttonDirPrev, FALSE);
378 gtk_widget_set_tooltip_text(buttonDirPrev, _(HISTORY_TOOLTIP_PREV));
379 gtk_box_pack_start(GTK_BOX(vbox), buttonDirPrev, FALSE, FALSE, 1);
380 image3 = gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_BUTTON);
381 gtk_container_add(GTK_CONTAINER(buttonDirPrev), image3);
382 g_signal_connect(G_OBJECT(buttonDirPrev), "clicked",
383 G_CALLBACK(onPrevClicked), (gpointer)0);
384
385 buttonDirNext = gtk_button_new();
386 gtk_widget_set_sensitive(buttonDirNext, FALSE);
387 gtk_widget_set_tooltip_text(buttonDirNext, _(HISTORY_TOOLTIP_NEXT));
388 gtk_box_pack_start(GTK_BOX(vbox), buttonDirNext, FALSE, FALSE, 1);
389 image3 = gtk_image_new_from_icon_name("go-next", GTK_ICON_SIZE_BUTTON);
390 gtk_container_add(GTK_CONTAINER(buttonDirNext), image3);
391 g_signal_connect(G_OBJECT(buttonDirNext), "clicked",
392 G_CALLBACK(onNextClicked), (gpointer)0);
393
394 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 5
395 label = gtk_label_new(_("Dir.:"));
396 gtk_label_set_angle(GTK_LABEL(label), 90.);
397 gtk_box_pack_end(GTK_BOX(vbox), label, TRUE, TRUE, 0);
398 #endif
399
400 /* The infobar for cancel if to long and other messages. */
401 vbox = gtk_vbox_new(FALSE, 3);
402 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
403 labelInfo = gtk_label_new("");
404 gtk_label_set_xalign(GTK_LABEL(labelInfo), 0.);
405 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 17
406 infoBar = gtk_info_bar_new();
407 gtk_container_add(GTK_CONTAINER(gtk_info_bar_get_content_area(GTK_INFO_BAR(infoBar))),
408 labelInfo);
409 #else
410 infoBar = gtk_hbox_new(FALSE, 5);
411 infoImg = gtk_image_new_from_stock(GTK_STOCK_INFO, GTK_ICON_SIZE_MENU);
412 gtk_box_pack_start(GTK_BOX(infoBar), infoImg, FALSE, FALSE, 0);
413 gtk_box_pack_start(GTK_BOX(infoBar), labelInfo, TRUE, TRUE, 0);
414 #endif
415 gtk_widget_set_no_show_all(infoBar, TRUE);
416 gtk_box_pack_start(GTK_BOX(vbox), infoBar, FALSE, FALSE, 0);
417
418 scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
419 gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow1, TRUE, TRUE, 0);
420 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow1),
421 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
422 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow1),
423 GTK_SHADOW_ETCHED_IN);
424
425 fileTree = gtk_tree_view_new ();
426 gtk_widget_set_tooltip_text(fileTree,
427 _("Double click on a file to render it."));
428 gtk_container_add (GTK_CONTAINER (scrolledwindow1), fileTree);
429 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(fileTree), showHeaders);
430
431 renderer = gtk_cell_renderer_toggle_new ();
432 g_signal_connect(G_OBJECT(renderer), "toggled",
433 G_CALLBACK(onCheckFile), (gpointer)0);
434 column = gtk_tree_view_column_new_with_attributes ("",
435 renderer,
436 "active", COLUMN_BOOLEAN,
437 "sensitive", COLUMN_FILE_VALID,
438 "activatable", COLUMN_FILE_VALID,
439 NULL);
440 gtk_tree_view_append_column (GTK_TREE_VIEW (fileTree), column);
441 column = gtk_tree_view_column_new();
442 gtk_tree_view_column_set_title(GTK_TREE_VIEW_COLUMN(column), _("File"));
443 renderer = gtk_cell_renderer_text_new ();
444 gtk_tree_view_column_pack_end(GTK_TREE_VIEW_COLUMN(column), renderer, TRUE);
445 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), renderer,
446 "markup", COLUMN_NAME_UTF8,
447 "sensitive", COLUMN_FILE_VALID,
448 NULL);
set_view(GtkWidget * button _U_,gpointer data _U_)449 renderer = gtk_cell_renderer_pixbuf_new();
450 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, FALSE);
451 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), renderer,
452 "icon-name", COLUMN_FILE_ERROR_ID,
453 NULL);
454 gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME_UTF8);
455 gtk_tree_view_column_set_expand(column, TRUE);
456 gtk_tree_view_append_column(GTK_TREE_VIEW (fileTree), column);
457 if (showDate)
458 {
459 renderer = gtk_cell_renderer_text_new ();
460 column = gtk_tree_view_column_new_with_attributes (_("Date"),
461 renderer,
462 "text", COLUMN_DATA,
463 "sensitive", COLUMN_FILE_VALID,
464 NULL);
465 gtk_tree_view_column_set_sort_column_id(column, COLUMN_DATE);
466 gtk_tree_view_append_column (GTK_TREE_VIEW (fileTree), column);
467 }
468
469 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(fileTree)),
470 GTK_SELECTION_SINGLE);
471
472 vbox = gtk_vbox_new (FALSE, 0);
473 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 2);
474
475 buttonUnselectAll = gtk_button_new();
476 gtk_widget_set_tooltip_text(buttonUnselectAll, _("Unselect all files."));
477 gtk_box_pack_start(GTK_BOX(vbox), buttonUnselectAll, FALSE, FALSE, 1);
478 image2 = create_pixmap ((GtkWidget*)0, "stock-unselect-all_20.png");
479 gtk_container_add(GTK_CONTAINER(buttonUnselectAll), image2);
480
481 buttonSelectAll = gtk_button_new();
482 gtk_widget_set_tooltip_text(buttonSelectAll, _("Select all files."));
483 gtk_box_pack_start(GTK_BOX (vbox), buttonSelectAll, FALSE, FALSE, 1);
484 image2 = create_pixmap ((GtkWidget*)0, "stock-select-all_20.png");
485 gtk_container_add (GTK_CONTAINER (buttonSelectAll), image2);
486
487 buttonDumpAll = gtk_button_new();
488 gtk_box_pack_start(GTK_BOX(vbox), buttonDumpAll, TRUE, FALSE, 0);
489 image4 = gtk_image_new_from_icon_name("document-save-as", GTK_ICON_SIZE_BUTTON);
490 gtk_container_add(GTK_CONTAINER(buttonDumpAll), image4);
491 gtk_widget_set_tooltip_text(buttonDumpAll,
492 _("Export the rendering of all selected files"
493 " in other formats."));
494
495 buttonNext = gtk_button_new ();
496 gtk_box_pack_end(GTK_BOX (vbox), buttonNext, FALSE, FALSE, 1);
497 gtk_widget_set_tooltip_text(buttonNext,
498 _("Render the next selected file."));
499 image1 = gtk_image_new_from_icon_name("go-down", GTK_ICON_SIZE_BUTTON);
500 gtk_container_add (GTK_CONTAINER (buttonNext), image1);
501
502 buttonPrevious = gtk_button_new ();
503 gtk_box_pack_end(GTK_BOX (vbox), buttonPrevious, FALSE, FALSE, 1);
504 gtk_widget_set_tooltip_text(buttonPrevious,
505 _("Render the previous selected file."));
506 image2 = gtk_image_new_from_icon_name("go-up", GTK_ICON_SIZE_BUTTON);
507 gtk_container_add (GTK_CONTAINER (buttonPrevious), image2);
508
509 hbox = gtk_hbox_new(FALSE, 0);
510 gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
511
512 label = gtk_label_new(_("<span size=\"smaller\">Current dir.: </span>"));
513 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
514 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
515
516 labelDirectory = gtk_label_new("");
517 gtk_label_set_use_markup(GTK_LABEL(labelDirectory), TRUE);
518 gtk_label_set_xalign(GTK_LABEL(labelDirectory), 0.);
519 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 5
520 gtk_label_set_ellipsize(GTK_LABEL(labelDirectory), PANGO_ELLIPSIZE_START);
521 #endif
522 gtk_box_pack_start(GTK_BOX(hbox), labelDirectory, TRUE, TRUE, 0);
523 panelBrowserSet_labelCurrentDir();
524
525 /***************/
526 /* Action part */
527 /***************/
528 hbox2 = gtk_hbox_new (FALSE, 0);
529 gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, TRUE, 1);
530
531 hbox5 = gtk_hbox_new(FALSE, 0);
532 gtk_widget_set_margin_end(hbox5, 5);
533 gtk_box_pack_start(GTK_BOX(hbox2), hbox5, FALSE, FALSE, 0);
534
535 radioGoAround = gtk_radio_button_new(NULL);
536 gtk_radio_button_set_group(GTK_RADIO_BUTTON(radioGoAround), (GSList*)0);
537 radiobuttonCycle_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioGoAround));
538 gtk_box_pack_start(GTK_BOX(hbox5), radioGoAround, FALSE, FALSE, 0);
539 image1 = create_pixmap((GtkWidget*)0, "stock-go-around.png");
540 gtk_container_add(GTK_CONTAINER(radioGoAround), image1);
541
542 radioGoOnce = gtk_radio_button_new(NULL);
543 gtk_radio_button_set_group(GTK_RADIO_BUTTON(radioGoOnce), radiobuttonCycle_group);
544 radiobuttonCycle_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioGoOnce));
545 gtk_box_pack_start(GTK_BOX(hbox5), radioGoOnce, FALSE, FALSE, 0);
546 image1 = create_pixmap((GtkWidget*)0, "stock-go-once.png");
547 gtk_container_add(GTK_CONTAINER(radioGoOnce), image1);
548
549 radioGoAndBack = gtk_radio_button_new(NULL);
550 gtk_radio_button_set_group(GTK_RADIO_BUTTON(radioGoAndBack), radiobuttonCycle_group);
551 radiobuttonCycle_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioGoAndBack));
552 gtk_box_pack_start(GTK_BOX(hbox5), radioGoAndBack, FALSE, FALSE, 0);
553 image1 = create_pixmap((GtkWidget*)0, "stock-go-and-back.png");
554 gtk_container_add(GTK_CONTAINER(radioGoAndBack), image1);
555
556 label4 = gtk_label_new (_("Play at "));
557 gtk_box_pack_start (GTK_BOX (hbox2), label4, TRUE, TRUE, 0);
558 gtk_label_set_xalign(GTK_LABEL(label4), 1.);
559
560 spinDelay = gtk_spin_button_new_with_range(10, 10000, 25);
561 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinDelay), 500);
562 gtk_box_pack_start (GTK_BOX (hbox2), spinDelay, FALSE, TRUE, 0);
563 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinDelay), TRUE);
564
565 /* Units: milliseconds */
566 label1 = gtk_label_new (_(" ms"));
567 gtk_box_pack_start (GTK_BOX (hbox2), label1, TRUE, TRUE, 0);
568 gtk_label_set_xalign(GTK_LABEL(label1), 0.);
569
570 buttonPlayStop = gtk_toggle_button_new();
571 gtk_widget_set_tooltip_text(buttonPlayStop, _("Cycle through the selected files at the given rate."));
572 gtk_box_pack_start (GTK_BOX (hbox2), buttonPlayStop, FALSE, FALSE, 5);
573
574 hbox5 = gtk_hbox_new (FALSE, 0);
575 gtk_container_add (GTK_CONTAINER (buttonPlayStop), hbox5);
576
577 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 5
578 imagePlay = create_pixmap ((GtkWidget*)0, "stock_media-play.png");
579 imageStop = create_pixmap ((GtkWidget*)0, "stock_media-stop.png");
580 #else
581 imagePlay = gtk_image_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_MENU);
582 imageStop = gtk_image_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_MENU);
583 #endif
584 gtk_widget_set_no_show_all(imageStop, TRUE);
585 gtk_box_pack_start (GTK_BOX (hbox5), imagePlay, TRUE, TRUE, 0);
586 gtk_box_pack_start (GTK_BOX (hbox5), imageStop, TRUE, TRUE, 0);
587
588 g_signal_connect(G_OBJECT(fileTree), "row-activated",
589 G_CALLBACK(onTreeviewActivated), (gpointer)0);
590 g_signal_connect(G_OBJECT(buttonPrevious), "clicked",
591 G_CALLBACK(navigateClicked), GINT_TO_POINTER(VISU_UI_PANEL_BROWSER_PREVIOUS));
592 g_signal_connect(G_OBJECT(buttonNext), "clicked",
593 G_CALLBACK(navigateClicked), GINT_TO_POINTER(VISU_UI_PANEL_BROWSER_NEXT));
594 g_signal_connect(G_OBJECT(buttonSelectAll), "clicked",
595 G_CALLBACK(checkFiles), GINT_TO_POINTER(TRUE));
596 g_signal_connect(G_OBJECT(buttonUnselectAll), "clicked",
597 G_CALLBACK(checkFiles), GINT_TO_POINTER(FALSE));
598 g_signal_connect(G_OBJECT(buttonDirectory), "clicked",
599 G_CALLBACK(onDirectoryClicked), (gpointer)entryFilterBrowser);
600 g_signal_connect(G_OBJECT(buttonPlayStop), "toggled",
601 G_CALLBACK(onPlayStopClicked), (gpointer)0);
602 g_signal_connect(G_OBJECT(spinDelay), "value-changed",
603 G_CALLBACK(onSpinDelayChangeValue), (gpointer)buttonPlayStop);
604 g_signal_connect(G_OBJECT(buttonDumpAll), "clicked",
605 G_CALLBACK(onDumpButtonClicked), (gpointer)0);
606 g_signal_connect(G_OBJECT(entryFilterBrowser), "changed",
607 G_CALLBACK(onFilterChanged), (gpointer)0);
608 g_signal_connect_swapped(G_OBJECT(comboFilter), "changed",
609 G_CALLBACK(gtk_tree_model_filter_refilter),
610 treeStoreFilesFilter);
611
612 gtk_widget_show_all(vbox1);
613
614 return vbox1;
615 }
616
617 /*************/
618 /* Callbacks */
619 /*************/
620
621 static void onFilterChanged(GtkEditable *entry, gpointer user_data _U_)
622 {
623 GPatternSpec *pattern;
624 gboolean valid;
625 GtkTreeIter iter;
626 gboolean match;
627 gchar *fileUTF8;
628
629 /* fprintf(stderr, "'%s'\n", gtk_entry_get_text(GTK_ENTRY(entry))); */
630
631 pattern = g_pattern_spec_new(gtk_entry_get_text(GTK_ENTRY(entry)));
632
633 for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treeStoreFiles), &iter);
634 valid;
635 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(treeStoreFiles), &iter))
636 {
637 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &iter,
638 COLUMN_NAME_UTF8, &fileUTF8, -1);
639 match = g_pattern_match_string(pattern, fileUTF8);
640 gtk_tree_store_set(treeStoreFiles, &iter,
641 COLUMN_ACTIVE, match, -1);
642 g_free(fileUTF8);
643 }
644 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(treeStoreFilesFilter));
645
646 g_pattern_spec_free(pattern);
647 }
648
649 static void onCheckFile(GtkCellRendererToggle *cell_renderer _U_, gchar *path,
650 gpointer user_data _U_)
651 {
652 GtkTreeIter iter, childIter;
653 gboolean checked;
654 GtkTreePath *currentPath;
655
656 currentPath = gtk_tree_path_new_from_string(path);
657 gtk_tree_model_get_iter(GTK_TREE_MODEL(treeStoreFilesFilter), &iter, currentPath);
658 gtk_tree_path_free(currentPath);
659
660 gtk_tree_model_filter_convert_iter_to_child_iter
661 (GTK_TREE_MODEL_FILTER(treeStoreFilesFilter), &childIter, &iter);
662
663 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &childIter,
664 COLUMN_BOOLEAN, &checked, -1);
665 gtk_tree_store_set(treeStoreFiles, &childIter,
666 COLUMN_BOOLEAN, !checked, -1);
667
668 }
669
670 static void onTreeviewActivated(GtkTreeView *treeview _U_, GtkTreePath *path,
671 GtkTreeViewColumn *col _U_, gpointer user_data _U_)
672 {
673 GtkTreeIter iter, childIter, parentIter;
674 gboolean checked;
675 gchar* filename, *utf8;
676 int nSet;
677
678 DBG_fprintf(stderr, "Panel Browser: double click detected.\n");
679 gtk_tree_model_get_iter(GTK_TREE_MODEL(treeStoreFilesFilter), &iter, path);
680 gtk_tree_model_filter_convert_iter_to_child_iter
681 (GTK_TREE_MODEL_FILTER(treeStoreFilesFilter), &childIter, &iter);
682 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &childIter,
683 COLUMN_NAME, &filename,
684 COLUMN_NAME_UTF8, &utf8,
685 COLUMN_BOOLEAN, &checked, -1);
686 if (!checked)
687 gtk_tree_store_set(GTK_TREE_STORE(treeStoreFiles), &childIter,
688 COLUMN_BOOLEAN, TRUE, -1);
689 if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(treeStoreFiles),
690 &parentIter, &childIter))
691 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &childIter,
692 COLUMN_DATE, &nSet, -1);
693 else
694 nSet = 0;
695
696 DBG_fprintf(stderr, "Panel Browser: double click asks for loading (%s).\n",
697 filename);
698 browserLoad(filename, utf8, &childIter, nSet);
699 g_free(filename);
700 g_free(utf8);
701 }
702 static void navigateClicked(GtkButton *button _U_, gpointer data)
703 {
704 GtkTreeIter iter;
705 GtkTreePath *path;
706 gboolean res;
707
708 res = visu_ui_panel_browser_getNextSelected(&path, &iter, GPOINTER_TO_INT(data));
709 if (!res)
710 return;
711
712 res = navigateInFiles(path, &iter);
713 gtk_tree_path_free(path);
714 }
715 static void onNextPrevFile(VisuUiRenderingWindow *window _U_, gpointer data)
716 {
717 GtkTreeIter iter;
718 GtkTreePath *path;
719 gboolean res;
720
721 res = visu_ui_panel_browser_getNextSelected(&path, &iter, GPOINTER_TO_INT(data));
722 if (!res)
723 return;
724
725 res = navigateInFiles(path, &iter);
726 gtk_tree_path_free(path);
727 }
728 static void checkFiles(GtkButton *button _U_, gpointer data)
729 {
730 gtk_tree_model_foreach(GTK_TREE_MODEL(treeStoreFilesFilter), checkFile, data);
731 }
732 static void onRefreshDir(GtkButton *button _U_, gpointer data _U_)
733 {
734 browseDirectory((gchar*)0);
735 }
736 gboolean playSelectedFiles(gpointer data _U_)
737 {
738 GtkTreeIter iter;
739 gboolean res, load;
740 GtkTreePath *path;
741
742 g_return_val_if_fail(startBrowsePath, FALSE);
743
744 /* We try to get the next iter. */
745 res = visu_ui_panel_browser_getNextSelected(&path, &iter, currentBrowseDirection);
746 if (!res)
747 return FALSE;
748
749 /* We follow the cycle policy to select the file. */
750 load = TRUE;
751 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioGoAndBack)))
752 {
753 if (!gtk_tree_path_compare(path, startBrowsePath))
754 {
755 DBG_fprintf(stderr, "Panel browser: One round is done, applyng policy.\n");
756 if (currentBrowseDirection == VISU_UI_PANEL_BROWSER_PREVIOUS)
757 currentBrowseDirection = VISU_UI_PANEL_BROWSER_NEXT;
758 else
759 {
760 currentBrowseDirection = VISU_UI_PANEL_BROWSER_PREVIOUS;
761 gtk_tree_path_free(path);
762 res = visu_ui_panel_browser_getNextSelected(&path, &iter,
763 currentBrowseDirection);
764 g_return_val_if_fail(res, FALSE);
765 }
766 }
767 }
768 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioGoOnce)))
769 {
770 if (!gtk_tree_path_compare(path, startBrowsePath))
771 {
772 DBG_fprintf(stderr, "Panel browser: One round is done, applyng policy.\n");
773 res = FALSE;
774 load = FALSE;
775 }
776 }
777
778 if (load)
779 {
780 /* We advance the select one. */
781 selectFile(path, &iter);
782 /* We render it. */
783 res = navigateInFiles(path, &iter);
784 }
785
786 gtk_tree_path_free(path);
787
788 return res;
789 }
790
791 static void onPlayStopClicked(GtkToggleButton *button, gpointer data _U_)
792 {
793 GtkTreeIter startIter;
794 gboolean res, checked, hasChild;
795 gulong *playCallbackId;
796
797 DBG_fprintf(stderr, "Panel Browser: toggle on play button.\n");
798 /* if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(panelBrowserListFilter), &startIter)) */
799 /* return; */
800
801 if (gtk_toggle_button_get_active(button))
802 {
803 /* Button has been pushed. */
804 checked = FALSE;
805 res = visu_ui_panel_browser_getCurrentSelected(&startBrowsePath, &startIter);
806 if (res)
807 {
808 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFilesFilter), &startIter,
809 COLUMN_BOOLEAN, &checked, -1);
810 hasChild = gtk_tree_model_iter_has_child(GTK_TREE_MODEL(treeStoreFilesFilter),
811 &startIter);
812 }
813 if (!res || !checked || hasChild)
814 {
815 res = visu_ui_panel_browser_getNextSelected(&startBrowsePath, &startIter,
816 VISU_UI_PANEL_BROWSER_NEXT);
817 if (!res)
818 {
819 startBrowsePath = gtk_tree_path_new();
820 /* No file selected. */
821 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonPlayStop), FALSE);
822 return;
823 }
824 }
825 navigateInFiles(startBrowsePath, &startIter);
826
827 /* Launch play */
828 gtk_widget_hide(imagePlay);
829 gtk_widget_show(imageStop);
830
831 currentBrowseDirection = VISU_UI_PANEL_BROWSER_NEXT;
832 playCallbackId = g_malloc(sizeof(gulong));
833 *playCallbackId =
834 g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,
835 (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinDelay)),
836 playSelectedFiles, (gpointer)0,
837 stopPlayStop);
838 g_object_set_data(G_OBJECT(button), "playCallbackId",
839 (gpointer)playCallbackId);
840 DBG_fprintf(stderr, " | start play\n");
841 }
842 else
843 {
844 /* Stop play */
845 playCallbackId = (gulong*)g_object_get_data(G_OBJECT(button), "playCallbackId");
846 if (playCallbackId)
847 g_source_remove(*playCallbackId);
848 DBG_fprintf(stderr, " | stop play\n");
849 }
850 }
851 void stopPlayStop(gpointer data _U_)
852 {
853 gtk_widget_hide(imageStop);
854 gtk_widget_show(imagePlay);
855 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonPlayStop), FALSE);
856 g_return_if_fail(startBrowsePath);
857 gtk_tree_path_free(startBrowsePath);
858 }
859 static void onSpinDelayChangeValue(GtkSpinButton *spinbutton _U_, gpointer user_data)
860 {
861 GtkTreePath *startPath;
862 GtkToggleButton *button;
863 gulong *playCallbackId;
864
865 g_return_if_fail(GTK_IS_TOGGLE_BUTTON(user_data));
866 button = GTK_TOGGLE_BUTTON(user_data);
867
868 if (gtk_toggle_button_get_active(button))
869 {
870 playCallbackId = (gulong*)g_object_get_data(G_OBJECT(button), "playCallbackId");
871 g_return_if_fail(playCallbackId);
872
873 startPath = gtk_tree_path_copy(startBrowsePath);
874 /* Stop playing at this rate */
875 g_source_remove(*playCallbackId);
876 startBrowsePath = startPath;
877 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttonPlayStop), TRUE);
878 }
879 }
880 void onDumpButtonClicked(GtkButton *button _U_, gpointer user_data _U_)
881 {
882 GtkWidget *dump;
883 GtkProgressBar *progressBarDump;
884 char *filename;
885 VisuDump *format;
886 GError *error;
887 GString *buffer;
888 GtkButton *abort;
889 char *chr, *chr2;
890 int goodPattern, flagAbort, i;
891 gint response;
892 GString *fileNumbered;
893 GtkTreeIter iter;
894 gboolean valid, errors;
895 GtkTreePath *currentPath, *startPath;
896 VisuGlView *view;
897
898 view = visu_ui_panel_getView(VISU_UI_PANEL(panelBrowser));
899 dump = visu_ui_dump_dialog_new
900 (visu_ui_panel_getData(VISU_UI_PANEL(panelBrowser)),
901 visu_ui_panel_getContainerWindow(VISU_UI_PANEL(panelBrowser)),
902 _("foo%02d.png"), view->window.width, view->window.height);
903
904 do
905 {
906 response = gtk_dialog_run(GTK_DIALOG(dump));
907
908 if (response != GTK_RESPONSE_ACCEPT)
909 {
910 gtk_widget_destroy(dump);
911 return;
912 }
913
914 filename = visu_ui_dump_dialog_getFilename(VISU_UI_DUMP_DIALOG(dump));
915 format = visu_ui_dump_dialog_getType(VISU_UI_DUMP_DIALOG(dump));
916 g_return_if_fail(filename && format);
917
918 DBG_fprintf(stderr, "Panel browser: dump all returns this filename"
919 " pattern '%s' (format : %s)\n", filename,
920 tool_file_format_getName(TOOL_FILE_FORMAT(format)));
921
922 buffer = g_string_new(_("Dumping all selected files to images,"));
923 g_string_append_printf(buffer, _(" format '%s'.\n\n"),
924 tool_file_format_getName(TOOL_FILE_FORMAT(format)));
925 /* Verify the name is regular */
926 if (g_pattern_match_simple("*%0?d*", filename))
927 {
928 chr = strchr(filename, '%');
929 if ((int)*(chr + 2) <= '0' || (int)*(chr + 2) > '9')
930 {
931 goodPattern = 0;
932 g_string_append_printf(buffer, _("Error! The numbering pattern is"
933 " wrong.\n"));
934 }
935 else
936 {
937 chr2 = strchr(chr + 1, '%');
938 if (chr2)
939 {
940 goodPattern = 0;
941 g_string_append_printf(buffer,
942 _("Error! Only one '%s' character"
943 " is allowed in the file name.\n"), "%");
944 }
945 else
946 goodPattern = 1;
947 }
948 }
949 else
950 {
951 goodPattern = 0;
952 g_string_append_printf(buffer, _("Error! Missing pattern in the filename.\n"));
953 }
954 if (!goodPattern)
955 {
956 g_string_append_printf(buffer,
957 _("\nHelp : you must specify '%s' in"
958 " the filename, where 'x' is a number [|1;9|]."
959 " This allows V_Sim to number the dumped"
960 " files.\n\n For example, with a pattern like this"
961 " : 'foo%s.pdf', dumped files will be named"
962 " : foo00.pdf, foo01.pdf..."),
963 "%0xd", "%02d");
964 visu_ui_raiseWarning(_("Exporting files"), buffer->str, (GtkWindow*)0);
965 g_string_free(buffer, TRUE);
966 }
967 }
968 while (!goodPattern);
969
970 error = (GError*)0;
971 abort = visu_ui_dump_dialog_getCancelButton(VISU_UI_DUMP_DIALOG(dump));
972 progressBarDump = visu_ui_dump_dialog_getProgressBar(VISU_UI_DUMP_DIALOG(dump));
973 visu_ui_dump_dialog_start(VISU_UI_DUMP_DIALOG(dump));
974
975 g_signal_connect (G_OBJECT(abort), "clicked",
976 G_CALLBACK(visu_dump_abort), (gpointer)&flagAbort);
977 g_signal_connect (G_OBJECT(abort), "clicked",
978 G_CALLBACK(abortDumpAll), (gpointer)progressBarDump);
979
980 gtk_progress_bar_set_fraction(progressBarDump, 0.);
981 fileNumbered = g_string_new("");
982 i = 0;
983 flagAbort = 0;
984
985 /* We write it only once to avoid blinking effects. */
986 gtk_progress_bar_set_text(progressBarDump,
987 _("Waiting for generating image in memory..."));
988 visu_ui_wait();
989
990 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(fileTree)));
991
992 errors = FALSE;
993 valid = visu_ui_panel_browser_getNextSelected(&startPath, &iter, VISU_UI_PANEL_BROWSER_NEXT);
994 if (valid)
995 valid = navigateInFiles(startPath, &iter);
996 while (valid && !errors && !flagAbort)
997 {
998 g_string_append_printf(buffer, _("Write to file %d ..."), i);
999 g_string_printf(fileNumbered, filename, i);
1000 DBG_fprintf(stderr, "Panel browser: write '%s'\n", fileNumbered->str);
1001
1002 errors = !visu_gl_node_scene_dump(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()),
1003 format, fileNumbered->str,
1004 visu_ui_dump_dialog_getWidth(VISU_UI_DUMP_DIALOG(dump)),
1005 visu_ui_dump_dialog_getHeight(VISU_UI_DUMP_DIALOG(dump)),
1006 updateDumpAllProgressBar, (gpointer)progressBarDump,
1007 &error);
1008 if (errors)
1009 g_string_append_printf(buffer, _(" error\n"));
1010 else
1011 g_string_append_printf(buffer, _(" OK\n"));
1012 i += 1;
1013
1014 valid = visu_ui_panel_browser_getNextSelected(¤tPath, &iter, VISU_UI_PANEL_BROWSER_NEXT);
1015 if (!gtk_tree_path_compare(currentPath, startPath))
1016 valid = FALSE;
1017 if (valid)
1018 valid = navigateInFiles(currentPath, &iter);
1019 gtk_tree_path_free(currentPath);
1020 }
1021 gtk_tree_path_free(startPath);
1022 if (error)
1023 {
1024 visu_ui_raiseWarning(_("Exporting files"), error->message, (GtkWindow*)0);
1025 g_error_free(error);
1026 }
1027 g_string_free(fileNumbered, TRUE);
1028
1029 gtk_widget_destroy(dump);
1030 }
1031 void updateDumpAllProgressBar(gpointer data)
1032 {
1033 gdouble val;
1034 gdouble percentage;
1035 gdouble nEle;
1036
1037 g_return_if_fail(GTK_PROGRESS_BAR(data));
1038
1039 nEle = (gdouble)gtk_tree_model_iter_n_children(GTK_TREE_MODEL(treeStoreFilesFilter), NULL);
1040 val = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(data));
1041 /* if (((int)(val * nEle)) % 100 == 1) */
1042 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(data), "");
1043
1044 percentage = val + 0.01 / nEle;
1045 if (percentage > 1.0)
1046 percentage = 1.0;
1047 if (percentage < 0.)
1048 percentage = 0.;
1049 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(data), percentage);
1050 visu_ui_wait();
1051 }
1052 void abortDumpAll(GtkButton *button _U_, gpointer data)
1053 {
1054 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(data),
1055 _("Abortion request, please wait..."));
1056 }
1057
1058
1059
1060
1061
1062 /******************/
1063 /* Public methods */
1064 /******************/
1065
1066 gboolean visu_ui_panel_browser_getCurrentSelected(GtkTreePath **path, GtkTreeIter *iterSelected)
1067 {
1068 GtkTreeSelection *selection;
1069 gboolean res;
1070 GtkTreeModel *model;
1071
1072 g_return_val_if_fail(path && iterSelected, FALSE);
1073
1074 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treeStoreFilesFilter), iterSelected))
1075 return FALSE;
1076
1077 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(fileTree));
1078 res = gtk_tree_selection_get_selected(selection, &model, iterSelected);
1079
1080 if (res)
1081 *path = gtk_tree_model_get_path(model, iterSelected);
1082 return res;
1083 }
1084
1085 gboolean visu_ui_panel_browser_getNextSelected(GtkTreePath **path, GtkTreeIter *iterSelected,
1086 int direction)
1087 {
1088 GtkTreeSelection *selection;
1089 GtkTreePath *currentPath, *firstPath;
1090 GtkTreeIter iter, child, parent;
1091 gboolean res, checked;
1092 GtkTreeModel *model;
1093 int loopComplete;
1094
1095 g_return_val_if_fail(path && iterSelected &&
1096 (direction == VISU_UI_PANEL_BROWSER_NEXT ||
1097 direction == VISU_UI_PANEL_BROWSER_PREVIOUS), FALSE);
1098
1099 *path = (GtkTreePath*)0;
1100
1101 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treeStoreFilesFilter), &iter))
1102 return FALSE;
1103
1104 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(fileTree));
1105 res = gtk_tree_selection_get_selected(selection, &model, &iter);
1106
1107 /* Nothing is selected. */
1108 if (!res)
1109 {
1110 if (direction == VISU_UI_PANEL_BROWSER_NEXT)
1111 res = gtk_tree_model_get_iter_last(GTK_TREE_MODEL(treeStoreFilesFilter),
1112 &iter, (GtkTreePath**)0);
1113 else if (GPOINTER_TO_INT(direction) == VISU_UI_PANEL_BROWSER_PREVIOUS)
1114 res = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treeStoreFilesFilter),
1115 &iter);
1116 }
1117 g_return_val_if_fail(res, FALSE);
1118
1119 currentPath = gtk_tree_model_get_path(GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1120 firstPath = gtk_tree_path_copy(currentPath);
1121 do
1122 {
1123 if (direction == VISU_UI_PANEL_BROWSER_NEXT)
1124 {
1125 /* If the current iter has child, we select the first. */
1126 if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(treeStoreFilesFilter),
1127 &iter))
1128 {
1129 gtk_tree_model_iter_children(GTK_TREE_MODEL(treeStoreFilesFilter),
1130 &child, &iter);
1131 iter = child;
1132 gtk_tree_path_free(currentPath);
1133 currentPath =
1134 gtk_tree_model_get_path(GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1135 }
1136 /* If the current iter has no child, we go next. */
1137 else
1138 {
1139 /* Avance d'un pas dans la liste */
1140 gtk_tree_path_next(currentPath);
1141 child = iter;
1142 res = gtk_tree_model_get_iter(GTK_TREE_MODEL(treeStoreFilesFilter),
1143 &iter, currentPath);
1144 /* In case, there's no next iter. */
1145 if (!res)
1146 {
1147 /* If the iter has no parent we go top. */
1148 if (!gtk_tree_model_iter_parent
1149 (GTK_TREE_MODEL(treeStoreFilesFilter), &parent, &child))
1150 {
1151 gtk_tree_model_get_iter_first
1152 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1153 gtk_tree_path_free(currentPath);
1154 currentPath =
1155 gtk_tree_model_get_path
1156 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1157 }
1158 /* If the iter has parent, we go next parent. */
1159 else
1160 {
1161 iter = parent;
1162 gtk_tree_path_free(currentPath);
1163 currentPath = gtk_tree_model_get_path
1164 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1165 gtk_tree_path_next(currentPath);
1166 res = gtk_tree_model_get_iter
1167 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter, currentPath);
1168 if (!res)
1169 {
1170 gtk_tree_model_get_iter_first
1171 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1172 gtk_tree_path_free(currentPath);
1173 currentPath = gtk_tree_model_get_path
1174 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1175 }
1176 }
1177 }
1178 }
1179 }
1180 else if (direction == VISU_UI_PANEL_BROWSER_PREVIOUS)
1181 {
1182 /* Recule d'un pas dans la liste */
1183 res = gtk_tree_path_prev(currentPath);
1184 /* Recup�re l'it�ration recul�e d'un pas */
1185 child = iter;
1186 res = res && gtk_tree_model_get_iter(GTK_TREE_MODEL(treeStoreFilesFilter),
1187 &iter, currentPath);
1188 /* If this prev iter does not exist. */
1189 if (!res)
1190 {
1191 /* In the case the current iter has a parent, we select it. */
1192 if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(treeStoreFilesFilter),
1193 &parent, &child))
1194 {
1195 iter = parent;
1196 gtk_tree_path_free(currentPath);
1197 currentPath = gtk_tree_model_get_path
1198 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1199 }
1200 /* Si ce path n'existe pas ou
1201 si cette iteration n'existe pas on va � la fin. */
1202 else
1203 {
1204 gtk_tree_path_free(currentPath);
1205 res = gtk_tree_model_get_iter_last
1206 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter, ¤tPath);
1207 if (!res)
1208 {
1209 g_warning("Panel browser: impossible to find"
1210 " the end of the list.\n");
1211 gtk_tree_path_free(currentPath);
1212 gtk_tree_path_free(firstPath);
1213 return FALSE;
1214 }
1215 }
1216 }
1217 /* If the previous iter has children, we select last. */
1218 else if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(treeStoreFilesFilter),
1219 &iter))
1220 {
1221 parent = iter;
1222 res = gtk_tree_model_iter_nth_child
1223 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter, &parent,
1224 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(treeStoreFilesFilter),
1225 &parent) - 1);
1226 if (!res)
1227 {
1228 g_warning("Panel browser: impossible to find"
1229 " the last child of this iter.\n");
1230 gtk_tree_path_free(currentPath);
1231 gtk_tree_path_free(firstPath);
1232 return FALSE;
1233 }
1234 gtk_tree_path_free(currentPath);
1235 currentPath = gtk_tree_model_get_path
1236 (GTK_TREE_MODEL(treeStoreFilesFilter), &iter);
1237 }
1238 }
1239
1240 checked = FALSE;
1241 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFilesFilter), &iter,
1242 COLUMN_BOOLEAN, &checked, -1);
1243 checked = checked && !gtk_tree_model_iter_has_child(GTK_TREE_MODEL(treeStoreFilesFilter),
1244 &iter);
1245 /* fprintf(stderr, "%d '%s'\n", nbSteps, filename); */
1246 loopComplete = !gtk_tree_path_compare(firstPath, currentPath);
1247 }
1248 while ( !checked && !loopComplete);
1249 gtk_tree_path_free(firstPath);
1250 if (!loopComplete)
1251 {
1252 *path = currentPath;
1253 *iterSelected = iter;
1254 return TRUE;
1255 }
1256 else
1257 {
1258 gtk_tree_path_free(currentPath);
1259 return FALSE;
1260 }
1261 }
1262
1263 static void selectFile(GtkTreePath *path, GtkTreeIter *iter)
1264 {
1265 GtkTreeSelection *selection;
1266
1267 g_return_if_fail(path && iter);
1268
1269 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(fileTree));
1270 gtk_tree_selection_select_iter(selection, iter);
1271 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(fileTree), path, NULL, FALSE, 0., 0.);
1272 }
1273 static gboolean navigateInFiles(GtkTreePath *path, GtkTreeIter *iterSelected)
1274 {
1275 gboolean res;
1276 gchar *filename, *utf8;
1277 int nSet;
1278 GtkTreeIter parentIter, iter;
1279
1280 g_return_val_if_fail(path && iterSelected, FALSE);
1281
1282 /* We select the given iter. */
1283 selectFile(path, iterSelected);
1284
1285 /* Load the new selected file */
1286 gtk_tree_model_filter_convert_iter_to_child_iter
1287 (GTK_TREE_MODEL_FILTER(treeStoreFilesFilter), &iter, iterSelected);
1288 if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(treeStoreFiles),
1289 &parentIter, &iter))
1290 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &iter,
1291 COLUMN_DATE, &nSet, -1);
1292 else
1293 nSet = 0;
1294 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &iter,
1295 COLUMN_NAME, &filename,
1296 COLUMN_NAME_UTF8, &utf8, -1);
1297 res = browserLoad(filename, utf8, &iter, nSet);
1298 g_free(filename);
1299 g_free(utf8);
1300 return res;
1301 }
1302
1303 static VisuDataLoadable* setFiles(const gchar *filename, const gchar *utf8,
1304 VisuData *oldData)
1305 {
1306 gchar *pt, **tokens, *name, *name2;
1307 VisuDataAtomic *atomic;
1308 VisuDataSpin *spin;
1309
1310 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(comboFilter)))
1311 {
1312 case 0:
1313 atomic = visu_data_atomic_new(filename, (VisuDataLoader*)0);
1314 return VISU_DATA_LOADABLE(atomic);
1315 case 1:
1316 /* The case where the name is used for all files. */
1317 pt = strrchr(utf8, ']');
1318 *pt = '\0';
1319 pt = strrchr(utf8, '[');
1320 tokens = g_strsplit(pt + 1, ",", 2);
1321 name = g_strdup_printf("%s.%s", filename, tokens[0]);
1322 name2 = g_strdup_printf("%s.%s", filename, tokens[1]);
1323 g_strfreev(tokens);
1324 spin = visu_data_spin_new(name, name2, (VisuDataLoader*)0, (VisuDataLoader*)0);
1325 g_free(name);
1326 g_free(name2);
1327 return VISU_DATA_LOADABLE(spin);
1328 case 2:
1329 g_return_val_if_fail(VISU_IS_DATA_LOADABLE(oldData), (VisuDataLoadable*)0);
1330 spin = visu_data_spin_new(filename, visu_data_loadable_getFilename(VISU_DATA_LOADABLE(oldData), 1), (VisuDataLoader*)0, (VisuDataLoader*)0);
1331 return VISU_DATA_LOADABLE(spin);
1332 case 3:
1333 g_return_val_if_fail(VISU_IS_DATA_LOADABLE(oldData), (VisuDataLoadable*)0);
1334 spin = visu_data_spin_new(visu_data_loadable_getFilename(VISU_DATA_LOADABLE(oldData), 0), filename, (VisuDataLoader*)0, (VisuDataLoader*)0);
1335 return VISU_DATA_LOADABLE(spin);
1336 default:
1337 return (VisuDataLoadable*)0;
1338 }
1339 }
1340
1341 static gboolean browserLoad(gchar *filename, gchar *utf8, GtkTreeIter *iter, int nSet)
1342 {
1343 GError *error;
1344 VisuDataLoadable *data;
1345 VisuData *prevData;
1346 gboolean valid;
1347 GtkTreeIter parentIter, childIter;
1348 int iSet, nSets;
1349 GtkTreePath *path;
1350 const gchar *comment;
1351 gchar *buf, *commentFormat;
1352
1353 g_return_val_if_fail(iter, FALSE);
1354
1355 prevData = visu_ui_panel_getData(VISU_UI_PANEL(panelBrowser));
1356 data = setFiles(filename, utf8, prevData);
1357 if (!data)
1358 {
1359 visu_ui_raiseWarning(_("Loading a file"),
1360 _("Can't load this file through the browser because it"
1361 " requires to read several files. You should use the 'Open'"
1362 " button on the main panel and then use the browser to vary"
1363 " one kind of file at a time."), (GtkWindow*)0);
1364 g_object_unref(data);
1365
1366 gtk_tree_store_set(treeStoreFiles, iter,
1367 COLUMN_FILE_VALID, FALSE,
1368 COLUMN_BOOLEAN, FALSE,
1369 -1);
1370 return FALSE;
1371 }
1372
1373 gtk_widget_set_sensitive(buttonPrevious, FALSE);
1374 gtk_widget_set_sensitive(buttonNext, FALSE);
1375 error = (GError*)0;
1376 if (!visu_gl_node_scene_loadData(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()), data, nSet, (GCancellable*)0, &error))
1377 {
1378 if (error)
1379 {
1380 visu_ui_raiseWarning(_("Loading a file"), error->message, (GtkWindow*)0);
1381 g_error_free(error);
1382 }
1383 g_object_unref(data);
1384 data = (VisuDataLoadable*)0;
1385 }
1386 gtk_widget_set_sensitive(buttonPrevious, TRUE);
1387 gtk_widget_set_sensitive(buttonNext, TRUE);
1388
1389 if (!data)
1390 gtk_tree_store_set(treeStoreFiles, iter,
1391 COLUMN_FILE_ERROR_ID, "dialog-error",
1392 COLUMN_FILE_VALID, FALSE,
1393 COLUMN_BOOLEAN, FALSE,
1394 -1);
1395 else
1396 gtk_tree_store_set(treeStoreFiles, iter,
1397 COLUMN_FILE_ERROR_ID, (gchar*)0,
1398 COLUMN_FILE_VALID, TRUE,
1399 -1);
1400
1401 if (data)
1402 {
1403 /* If the file has more than one node set, we create the child
1404 entries in the tree view. */
1405 nSets = visu_data_loadable_getNSets(data);
1406 if (nSets > 1)
1407 {
1408 /* We get the parent iter. */
1409 if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(treeStoreFiles),
1410 &parentIter, iter))
1411 {
1412 /* We clear its children. */
1413 valid = gtk_tree_model_iter_children
1414 (GTK_TREE_MODEL(treeStoreFiles), &childIter, iter);
1415 while (valid)
1416 {
1417 gtk_tree_store_remove(treeStoreFiles, &childIter);
1418 valid = gtk_tree_model_iter_children
1419 (GTK_TREE_MODEL(treeStoreFiles), &childIter, iter);
1420 }
1421 /* We create the new ones. */
1422 commentFormat = g_strdup_printf(_("data set %s0%dd"), "%",
1423 (int)log10(nSets) + 1);
1424 for (iSet = 0; iSet < nSets; iSet++)
1425 {
1426 comment = visu_data_loadable_getSetLabel(data, iSet);
1427 if (!comment || !comment[0])
1428 {
1429 buf = g_strdup_printf(commentFormat, iSet + 1);
1430 comment = buf;
1431 }
1432 else
1433 buf = (gchar*)0;
1434 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 9
1435 gtk_tree_store_insert_with_values(treeStoreFiles,
1436 &childIter, iter, iSet,
1437 COLUMN_BOOLEAN, TRUE,
1438 COLUMN_NAME, filename,
1439 COLUMN_NAME_UTF8, comment,
1440 COLUMN_ACTIVE, TRUE,
1441 COLUMN_DATE, iSet,
1442 COLUMN_FILE_VALID, TRUE,
1443 -1);
1444 #else
1445 gtk_tree_store_insert(treeStoreFiles, &childIter,
1446 iter, iSet);
1447 gtk_tree_store_set(treeStoreFiles, &childIter,
1448 COLUMN_BOOLEAN, TRUE,
1449 COLUMN_NAME, filename,
1450 COLUMN_NAME_UTF8, comment,
1451 COLUMN_ACTIVE, TRUE,
1452 COLUMN_DATE, iSet,
1453 COLUMN_FILE_VALID, TRUE,
1454 -1);
1455 #endif
1456 if (buf)
1457 g_free(buf);
1458 }
1459 g_free(commentFormat);
1460 /* We expand the row. */
1461 gtk_tree_model_filter_convert_child_iter_to_iter
1462 (GTK_TREE_MODEL_FILTER(treeStoreFilesFilter),
1463 &parentIter, iter);
1464 path = gtk_tree_model_get_path(GTK_TREE_MODEL(treeStoreFilesFilter),
1465 &parentIter);
1466 gtk_tree_view_expand_row(GTK_TREE_VIEW(fileTree), path, TRUE);
1467 /* We select the first. */
1468 /* selectFile(path, iterSelected); */
1469 gtk_tree_path_free(path);
1470 }
1471 }
1472 g_object_unref(data);
1473 }
1474
1475 if (data)
1476 return TRUE;
1477 else
1478 return FALSE;
1479 }
1480
1481 static gboolean checkFile(GtkTreeModel *model, GtkTreePath *path _U_,
1482 GtkTreeIter *iter, gpointer data)
1483 {
1484 gboolean filterOk, valid;
1485 GtkTreeIter iterList;
1486 GtkTreeStore *tree;
1487
1488 /* If we check the row, the checkbutton is on only
1489 if the name is in accordance with the filter. */
1490 gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(treeStoreFilesFilter),
1491 &iterList, iter);
1492 tree = GTK_TREE_STORE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(treeStoreFilesFilter)));
1493 if (GPOINTER_TO_INT(data))
1494 {
1495 gtk_tree_model_get(GTK_TREE_MODEL(model), iter,
1496 COLUMN_ACTIVE, &filterOk, COLUMN_FILE_VALID, &valid, -1);
1497
1498 if (filterOk && valid)
1499 gtk_tree_store_set(tree, &iterList, COLUMN_BOOLEAN,
1500 TRUE, -1);
1501 /* else */
1502 /* gtk_tree_store_set(tree, &iterList, COLUMN_BOOLEAN, */
1503 /* FALSE, -1); */
1504 }
1505 else
1506 {
1507 gtk_tree_store_set(tree, &iterList, COLUMN_BOOLEAN,
1508 FALSE, -1);
1509 }
1510 return FALSE;
1511 }
1512
1513 void visu_ui_panel_browser_setCurrentDirectory(const gchar *dir)
1514 {
1515 g_return_if_fail(dir && dir[0]);
1516
1517 if (currentBrowseredDirectory)
1518 DBG_fprintf(stderr, "Panel Browser: compare dirs '%s' and '%s'.\n",
1519 currentBrowseredDirectory[0], dir);
1520
1521 /* Test if the new directory is not already the current one. */
1522 if (currentBrowseredDirectory && currentBrowseredDirectory[0] &&
1523 !strcmp(currentBrowseredDirectory[0], dir) && !currentBrowseredDirectory[1])
1524 return;
1525
1526 /* Set the new directory current. */
1527 currentBrowseredDirectory = g_malloc(sizeof(gchar*) * 2);
1528 currentBrowseredDirectory[0] = g_strdup(dir);
1529 currentBrowseredDirectory[1] = (gchar*)0;
1530 DBG_fprintf(stderr, "Panel Browser: set currentBrowseredDirectory to '%s'.\n",
1531 currentBrowseredDirectory[0]);
1532 if (commonBrowseredDirectory)
1533 g_free(commonBrowseredDirectory);
1534 commonBrowseredDirectory = tool_path_normalize(dir);
1535 DBG_fprintf(stderr, "Panel Browser: set common path to '%s'.\n",
1536 commonBrowseredDirectory);
1537
1538 /* Save the new list of current directories. */
1539 updateHistory();
1540
1541 /* Refresh the list if visible, else let the page-enter
1542 signal do it. */
1543 DBG_fprintf(stderr, "Panel Browser: ask for refresh.\n");
1544 if (visu_ui_panel_getVisible(VISU_UI_PANEL(panelBrowser)))
1545 browseDirectory();
1546 else
1547 dirDirty = TRUE;
1548
1549 visu_ui_main_setLastOpenDirectory(visu_ui_main_class_getCurrentPanel(),
1550 commonBrowseredDirectory, VISU_UI_DIR_BROWSER);
1551 }
1552 static void setCurrentDirectories(gchar **dirs)
1553 {
1554 int i, j;
1555 gchar *tmp;
1556
1557 /* Set the new directory current. */
1558 currentBrowseredDirectory = dirs;
1559
1560 DBG_fprintf(stderr, "Panel Browser: set currentBrowseredDirectory to the list:\n");
1561 /* Try to find a common path for all directories. */
1562 if (commonBrowseredDirectory)
1563 g_free(commonBrowseredDirectory);
1564 commonBrowseredDirectory = g_strdup(dirs[0]);
1565 for (i = 0; dirs[i]; i++)
1566 {
1567 DBG_fprintf(stderr, " | '%s'\n", dirs[i]);
1568 for (j = 0; dirs[i][j] && commonBrowseredDirectory[j]; j++)
1569 if (dirs[i][j] != commonBrowseredDirectory[j])
1570 commonBrowseredDirectory[j] = '\0';
1571 }
1572 tmp = commonBrowseredDirectory;
1573 commonBrowseredDirectory = tool_path_normalize(tmp);
1574 g_free(tmp);
1575 DBG_fprintf(stderr, "Panel Browser: set common path to '%s'.\n",
1576 commonBrowseredDirectory);
1577
1578 /* Refresh the list if visible, else let the page-enter
1579 signal do it. */
1580 if (visu_ui_panel_getVisible(VISU_UI_PANEL(panelBrowser)))
1581 browseDirectory();
1582 else
1583 dirDirty = TRUE;
1584
1585 visu_ui_main_setLastOpenDirectory(visu_ui_main_class_getCurrentPanel(),
1586 commonBrowseredDirectory, VISU_UI_DIR_BROWSER);
1587 }
1588 static void updateHistory()
1589 {
1590 GList *tmpLst, *del;
1591
1592 g_return_if_fail(currentBrowseredDirectory);
1593
1594 DBG_fprintf(stderr, "Panel Browser: update the history.\n");
1595
1596 /* We kill the history between historyBrowseredDirectory and
1597 currentHistory. */
1598 tmpLst = historyBrowseredDirectory;
1599 while (tmpLst != currentHistory)
1600 {
1601 DBG_fprintf(stderr, "Panel Browser: removing a group of"
1602 " directories from history.\n");
1603 g_strfreev((gchar**)tmpLst->data);
1604 del = tmpLst;
1605 tmpLst = g_list_next(tmpLst);
1606 g_list_free_1(del);
1607 }
1608 if (currentHistory)
1609 currentHistory->prev = (GList*)0;
1610 historyBrowseredDirectory = currentHistory;
1611 DBG_fprintf(stderr, "Panel Browser: adding a group of"
1612 " directories to history.\n");
1613 historyBrowseredDirectory = g_list_prepend(historyBrowseredDirectory,
1614 currentBrowseredDirectory);
1615 currentHistory = historyBrowseredDirectory;
1616 DBG_fprintf(stderr, "Panel Browser: set current history to %p (%d).\n",
1617 (gpointer)currentHistory, g_list_length(currentHistory));
1618
1619 if (buttonDirPrev) gtk_widget_set_sensitive(buttonDirPrev, TRUE);
1620 if (buttonDirNext) gtk_widget_set_sensitive(buttonDirNext, FALSE);
1621
1622 DBG_fprintf(stderr, "Panel Browser: history updated OK.\n");
1623
1624 updateDirectionalTooltips();
1625 }
1626 void visu_ui_panel_browser_setCurrentDirectories(gchar **dirs)
1627 {
1628 g_return_if_fail(dirs && dirs[0]);
1629
1630 /* Change the current directories. */
1631 setCurrentDirectories(dirs);
1632
1633 /* Save the new list of current directories. */
1634 updateHistory();
1635 DBG_fprintf(stderr, "Panel Browser: directories updated OK.\n");
1636 }
1637 static void updateDirectionalTooltips()
1638 {
1639 GString *lbl;
1640 int i;
1641 gchar **history;
1642 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 12
1643 GtkTooltips *tooltips;
1644
1645 tooltips = gtk_tooltips_new ();
1646 #endif
1647
1648 DBG_fprintf(stderr, "Panel Browser: update directional tooltips.\n");
1649
1650 if (currentHistory && currentHistory->prev && buttonDirNext)
1651 {
1652 history = (gchar**)(currentHistory->prev->data);
1653
1654 lbl = g_string_new(_(HISTORY_TOOLTIP_NEXT));
1655 if (history)
1656 {
1657 g_string_append_printf(lbl, "\n\n(%s", history[0]);
1658 for (i = 1; history[i]; i++)
1659 g_string_append_printf(lbl, ", %s", history[i]);
1660 g_string_append_printf(lbl, ")");
1661 }
1662 gtk_widget_set_tooltip_text(buttonDirNext, lbl->str);
1663 g_string_free(lbl, TRUE);
1664 }
1665 if (currentHistory && currentHistory->next && buttonDirPrev)
1666 {
1667 history = (gchar**)(currentHistory->next->data);
1668
1669 lbl = g_string_new(_(HISTORY_TOOLTIP_PREV));
1670 if (history)
1671 {
1672 g_string_append_printf(lbl, "\n\n(%s", history[0]);
1673 for (i = 1; history[i]; i++)
1674 g_string_append_printf(lbl, ", %s", history[i]);
1675 g_string_append_printf(lbl, ")");
1676 }
1677 gtk_widget_set_tooltip_text(buttonDirPrev, lbl->str);
1678 g_string_free(lbl, TRUE);
1679 }
1680 }
1681 gboolean panelBrowserSet_previousHistoryDirectories()
1682 {
1683 if (!currentHistory || !g_list_next(currentHistory))
1684 return FALSE;
1685
1686 currentHistory = g_list_next(currentHistory);
1687 DBG_fprintf(stderr, "Panel Browser: set current history to %p (%d).\n",
1688 (gpointer)currentHistory, g_list_length(currentHistory));
1689
1690 setCurrentDirectories((gchar**)(currentHistory->data));
1691 updateDirectionalTooltips();
1692
1693 gtk_widget_set_sensitive(buttonDirPrev, g_list_next(currentHistory) != (gpointer)0);
1694 gtk_widget_set_sensitive(buttonDirNext, TRUE);
1695
1696 return TRUE;
1697 }
1698 gboolean panelBrowserSet_nextHistoryDirectories()
1699 {
1700 if (!currentHistory || !g_list_previous(currentHistory))
1701 return FALSE;
1702
1703 currentHistory = g_list_previous(currentHistory);
1704 DBG_fprintf(stderr, "Panel Browser: set current history to %p (%d).\n",
1705 (gpointer)currentHistory, g_list_length(currentHistory));
1706
1707 setCurrentDirectories((gchar**)(currentHistory->data));
1708 updateDirectionalTooltips();
1709
1710 gtk_widget_set_sensitive(buttonDirPrev, TRUE);
1711 gtk_widget_set_sensitive(buttonDirNext, g_list_previous(currentHistory) != (gpointer)0);
1712
1713 return TRUE;
1714 }
1715
1716 static void associateFiles(int nbKind, int commonPathLen)
1717 {
1718 gboolean valid;
1719 GtkTreeIter iter;
1720 int kind, searchKind, i;
1721 gchar *filename, *searchName, *pt, *fileUTF8;
1722 GList *tmpLst, *storeLst;
1723 gsize lu, ecrit;
1724 gchar **ext;
1725
1726 /* Read all the stored files and try to associate them on their names.
1727 When the name matches the previous one without the extension, then the kind
1728 is stored. If a full set of names can be retrieved, then it is stored. The
1729 extensions are stored in the ext array. */
1730 searchName = g_strdup(".");
1731 searchKind = 0;
1732 storeLst = (GList*)0;
1733 ext = g_malloc(sizeof(gchar*) * (nbKind + 1));
1734 memset(ext, 0, sizeof(gchar*) * (nbKind + 1));
1735 for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(treeStoreFiles), &iter);
1736 valid; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(treeStoreFiles), &iter))
1737 {
1738 gtk_tree_model_get(GTK_TREE_MODEL(treeStoreFiles), &iter,
1739 COLUMN_FILE_KIND, &kind, COLUMN_NAME, &filename, -1);
1740 pt = strrchr(filename, '.');
1741 if (pt)
1742 *pt = '\0';
1743 if (kind >= 0 && kind < nbKind)
1744 ext[kind] = g_strdup(pt + 1);
1745 /* fprintf(stderr, "'%s' %d %d\n", filename, kind, searchKind); */
1746 if (kind >= 0 && kind < nbKind && !strcmp(searchName, filename))
1747 {
1748 /* Ok, match, we continue. */
1749 searchKind += kind;
1750 g_free(filename);
1751 if (searchKind == nbKind * (nbKind - 1) / 2)
1752 {
1753 pt = g_strjoinv(",", ext);
1754 /* We found a complete set. */
1755 storeLst =
1756 g_list_prepend(storeLst, g_markup_printf_escaped("%s<span size=\"smaller\" foreground=\"grey\">.[%s]</span>", searchName, pt));
1757 g_free(pt);
1758 for (i = 0; i < nbKind; i++)
1759 g_free(ext[i]);
1760 memset(ext, 0, sizeof(gchar*) * (nbKind + 1));
1761 }
1762 }
1763 else
1764 {
1765 /* Doesn't match, try for new. */
1766 g_free(searchName);
1767 for (i = 0; i < nbKind; i++)
1768 if (ext[i])
1769 g_free(ext[i]);
1770 memset(ext, 0, sizeof(gchar*) * (nbKind + 1));
1771 searchName = filename;
1772 searchKind = kind;
1773 if (kind >= 0 && kind < nbKind)
1774 ext[kind] = g_strdup(pt + 1);
1775 }
1776 }
1777 g_free(searchName);
1778 /* Store now the associated list. */
1779 for (tmpLst = storeLst; tmpLst; tmpLst = g_list_next(tmpLst))
1780 {
1781 fileUTF8 = g_filename_to_utf8((gchar*)tmpLst->data + commonPathLen + 1,
1782 -1, &lu, &ecrit, NULL);
1783 pt = g_strrstr((gchar*)tmpLst->data, "<span ");
1784 *pt = '\0';
1785 /* fprintf(stderr, "Panel Browser: found association for '%s'.\n", fileUTF8); */
1786 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 9
1787 gtk_tree_store_insert_with_values(treeStoreFiles, &iter, (GtkTreeIter*)0, 0,
1788 COLUMN_BOOLEAN, FALSE,
1789 COLUMN_NAME, tmpLst->data,
1790 COLUMN_NAME_UTF8, fileUTF8,
1791 COLUMN_ACTIVE, TRUE,
1792 COLUMN_FILE_KIND, nbKind,
1793 COLUMN_FILE_VALID, TRUE,
1794 -1);
1795 #else
1796 gtk_tree_store_prepend(treeStoreFiles, &iter, (GtkTreeIter*)0);
1797 gtk_tree_store_set(treeStoreFiles, &iter,
1798 COLUMN_BOOLEAN, FALSE,
1799 COLUMN_NAME, tmpLst->data,
1800 COLUMN_NAME_UTF8, fileUTF8,
1801 COLUMN_ACTIVE, TRUE,
1802 COLUMN_FILE_KIND, nbKind,
1803 COLUMN_FILE_VALID, TRUE,
1804 -1);
1805 #endif
1806 g_free(tmpLst->data);
1807 if (fileUTF8)
1808 g_free(fileUTF8);
1809 }
1810 g_list_free(storeLst);
1811 }
1812
1813 static void browseDirectory()
1814 {
1815 GDir *gdir;
1816 gint len;
1817 int i;
1818 GList *atFmt, *spFmt;
1819 gint atKind, spKind;
1820 gboolean success;
1821 struct TimerInfo_ info;
1822
1823 if (!currentBrowseredDirectory)
1824 return;
1825
1826 dirDirty = FALSE;
1827
1828 atFmt = spFmt = (GList*)0;
1829 atKind = spKind = -1;
1830 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(comboFilter)))
1831 {
1832 case 0:
1833 atKind = 0;
1834 atFmt = visu_data_atomic_class_getLoaders();
1835 break;
1836 case 1:
1837 atFmt = visu_data_atomic_class_getLoaders();
1838 spFmt = visu_data_spin_class_getLoaders();
1839 atKind = 2;
1840 spKind = 3;
1841 break;
1842 case 2:
1843 atFmt = visu_data_atomic_class_getLoaders();
1844 atKind = 2;
1845 break;
1846 case 3:
1847 spFmt = visu_data_spin_class_getLoaders();
1848 spKind = 3;
1849 break;
1850 default:
1851 break;
1852 }
1853 if (!atFmt && !spFmt)
1854 return;
1855
1856 DBG_fprintf(stderr, "Panel browser: cleaning of the list.\n");
1857 gtk_tree_store_clear(treeStoreFiles);
1858
1859 /* Remove temporary the model. */
1860 gtk_tree_view_set_model(GTK_TREE_VIEW(fileTree),
1861 (GtkTreeModel*)0);
1862 gtk_widget_set_sensitive(scrolledwindow1, FALSE);
1863
1864 /* Add a timeout to show the progress bar if the scan is too long. */
1865 info.abort = FALSE;
1866 info.nbFiles = 0;
1867 info.bt = (GtkWidget*)0;
1868 #if GLIB_MINOR_VERSION < 13
1869 info.timer = g_timeout_add(1000, showProgressBar, (gpointer)(&info));
1870 #else
1871 info.timer = g_timeout_add_seconds(1, showProgressBar, (gpointer)(&info));
1872 #endif
1873 info.label = 0;
1874
1875 success = TRUE;
1876 len = strlen(commonBrowseredDirectory);
1877 for (i = 0; success && currentBrowseredDirectory[i] && !info.abort; i++)
1878 {
1879 DBG_fprintf(stderr, "Panel browser: scanning directory '%s'.\n",
1880 currentBrowseredDirectory[i]);
1881 gdir = g_dir_open(currentBrowseredDirectory[i], 0, NULL);
1882 if (gdir)
1883 {
1884 addParsedDirectory(len, currentBrowseredDirectory[i], gdir,
1885 gtk_toggle_button_get_active
1886 (GTK_TOGGLE_BUTTON(buttonRecurse)),
1887 atFmt, atKind, spFmt, spKind, &info);
1888 g_dir_close(gdir);
1889 }
1890 else
1891 success = FALSE;
1892 }
1893 hideProgressBar(&info);
1894
1895 panelBrowserSet_labelCurrentDir();
1896
1897 if (gtk_combo_box_get_active(GTK_COMBO_BOX(comboFilter)) == 1)
1898 associateFiles(2, len);
1899
1900 onFilterChanged(GTK_EDITABLE(entryFilterBrowser), (gpointer)0);
1901
1902 /* Reattach the model. */
1903 gtk_tree_view_set_model(GTK_TREE_VIEW(fileTree), GTK_TREE_MODEL(treeStoreFilesFilter));
1904 gtk_widget_set_sensitive(scrolledwindow1, TRUE);
1905
1906 if (!success)
1907 visu_ui_raiseWarning(_("Browsing a directory"),
1908 _("The specified directory is unreadable."),
1909 (GtkWindow*)0);
1910 }
1911
1912 static void addParsedDirectory(int commonPathLen, const gchar *root,
1913 GDir *gdir, gboolean recurse,
1914 GList *atFmt, gint atKind, GList *spFmt, gint spKind,
1915 struct TimerInfo_ *timer)
1916 {
1917 const gchar *fileFromDir;
1918 gchar *fileUTF8, *file;
1919 gint kind;
1920 gsize lu, ecrit;
1921 GDir *recursedDir;
1922 GtkTreeIter iter;
1923 GList *lst;
1924 #if GLIB_MINOR_VERSION > 5
1925 struct stat buf;
1926 struct tm *tm;
1927 gchar data[256];
1928 #endif
1929
1930 g_return_if_fail(root && root[0]);
1931 DBG_fprintf(stderr, "Panel Browser: read dir '%s' %d.\n", root, (int)recurse);
1932 fileFromDir = g_dir_read_name(gdir);
1933 while(fileFromDir && !timer->abort)
1934 {
1935 file = g_build_filename(root, fileFromDir, NULL);
1936 fileUTF8 = g_filename_to_utf8(file + commonPathLen + 1,
1937 -1, &lu, &ecrit, NULL);
1938
1939 if(fileUTF8)
1940 {
1941 if (g_file_test(file, G_FILE_TEST_IS_DIR))
1942 {
1943 DBG_fprintf(stderr, "Panel Browser: read dir '%s'\n", file);
1944 if (recurse)
1945 {
1946 recursedDir = g_dir_open(file, 0, NULL);
1947 if (recursedDir)
1948 {
1949 addParsedDirectory(commonPathLen, file, recursedDir, TRUE,
1950 atFmt, atKind, spFmt, spKind, timer);
1951 g_dir_close(recursedDir);
1952 }
1953 }
1954 }
1955 else
1956 {
1957 kind = -1;
1958 for (lst = atFmt; lst && kind < 0; lst = g_list_next(lst))
1959 if (tool_file_format_validate(TOOL_FILE_FORMAT(lst->data), fileUTF8))
1960 kind = atKind;
1961 for (lst = spFmt; lst && kind < 0; lst = g_list_next(lst))
1962 if (tool_file_format_validate(TOOL_FILE_FORMAT(lst->data), fileUTF8))
1963 kind = spKind;
1964 #if GLIB_MINOR_VERSION > 5
1965 if (showDate)
1966 {
1967 if (g_stat(file, &buf))
1968 buf.st_mtime = 0;
1969 DBG_fprintf(stderr, "Panel Browser: mtime %d.\n", (int)buf.st_mtime);
1970 tm = localtime(&buf.st_mtime);
1971 strftime(data, 256, _("%Y-%m-%d %H:%M"), tm);
1972 }
1973 else
1974 {
1975 buf.st_mtime = 0;
1976 data[0] = '\0';
1977 }
1978 #endif
1979 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 9
1980 gtk_tree_store_insert_with_values(treeStoreFiles, &iter,
1981 (GtkTreeIter*)0, 0,
1982 COLUMN_BOOLEAN, FALSE,
1983 COLUMN_NAME, file,
1984 COLUMN_NAME_UTF8, fileUTF8,
1985 COLUMN_ACTIVE, TRUE,
1986 COLUMN_FILE_KIND, kind,
1987 COLUMN_FILE_VALID, (kind >= 0),
1988 #if GLIB_MINOR_VERSION > 5
1989 COLUMN_DATE, buf.st_mtime,
1990 COLUMN_DATA, data,
1991 #endif
1992 -1);
1993 #else
1994 gtk_tree_store_append(treeStoreFiles, &iter, (GtkTreeIter*)0);
1995 gtk_tree_store_set(treeStoreFiles, &iter,
1996 COLUMN_BOOLEAN, FALSE,
1997 COLUMN_NAME, file,
1998 COLUMN_NAME_UTF8, fileUTF8,
1999 COLUMN_FILE_KIND, kind,
2000 COLUMN_ACTIVE, TRUE,
2001 COLUMN_FILE_VALID, (kind >= 0),
2002 #if GLIB_MINOR_VERSION > 5
2003 COLUMN_DATE, buf.st_mtime,
2004 COLUMN_DATA, data,
2005 #endif
2006 -1);
2007 #endif
2008 timer->nbFiles += 1;
2009 }
2010 g_free(fileUTF8);
2011 }
2012 g_free(file);
2013 visu_ui_wait();
2014 fileFromDir = g_dir_read_name(gdir);
2015 }
2016 }
2017
2018 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 17
2019 static void onParseAbortClicked(GtkButton *button _U_, gpointer data)
2020 {
2021 (*(gboolean*)data) = TRUE;
2022 }
2023 #else
2024 static void onParseAbortClicked(GtkInfoBar *infoBar _U_, gint response,
2025 gpointer data)
2026 {
2027 (*(gboolean*)data) = (response == GTK_RESPONSE_CANCEL);
2028 }
2029 #endif
2030
2031 static void onEnter(VisuUiPanel *visu_ui_panel _U_, gpointer data _U_)
2032 {
2033 DBG_fprintf(stderr, "Panel Browser: enter, parse directory (%d).\n",
2034 !fileTree);
2035 if (!fileTree)
2036 createInteriorBrowser();
2037 if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(treeStoreFiles), (GtkTreeIter*)0) == 0 || dirDirty)
2038 browseDirectory();
2039 }
2040
2041 static void onDirectoryClicked(GtkButton *button _U_, gpointer data _U_)
2042 {
2043 gchar **filenames;
2044
2045 filenames = visu_ui_main_getSelectedDirectory
2046 (visu_ui_main_class_getCurrentPanel(),
2047 visu_ui_panel_getContainerWindow(VISU_UI_PANEL(panelBrowser)),
2048 TRUE, commonBrowseredDirectory);
2049
2050 if (!filenames)
2051 return;
2052
2053 visu_ui_panel_browser_setCurrentDirectories(filenames);
2054 }
2055
2056 static void onRecurseToggled(GtkToggleButton *toggle _U_, gpointer data _U_)
2057 {
2058 browseDirectory();
2059 }
2060
2061 static void onPrevClicked(GtkButton *button _U_, gpointer data _U_)
2062 {
2063 panelBrowserSet_previousHistoryDirectories();
2064 }
2065 static void onNextClicked(GtkButton *button _U_, gpointer data _U_)
2066 {
2067 panelBrowserSet_nextHistoryDirectories();
2068 }
2069
2070 static gboolean pulseProgressBar(gpointer data)
2071 {
2072 struct TimerInfo_ *timer;
2073 gchar nbFilesLabel[36];
2074
2075 timer = (struct TimerInfo_*)data;
2076 sprintf(nbFilesLabel, _("%4d files found."), timer->nbFiles);
2077 gtk_label_set_text(GTK_LABEL(labelInfo), nbFilesLabel);
2078 DBG_fprintf(stderr, "Panel browser: update label to '%s'.\n", nbFilesLabel);
2079
2080 return TRUE;
2081 }
2082 static gboolean showProgressBar(gpointer data)
2083 {
2084 gchar nbFilesLabel[36];
2085 struct TimerInfo_ *timer;
2086
2087 DBG_fprintf(stderr, "Panel browser: scanning is too slow, showing progress bar.\n");
2088
2089 timer = (struct TimerInfo_*)data;
2090 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 17
2091 timer->bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
2092 gtk_box_pack_end(GTK_BOX(infoBar), timer->bt, FALSE, FALSE, 0);
2093 g_signal_connect(G_OBJECT(timer->bt), "clicked",
2094 G_CALLBACK(onParseAbortClicked), (gpointer)&timer->abort);
2095 #else
2096 timer->bt = gtk_info_bar_add_button(GTK_INFO_BAR(infoBar),
2097 TOOL_ICON_CANCEL, GTK_RESPONSE_CANCEL);
2098 g_signal_connect(G_OBJECT(infoBar), "response",
2099 G_CALLBACK(onParseAbortClicked), (gpointer)&timer->abort);
2100 #endif
2101
2102 sprintf(nbFilesLabel, _("%4d files found."), timer->nbFiles);
2103 visu_ui_panel_browser_setMessage(nbFilesLabel, GTK_MESSAGE_INFO);
2104
2105 timer->label = g_timeout_add(250, pulseProgressBar, data);
2106
2107 return FALSE;
2108 }
2109 static void hideProgressBar(struct TimerInfo_ *timer)
2110 {
2111 DBG_fprintf(stderr, "Panel browser: scanning is finished, hiding progress bar.\n");
2112
2113 g_source_remove(timer->timer);
2114 if (timer->label)
2115 {
2116 g_source_remove(timer->label);
2117 visu_ui_panel_browser_setMessage((const gchar*)0, GTK_MESSAGE_INFO);
2118 }
2119 if (timer->bt)
2120 gtk_widget_destroy(timer->bt);
2121 }
2122
2123
2124 /***************************/
2125 /* Miscellaneous functions */
2126 /***************************/
2127
2128 gboolean gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *last, GtkTreePath **path)
2129 {
2130 gboolean valid;
2131 gint n;
2132
2133 g_return_val_if_fail(model && last, FALSE);
2134
2135 n = gtk_tree_model_iter_n_children(model, (GtkTreeIter*)0);
2136 if (n == 0)
2137 return FALSE;
2138
2139 valid = gtk_tree_model_iter_nth_child(model, last, (GtkTreeIter*)0, n - 1);
2140 g_return_val_if_fail(valid, FALSE);
2141
2142 if (path)
2143 *path = gtk_tree_model_get_path(model, last);
2144
2145 return TRUE;
2146 }
2147
2148 static gboolean panelBrowserIsIterVisible(GtkTreeModel *model, GtkTreeIter *iter,
2149 gpointer data _U_)
2150 {
2151 gboolean passUserFilter;
2152 gint kind;
2153
2154 gtk_tree_model_get(model, iter,
2155 COLUMN_FILE_KIND, &kind,
2156 COLUMN_ACTIVE, &passUserFilter,
2157 -1);
2158 return (passUserFilter && (kind == gtk_combo_box_get_active(GTK_COMBO_BOX(comboFilter)) || kind < 0));
2159 }
2160
2161 static gint onSortNames(GtkTreeModel *model, GtkTreeIter *a,
2162 GtkTreeIter *b, gpointer user_data _U_)
2163 {
2164 gint kindA, kindB;
2165 gchar *lblA, *lblB;
2166 gint diff, iSetA, iSetB;
2167 GtkTreeIter parentA, parentB;
2168
2169 /* We always sort the kind first. */
2170 gtk_tree_model_get(model, a, COLUMN_FILE_KIND, &kindA, -1);
2171 gtk_tree_model_get(model, b, COLUMN_FILE_KIND, &kindB, -1);
2172
2173 if ((kindA < 0 && kindB >= 0) || (kindA >= 0 && kindB < 0))
2174 return (kindB - kindA);
2175 else
2176 {
2177 if (gtk_tree_model_iter_parent(model, &parentA, a) &&
2178 gtk_tree_model_iter_parent(model, &parentB, b))
2179 {
2180 gtk_tree_model_get(model, a, COLUMN_DATE, &iSetA, -1);
2181 gtk_tree_model_get(model, b, COLUMN_DATE, &iSetB, -1);
2182
2183 diff = iSetA - iSetB;
2184 }
2185 else
2186 {
2187 gtk_tree_model_get(model, a, COLUMN_NAME_UTF8, &lblA, -1);
2188 gtk_tree_model_get(model, b, COLUMN_NAME_UTF8, &lblB, -1);
2189
2190 diff = g_utf8_collate(lblA, lblB);
2191
2192 g_free(lblA);
2193 g_free(lblB);
2194 }
2195
2196 return diff;
2197 }
2198 }
2199
2200 void panelBrowserSet_labelCurrentDir()
2201 {
2202 gchar *directoryUTF8, *markup;
2203
2204 if (!commonBrowseredDirectory)
2205 return;
2206
2207 directoryUTF8 = g_filename_to_utf8(commonBrowseredDirectory, -1, NULL, NULL, NULL);
2208 g_return_if_fail(directoryUTF8);
2209
2210 markup = g_markup_printf_escaped(_("<span style=\"italic\" size=\"smaller\">%s</span>"),
2211 directoryUTF8);
2212 g_free(directoryUTF8);
2213 gtk_label_set_markup(GTK_LABEL(labelDirectory), markup);
2214 g_free(markup);
2215 }
2216
2217 static void onNewDir(GObject *obj _U_, VisuUiDirectoryType type, gpointer user _U_)
2218 {
2219 DBG_fprintf(stderr, "Panel Browser: caught 'DirectoryChanged'"
2220 " signal for type %d.\n", type);
2221 if (type == VISU_UI_DIR_FILE)
2222 visu_ui_panel_browser_setCurrentDirectory(visu_ui_main_getLastOpenDirectory(visu_ui_main_class_getCurrentPanel()));
2223 }
2224
2225 static void exportParameters(GString *data, VisuData *dataObj _U_)
2226 {
2227 g_string_append_printf(data, "# %s\n", DESC_PARAMETER_BROWSER_HEADERS);
2228 g_string_append_printf(data, "%s[gtk]: %i\n\n", FLAG_PARAMETER_BROWSER_HEADERS,
2229 (int)showHeaders);
2230 g_string_append_printf(data, "# %s\n", DESC_PARAMETER_BROWSER_DATE);
2231 g_string_append_printf(data, "%s[gtk]: %i\n\n", FLAG_PARAMETER_BROWSER_DATE,
2232 (int)showDate);
2233 }
2234 /**
2235 * visu_ui_panel_browser_setMessage:
2236 * @message: a string to be displaied.
2237 * @message_type: the kind of message.
2238 *
2239 * This routine is used to give the user a message. This message can
2240 * be mere information or a warning or an error.
2241 *
2242 * Since: 3.6
2243 */
2244 void visu_ui_panel_browser_setMessage(const gchar* message, GtkMessageType message_type)
2245 {
2246 if (!fileTree)
2247 createInteriorBrowser();
2248
2249 if (message)
2250 {
2251 gtk_label_set_text(GTK_LABEL(labelInfo), message);
2252 #if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 17
2253 gtk_info_bar_set_message_type(GTK_INFO_BAR(infoBar), message_type);
2254 #else
2255 switch (message_type)
2256 {
2257 case GTK_MESSAGE_INFO:
2258 gtk_image_set_from_stock(GTK_IMAGE(infoImg),
2259 GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON);
2260 break;
2261 default:
2262 gtk_image_clear(GTK_IMAGE(infoImg));
2263 break;
2264 }
2265 #endif
2266 gtk_widget_set_no_show_all(infoBar, FALSE);
2267 gtk_widget_show_all(infoBar);
2268 }
2269 else
2270 {
2271 gtk_widget_hide(infoBar);
2272 }
2273 }
2274