~ubuntu-branches/ubuntu/saucy/darktable/saucy

« back to all changes in this revision

Viewing changes to src/gui/gtk.c

  • Committer: Bazaar Package Importer
  • Author(s): David Bremner
  • Date: 2011-04-14 23:42:12 UTC
  • Revision ID: james.westby@ubuntu.com-20110414234212-kuffcz5wiu18v6ra
Tags: upstream-0.8
ImportĀ upstreamĀ versionĀ 0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of darktable,
 
3
    copyright (c) 2009--2011 johannes hanika.
 
4
 
 
5
    darktable is free software: you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation, either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    darktable is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
#ifndef _XOPEN_SOURCE
 
19
#define _XOPEN_SOURCE 600 // for setenv
 
20
#endif
 
21
#include <stdlib.h>
 
22
#include <unistd.h>
 
23
#include <string.h>
 
24
#include <math.h>
 
25
#include <gtk/gtk.h>
 
26
#include <glade/glade.h>
 
27
#include <gdk/gdkkeysyms.h>
 
28
#include <pthread.h>
 
29
 
 
30
#include "common/darktable.h"
 
31
#ifdef HAVE_GPHOTO2
 
32
#   include "common/camera_control.h"
 
33
#   include "gui/devices.h"
 
34
#   include "views/capture.h"
 
35
#endif
 
36
#include "common/collection.h"
 
37
#include "common/image.h"
 
38
#include "common/image_cache.h"
 
39
#include "develop/develop.h"
 
40
#include "develop/imageop.h"
 
41
#include "dtgtk/label.h"
 
42
#include "dtgtk/button.h"
 
43
#include "gui/contrast.h"
 
44
#include "gui/gtk.h"
 
45
#include "gui/metadata.h"
 
46
#include "gui/iop_history.h"
 
47
#include "gui/iop_modulegroups.h"
 
48
 
 
49
#include "gui/presets.h"
 
50
#include "gui/preferences.h"
 
51
#include "control/control.h"
 
52
#include "control/jobs.h"
 
53
#include "control/conf.h"
 
54
#include "views/view.h"
 
55
#include "tool_colorlabels.h"
 
56
 
 
57
static gboolean
 
58
borders_button_pressed (GtkWidget *w, GdkEventButton *event, gpointer user_data)
 
59
{
 
60
  GtkWidget *widget;
 
61
  long int which = (long int)user_data;
 
62
  int32_t bit = 0;
 
63
  int mode = dt_conf_get_int("ui_last/view");
 
64
  switch(which)
 
65
  {
 
66
    case 0:
 
67
      bit = dt_conf_get_int("ui_last/panel_left");
 
68
      widget = glade_xml_get_widget (darktable.gui->main_window, "left");
 
69
      break;
 
70
    case 1:
 
71
      bit = dt_conf_get_int("ui_last/panel_right");
 
72
      widget = glade_xml_get_widget (darktable.gui->main_window, "right");
 
73
      break;
 
74
    case 2:
 
75
      bit = dt_conf_get_int("ui_last/panel_top");
 
76
      widget = glade_xml_get_widget (darktable.gui->main_window, "top");
 
77
      break;
 
78
    default:
 
79
      bit = dt_conf_get_int("ui_last/panel_bottom");
 
80
      widget = glade_xml_get_widget (darktable.gui->main_window, "bottom");
 
81
      break;
 
82
  }
 
83
 
 
84
  if(GTK_WIDGET_VISIBLE(widget))
 
85
  {
 
86
    gtk_widget_hide(widget);
 
87
    bit &= ~(1<<mode);
 
88
  }
 
89
  else
 
90
  {
 
91
    gtk_widget_show(widget);
 
92
    bit |=   1<<mode;
 
93
  }
 
94
 
 
95
  switch(which)
 
96
  {
 
97
    case 0:
 
98
      dt_conf_set_int("ui_last/panel_left", bit);
 
99
      break;
 
100
    case 1:
 
101
      dt_conf_set_int("ui_last/panel_right", bit);
 
102
      break;
 
103
    case 2:
 
104
      dt_conf_set_int("ui_last/panel_top", bit);
 
105
      break;
 
106
    default:
 
107
      dt_conf_set_int("ui_last/panel_bottom", bit);
 
108
      break;
 
109
  }
 
110
  gtk_widget_queue_draw(w);
 
111
  return TRUE;
 
112
}
 
113
 
 
114
static gboolean
 
115
_widget_focus_in_block_key_accelerators (GtkWidget *widget,GdkEventFocus *event,gpointer data)
 
116
{
 
117
  dt_control_key_accelerators_off (darktable.control);
 
118
  return FALSE;
 
119
}
 
120
 
 
121
static gboolean
 
122
_widget_focus_out_unblock_key_accelerators (GtkWidget *widget,GdkEventFocus *event,gpointer data)
 
123
{
 
124
  dt_control_key_accelerators_on (darktable.control);
 
125
  return FALSE;
 
126
}
 
127
 
 
128
void
 
129
dt_gui_key_accel_block_on_focus (GtkWidget *w)
 
130
{
 
131
  /* first off add focus change event mask */
 
132
  gtk_widget_add_events(w, GDK_FOCUS_CHANGE_MASK);
 
133
 
 
134
  /* conenct the signals */
 
135
  g_signal_connect (G_OBJECT (w), "focus-in-event", G_CALLBACK(_widget_focus_in_block_key_accelerators), (gpointer)w);
 
136
  g_signal_connect (G_OBJECT (w), "focus-out-event", G_CALLBACK(_widget_focus_out_unblock_key_accelerators), (gpointer)w);
 
137
}
 
138
 
 
139
static gboolean
 
140
expose_borders (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
 
141
{
 
142
  // draw arrows on borders
 
143
  if(!dt_control_running()) return TRUE;
 
144
  long int which = (long int)user_data;
 
145
  float width = widget->allocation.width, height = widget->allocation.height;
 
146
  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
 
147
  cairo_t *cr = cairo_create(cst);
 
148
  GtkWidget *cwidget = glade_xml_get_widget (darktable.gui->main_window, "center");
 
149
  GtkStyle *style = gtk_widget_get_style(cwidget);
 
150
  cairo_set_source_rgb (cr,
 
151
                        .5f*style->bg[GTK_STATE_NORMAL].red/65535.0,
 
152
                        .5f*style->bg[GTK_STATE_NORMAL].green/65535.0,
 
153
                        .5f*style->bg[GTK_STATE_NORMAL].blue/65535.0
 
154
                       );
 
155
  // cairo_set_source_rgb (cr, .13, .13, .13);
 
156
  cairo_paint(cr);
 
157
 
 
158
  // draw scrollbar indicators
 
159
  int v = darktable.view_manager->current_view;
 
160
  dt_view_t *view = NULL;
 
161
  if(v >= 0 && v < darktable.view_manager->num_views) view = darktable.view_manager->view + v;
 
162
  // cairo_set_source_rgb (cr, .16, .16, .16);
 
163
  cairo_set_source_rgb (cr,
 
164
                        style->bg[GTK_STATE_NORMAL].red/65535.0,
 
165
                        style->bg[GTK_STATE_NORMAL].green/65535.0,
 
166
                        style->bg[GTK_STATE_NORMAL].blue/65535.0
 
167
                       );
 
168
  const float border = 0.3;
 
169
  if(!view) cairo_paint(cr);
 
170
  else
 
171
  {
 
172
    switch(which)
 
173
    {
 
174
      case 0:
 
175
      case 1: // left, right: vertical
 
176
        cairo_rectangle(cr, 0.0, view->vscroll_pos/view->vscroll_size * height, width, view->vscroll_viewport_size/view->vscroll_size * height);
 
177
        break;
 
178
      default:        // bottom, top: horizontal
 
179
        cairo_rectangle(cr, view->hscroll_pos/view->hscroll_size * width, 0.0, view->hscroll_viewport_size/view->hscroll_size * width, height);
 
180
        break;
 
181
    }
 
182
    cairo_fill(cr);
 
183
    switch(which)
 
184
    {
 
185
      case 0:
 
186
        cairo_rectangle(cr, (1.0-border)*width, 0.0, border*width, height);
 
187
        break;
 
188
      case 1:
 
189
        cairo_rectangle(cr, 0.0, 0.0, border*width, height);
 
190
        break;
 
191
      case 2:
 
192
        cairo_rectangle(cr, (1.0-border)*height, (1.0-border)*height, width-2*(1.0-border)*height, border*height);
 
193
        break;
 
194
      default:
 
195
        cairo_rectangle(cr, (1.0-border)*height, 0.0, width-2*(1.0-border)*height, border*height);
 
196
        break;
 
197
    }
 
198
    cairo_fill(cr);
 
199
  }
 
200
 
 
201
  // draw gui arrows.
 
202
  cairo_set_source_rgb (cr, .6, .6, .6);
 
203
 
 
204
  GtkWidget *panel;
 
205
  switch(which)
 
206
  {
 
207
    case 0: // left
 
208
      panel = glade_xml_get_widget (darktable.gui->main_window, "left");
 
209
      if(GTK_WIDGET_VISIBLE(panel))
 
210
      {
 
211
        cairo_move_to (cr, width, height/2-width);
 
212
        cairo_rel_line_to (cr, 0.0, 2*width);
 
213
        cairo_rel_line_to (cr, -width, -width);
 
214
      }
 
215
      else
 
216
      {
 
217
        cairo_move_to (cr, 0.0, height/2-width);
 
218
        cairo_rel_line_to (cr, 0.0, 2*width);
 
219
        cairo_rel_line_to (cr, width, -width);
 
220
      }
 
221
      break;
 
222
    case 1: // right
 
223
      panel = glade_xml_get_widget (darktable.gui->main_window, "right");
 
224
      if(GTK_WIDGET_VISIBLE(panel))
 
225
      {
 
226
        cairo_move_to (cr, 0.0, height/2-width);
 
227
        cairo_rel_line_to (cr, 0.0, 2*width);
 
228
        cairo_rel_line_to (cr, width, -width);
 
229
      }
 
230
      else
 
231
      {
 
232
        cairo_move_to (cr, width, height/2-width);
 
233
        cairo_rel_line_to (cr, 0.0, 2*width);
 
234
        cairo_rel_line_to (cr, -width, -width);
 
235
      }
 
236
      break;
 
237
    case 2: // top
 
238
      panel = glade_xml_get_widget (darktable.gui->main_window, "top");
 
239
      if(GTK_WIDGET_VISIBLE(panel))
 
240
      {
 
241
        cairo_move_to (cr, width/2-height, height);
 
242
        cairo_rel_line_to (cr, 2*height, 0.0);
 
243
        cairo_rel_line_to (cr, -height, -height);
 
244
      }
 
245
      else
 
246
      {
 
247
        cairo_move_to (cr, width/2-height, 0.0);
 
248
        cairo_rel_line_to (cr, 2*height, 0.0);
 
249
        cairo_rel_line_to (cr, -height, height);
 
250
      }
 
251
      break;
 
252
    default: // bottom
 
253
      panel = glade_xml_get_widget (darktable.gui->main_window, "bottom");
 
254
      if(GTK_WIDGET_VISIBLE(panel))
 
255
      {
 
256
        cairo_move_to (cr, width/2-height, 0.0);
 
257
        cairo_rel_line_to (cr, 2*height, 0.0);
 
258
        cairo_rel_line_to (cr, -height, height);
 
259
      }
 
260
      else
 
261
      {
 
262
        cairo_move_to (cr, width/2-height, height);
 
263
        cairo_rel_line_to (cr, 2*height, 0.0);
 
264
        cairo_rel_line_to (cr, -height, -height);
 
265
      }
 
266
      break;
 
267
  }
 
268
  cairo_close_path (cr);
 
269
  cairo_fill(cr);
 
270
 
 
271
  cairo_destroy(cr);
 
272
  cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget));
 
273
  cairo_set_source_surface (cr_pixmap, cst, 0, 0);
 
274
  cairo_paint(cr_pixmap);
 
275
  cairo_destroy(cr_pixmap);
 
276
  cairo_surface_destroy(cst);
 
277
  return TRUE;
 
278
}
 
279
 
 
280
static dt_iop_module_t *get_colorout_module()
 
281
{
 
282
  GList *modules = darktable.develop->iop;
 
283
  while(modules)
 
284
  {
 
285
    dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
 
286
    if(!strcmp(module->op, "colorout")) return module;
 
287
    modules = g_list_next(modules);
 
288
  }
 
289
  return NULL;
 
290
}
 
291
 
 
292
static void
 
293
update_colorpicker_panel()
 
294
{
 
295
  // synch bottom panel for develop mode
 
296
  dt_iop_module_t *module = get_colorout_module();
 
297
  if(module)
 
298
  {
 
299
    char colstring[512];
 
300
    GtkWidget *w;
 
301
    // w = glade_xml_get_widget (darktable.gui->main_window, "colorpicker_module_label");
 
302
    // snprintf(colstring, 512, C_("color picker module", "`%s'"), module->name());
 
303
    // gtk_label_set_label(GTK_LABEL(w), colstring);
 
304
    w = glade_xml_get_widget (darktable.gui->main_window, "colorpicker_togglebutton");
 
305
    darktable.gui->reset = 1;
 
306
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), module->request_color_pick);
 
307
    darktable.gui->reset = 0;
 
308
 
 
309
    // int input_color = 1; // Lab
 
310
    // always adjust picked color:
 
311
    int m = dt_conf_get_int("ui_last/colorpicker_mean");
 
312
    float *col;
 
313
    switch(m)
 
314
    {
 
315
      case 0: // mean
 
316
        //if(input_color == 1)
 
317
        col = module->picked_color_Lab;
 
318
        //else col = module->picked_color;
 
319
        break;
 
320
      case 1: //min
 
321
        //if(input_color == 1)
 
322
        col = module->picked_color_min_Lab;
 
323
        //else col = module->picked_color_min;
 
324
        break;
 
325
      default:
 
326
        //if(input_color == 1)
 
327
        col = module->picked_color_max_Lab;
 
328
        //else col = module->picked_color_max;
 
329
        break;
 
330
    }
 
331
    w = glade_xml_get_widget (darktable.gui->main_window, "colorpicker_Lab_label");
 
332
    // switch(input_color)
 
333
    // {
 
334
    //   case 0: // linear rgb
 
335
    //     snprintf(colstring, 512, "%s: (%.03f, %.03f, %.03f)", _("linear rgb"), col[0], col[1], col[2]);
 
336
    //     break;
 
337
    //   case 1: // Lab
 
338
    snprintf(colstring, 512, "%s: (%.02f, %.02f, %.02f)", _("Lab"), col[0], col[1], col[2]);
 
339
    //     break;
 
340
    //   default: // output color profile
 
341
    //     snprintf(colstring, 512, "%s: (%.03f, %.03f, %.03f)", _("output profile"), col[0], col[1], col[2]);
 
342
    //     break;
 
343
    // }
 
344
    gtk_label_set_label(GTK_LABEL(w), colstring);
 
345
  }
 
346
}
 
347
 
 
348
static gboolean
 
349
expose (GtkWidget *da, GdkEventExpose *event, gpointer user_data)
 
350
{
 
351
  dt_control_expose(NULL);
 
352
  gdk_draw_drawable(da->window,
 
353
                    da->style->fg_gc[GTK_WIDGET_STATE(da)], darktable.gui->pixmap,
 
354
                    // Only copy the area that was exposed.
 
355
                    event->area.x, event->area.y,
 
356
                    event->area.x, event->area.y,
 
357
                    event->area.width, event->area.height);
 
358
 
 
359
  // update other widgets
 
360
  GtkWidget *widget = glade_xml_get_widget (darktable.gui->main_window, "navigation");
 
361
  gtk_widget_queue_draw(widget);
 
362
 
 
363
  GList *wdl = darktable.gui->redraw_widgets;
 
364
  while(wdl)
 
365
  {
 
366
    GtkWidget *w = (GtkWidget *)wdl->data;
 
367
    gtk_widget_queue_draw(w);
 
368
    wdl = g_list_next(wdl);
 
369
  }
 
370
 
 
371
  update_colorpicker_panel();
 
372
 
 
373
  // test quit cond (thread safe, 2nd pass)
 
374
  if(!dt_control_running())
 
375
  {
 
376
    dt_cleanup();
 
377
    gtk_main_quit();
 
378
  }
 
379
  else
 
380
  {
 
381
    widget = glade_xml_get_widget (darktable.gui->main_window, "metadata_expander");
 
382
    if(gtk_expander_get_expanded(GTK_EXPANDER(widget))) dt_gui_metadata_update();
 
383
  }
 
384
 
 
385
  return TRUE;
 
386
}
 
387
 
 
388
gboolean
 
389
view_label_clicked (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
 
390
{
 
391
  if(event->button == 1)
 
392
  {
 
393
    dt_ctl_switch_mode();
 
394
    return TRUE;
 
395
  }
 
396
  return FALSE;
 
397
}
 
398
 
 
399
gboolean
 
400
darktable_label_clicked (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
 
401
{
 
402
  GtkWidget *dialog = gtk_about_dialog_new();
 
403
  gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), PACKAGE_NAME);
 
404
  gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), PACKAGE_VERSION);
 
405
  gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), "copyright (c) johannes hanika, henrik andersson, tobias ellinghaus et al. 2009-2011");
 
406
  gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("organize and develop images from digital cameras"));
 
407
  gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://darktable.sf.net/");
 
408
  gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "darktable");
 
409
  const char *authors[] =
 
410
  {
 
411
    _("* developers *"),
 
412
    "Henrik Andersson",
 
413
    "Johannes Hanika",
 
414
    "Tobias Ellinghaus",
 
415
    "",
 
416
    _("* ubuntu packaging, color management, video tutorials *"),
 
417
    "Pascal de Bruijn",
 
418
    "",
 
419
    _("* networking, battle testing, translation expert *"),
 
420
    "Alexandre Prokoudine",
 
421
    "",
 
422
    _("* contributors *"),
 
423
    "Alexandre Prokoudine",
 
424
    "Alexander Rabtchevich",
 
425
    "Andrea Purracchio",
 
426
    "Andrey Kaminsky",
 
427
    "Anton Blanchard",
 
428
    "Bernhard Schneider",
 
429
    "Boucman",
 
430
    "Brian Teague",
 
431
    "Bruce Guenter",
 
432
    "Christian Fuchs",
 
433
    "Christian Himpel",
 
434
    "Daniele Giorgis",
 
435
    "David Bremner",
 
436
    "Ger Siemerink",
 
437
    "Gianluigi Calcaterra",
 
438
    "Gregor Quade",
 
439
    "Jan Rinze",
 
440
    "Jochen Schroeder",
 
441
    "Jose Carlos Garcia Sogo",
 
442
    "Karl Mikaelsson",
 
443
    "Klaus Staedtler",
 
444
    "Mikko Ruohola",
 
445
    "Nao Nakashima",
 
446
    "Olivier Tribout",
 
447
    "Pascal de Bruijn",
 
448
    "Pascal Obry",
 
449
    "Robert Park",
 
450
    "Richard Hughes",
 
451
    "Simon Spannagel",
 
452
    "Stephen van den Berg",
 
453
    "Stuart Henderson",
 
454
    "Thierry Leconte",
 
455
    "Wyatt Olson",
 
456
    "Xavier Besse",
 
457
    "Zeus Panchenko",
 
458
    NULL
 
459
  };
 
460
  gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
 
461
 
 
462
  gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), _("translator-credits"));
 
463
  GtkWidget *win = glade_xml_get_widget (darktable.gui->main_window, "main_window");
 
464
  gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(win));
 
465
  gtk_dialog_run(GTK_DIALOG (dialog));
 
466
  gtk_widget_destroy(dialog);
 
467
  return TRUE;
 
468
}
 
469
 
 
470
static void
 
471
colorpicker_mean_changed (GtkComboBox *widget, gpointer p)
 
472
{
 
473
  dt_conf_set_int("ui_last/colorpicker_mean", gtk_combo_box_get_active(widget));
 
474
  update_colorpicker_panel();
 
475
}
 
476
 
 
477
static void
 
478
colorpicker_toggled (GtkToggleButton *button, gpointer p)
 
479
{
 
480
  if(darktable.gui->reset) return;
 
481
  dt_iop_module_t *module = get_colorout_module();
 
482
  if(module)
 
483
  {
 
484
    dt_iop_request_focus(module);
 
485
    module->request_color_pick = gtk_toggle_button_get_active(button);
 
486
  }
 
487
  else
 
488
  {
 
489
    dt_iop_request_focus(NULL);
 
490
  }
 
491
  dt_control_gui_queue_draw();
 
492
}
 
493
 
 
494
static void
 
495
lighttable_zoom_changed (GtkSpinButton *widget, gpointer user_data)
 
496
{
 
497
  const int i = gtk_spin_button_get_value(widget);
 
498
  dt_conf_set_int("plugins/lighttable/images_in_row", i);
 
499
  dt_control_gui_queue_draw();
 
500
}
 
501
 
 
502
static void
 
503
lighttable_layout_changed (GtkComboBox *widget, gpointer user_data)
 
504
{
 
505
  const int i = gtk_combo_box_get_active(widget);
 
506
  dt_conf_set_int("plugins/lighttable/layout", i);
 
507
  dt_control_gui_queue_draw();
 
508
}
 
509
 
 
510
static void
 
511
update_query()
 
512
{
 
513
  /* updates query */
 
514
  dt_collection_update_query (darktable.collection);
 
515
 
 
516
  /* updates visual */
 
517
  GtkWidget *win = glade_xml_get_widget (darktable.gui->main_window, "center");
 
518
  gtk_widget_queue_draw (win);
 
519
 
 
520
  /* update film strip, jump to currently opened image, if any: */
 
521
  if(darktable.develop->image)
 
522
    dt_view_film_strip_scroll_to(darktable.view_manager, darktable.develop->image->id);
 
523
}
 
524
 
 
525
static void
 
526
image_filter_changed (GtkComboBox *widget, gpointer user_data)
 
527
{
 
528
  // image_filter
 
529
  int i = gtk_combo_box_get_active(widget);
 
530
  if     (i == 0)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_ALL);
 
531
  else if(i == 1)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_NO);
 
532
  else if(i == 2)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_1);
 
533
  else if(i == 3)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_2);
 
534
  else if(i == 4)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_3);
 
535
  else if(i == 5)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_4);
 
536
  else if(i == 6)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_STAR_5);
 
537
  else if(i == 7)  dt_conf_set_int("ui_last/combo_filter",     DT_LIB_FILTER_REJECT);
 
538
 
 
539
 
 
540
  /* update collection star filter flags */
 
541
  if (i == 0)
 
542
    dt_collection_set_filter_flags (darktable.collection, dt_collection_get_filter_flags (darktable.collection) & ~(COLLECTION_FILTER_ATLEAST_RATING|COLLECTION_FILTER_EQUAL_RATING));
 
543
  else if (i == 1 || i == 7)
 
544
    dt_collection_set_filter_flags (darktable.collection, (dt_collection_get_filter_flags (darktable.collection) | COLLECTION_FILTER_EQUAL_RATING) & ~COLLECTION_FILTER_ATLEAST_RATING);
 
545
  else
 
546
    dt_collection_set_filter_flags (darktable.collection, dt_collection_get_filter_flags (darktable.collection) | COLLECTION_FILTER_ATLEAST_RATING );
 
547
 
 
548
  /* set the star filter in collection */
 
549
  dt_collection_set_rating(darktable.collection, i-1);
 
550
 
 
551
  update_query();
 
552
}
 
553
 
 
554
 
 
555
static void
 
556
image_sort_changed (GtkComboBox *widget, gpointer user_data)
 
557
{
 
558
  // image_sort
 
559
  int i = gtk_combo_box_get_active(widget);
 
560
  if     (i == 0)  dt_conf_set_int("ui_last/combo_sort",     DT_LIB_SORT_FILENAME);
 
561
  else if(i == 1)  dt_conf_set_int("ui_last/combo_sort",     DT_LIB_SORT_DATETIME);
 
562
  else if(i == 2)  dt_conf_set_int("ui_last/combo_sort",     DT_LIB_SORT_RATING);
 
563
  else if(i == 3)  dt_conf_set_int("ui_last/combo_sort",     DT_LIB_SORT_ID);
 
564
  else if(i == 4)  dt_conf_set_int("ui_last/combo_sort",     DT_LIB_SORT_COLOR);
 
565
 
 
566
  update_query();
 
567
}
 
568
 
 
569
 
 
570
static void
 
571
snapshot_add_button_clicked (GtkWidget *widget, gpointer user_data)
 
572
{
 
573
 
 
574
  if (!darktable.develop->image) return;
 
575
  char wdname[64], oldfilename[30];
 
576
  GtkWidget *sbody =  glade_xml_get_widget (darktable.gui->main_window, "snapshots_body");
 
577
  GtkWidget *sbox = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (sbody)), 0);
 
578
 
 
579
  GtkWidget *wid = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (sbox)), 0);
 
580
  gchar *label1 = g_strdup (gtk_button_get_label (GTK_BUTTON (wid)));
 
581
  snprintf (oldfilename, 30, "%s", darktable.gui->snapshot[3].filename);
 
582
  for (int k=1; k<4; k++)
 
583
  {
 
584
    wid = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (sbox)), k);
 
585
    if (k<MIN (4,darktable.gui->num_snapshots+1)) gtk_widget_set_visible (wid, TRUE);
 
586
    gchar *label2 = g_strdup(gtk_button_get_label (GTK_BUTTON (wid)));
 
587
    gtk_button_set_label (GTK_BUTTON (wid), label1);
 
588
    g_free (label1);
 
589
    label1 = label2;
 
590
    darktable.gui->snapshot[k] = darktable.gui->snapshot[k-1];
 
591
  }
 
592
 
 
593
  // rotate filenames, so we don't waste hd space
 
594
  snprintf(darktable.gui->snapshot[0].filename, 30, "%s", oldfilename);
 
595
  g_free(label1);
 
596
 
 
597
  wid = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (sbox)), 0);
 
598
  char *fname = darktable.develop->image->filename + strlen(darktable.develop->image->filename);
 
599
  while(fname > darktable.develop->image->filename && *fname != '/') fname--;
 
600
  snprintf(wdname, 64, "%s", fname);
 
601
  fname = wdname + strlen(wdname);
 
602
  while(fname > wdname && *fname != '.') fname --;
 
603
  if(*fname != '.') fname = wdname + strlen(wdname);
 
604
  if(wdname + 64 - fname > 4) sprintf(fname, "(%d)", darktable.develop->history_end);
 
605
  // snprintf(wdname, 64, _("snapshot %d"), darktable.gui->num_snapshots+1);
 
606
 
 
607
  gtk_button_set_label (GTK_BUTTON (wid), wdname);
 
608
  gtk_widget_set_visible (wid, TRUE);
 
609
 
 
610
  /* get zoom pos from develop */
 
611
  dt_gui_snapshot_t *s = darktable.gui->snapshot + 0;
 
612
  DT_CTL_GET_GLOBAL (s->zoom_y, dev_zoom_y);
 
613
  DT_CTL_GET_GLOBAL (s->zoom_x, dev_zoom_x);
 
614
  DT_CTL_GET_GLOBAL (s->zoom, dev_zoom);
 
615
  DT_CTL_GET_GLOBAL (s->closeup, dev_closeup);
 
616
  DT_CTL_GET_GLOBAL (s->zoom_scale, dev_zoom_scale);
 
617
 
 
618
  /* set take snap bit for darkroom */
 
619
  darktable.gui->request_snapshot = 1;
 
620
  darktable.gui->num_snapshots ++;
 
621
  dt_control_gui_queue_draw ();
 
622
 
 
623
}
 
624
 
 
625
static void
 
626
snapshot_toggled (GtkToggleButton *widget, long int which)
 
627
{
 
628
  if(!gtk_toggle_button_get_active(widget) && darktable.gui->selected_snapshot == which)
 
629
  {
 
630
    if(darktable.gui->snapshot_image)
 
631
    {
 
632
      cairo_surface_destroy(darktable.gui->snapshot_image);
 
633
      darktable.gui->snapshot_image = NULL;
 
634
      dt_control_gui_queue_draw();
 
635
    }
 
636
  }
 
637
  else if(gtk_toggle_button_get_active(widget))
 
638
  {
 
639
    GtkWidget *sbody =  glade_xml_get_widget (darktable.gui->main_window, "snapshots_body");
 
640
    GtkWidget *sbox = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (sbody)), 0);
 
641
 
 
642
    for(int k=0; k<4; k++)
 
643
    {
 
644
      GtkWidget *w = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER(sbox)), k);
 
645
      if(GTK_TOGGLE_BUTTON(w) != widget)
 
646
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE);
 
647
    }
 
648
    if(darktable.gui->snapshot_image)
 
649
    {
 
650
      cairo_surface_destroy(darktable.gui->snapshot_image);
 
651
      darktable.gui->snapshot_image = NULL;
 
652
    }
 
653
    darktable.gui->selected_snapshot = which;
 
654
    dt_gui_snapshot_t *s = darktable.gui->snapshot + which;
 
655
    DT_CTL_SET_GLOBAL(dev_zoom_y,     s->zoom_y);
 
656
    DT_CTL_SET_GLOBAL(dev_zoom_x,     s->zoom_x);
 
657
    DT_CTL_SET_GLOBAL(dev_zoom,       s->zoom);
 
658
    DT_CTL_SET_GLOBAL(dev_closeup,    s->closeup);
 
659
    DT_CTL_SET_GLOBAL(dev_zoom_scale, s->zoom_scale);
 
660
    dt_dev_invalidate(darktable.develop);
 
661
    darktable.gui->snapshot_image = cairo_image_surface_create_from_png(s->filename);
 
662
    dt_control_gui_queue_draw();
 
663
  }
 
664
}
 
665
 
 
666
void
 
667
preferences_button_clicked (GtkWidget *widget, gpointer user_data)
 
668
{
 
669
  dt_gui_preferences_show();
 
670
}
 
671
 
 
672
void
 
673
import_button_clicked (GtkWidget *widget, gpointer user_data)
 
674
{
 
675
  GtkWidget *win = glade_xml_get_widget (darktable.gui->main_window, "main_window");
 
676
  GtkWidget *filechooser = gtk_file_chooser_dialog_new (_("import film"),
 
677
                           GTK_WINDOW (win),
 
678
                           GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
 
679
                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
680
                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
 
681
                           (char *)NULL);
 
682
 
 
683
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), TRUE);
 
684
 
 
685
  char *last_directory = dt_conf_get_string("ui_last/import_last_directory");
 
686
  if(last_directory != NULL)
 
687
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (filechooser), last_directory);
 
688
 
 
689
  // add extra lines to 'extra'. don't forget to destroy the widgets later.
 
690
  GtkWidget *extra;
 
691
  extra = gtk_vbox_new(FALSE, 0);
 
692
 
 
693
  // recursive opening.
 
694
  GtkWidget *recursive;
 
695
  recursive = gtk_check_button_new_with_label (_("import directories recursively"));
 
696
  g_object_set(recursive, "tooltip-text", _("recursively import subdirectories. each directory goes into a new film roll."), NULL);
 
697
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (recursive), dt_conf_get_bool("ui_last/import_recursive"));
 
698
  gtk_widget_show (recursive);
 
699
  gtk_box_pack_start(GTK_BOX (extra), recursive, FALSE, FALSE, 0);
 
700
 
 
701
  // ignoring of jpegs. hack while we don't handle raw+jpeg in the same directories.
 
702
  GtkWidget *ignore_jpeg;
 
703
  ignore_jpeg = gtk_check_button_new_with_label (_("ignore jpeg files"));
 
704
  g_object_set(ignore_jpeg, "tooltip-text", _("do not load files with an extension of .jpg or .jpeg. this can be useful when there are raw+jpeg in a directory."), NULL);
 
705
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (ignore_jpeg), dt_conf_get_bool("ui_last/import_ignore_jpegs"));
 
706
  gtk_widget_show (ignore_jpeg);
 
707
  gtk_box_pack_start(GTK_BOX (extra), ignore_jpeg, FALSE, FALSE, 0);
 
708
 
 
709
  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (filechooser), extra);
 
710
 
 
711
  if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
 
712
  {
 
713
    dt_conf_set_bool("ui_last/import_recursive", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (recursive)));
 
714
    dt_conf_set_bool("ui_last/import_ignore_jpegs", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (ignore_jpeg)));
 
715
    dt_conf_set_string("ui_last/import_last_directory", gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER (filechooser)));
 
716
 
 
717
    char *filename;
 
718
    GSList *list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser));
 
719
    GSList *it = list;
 
720
    int id = 0;
 
721
    while(it)
 
722
    {
 
723
      filename = (char *)it->data;
 
724
      id = dt_film_import(filename);
 
725
      g_free (filename);
 
726
      it = g_slist_next(it);
 
727
    }
 
728
    if(id)
 
729
    {
 
730
      dt_film_open(id);
 
731
      dt_ctl_switch_mode_to(DT_LIBRARY);
 
732
    }
 
733
    g_slist_free (list);
 
734
  }
 
735
  gtk_widget_destroy(recursive);
 
736
  gtk_widget_destroy(ignore_jpeg);
 
737
  gtk_widget_destroy(extra);
 
738
  gtk_widget_destroy (filechooser);
 
739
  win = glade_xml_get_widget (darktable.gui->main_window, "center");
 
740
  gtk_widget_queue_draw(win);
 
741
}
 
742
 
 
743
void
 
744
import_image_button_clicked (GtkWidget *widget, gpointer user_data)
 
745
{
 
746
  GtkWidget *win = glade_xml_get_widget (darktable.gui->main_window, "main_window");
 
747
  GtkWidget *filechooser = gtk_file_chooser_dialog_new (_("import image"),
 
748
                           GTK_WINDOW (win),
 
749
                           GTK_FILE_CHOOSER_ACTION_OPEN,
 
750
                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
751
                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
 
752
                           (char *)NULL);
 
753
 
 
754
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), TRUE);
 
755
 
 
756
  char *last_directory = dt_conf_get_string("ui_last/import_last_directory");
 
757
  if(last_directory != NULL)
 
758
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (filechooser), last_directory);
 
759
 
 
760
  char *cp, **extensions, ext[1024];
 
761
  GtkFileFilter *filter;
 
762
  filter = GTK_FILE_FILTER(gtk_file_filter_new());
 
763
  extensions = g_strsplit(dt_supported_extensions, ",", 100);
 
764
  for(char **i=extensions; *i!=NULL; i++)
 
765
  {
 
766
    snprintf(ext, 1024, "*.%s", *i);
 
767
    gtk_file_filter_add_pattern(filter, ext);
 
768
    gtk_file_filter_add_pattern(filter, cp=g_ascii_strup(ext, -1));
 
769
    g_free(cp);
 
770
  }
 
771
  g_strfreev(extensions);
 
772
  gtk_file_filter_set_name(filter, _("supported images"));
 
773
  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
 
774
 
 
775
  filter = GTK_FILE_FILTER(gtk_file_filter_new());
 
776
  gtk_file_filter_add_pattern(filter, "*");
 
777
  gtk_file_filter_set_name(filter, _("all files"));
 
778
  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
 
779
 
 
780
  if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
 
781
  {
 
782
    dt_conf_set_string("ui_last/import_last_directory", gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER (filechooser)));
 
783
 
 
784
    char *filename;
 
785
    dt_film_t film;
 
786
    GSList *list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser));
 
787
    GSList *it = list;
 
788
    int id = 0;
 
789
    int filmid = 0;
 
790
    while(it)
 
791
    {
 
792
      filename = (char *)it->data;
 
793
      gchar *directory = g_path_get_dirname((const gchar *)filename);
 
794
      filmid = dt_film_new(&film, directory);
 
795
      id = dt_image_import(filmid, filename, TRUE);
 
796
      if(!id) dt_control_log(_("error loading file `%s'"), filename);
 
797
      g_free (filename);
 
798
      g_free (directory);
 
799
      it = g_slist_next(it);
 
800
    }
 
801
 
 
802
    if(id)
 
803
    {
 
804
      dt_film_open(filmid);
 
805
      // make sure buffers are loaded (load full for testing)
 
806
      dt_image_t *img = dt_image_cache_get(id, 'r');
 
807
      dt_image_buffer_t buf = dt_image_get_blocking(img, DT_IMAGE_FULL, 'r');
 
808
      if(!buf)
 
809
      {
 
810
        dt_image_cache_release(img, 'r');
 
811
        dt_control_log(_("file `%s' has unknown format!"), filename);
 
812
      }
 
813
      else
 
814
      {
 
815
        dt_image_release(img, DT_IMAGE_FULL, 'r');
 
816
        dt_image_cache_release(img, 'r');
 
817
        DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id);
 
818
        dt_ctl_switch_mode_to(DT_DEVELOP);
 
819
      }
 
820
    }
 
821
  }
 
822
  gtk_widget_destroy (filechooser);
 
823
  win = glade_xml_get_widget (darktable.gui->main_window, "center");
 
824
  gtk_widget_queue_draw(win);
 
825
}
 
826
 
 
827
static gboolean
 
828
scrolled (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
 
829
{
 
830
  dt_view_manager_scrolled(darktable.view_manager, event->x, event->y, event->direction == GDK_SCROLL_UP, event->state & 0xf);
 
831
  gtk_widget_queue_draw(widget);
 
832
  return TRUE;
 
833
}
 
834
 
 
835
static gboolean
 
836
borders_scrolled (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
 
837
{
 
838
  dt_view_manager_border_scrolled(darktable.view_manager, event->x, event->y, (long int)user_data, event->direction == GDK_SCROLL_UP);
 
839
  gtk_widget_queue_draw(widget);
 
840
  return TRUE;
 
841
}
 
842
 
 
843
void quit()
 
844
{
 
845
  // thread safe quit, 1st pass:
 
846
  GtkWindow *win = GTK_WINDOW(glade_xml_get_widget (darktable.gui->main_window, "main_window"));
 
847
  gtk_window_iconify(win);
 
848
 
 
849
  GtkWidget *widget;
 
850
  widget = glade_xml_get_widget (darktable.gui->main_window, "leftborder");
 
851
  g_signal_handlers_block_by_func (widget, expose_borders, (gpointer)0);
 
852
  widget = glade_xml_get_widget (darktable.gui->main_window, "rightborder");
 
853
  g_signal_handlers_block_by_func (widget, expose_borders, (gpointer)1);
 
854
  widget = glade_xml_get_widget (darktable.gui->main_window, "topborder");
 
855
  g_signal_handlers_block_by_func (widget, expose_borders, (gpointer)2);
 
856
  widget = glade_xml_get_widget (darktable.gui->main_window, "bottomborder");
 
857
  g_signal_handlers_block_by_func (widget, expose_borders, (gpointer)3);
 
858
 
 
859
  dt_pthread_mutex_lock(&darktable.control->cond_mutex);
 
860
  dt_pthread_mutex_lock(&darktable.control->run_mutex);
 
861
  darktable.control->running = 0;
 
862
  dt_pthread_mutex_unlock(&darktable.control->run_mutex);
 
863
  dt_pthread_mutex_unlock(&darktable.control->cond_mutex);
 
864
  widget = glade_xml_get_widget (darktable.gui->main_window, "center");
 
865
  gtk_widget_queue_draw(widget);
 
866
}
 
867
 
 
868
static void _gui_switch_view_key_accel_callback(void *p)
 
869
{
 
870
  int view=(long int)p;
 
871
  dt_ctl_gui_mode_t mode=DT_MODE_NONE;
 
872
  /* do some setup before switch view*/
 
873
  switch (view)
 
874
  {
 
875
#ifdef HAVE_GPHOTO2
 
876
    case DT_GUI_VIEW_SWITCH_TO_TETHERING:
 
877
      // switching to capture view using "plugins/capture/current_filmroll" as session...
 
878
      // and last used camera
 
879
      if (dt_camctl_can_enter_tether_mode(darktable.camctl,NULL) )
 
880
      {
 
881
        dt_conf_set_int( "plugins/capture/mode", DT_CAPTURE_MODE_TETHERED);
 
882
        mode = DT_CAPTURE;
 
883
      }
 
884
      break;
 
885
#endif
 
886
 
 
887
    case DT_GUI_VIEW_SWITCH_TO_DARKROOM:
 
888
      mode = DT_DEVELOP;
 
889
      break;
 
890
 
 
891
    case DT_GUI_VIEW_SWITCH_TO_LIBRARY:
 
892
      mode = DT_LIBRARY;
 
893
      break;
 
894
 
 
895
  }
 
896
 
 
897
  /* try switch to mode */
 
898
  dt_ctl_switch_mode_to (mode);
 
899
}
 
900
 
 
901
static void quit_callback(void *p)
 
902
{
 
903
  quit();
 
904
}
 
905
 
 
906
static gboolean
 
907
configure (GtkWidget *da, GdkEventConfigure *event, gpointer user_data)
 
908
{
 
909
  static int oldw = 0;
 
910
  static int oldh = 0;
 
911
  //make our selves a properly sized pixmap if our window has been resized
 
912
  if (oldw != event->width || oldh != event->height)
 
913
  {
 
914
    //create our new pixmap with the correct size.
 
915
    GdkPixmap *tmppixmap = gdk_pixmap_new(da->window, event->width,  event->height, -1);
 
916
    //copy the contents of the old pixmap to the new pixmap.  This keeps ugly uninitialized
 
917
    //pixmaps from being painted upon resize
 
918
    int minw = oldw, minh = oldh;
 
919
    if(event->width  < minw) minw = event->width;
 
920
    if(event->height < minh) minh = event->height;
 
921
    gdk_draw_drawable(tmppixmap, da->style->fg_gc[GTK_WIDGET_STATE(da)], darktable.gui->pixmap, 0, 0, 0, 0, minw, minh);
 
922
    //we're done with our old pixmap, so we can get rid of it and replace it with our properly-sized one.
 
923
    g_object_unref(darktable.gui->pixmap);
 
924
    darktable.gui->pixmap = tmppixmap;
 
925
  }
 
926
  oldw = event->width;
 
927
  oldh = event->height;
 
928
 
 
929
  return dt_control_configure(da, event, user_data);
 
930
}
 
931
 
 
932
void dt_gui_key_accel_register(guint state, guint keyval, void (*callback)(void *), void *data)
 
933
{
 
934
  dt_gui_key_accel_t *a = (dt_gui_key_accel_t *)malloc(sizeof(dt_gui_key_accel_t));
 
935
  a->state = state;
 
936
  a->keyval = keyval;
 
937
  a->callback = callback;
 
938
  a->data = data;
 
939
  darktable.gui->key_accels = g_list_append(darktable.gui->key_accels, a);
 
940
}
 
941
 
 
942
void dt_gui_key_accel_unregister(void (*callback)(void *))
 
943
{
 
944
  GList *i = darktable.gui->key_accels;
 
945
  while(i)
 
946
  {
 
947
    dt_gui_key_accel_t *a = (dt_gui_key_accel_t *)i->data;
 
948
    GList *ii = g_list_next(i);
 
949
    if(a->callback == callback)
 
950
    {
 
951
      free(a);
 
952
      darktable.gui->key_accels = g_list_delete_link(darktable.gui->key_accels, i);
 
953
    }
 
954
    i = ii;
 
955
  }
 
956
}
 
957
 
 
958
static gboolean
 
959
key_pressed_override (GtkWidget *w, GdkEventKey *event, gpointer user_data)
 
960
{
 
961
  GList *i = darktable.gui->key_accels;
 
962
  // fprintf(stderr,"Key Press state: %d hwkey: %d\n",event->state, event->hardware_keycode);
 
963
 
 
964
  /* check if we should handle key press */
 
965
  if (dt_control_is_key_accelerators_on (darktable.control) !=1)
 
966
    return FALSE;
 
967
 
 
968
  // we're only interested in ctrl, shift, mod1 (alt)
 
969
  int estate = event->state & 0xf;
 
970
 
 
971
  while(i)
 
972
  {
 
973
    dt_gui_key_accel_t *a = (dt_gui_key_accel_t *)i->data;
 
974
    // if a->state == 0, i.e. no modifiers are selected, no modifiers are allowed, in fact.
 
975
    if(
 
976
      (
 
977
        (!a->state && (!estate || (!(estate&GDK_MOD1_MASK) && !(estate&GDK_CONTROL_MASK)) ) ) ||
 
978
        (a->state && (a->state == (a->state & estate)))
 
979
      ) && a->keyval == event->keyval)
 
980
    {
 
981
      a->callback(a->data);
 
982
      return TRUE;
 
983
    }
 
984
    i = g_list_next(i);
 
985
  }
 
986
  return dt_control_key_pressed_override(event->hardware_keycode);
 
987
}
 
988
 
 
989
static gboolean
 
990
key_pressed (GtkWidget *w, GdkEventKey *event, gpointer user_data)
 
991
{
 
992
  return dt_control_key_pressed(event->hardware_keycode);
 
993
}
 
994
 
 
995
static gboolean
 
996
key_released (GtkWidget *w, GdkEventKey *event, gpointer user_data)
 
997
{
 
998
  return dt_control_key_released(event->hardware_keycode);
 
999
}
 
1000
 
 
1001
static gboolean
 
1002
button_pressed (GtkWidget *w, GdkEventButton *event, gpointer user_data)
 
1003
{
 
1004
  dt_control_button_pressed(event->x, event->y, event->button, event->type, event->state & 0xf);
 
1005
  gtk_widget_grab_focus(w);
 
1006
  gtk_widget_queue_draw(w);
 
1007
  return TRUE;
 
1008
}
 
1009
 
 
1010
static gboolean
 
1011
button_released (GtkWidget *w, GdkEventButton *event, gpointer user_data)
 
1012
{
 
1013
  dt_control_button_released(event->x, event->y, event->button, event->state & 0xf);
 
1014
  gtk_widget_queue_draw(w);
 
1015
  return TRUE;
 
1016
}
 
1017
 
 
1018
static gboolean
 
1019
mouse_moved (GtkWidget *w, GdkEventMotion *event, gpointer user_data)
 
1020
{
 
1021
  dt_control_mouse_moved(event->x, event->y, event->state & 0xf);
 
1022
  gint x, y;
 
1023
  gdk_window_get_pointer(event->window, &x, &y, NULL);
 
1024
  return TRUE;
 
1025
}
 
1026
 
 
1027
static gboolean
 
1028
center_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
 
1029
{
 
1030
  dt_control_mouse_leave();
 
1031
  return TRUE;
 
1032
}
 
1033
 
 
1034
static gboolean
 
1035
center_enter(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
 
1036
{
 
1037
  dt_control_mouse_enter();
 
1038
  return TRUE;
 
1039
}
 
1040
 
 
1041
#include "background_jobs.h"
 
1042
int
 
1043
dt_gui_gtk_init(dt_gui_gtk_t *gui, int argc, char *argv[])
 
1044
{
 
1045
  // unset gtk rc from kde:
 
1046
  char path[1024], datadir[1024];
 
1047
  dt_get_datadir(datadir, 1024);
 
1048
  gchar *themefile = dt_conf_get_string("themefile");
 
1049
  if(themefile && themefile[0] == '/') snprintf(path, 1023, "%s", themefile);
 
1050
  else snprintf(path, 1023, "%s/%s", datadir, themefile ? themefile : "darktable.gtkrc");
 
1051
  if(!g_file_test(path, G_FILE_TEST_EXISTS))
 
1052
    snprintf(path, 1023, "%s/%s", DARKTABLE_DATADIR, themefile ? themefile : "darktable.gtkrc");
 
1053
  (void)setenv("GTK2_RC_FILES", path, 1);
 
1054
 
 
1055
  GtkWidget *widget;
 
1056
 
 
1057
  gui->num_snapshots = 0;
 
1058
  gui->request_snapshot = 0;
 
1059
  gui->selected_snapshot = 0;
 
1060
  gui->snapshot_image = NULL;
 
1061
  gui->pixmap = NULL;
 
1062
  gui->center_tooltip = 0;
 
1063
  memset(gui->snapshot, 0, sizeof(gui->snapshot));
 
1064
  for(int k=0; k<4; k++) snprintf(gui->snapshot[k].filename, 30, "/tmp/dt_snapshot_%d.png", k);
 
1065
  gui->presets_popup_menu = NULL;
 
1066
  if (!g_thread_supported ()) g_thread_init(NULL);
 
1067
  gdk_threads_init();
 
1068
  gdk_threads_enter();
 
1069
  gtk_init (&argc, &argv);
 
1070
 
 
1071
  if(g_file_test(path, G_FILE_TEST_EXISTS)) gtk_rc_parse (path);
 
1072
  else
 
1073
  {
 
1074
    fprintf(stderr, "[gtk_init] could not find darktable.gtkrc in . or %s!\n", datadir);
 
1075
    return 1;
 
1076
  }
 
1077
  g_free(themefile);
 
1078
 
 
1079
 
 
1080
  /* load the interface */
 
1081
  snprintf(path, 1023, "%s/darktable.glade", datadir);
 
1082
  if(g_file_test(path, G_FILE_TEST_EXISTS)) darktable.gui->main_window = glade_xml_new (path, NULL, NULL);
 
1083
  else
 
1084
  {
 
1085
    snprintf(path, 1023, "%s/darktable.glade", DARKTABLE_DATADIR);
 
1086
    if(g_file_test(path, G_FILE_TEST_EXISTS)) darktable.gui->main_window = glade_xml_new (path, NULL, NULL);
 
1087
    else
 
1088
    {
 
1089
      fprintf(stderr, "[gtk_init] could not find darktable.glade in . or %s!\n", DARKTABLE_DATADIR);
 
1090
      return 1;
 
1091
    }
 
1092
  }
 
1093
 
 
1094
  // set constant width from gconf key
 
1095
  int panel_width = dt_conf_get_int("panel_width");
 
1096
  if(panel_width < 20 || panel_width > 500)
 
1097
  {
 
1098
    // fix for unset/insane values.
 
1099
    panel_width = 300;
 
1100
    dt_conf_set_int("panel_width", panel_width);
 
1101
  }
 
1102
  widget = glade_xml_get_widget (darktable.gui->main_window, "right");
 
1103
  gtk_widget_set_size_request (widget, panel_width, -1);
 
1104
  widget = glade_xml_get_widget (darktable.gui->main_window, "left");
 
1105
  gtk_widget_set_size_request (widget, panel_width, -1);
 
1106
  widget = glade_xml_get_widget (darktable.gui->main_window, "right_vbox");
 
1107
  gtk_widget_set_size_request (widget, panel_width-5, -1);
 
1108
  widget = glade_xml_get_widget (darktable.gui->main_window, "left_vbox");
 
1109
  gtk_widget_set_size_request (widget, panel_width-5, -1);
 
1110
  // leave some space for scrollbars to appear:
 
1111
  widget = glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox");
 
1112
  gtk_widget_set_size_request (widget, panel_width-5-13, -1);
 
1113
  widget = glade_xml_get_widget (darktable.gui->main_window, "left_scrolled");
 
1114
  gtk_widget_set_size_request (widget, panel_width-5-13, -1);
 
1115
  // and make the scrollbars disappear when not needed:
 
1116
  widget = glade_xml_get_widget (darktable.gui->main_window, "left_scrolledwindow");
 
1117
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
1118
  widget = glade_xml_get_widget (darktable.gui->main_window, "right_scrolledwindow");
 
1119
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
1120
 
 
1121
  // create preferences button:
 
1122
  widget = glade_xml_get_widget (darktable.gui->main_window, "topfilterhbox");
 
1123
  GtkWidget *button = dtgtk_button_new(dtgtk_cairo_paint_preferences, CPF_STYLE_FLAT);
 
1124
  gtk_box_pack_end(GTK_BOX(widget), button, FALSE, FALSE, 20);
 
1125
  gtk_object_set(GTK_OBJECT(button), "tooltip-text", _("show global preferences"), (char *)NULL);
 
1126
  g_signal_connect (G_OBJECT (button), "clicked",
 
1127
                    G_CALLBACK (preferences_button_clicked),
 
1128
                    NULL);
 
1129
 
 
1130
 
 
1131
  // Update the devices module with available devices
 
1132
#ifdef HAVE_GPHOTO2
 
1133
  dt_gui_devices_init();
 
1134
#endif
 
1135
  dt_gui_background_jobs_init();
 
1136
 
 
1137
  /* connect the signals in the interface */
 
1138
 
 
1139
  widget = glade_xml_get_widget (darktable.gui->main_window, "button_import");
 
1140
  g_signal_connect (G_OBJECT (widget), "clicked",
 
1141
                    G_CALLBACK (import_button_clicked),
 
1142
                    NULL);
 
1143
 
 
1144
  widget = glade_xml_get_widget (darktable.gui->main_window, "button_import_single");
 
1145
  g_signal_connect (G_OBJECT (widget), "clicked",
 
1146
                    G_CALLBACK (import_image_button_clicked),
 
1147
                    NULL);
 
1148
 
 
1149
  /* Have the delete event (window close) end the program */
 
1150
  dt_get_datadir(datadir, 1024);
 
1151
  snprintf(path, 1024, "%s/icons", datadir);
 
1152
  gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), path);
 
1153
  widget = glade_xml_get_widget (darktable.gui->main_window, "main_window");
 
1154
  gtk_window_set_icon_name(GTK_WINDOW(widget), "darktable");
 
1155
  gtk_window_set_title(GTK_WINDOW(widget), "Darktable");
 
1156
 
 
1157
  g_signal_connect (G_OBJECT (widget), "delete_event",
 
1158
                    G_CALLBACK (quit), NULL);
 
1159
  g_signal_connect (G_OBJECT (widget), "key-press-event",
 
1160
                    G_CALLBACK (key_pressed_override), NULL);
 
1161
  g_signal_connect (G_OBJECT (widget), "key-release-event",
 
1162
                    G_CALLBACK (key_released), NULL);
 
1163
 
 
1164
  gtk_widget_show_all(widget);
 
1165
 
 
1166
  widget = glade_xml_get_widget (darktable.gui->main_window, "darktable_label");
 
1167
  gtk_label_set_label(GTK_LABEL(widget), "<span color=\"#7f7f7f\"><big><b>"PACKAGE_NAME" "PACKAGE_VERSION"</b></big></span>");
 
1168
 
 
1169
  widget = glade_xml_get_widget (darktable.gui->main_window, "center");
 
1170
 
 
1171
  g_signal_connect (G_OBJECT (widget), "key-press-event",
 
1172
                    G_CALLBACK (key_pressed), NULL);
 
1173
  g_signal_connect (G_OBJECT (widget), "configure-event",
 
1174
                    G_CALLBACK (configure), NULL);
 
1175
  g_signal_connect (G_OBJECT (widget), "expose-event",
 
1176
                    G_CALLBACK (expose), NULL);
 
1177
  g_signal_connect (G_OBJECT (widget), "motion-notify-event",
 
1178
                    G_CALLBACK (mouse_moved), NULL);
 
1179
  g_signal_connect (G_OBJECT (widget), "leave-notify-event",
 
1180
                    G_CALLBACK (center_leave), NULL);
 
1181
  g_signal_connect (G_OBJECT (widget), "enter-notify-event",
 
1182
                    G_CALLBACK (center_enter), NULL);
 
1183
  g_signal_connect (G_OBJECT (widget), "button-press-event",
 
1184
                    G_CALLBACK (button_pressed), NULL);
 
1185
  g_signal_connect (G_OBJECT (widget), "button-release-event",
 
1186
                    G_CALLBACK (button_released), NULL);
 
1187
  g_signal_connect (G_OBJECT (widget), "scroll-event",
 
1188
                    G_CALLBACK (scrolled), NULL);
 
1189
  // TODO: left, right, top, bottom:
 
1190
  //leave-notify-event
 
1191
 
 
1192
  widget = glade_xml_get_widget (darktable.gui->main_window, "leftborder");
 
1193
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)0);
 
1194
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), (gpointer)0);
 
1195
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)0);
 
1196
  widget = glade_xml_get_widget (darktable.gui->main_window, "rightborder");
 
1197
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)1);
 
1198
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), (gpointer)1);
 
1199
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)1);
 
1200
  widget = glade_xml_get_widget (darktable.gui->main_window, "topborder");
 
1201
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)2);
 
1202
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), (gpointer)2);
 
1203
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)2);
 
1204
  widget = glade_xml_get_widget (darktable.gui->main_window, "bottomborder");
 
1205
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)3);
 
1206
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), (gpointer)3);
 
1207
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)3);
 
1208
 
 
1209
 
 
1210
 
 
1211
  widget = glade_xml_get_widget (darktable.gui->main_window, "navigation");
 
1212
  dt_gui_navigation_init(&gui->navigation, widget);
 
1213
  gtk_widget_set_size_request(widget, -1, panel_width*.5);
 
1214
 
 
1215
  widget = glade_xml_get_widget (darktable.gui->main_window, "histogram");
 
1216
  gtk_widget_set_size_request(widget, -1, panel_width*.5);
 
1217
  dt_gui_histogram_init(&gui->histogram, widget);
 
1218
 
 
1219
  dt_gui_presets_init();
 
1220
 
 
1221
  // image op history
 
1222
  dt_gui_iop_history_init();
 
1223
 
 
1224
  /* initializes the module groups buttonbar control */
 
1225
  dt_gui_iop_modulegroups_init ();
 
1226
 
 
1227
  // image filtering/sorting
 
1228
  widget = glade_xml_get_widget (darktable.gui->main_window, "image_filter");
 
1229
  g_signal_connect (G_OBJECT (widget), "changed",
 
1230
                    G_CALLBACK (image_filter_changed),
 
1231
                    (gpointer)0);
 
1232
  widget = glade_xml_get_widget (darktable.gui->main_window, "image_sort");
 
1233
  g_signal_connect (G_OBJECT (widget), "changed",
 
1234
                    G_CALLBACK (image_sort_changed),
 
1235
                    (gpointer)0);
 
1236
 
 
1237
  // snapshot management
 
1238
  GtkWidget *sbody = glade_xml_get_widget (darktable.gui->main_window, "snapshots_body");
 
1239
  GtkWidget *svbox = gtk_vbox_new (FALSE,0);
 
1240
  GtkWidget *sbutton = gtk_button_new_with_label (_("take snapshot"));
 
1241
  gtk_box_pack_start (GTK_BOX (sbody),svbox,FALSE,FALSE,0);
 
1242
  gtk_box_pack_start (GTK_BOX (sbody),sbutton,FALSE,FALSE,0);
 
1243
  g_signal_connect(G_OBJECT(sbutton), "clicked", G_CALLBACK(snapshot_add_button_clicked), NULL);
 
1244
  gtk_widget_show_all(sbody);
 
1245
 
 
1246
  for (long k=1; k<5; k++)
 
1247
  {
 
1248
    char wdname[20];
 
1249
    snprintf (wdname, 20, "snapshot_%ld_togglebutton", k);
 
1250
    GtkWidget *button = dtgtk_togglebutton_new_with_label (wdname,NULL,CPF_STYLE_FLAT);
 
1251
    gtk_box_pack_start (GTK_BOX (svbox),button,FALSE,FALSE,0);
 
1252
    g_signal_connect (G_OBJECT (button), "clicked",
 
1253
                      G_CALLBACK (snapshot_toggled),
 
1254
                      (gpointer)(k-1));
 
1255
  }
 
1256
 
 
1257
  /* add content to toolbar */
 
1258
  /* top left: color labels */
 
1259
  dt_create_color_label_buttons(GTK_BOX (glade_xml_get_widget (darktable.gui->main_window, "top_left_toolbox")));
 
1260
 
 
1261
  // color picker
 
1262
  widget = glade_xml_get_widget (darktable.gui->main_window, "colorpicker_mean_combobox");
 
1263
  gtk_combo_box_set_active(GTK_COMBO_BOX(widget), dt_conf_get_int("ui_last/colorpicker_mean"));
 
1264
  g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(colorpicker_mean_changed), NULL);
 
1265
  widget = glade_xml_get_widget (darktable.gui->main_window, "colorpicker_togglebutton");
 
1266
  g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(colorpicker_toggled), NULL);
 
1267
 
 
1268
  // lighttable layout
 
1269
  widget = glade_xml_get_widget (darktable.gui->main_window, "lighttable_layout_combobox");
 
1270
  g_signal_connect (G_OBJECT (widget), "changed",
 
1271
                    G_CALLBACK (lighttable_layout_changed),
 
1272
                    (gpointer)0);
 
1273
 
 
1274
  widget = glade_xml_get_widget (darktable.gui->main_window, "lighttable_zoom_spinbutton");
 
1275
  g_signal_connect (G_OBJECT (widget), "value-changed",
 
1276
                    G_CALLBACK (lighttable_zoom_changed),
 
1277
                    (gpointer)0);
 
1278
 
 
1279
  // nice endmarker drawing.
 
1280
  widget = glade_xml_get_widget (darktable.gui->main_window, "endmarker_left");
 
1281
  g_signal_connect (G_OBJECT (widget), "expose-event",
 
1282
                    G_CALLBACK (dt_control_expose_endmarker), (gpointer)1);
 
1283
 
 
1284
  // switch modes in gui by double-clicking label
 
1285
  widget = glade_xml_get_widget (darktable.gui->main_window, "view_label_eventbox");
 
1286
  g_signal_connect (G_OBJECT (widget), "button-press-event",
 
1287
                    G_CALLBACK (view_label_clicked),
 
1288
                    (gpointer)0);
 
1289
 
 
1290
  // show about dialog when darktable label is clicked
 
1291
  widget = glade_xml_get_widget (darktable.gui->main_window, "darktable_label_eventbox");
 
1292
  g_signal_connect (G_OBJECT (widget), "button-press-event",
 
1293
                    G_CALLBACK (darktable_label_clicked),
 
1294
                    (gpointer)0);
 
1295
 
 
1296
 
 
1297
  widget = glade_xml_get_widget (darktable.gui->main_window, "center");
 
1298
  GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
 
1299
  // GTK_WIDGET_SET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
 
1300
  GTK_WIDGET_SET_FLAGS   (widget, GTK_APP_PAINTABLE);
 
1301
 
 
1302
  // TODO: make this work as: libgnomeui testgnome.c
 
1303
  GtkContainer *box = GTK_CONTAINER(glade_xml_get_widget (darktable.gui->main_window, "plugins_vbox"));
 
1304
  GtkScrolledWindow *swin = GTK_SCROLLED_WINDOW(glade_xml_get_widget (darktable.gui->main_window, "right_scrolledwindow"));
 
1305
  gtk_container_set_focus_vadjustment (box, gtk_scrolled_window_get_vadjustment (swin));
 
1306
 
 
1307
  dt_ctl_get_display_profile(widget, &darktable.control->xprofile_data, &darktable.control->xprofile_size);
 
1308
 
 
1309
  darktable.gui->redraw_widgets = NULL;
 
1310
  darktable.gui->key_accels = NULL;
 
1311
 
 
1312
  // register keys for view switching
 
1313
  dt_gui_key_accel_register(0, GDK_t, _gui_switch_view_key_accel_callback, (void *)DT_GUI_VIEW_SWITCH_TO_TETHERING);
 
1314
  dt_gui_key_accel_register(0, GDK_l, _gui_switch_view_key_accel_callback, (void *)DT_GUI_VIEW_SWITCH_TO_LIBRARY);
 
1315
  dt_gui_key_accel_register(0, GDK_d, _gui_switch_view_key_accel_callback, (void *)DT_GUI_VIEW_SWITCH_TO_DARKROOM);
 
1316
 
 
1317
  // register ctrl-q to quit:
 
1318
  dt_gui_key_accel_register(GDK_CONTROL_MASK, GDK_q, quit_callback, (void *)0);
 
1319
  darktable.gui->reset = 0;
 
1320
  for(int i=0; i<3; i++) darktable.gui->bgcolor[i] = 0.1333;
 
1321
 
 
1322
  /* apply contrast to theme */
 
1323
  dt_gui_contrast_init ();
 
1324
 
 
1325
  return 0;
 
1326
}
 
1327
 
 
1328
void dt_gui_gtk_cleanup(dt_gui_gtk_t *gui)
 
1329
{
 
1330
  g_free(darktable.control->xprofile_data);
 
1331
  darktable.control->xprofile_size = 0;
 
1332
  dt_gui_navigation_cleanup(&gui->navigation);
 
1333
  dt_gui_histogram_cleanup(&gui->histogram);
 
1334
}
 
1335
 
 
1336
void dt_gui_gtk_run(dt_gui_gtk_t *gui)
 
1337
{
 
1338
  GtkWidget *widget = glade_xml_get_widget (darktable.gui->main_window, "center");
 
1339
  darktable.gui->pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1);
 
1340
  /* start the event loop */
 
1341
  gtk_main ();
 
1342
  gdk_threads_leave();
 
1343
}
 
1344