Little bugfix for gpicview.
[lxde/gpicview.git] / src / mainwin.cpp
CommitLineData
1d48a247
HJYP
1/***************************************************************************
2 * Copyright (C) 2007 by PCMan (Hong Jen Yee) *
3 * pcman.tw@gmail.com *
4 * *
5 * This program 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 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program 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 this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#include "mainwin.h"
26#include <new>
27#include <glib/gi18n.h>
28#include <glib/gstdio.h>
29#include <gdk/gdkkeysyms.h>
30
31#include <string.h>
32#include <errno.h>
33
34#include "working-area.h"
35
36gpointer MainWin::_parent_class = NULL;
37
38// For drag & drop
39GtkTargetEntry drop_targets[] =
40{
41 {"text/uri-list", 0, 0},
42 {"text/plain", 0, 1}
43};
44
45// Begin of GObject-related stuff
46
47void MainWin::_init( GTypeInstance *instance, gpointer g_class )
48{
49 ::new( instance ) MainWin(); // placement new
50}
51
52GType MainWin::_get_type()
53{
54 static GType g_define_type_id = 0;
55 if (G_UNLIKELY (g_define_type_id == 0))
56 {
57 static const GTypeInfo g_define_type_info = {
58 sizeof (MainWin::Class),
59 (GBaseInitFunc) NULL,
60 (GBaseFinalizeFunc) NULL,
61 (GClassInitFunc) MainWin::_class_init,
62 (GClassFinalizeFunc) NULL,
63 NULL, /* class_data */
64 sizeof (MainWin),
65 0, /* n_preallocs */
66 (GInstanceInitFunc) MainWin::_init,
67 };
68 g_define_type_id = g_type_register_static (GTK_TYPE_WINDOW, "MainWin", &g_define_type_info, (GTypeFlags)0);
69 }
70 return g_define_type_id;
71}
72
73void MainWin::_class_init( MainWin::Class* klass )
74{
75 _parent_class = g_type_class_peek_parent (klass);
76
77 GObjectClass * obj_class;
78 GtkWidgetClass *widget_class;
79
80 obj_class = ( GObjectClass * ) klass;
81// obj_class->set_property = _set_property;
82// obj_class->get_property = _get_property;
83 obj_class->finalize = _finalize;
84
85 widget_class = GTK_WIDGET_CLASS ( klass );
86 widget_class->delete_event = on_delete_event;
87 widget_class->size_allocate = on_size_allocate;
88 widget_class->key_press_event = on_key_press_event;
89}
90
91void MainWin::_finalize(GObject *self)
92{
93 ((MainWin*)self)->~MainWin();
94}
95
96// End of GObject-related stuff
97
98MainWin::MainWin()
99{
100 gtk_window_set_title( (GtkWindow*)this, _("Image Viewer"));
101 gtk_window_set_icon_from_file( (GtkWindow*)this, PACKAGE_DATA_DIR"/pixmaps/gpicview.png", NULL );
102 gtk_window_set_default_size( (GtkWindow*)this, 640, 480 );
103
104 GtkWidget* box = gtk_vbox_new( FALSE, 0 );
105 gtk_container_add( (GtkContainer*)this, box);
106
107 // image area
108 evt_box = gtk_event_box_new();
5bfec971 109 GTK_WIDGET_SET_FLAGS( evt_box, GTK_CAN_FOCUS );
1d48a247
HJYP
110 gtk_widget_add_events( evt_box,
111 GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK|
112 GDK_BUTTON_RELEASE_MASK|GDK_SCROLL_MASK );
113 g_signal_connect( evt_box, "button-press-event", G_CALLBACK(on_button_press), this );
114 g_signal_connect( evt_box, "button-release-event", G_CALLBACK(on_button_release), this );
115 g_signal_connect( evt_box, "motion-notify-event", G_CALLBACK(on_mouse_move), this );
5bfec971
HJYP
116 g_signal_connect( evt_box, "scroll-event", G_CALLBACK(on_scroll_event), this );
117 // Set bg color to white
118 GdkColor white = {0, 65535, 65535, 65535};
119 gtk_widget_modify_bg( evt_box, GTK_STATE_NORMAL, &white );
1d48a247
HJYP
120
121 img_view = gtk_image_new();
122 gtk_container_add( (GtkContainer*)evt_box, img_view);
123
124 scroll = gtk_scrolled_window_new( NULL, NULL );
125 gtk_scrolled_window_set_shadow_type( (GtkScrolledWindow*)scroll, GTK_SHADOW_NONE );
126 gtk_scrolled_window_set_policy((GtkScrolledWindow*)scroll,
127 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
128 GtkAdjustment *hadj, *vadj;
129 hadj = gtk_scrolled_window_get_hadjustment((GtkScrolledWindow*)scroll);
130 hadj->page_increment = 10;
131 gtk_adjustment_changed(hadj);
132// g_object_set( hadj, "page-increment", 10, NULL );
133 vadj = gtk_scrolled_window_get_vadjustment((GtkScrolledWindow*)scroll);
134 vadj->page_increment = 10;
135 gtk_adjustment_changed(vadj);
136// g_object_set( vadj, "page-increment", 10, NULL );
137 gtk_scrolled_window_add_with_viewport( (GtkScrolledWindow*)scroll, evt_box );
138
139 gtk_box_pack_start( (GtkBox*)box, scroll, TRUE, TRUE, 0 );
140
141 // build toolbar
142 tooltips = gtk_tooltips_new();
143#if GTK_CHECK_VERSION( 2, 10, 0 )
144 g_object_ref_sink( tooltips );
145#else
146 gtk_object_sink( tooltips );
147#endif
148 create_nav_bar( box );
149
150 gtk_widget_show_all( box );
151
152 hand_cursor = gdk_cursor_new_for_display( gtk_widget_get_display((GtkWidget*)this), GDK_FLEUR );
153
5bfec971 154// zoom_mode = ZOOM_NONE;
1d48a247
HJYP
155 zoom_mode = ZOOM_FIT;
156
157 // Set up drag & drop
158 gtk_drag_dest_set( (GtkWidget*)this, GTK_DEST_DEFAULT_ALL,
159 drop_targets, G_N_ELEMENTS(drop_targets), GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_ASK) );
160 g_signal_connect( this, "drag-data-received", G_CALLBACK(on_drag_data_received), this );
161}
162
163MainWin::~MainWin()
164{
165 close();
166 gdk_cursor_unref( hand_cursor );
167 g_object_unref( tooltips );
168
169 // FIXME: Put this here is weird
170 gtk_main_quit();
171}
172
173void MainWin::create_nav_bar( GtkWidget* box )
174{
175 nav_bar = gtk_hbox_new( FALSE, 0 );
176
177 add_nav_btn( GTK_STOCK_GO_BACK, _("Previous"), G_CALLBACK(on_prev) );
178 add_nav_btn( GTK_STOCK_GO_FORWARD, _("Next"), G_CALLBACK(on_next) );
179
180 gtk_box_pack_start( (GtkBox*)nav_bar, gtk_vseparator_new(), FALSE, FALSE, 0 );
181
182 add_nav_btn( GTK_STOCK_ZOOM_OUT, _("Zoom Out"), G_CALLBACK(on_zoom_out) );
183 add_nav_btn( GTK_STOCK_ZOOM_IN, _("Zoom In"), G_CALLBACK(on_zoom_in) );
5bfec971
HJYP
184
185// percent = gtk_entry_new(); // show scale (in percentage)
186// g_signal_connect( percent, "activate", G_CALLBACK(on_percentage), this );
187// gtk_widget_set_size_request( percent, 45, -1 );
188// gtk_box_pack_start( (GtkBox*)nav_bar, percent, FALSE, FALSE, 2 );
189
1d48a247
HJYP
190 btn_fit = add_nav_btn( GTK_STOCK_ZOOM_FIT, _("Fit Image To Window Size"),
191 G_CALLBACK(on_zoom_fit), true );
192 btn_orig = add_nav_btn( GTK_STOCK_ZOOM_100, _("Original Size"),
193 G_CALLBACK(on_orig_size), true );
1d48a247 194 gtk_toggle_button_set_active( (GtkToggleButton*)btn_fit, TRUE );
5bfec971 195
1d48a247
HJYP
196#ifndef GTK_STOCK_FULLSCREEN
197#define GTK_STOCK_FULLSCREEN "gtk-fullscreen"
198#endif
199 add_nav_btn( GTK_STOCK_FULLSCREEN, _(" Full Screen"), G_CALLBACK(on_full_screen) ); // gtk+ 2.8+
200
201 gtk_box_pack_start( (GtkBox*)nav_bar, gtk_vseparator_new(), FALSE, FALSE, 0 );
202
203 add_nav_btn( "gtk-counterclockwise", _("Rotate Counterclockwise"),
204 G_CALLBACK(on_rotate_counterclockwise) );
205 add_nav_btn( "gtk-clockwise", _("Rotate Clockwise"), G_CALLBACK(on_rotate_clockwise) );
206
207 gtk_box_pack_start( (GtkBox*)nav_bar, gtk_vseparator_new(), FALSE, FALSE, 0 );
208
209 add_nav_btn( GTK_STOCK_OPEN, _("Open File"), G_CALLBACK(on_open) );
210 add_nav_btn( GTK_STOCK_SAVE, _("Save File"), G_CALLBACK(on_save) );
211 add_nav_btn( GTK_STOCK_SAVE_AS, _("Save File As"), G_CALLBACK(on_save_as) );
212 add_nav_btn( GTK_STOCK_DELETE, _("Delete File"), G_CALLBACK(on_delete) );
213
214/*
215 gtk_box_pack_start( (GtkBox*)nav_bar, gtk_vseparator_new(), FALSE, FALSE, 0 );
216
217 add_nav_btn( GTK_STOCK_PREFERENCES, _("Preference"), G_CALLBACK(on_preference) );
218*/
219
220 GtkWidget* align = gtk_alignment_new( 0.5, 0, 0, 0 );
221 gtk_container_add( (GtkContainer*)align, nav_bar );
222 gtk_box_pack_start( (GtkBox*)box, align, FALSE, TRUE, 2 );
223}
224
225gboolean MainWin::on_delete_event( GtkWidget* widget, GdkEventAny* evt )
226{
227 gtk_widget_destroy( widget );
228 return TRUE;
229}
230
231bool MainWin::open( const char* file_path )
232{
233 close();
234 GError* err = NULL;
235 pic_orig = gdk_pixbuf_new_from_file( file_path, &err );
236 if( ! pic_orig )
237 {
238 show_error( err->message );
239 return false;
240 }
5bfec971
HJYP
241/*
242 // select most suitable viewing mode
243 if( zoom_mode == ZOOM_NONE )
1d48a247 244 {
5bfec971
HJYP
245 int w = gdk_pixbuf_get_width( pic_orig );
246 int h = gdk_pixbuf_get_height( pic_orig );
1d48a247 247
1d48a247
HJYP
248 GdkRectangle area;
249 get_working_area( gtk_widget_get_screen((GtkWidget*)this), &area );
5bfec971 250 g_debug("zoom none! w=%d, h=%d", w, h);
1d48a247
HJYP
251 if( w < area.width && h < area.height )
252 {
5bfec971 253 g_debug("zoom none!");
1d48a247 254 gtk_scrolled_window_set_policy( (GtkScrolledWindow*)scroll,
5bfec971
HJYP
255 GTK_POLICY_NEVER, GTK_POLICY_NEVER );
256 gtk_widget_set_size_request( img_view, w, h );
257 GtkRequisition req;
258 gtk_widget_size_request ( (GtkWidget*)this, &req );
259 g_debug( "size request: w = %d, h = %d", req.width, req.height );
260 gtk_window_resize( (GtkWindow*)this, req.width, req.height );
261 gtk_widget_set_size_request( img_view, -1, -1 );
1d48a247 262 gtk_scrolled_window_set_policy( (GtkScrolledWindow*)scroll,
5bfec971
HJYP
263 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
264 zoom_mode = ZOOM_ORIG;
265 on_orig_size( (GtkToggleButton*)btn_orig, this );
1d48a247
HJYP
266 }
267 else
268 {
5bfec971 269 zoom_mode = ZOOM_FIT;
1d48a247 270 }
5bfec971 271 }
1d48a247 272*/
5bfec971
HJYP
273
274 if( zoom_mode == ZOOM_FIT )
275 fit_window_size();
276 else if( zoom_mode == ZOOM_SCALE ) // scale
277 scale_image( scale );
278 else if( zoom_mode == ZOOM_ORIG ) // original size
279 {
280 pic = gdk_pixbuf_ref( pic_orig );
281 gtk_image_set_from_pixbuf( (GtkImage*)img_view, pic );
282 int w = gdk_pixbuf_get_width( pic );
283 int h = gdk_pixbuf_get_height( pic );
284
1d48a247
HJYP
285 center_image();
286 }
287
288// while (gtk_events_pending ())
289// gtk_main_iteration ();
290
291 // build file list
292 char* dir_path = g_path_get_dirname( file_path );
293 img_list.open_dir( dir_path );
294 g_free( dir_path );
295 char* base_name = g_path_get_basename( file_path );
296 img_list.set_current( base_name );
297 g_free( base_name );
298
299 char* disp_path = g_filename_display_name( file_path );
300 gtk_window_set_title( (GtkWindow*)this, disp_path );
301 g_free( disp_path );
302
303 return true;
304}
305
306void MainWin::close()
307{
308 if( pic ) {
309 gdk_pixbuf_unref( pic );
310 pic = NULL;
311 }
312 if( pic_orig ) {
313 gdk_pixbuf_unref( pic_orig );
314 pic_orig = NULL;
315 }
316}
317
318void MainWin::show_error( const char* message )
319{
320 GtkWidget* dlg = gtk_message_dialog_new( (GtkWindow*)this,
321 GTK_DIALOG_MODAL,
322 GTK_MESSAGE_ERROR,
323 GTK_BUTTONS_OK,
324 message );
325 gtk_dialog_run( (GtkDialog*)dlg );
326 gtk_widget_destroy( dlg );
327}
328
329void MainWin::on_size_allocate( GtkWidget* widget, GtkAllocation *allocation )
330{
331 GTK_WIDGET_CLASS(_parent_class)->size_allocate( widget, allocation );
332 MainWin* self = (MainWin*)widget;
333 if( self->zoom_mode == ZOOM_FIT )
334 {
335 while(gtk_events_pending ())
336 gtk_main_iteration(); // makes it more fluid
337
338 allocation = &self->scroll->allocation;
339 self->fit_window_size();
340 }
341}
342
343void MainWin::fit_size( int width, int height, GdkInterpType type )
344{
345 if( ! pic_orig )
346 return;
347
348 if( pic ){
349 gdk_pixbuf_unref( pic );
350 pic = NULL;
351 }
352
353 int orig_w = gdk_pixbuf_get_width(pic_orig);
354 int orig_h = gdk_pixbuf_get_height(pic_orig);
355
356 double xscale = double(width) / orig_w;
357 double yscale = double(height) / orig_h;
358 double final_scale = xscale < yscale ? xscale : yscale;
359
360 scale_image( final_scale, type );
361}
362
363
364void MainWin::fit_window_size( GdkInterpType type )
365{
366 int space = 0;
367 gtk_widget_style_get( scroll, "scrollbar-spacing", &space, NULL );
368 space *= 2;
369 fit_size( scroll->allocation.width - space, scroll->allocation.height - space, type );
370}
371
372GtkWidget* MainWin::add_nav_btn( const char* icon, const char* tip, GCallback cb, bool toggle )
373{
374 GtkWidget* img = gtk_image_new_from_stock(icon, GTK_ICON_SIZE_SMALL_TOOLBAR);
375 GtkWidget* btn;
376 if( G_UNLIKELY(toggle) )
377 {
378 btn = gtk_toggle_button_new();
379 g_signal_connect( btn, "toggled", cb, this );
380 }
381 else
382 {
383 btn = gtk_button_new();
384 g_signal_connect( btn, "clicked", cb, this );
385 }
386 gtk_button_set_relief( (GtkButton*)btn, GTK_RELIEF_NONE );
387 gtk_button_set_focus_on_click( (GtkButton*)btn, FALSE );
388 gtk_container_add( (GtkContainer*)btn, img );
389 gtk_tooltips_set_tip( tooltips, btn, tip, NULL );
390 gtk_box_pack_start( (GtkBox*)nav_bar, btn, FALSE, FALSE, 0 );
391 return btn;
392}
393
394void MainWin::on_zoom_fit_menu( GtkMenuItem* item, MainWin* self )
395{
396 gtk_button_clicked( (GtkButton*)self->btn_fit );
397}
398
399void MainWin::on_zoom_fit( GtkToggleButton* btn, MainWin* self )
400{
401 if( ! btn->active )
402 {
403 if( self->zoom_mode == ZOOM_FIT )
404 gtk_toggle_button_set_active( btn, TRUE );
405 return;
406 }
407 self->zoom_mode = ZOOM_FIT;
408
409 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_orig, FALSE );
410
411 self->fit_window_size();
412}
413
414void MainWin::on_full_screen( GtkWidget* btn, MainWin* self )
415{
416 if( ! self->full_screen )
417 {
5bfec971
HJYP
418 static GdkColor black = {0};
419 gtk_widget_modify_bg( self->evt_box, GTK_STATE_NORMAL, &black );
1d48a247
HJYP
420 gtk_widget_hide( gtk_widget_get_parent(self->nav_bar) );
421 gtk_window_fullscreen( (GtkWindow*)self );
422 }
423 else
424 {
5bfec971
HJYP
425// gtk_widget_reset_rc_styles( self->evt_box );
426 static GdkColor white = {0, 65535, 65535, 65535};
427 gtk_widget_modify_bg( self->evt_box, GTK_STATE_NORMAL, &white );
1d48a247
HJYP
428 gtk_widget_show( gtk_widget_get_parent(self->nav_bar) );
429 gtk_window_unfullscreen( (GtkWindow*)self );
430 }
431 self->full_screen = ! self->full_screen;
432}
433
434void MainWin::on_orig_size_menu( GtkToggleButton* btn, MainWin* self )
435{
436 gtk_button_clicked( (GtkButton*)self->btn_orig );
437}
438
439void MainWin::on_orig_size( GtkToggleButton* btn, MainWin* self )
440{
441 // This callback could be called from activate signal of menu item.
442 if( GTK_IS_MENU_ITEM(btn) )
443 {
444 gtk_button_clicked( (GtkButton*)self->btn_orig );
445 return;
446 }
447
448 if( ! btn->active )
449 {
450 if( self->zoom_mode == ZOOM_ORIG )
451 gtk_toggle_button_set_active( btn, TRUE );
452 return;
453 }
454 self->zoom_mode = ZOOM_ORIG;
455 self->scale = 1.0;
456
457 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_fit, FALSE );
458
459 if( ! self->pic_orig )
460 return;
461
462 if( self->pic )
463 gdk_pixbuf_unref( self->pic );
464 self->pic = gdk_pixbuf_ref( self->pic_orig );
465 gtk_image_set_from_pixbuf( (GtkImage*)self->img_view, self->pic );
466
467// self->center_image(); // FIXME: This doesn't work well. Why?
468}
469
470void MainWin::on_prev( GtkWidget* btn, MainWin* self )
471{
472 if( self->img_list.is_empty() )
473 return;
474
475 const char* name = self->img_list.get_prev();
476
477 if( ! name && self->img_list.has_multiple_files() )
478 {
479 // FIXME: need to ask user first?
480 name = self->img_list.get_last();
481 }
482
483 if( name )
484 {
485 char* file_path = self->img_list.get_current_file_path();
486 self->open( file_path );
487 g_free( file_path );
488 }
489}
490
491void MainWin::on_next( GtkWidget* btn, MainWin* self )
492{
493 if( self->img_list.is_empty() )
494 return;
495
496 const char* name = self->img_list.get_next();
497
498 if( ! name && self->img_list.has_multiple_files() )
499 {
500 // FIXME: need to ask user first?
501 name = self->img_list.get_first();
502 }
503
504 if( name )
505 {
506 char* file_path = self->img_list.get_current_file_path();
507 self->open( file_path );
508 g_free( file_path );
509 }
510}
511
512void MainWin::on_rotate_clockwise( GtkWidget* btn, MainWin* self )
513{
514 self->rotate_image( GDK_PIXBUF_ROTATE_CLOCKWISE );
515}
516
517void MainWin::on_rotate_counterclockwise( GtkWidget* btn, MainWin* self )
518{
519 self->rotate_image( GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE );
520}
521
522static void on_update_preview( GtkFileChooser *chooser, GtkImage* img )
523{
524 char* file = gtk_file_chooser_get_preview_filename( chooser );
525 GdkPixbuf* pix = NULL;
526 if( file )
527 {
528 pix = gdk_pixbuf_new_from_file_at_scale( file, 128, 128, TRUE, NULL );
529 g_free( file );
530 }
531 gtk_image_set_from_pixbuf( img, pix );
532 if( pix )
533 gdk_pixbuf_unref( pix );
534}
535
536void MainWin::on_save_as( GtkWidget* btn, MainWin* self )
537{
538 if( ! self->pic_orig )
539 return;
540
541 GtkFileChooser* dlg = (GtkFileChooser*)gtk_file_chooser_dialog_new( NULL, (GtkWindow*)self,
542 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
543 GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL );
544
545 gtk_file_chooser_set_current_folder( dlg, self->img_list.get_dir() );
546
547 GtkWidget* img = gtk_image_new();
548 gtk_widget_set_size_request( img, 128, 128 );
549 gtk_file_chooser_set_preview_widget( dlg, img );
550 g_signal_connect( dlg, "update-preview", G_CALLBACK(on_update_preview), img );
551
552 GtkFileFilter *filter;
553
554 /*
555 /// TODO: determine file type from file name
556 filter = gtk_file_filter_new();
557 gtk_file_filter_set_name( filter, _("Determined by File Name") );
558 gtk_file_filter_add_pixbuf_formats( filter );
559 gtk_file_chooser_add_filter( dlg, filter );
560 */
561
562 GSList* modules = gdk_pixbuf_get_formats();
563 GSList* module;
564 for( module = modules; module; module = module->next )
565 {
566 GdkPixbufFormat* format = (GdkPixbufFormat*)module->data;
567 if( ! gdk_pixbuf_format_is_writable( format ) )
568 continue;
569
570 filter = gtk_file_filter_new();
571
572 char* desc = gdk_pixbuf_format_get_description( format );
573 char* name = gdk_pixbuf_format_get_name( format );
574 char* tmp = g_strjoin( ": ", name, desc, NULL );
575 g_free( desc );
576 g_free( name );
577 gtk_file_filter_set_name( filter, tmp );
578 g_free( tmp );
579
580 char** mimes = gdk_pixbuf_format_get_mime_types( format ), **mime;
581 for( mime = mimes; *mime ; ++mime )
582 gtk_file_filter_add_mime_type( filter, *mime );
583 g_strfreev( mimes );
584 gtk_file_chooser_add_filter( dlg, filter );
585 }
586
587 if( gtk_dialog_run( (GtkDialog*)dlg ) == GTK_RESPONSE_OK )
588 {
589 filter = gtk_file_chooser_get_filter( dlg );
590 const char* filter_name = gtk_file_filter_get_name( filter );
591 char* p = strstr( filter_name, ": " );
592 char* type = NULL;
593 if( ! p ) // auto detection
594 {
595 /// TODO: auto file type
596 }
597 else
598 {
599 type = g_strndup( filter_name, (p - filter_name) );
600 }
601 char* file = gtk_file_chooser_get_filename( dlg );
602 // g_debug("type = %s", type);
603 self->save( file, type );
604 g_free( file );
605 g_free( type );
606 }
607 gtk_widget_destroy( (GtkWidget*)dlg );
608}
609
610void MainWin::on_save( GtkWidget* btn, MainWin* self )
611{
612 if( ! self->pic_orig )
613 return;
614
615 char* file_name = g_build_filename( self->img_list.get_dir(),
616 self->img_list.get_current(), NULL );
617 GdkPixbufFormat* info;
618 info = gdk_pixbuf_get_file_info( file_name, NULL, NULL );
619 char* type = gdk_pixbuf_format_get_name( info );
620 self->save( file_name, type, true );
621 g_free( file_name );
622 g_free( type );
623}
624
625void MainWin::on_open( GtkWidget* btn, MainWin* self )
626{
627 GtkFileChooser* dlg = (GtkFileChooser*)gtk_file_chooser_dialog_new( NULL, (GtkWindow*)self,
628 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
629 GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL );
630
631 if( self->img_list.get_dir() )
632 gtk_file_chooser_set_current_folder( dlg, self->img_list.get_dir() );
633
634 GtkWidget* img = gtk_image_new();
635 gtk_widget_set_size_request( img, 128, 128 );
636 gtk_file_chooser_set_preview_widget( dlg, img );
637 g_signal_connect( dlg, "update-preview", G_CALLBACK(on_update_preview), img );
638
639 GtkFileFilter *filter = gtk_file_filter_new();
640 gtk_file_filter_set_name( filter, _("All Supported Images") );
641 gtk_file_filter_add_pixbuf_formats( filter );
642 gtk_file_chooser_add_filter( dlg, filter );
643
644 filter = gtk_file_filter_new();
645 gtk_file_filter_set_name( filter, _("All Files") );
646 gtk_file_filter_add_pattern( filter, "*" );
647 gtk_file_chooser_add_filter( dlg, filter );
648
649 char* file = NULL;
650 if( gtk_dialog_run( (GtkDialog*)dlg ) == GTK_RESPONSE_OK )
651 file = gtk_file_chooser_get_filename( dlg );
652 gtk_widget_destroy( (GtkWidget*)dlg );
653
654 if( file )
655 {
656 self->open( file );
657 g_free( file );
658 }
659}
660
661void MainWin::on_zoom_in( GtkWidget* btn, MainWin* self )
662{
5bfec971 663 self->zoom_mode = ZOOM_SCALE;
1d48a247
HJYP
664 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_fit, FALSE );
665 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_orig, FALSE );
666
667 double scale = self->scale;
668 if( self->pic_orig && scale < 3.0 )
669 {
670// busy(true);
671 (scale > 0.2) ? scale += scale*0.2 : scale *= 1.5;
672 self->scale_image( scale );
673// adjust_adjustment_on_zoom(oldscale);
674// busy(false);
675 }
676}
677
678void MainWin::on_zoom_out( GtkWidget* btn, MainWin* self )
679{
5bfec971 680 self->zoom_mode = ZOOM_SCALE;
1d48a247
HJYP
681 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_fit, FALSE );
682 gtk_toggle_button_set_active( (GtkToggleButton*)self->btn_orig, FALSE );
683
684 double scale = self->scale;
685 if( self->pic_orig && scale > 0.05 )
686 {
687// busy(true);
688 (scale > 0.2) ? scale -= scale*0.2 : scale *= 0.667;
689 self->scale_image( scale );
690// adjust_adjustment_on_zoom(oldscale);
691// busy(false);
692 }
693}
694
695void MainWin::on_preference( GtkWidget* btn, MainWin* self )
696{
697 self->show_error( "Not implemented yet!" );
698}
699
700void MainWin::on_quit( GtkWidget* btn, MainWin* self )
701{
702 gtk_widget_destroy( (GtkWidget*)self );
703}
704
705gboolean MainWin::on_button_press( GtkWidget* widget, GdkEventButton* evt, MainWin* self )
706{
5bfec971
HJYP
707 gtk_widget_grab_focus( widget );
708
1d48a247
HJYP
709 if( evt->type == GDK_BUTTON_PRESS)
710 {
711 if( evt->button == 1 ) // left button
712 {
713 if( ! self->pic_orig )
714 return FALSE;
715 self->dragging = true;
716 gtk_widget_get_pointer( (GtkWidget*)self, &self->drag_old_x ,&self->drag_old_y );
717 gdk_window_set_cursor( widget->window, self->hand_cursor );
718 }
719 else if( evt->button == 3 ) // right button
720 {
721 self->show_popup_menu( evt );
722 }
723 }
724 else if( evt->type == GDK_2BUTTON_PRESS && evt->button == 1 ) // double clicked
725 {
726 on_full_screen( NULL, self );
727 }
728
729 return FALSE;
730}
731
732gboolean MainWin::on_mouse_move( GtkWidget* widget, GdkEventMotion* evt, MainWin* self )
733{
734 if( ! self->dragging )
735 {
736/*
737 if( self->full_screen )
738 {
739 int barh;
740 gtk_widget_get_size_request( self->nav_bar, NULL, &barh );
741 if( evt->y > ( ((GtkWidget*)self)->allocation.height - barh) )
742 gtk_widget_show( self->nav_bar );
743 else
744 gtk_widget_hide( self->nav_bar );
745 }
746*/
747 return FALSE;
748 }
749 int cur_x, cur_y;
750 gtk_widget_get_pointer( (GtkWidget*)self, &cur_x ,&cur_y );
751
752 int dx = (self->drag_old_x - cur_x);
753 int dy = (self->drag_old_y - cur_y);
754
755 GtkAdjustment *hadj, *vadj;
756 hadj = gtk_scrolled_window_get_hadjustment((GtkScrolledWindow*)self->scroll);
757 vadj = gtk_scrolled_window_get_vadjustment((GtkScrolledWindow*)self->scroll);
758
759 int imgw = gdk_pixbuf_get_width( self->pic );
760 int imgh = gdk_pixbuf_get_height( self->pic );
761
762 if( ABS(dx) > 4 )
763 {
764 self->drag_old_x = cur_x;
765 if( imgw > hadj->page_size )
766 {
767 gdouble x = gtk_adjustment_get_value (hadj) + dx;
768 if( x < hadj->lower )
769 x = hadj->lower;
770 else if( (x + hadj->page_size) > hadj->upper )
771 x = hadj->upper - hadj->page_size;
772
773 if( x != hadj->value )
774 gtk_adjustment_set_value (hadj, x );
775 }
776 }
777
778 if( ABS(dy) > 4 )
779 {
780 if( imgh > vadj->page_size )
781 {
782 self->drag_old_y = cur_y;
783 gdouble y = gtk_adjustment_get_value (vadj) + dy;
784 if( y < vadj->lower )
785 y = vadj->lower;
786 else if( (y + vadj->page_size) > vadj->upper )
787 y = vadj->upper - vadj->page_size;
788
789 if( y != vadj->value )
790 gtk_adjustment_set_value (vadj, y );
791 }
792 }
793 return FALSE;
794}
795
796gboolean MainWin::on_button_release( GtkWidget* widget, GdkEventButton* evt, MainWin* self )
797{
798 self->dragging = false;
799 gdk_window_set_cursor( widget->window, NULL );
800 return FALSE;
801}
802
5bfec971
HJYP
803gboolean MainWin::on_scroll_event( GtkWidget* widget, GdkEventScroll* evt, MainWin* self )
804{
805 switch( evt->direction )
806 {
807 case GDK_SCROLL_UP:
808 on_zoom_out( NULL, self );
809 break;
810 case GDK_SCROLL_DOWN:
811 on_zoom_in( NULL, self );
812 break;
813 case GDK_SCROLL_LEFT:
814 on_prev( NULL, self );
815 break;
816 case GDK_SCROLL_RIGHT:
817 on_next( NULL, self );
818 break;
819 }
820 return FALSE;
821}
822
1d48a247
HJYP
823gboolean MainWin::on_key_press_event(GtkWidget* widget, GdkEventKey * key)
824{
825 MainWin* self = (MainWin*)widget;
826 switch( key->keyval )
827 {
5bfec971
HJYP
828 case GDK_Left:
829 case GDK_KP_Left:
830 case GDK_leftarrow:
1d48a247
HJYP
831 case GDK_Return:
832 case GDK_space:
833 case GDK_Next:
5bfec971
HJYP
834 case GDK_KP_Down:
835 case GDK_Down:
836 case GDK_downarrow:
1d48a247
HJYP
837 on_next( NULL, self );
838 break;
5bfec971
HJYP
839 case GDK_Right:
840 case GDK_KP_Right:
841 case GDK_rightarrow:
1d48a247
HJYP
842 case GDK_Prior:
843 case GDK_BackSpace:
5bfec971
HJYP
844 case GDK_KP_Up:
845 case GDK_Up:
846 case GDK_uparrow:
1d48a247
HJYP
847 on_prev( NULL, self );
848 break;
849 case GDK_KP_Add:
850 case GDK_plus:
851 on_zoom_in( NULL, self );
852 break;
853 case GDK_KP_Subtract:
854 case GDK_minus:
855 on_zoom_out( NULL, self );
856 break;
1d48a247
HJYP
857 case GDK_s:
858 case GDK_S:
859 on_save( NULL, self );
860 break;
861 case GDK_l:
5bfec971 862// case GDK_L:
1d48a247
HJYP
863 on_rotate_counterclockwise( NULL, self );
864 break;
865 case GDK_r:
5bfec971 866// case GDK_R:
1d48a247
HJYP
867 on_rotate_clockwise( NULL, self );
868 break;
869 case GDK_f:
5bfec971 870// case GDK_F:
1d48a247
HJYP
871 if( self->zoom_mode != ZOOM_FIT )
872 gtk_button_clicked((GtkButton*)self->btn_fit );
873 break;
874 case GDK_g:
5bfec971 875// case GDK_G:
1d48a247
HJYP
876 if( self->zoom_mode != ZOOM_ORIG )
877 gtk_button_clicked((GtkButton*)self->btn_orig );
878 break;
879 case GDK_o:
5bfec971
HJYP
880// case GDK_O:
881 on_open( NULL, self );
882 break;
883 case GDK_Delete:
884 case GDK_d:
885// case GDK_D:
886 on_delete( NULL, self );
1d48a247
HJYP
887 break;
888 case GDK_Escape:
889 if( self->full_screen )
890 on_full_screen( NULL, self );
891 else
892 on_quit( NULL, self );
893 break;
894 case GDK_F11:
895 on_full_screen( NULL, self );
896 break;
897
898 default:
899 GTK_WIDGET_CLASS(_parent_class)->key_press_event( widget, key );
900 }
901 return FALSE;
902}
903
904void MainWin::center_image()
905{
906 GtkAdjustment *hadj, *vadj;
907 hadj = gtk_scrolled_window_get_hadjustment((GtkScrolledWindow*)scroll);
908 vadj = gtk_scrolled_window_get_vadjustment((GtkScrolledWindow*)scroll);
909
910 int imgw = gdk_pixbuf_get_width( pic );
911 int imgh = gdk_pixbuf_get_height( pic );
912
913 if( imgw > hadj->page_size )
914 gtk_adjustment_set_value(hadj, (imgw - hadj->page_size ) / 2 );
915
916 if( imgh > vadj->page_size )
917 gtk_adjustment_set_value(vadj, (imgh - vadj->page_size ) / 2 );
918}
919
920void MainWin::rotate_image( GdkPixbufRotation angle )
921{
922 if( ! pic_orig )
923 return;
924
925 GdkPixbuf* orig;
926 orig = gdk_pixbuf_rotate_simple( pic_orig, angle );
927 gdk_pixbuf_unref( pic_orig );
928 pic_orig = orig;
929
930 gdk_pixbuf_unref( pic );
931 pic = NULL;
932 if( zoom_mode == ZOOM_FIT )
933 fit_window_size();
934 else // original size
935 {
936 pic = gdk_pixbuf_ref( pic_orig );
937 gtk_image_set_from_pixbuf( (GtkImage*)img_view, pic );
938 center_image();
939 }
940}
941
942bool MainWin::scale_image( double new_scale, GdkInterpType type )
943{
944 if( G_UNLIKELY( new_scale == 1.0 ) )
945 {
946 gtk_toggle_button_set_active( (GtkToggleButton*)btn_orig, TRUE );
947 return true;
948 }
949
950 int orig_w = gdk_pixbuf_get_width(pic_orig);
951 int orig_h = gdk_pixbuf_get_height(pic_orig);
952
953 int width = int(orig_w * new_scale);
954 int height = int(orig_h * new_scale);
955
956 GdkPixbuf* new_pic = gdk_pixbuf_scale_simple( pic_orig, width, height, type );
957 if( G_LIKELY(new_pic) )
958 {
959 if( pic )
960 gdk_pixbuf_unref( pic );
961 pic = new_pic;
962 gtk_image_set_from_pixbuf( (GtkImage*)img_view, pic );
963 scale = new_scale;
964 return true;
965 }
966 return false;
967}
968
969bool MainWin::save( const char* file_path, const char* type, bool confirm )
970{
971 if( ! pic_orig )
972 return false;
973
974 if( confirm ) // check existing file
975 {
976 if( g_file_test( file_path, G_FILE_TEST_EXISTS ) )
977 {
978 GtkWidget* dlg = gtk_message_dialog_new( (GtkWindow*)this,
979 GTK_DIALOG_MODAL,
980 GTK_MESSAGE_QUESTION,
981 GTK_BUTTONS_YES_NO,
982 _("The file name you selected already exist.\nDo you want to overwrite existing file?\n(Warning: The quality of original image might be lost)") );
983 if( gtk_dialog_run( (GtkDialog*)dlg ) != GTK_RESPONSE_YES )
984 {
985 gtk_widget_destroy( dlg );
986 return false;
987 }
988 gtk_widget_destroy( dlg );
989 }
990 }
991
992 GError* err = NULL;
993 if( ! gdk_pixbuf_save( pic_orig, file_path, type, &err, NULL ) )
994 {
995 show_error( err->message );
996 return false;
997 }
998
999 return true;
1000}
1001
1002void MainWin::on_delete( GtkWidget* btn, MainWin* self )
1003{
1004 char* file_path = self->img_list.get_current_file_path();
1005 if( file_path )
1006 {
1007 GtkWidget* dlg = gtk_message_dialog_new( (GtkWindow*)self,
1008 GTK_DIALOG_MODAL,
1009 GTK_MESSAGE_QUESTION,
1010 GTK_BUTTONS_YES_NO,
1011 _("Are you sure you want to delete current file?\n\nWarning: Once deleted, the file cannot be recovered.") );
1012 int resp = gtk_dialog_run( (GtkDialog*)dlg );
1013 gtk_widget_destroy( dlg );
1014
1015 if( resp == GTK_RESPONSE_YES )
1016 {
1017 g_unlink( file_path );
1018 if( errno )
1019 self->show_error( g_strerror(errno) );
1020 g_free( file_path );
1021 }
1022 }
1023}
1024
5bfec971 1025#include "ptk-menu.h"
1d48a247
HJYP
1026void MainWin::show_popup_menu( GdkEventButton* evt )
1027{
5bfec971 1028/*
1d48a247
HJYP
1029 GtkMenuShell* popup = (GtkMenuShell*)gtk_menu_new();
1030
1031 GtkWidget *item;
1032 add_menu_item( popup, _("Previous"), GTK_STOCK_GO_BACK, G_CALLBACK(on_prev) );
1033 add_menu_item( popup, _("Next"), GTK_STOCK_GO_FORWARD, G_CALLBACK(on_next) );
1034
1035 gtk_menu_shell_append( popup, gtk_separator_menu_item_new() );
1036
1037 add_menu_item( popup, _("Zoom Out"), GTK_STOCK_ZOOM_OUT, G_CALLBACK(on_zoom_out) );
1038 add_menu_item( popup, _("Zoom In"), GTK_STOCK_ZOOM_IN, G_CALLBACK(on_zoom_in) );
1039 add_menu_item( popup, _("Fit Image To Window Size"), GTK_STOCK_ZOOM_OUT,
1040 G_CALLBACK(on_zoom_fit_menu) );
1041 add_menu_item( popup, _("Original Size"), GTK_STOCK_ZOOM_100,
1042 G_CALLBACK(on_orig_size_menu) );
1043
1044#ifndef GTK_STOCK_FULLSCREEN
1045// This stock item is only available after gtk+ 2.8
1046#define GTK_STOCK_FULLSCREEN "gtk-fullscreen"
1047#endif
1048 add_menu_item( popup, _("Full Screen"), GTK_STOCK_FULLSCREEN, G_CALLBACK(on_full_screen) );
1049
1050 gtk_menu_shell_append( popup, gtk_separator_menu_item_new() );
1051
1052 add_menu_item( popup, _("Rotate Counterclockwise"), "gtk-counterclockwise",
1053 G_CALLBACK(on_rotate_counterclockwise) );
1054 add_menu_item( popup, _("Rotate Clockwise"), "gtk-clockwise",
1055 G_CALLBACK(on_rotate_clockwise) );
1056
1057 gtk_menu_shell_append( popup, gtk_separator_menu_item_new() );
1058
1059 add_menu_item( popup, _("Open File"), GTK_STOCK_OPEN, G_CALLBACK(on_open) );
1060 add_menu_item( popup, _("Save File"), GTK_STOCK_SAVE, G_CALLBACK(on_save) );
1061 add_menu_item( popup, _("Save As"), GTK_STOCK_SAVE_AS, G_CALLBACK(on_save_as) );
1062 add_menu_item( popup, _("Delete File"), GTK_STOCK_DELETE, G_CALLBACK(on_delete) );
1063
1064 gtk_menu_shell_append( popup, gtk_separator_menu_item_new() );
1065
1066 item = gtk_image_menu_item_new_from_stock( GTK_STOCK_ABOUT, NULL );
1067 g_signal_connect(item, "activate", G_CALLBACK(on_about), this);
1068 gtk_menu_shell_append( popup, item );
5bfec971 1069*/
1d48a247 1070
5bfec971
HJYP
1071 static PtkMenuItemEntry menu_def[] =
1072 {
1073 PTK_IMG_MENU_ITEM( N_( "Previous" ), GTK_STOCK_GO_BACK, on_prev, GDK_leftarrow, 0 ),
1074 PTK_IMG_MENU_ITEM( N_( "Next" ), GTK_STOCK_GO_FORWARD, on_next, GDK_rightarrow, 0 ),
1075 PTK_SEPARATOR_MENU_ITEM,
1076 PTK_IMG_MENU_ITEM( N_( "Zoom Out" ), GTK_STOCK_ZOOM_OUT, on_zoom_out, GDK_minus, 0 ),
1077 PTK_IMG_MENU_ITEM( N_( "Zoom In" ), GTK_STOCK_ZOOM_IN, on_zoom_in, GDK_plus, 0 ),
1078 PTK_IMG_MENU_ITEM( N_( "Fit Image To Window Size" ), GTK_STOCK_ZOOM_FIT, on_zoom_fit_menu, GDK_F, 0 ),
1079 PTK_IMG_MENU_ITEM( N_( "Original Size" ), GTK_STOCK_ZOOM_100, on_orig_size_menu, GDK_G, 0 ),
1080 PTK_SEPARATOR_MENU_ITEM,
0c8ac162 1081 PTK_IMG_MENU_ITEM( N_( "Full Screen" ), GTK_STOCK_FULLSCREEN, on_full_screen, GDK_F11, 0 ),
5bfec971
HJYP
1082 PTK_SEPARATOR_MENU_ITEM,
1083 PTK_IMG_MENU_ITEM( N_( "Rotate Counterclockwise" ), "gtk-counterclockwise", on_rotate_counterclockwise, GDK_L, 0 ),
1084 PTK_IMG_MENU_ITEM( N_( "Rotate Clockwise" ), "gtk-clockwise", on_rotate_clockwise, GDK_R, 0 ),
1085 PTK_SEPARATOR_MENU_ITEM,
1086 PTK_IMG_MENU_ITEM( N_("Open File"), GTK_STOCK_OPEN, G_CALLBACK(on_open), GDK_O, 0 ),
1087 PTK_IMG_MENU_ITEM( N_("Save File"), GTK_STOCK_SAVE, G_CALLBACK(on_save), GDK_S, 0 ),
1088 PTK_IMG_MENU_ITEM( N_("Save As"), GTK_STOCK_SAVE_AS, G_CALLBACK(on_save_as), GDK_A, 0 ),
1089 PTK_IMG_MENU_ITEM( N_("Delete File"), GTK_STOCK_DELETE, G_CALLBACK(on_delete), GDK_Delete, 0 ),
1090 PTK_SEPARATOR_MENU_ITEM,
1091 PTK_STOCK_MENU_ITEM( GTK_STOCK_ABOUT, on_about ),
1092 PTK_MENU_END
1093 };
1094
1095 // This accel group is useless. It's only used to display accels in popup menu
1096 GtkAccelGroup* accel_group = gtk_accel_group_new();
1097 GtkMenuShell* popup = (GtkMenuShell*)ptk_menu_new_from_data( menu_def, this, accel_group );
1d48a247
HJYP
1098
1099 gtk_widget_show_all( (GtkWidget*)popup );
1100 g_signal_connect( popup, "selection-done", G_CALLBACK(gtk_widget_destroy), NULL );
1101 gtk_menu_popup( (GtkMenu*)popup, NULL, NULL, NULL, NULL, evt->button, evt->time );
1102}
1103
5bfec971 1104/*
1d48a247
HJYP
1105GtkWidget* MainWin::add_menu_item( GtkMenuShell* menu, const char* label,
1106 const char* icon, GCallback cb, bool toggle )
1107{
1108 GtkWidget* item;
1109 if( G_UNLIKELY(toggle) )
1110 {
1111 item = gtk_check_menu_item_new_with_mnemonic( label );
1112 g_signal_connect( item, "toggled", cb, this );
1113 }
1114 else
1115 {
1116 if( icon )
1117 {
1118 item = gtk_image_menu_item_new_with_mnemonic( label);
1119 GtkWidget* img = gtk_image_new_from_stock( icon, GTK_ICON_SIZE_MENU );
1120 gtk_image_menu_item_set_image( (GtkImageMenuItem*)item, img );
1121 }
1122 else {
1123 item = gtk_menu_item_new_with_mnemonic( label );
1124 }
1125 g_signal_connect( item, "activate", cb, this );
1126 }
1127 gtk_menu_shell_append( (GtkMenuShell*)menu, item );
1128}
5bfec971 1129*/
1d48a247
HJYP
1130
1131void MainWin::on_about( GtkWidget* menu, MainWin* self )
1132{
1133 GtkWidget * about_dlg;
1134 const gchar *authors[] =
1135 {
1136 "洪任諭 Hong Jen Yee <pcman.tw@gmail.com>",
1137 _(" * Some icons are taken from gimmage"),
1138 NULL
1139 };
1140 /* TRANSLATORS: Replace this string with your names, one name per line. */
1141 gchar *translators = _( "translator-credits" );
1142
1143 about_dlg = gtk_about_dialog_new ();
1144 gtk_container_set_border_width ( GTK_CONTAINER ( about_dlg ), 2 );
1145 gtk_about_dialog_set_version ( GTK_ABOUT_DIALOG ( about_dlg ), VERSION );
1146 gtk_about_dialog_set_name ( GTK_ABOUT_DIALOG ( about_dlg ), _( "GPicView" ) );
1147 gtk_about_dialog_set_copyright ( GTK_ABOUT_DIALOG ( about_dlg ), _( "Copyright (C) 2007" ) );
1148 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG ( about_dlg ), _( "Lightweight image viewer\n\nDeveloped by Hon Jen Yee (PCMan)" ) );
1149 gtk_about_dialog_set_license ( GTK_ABOUT_DIALOG ( about_dlg ), "GPicView\n\nCopyright (C) 2007 Hong Jen Yee (PCMan)\n\nThis program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 2\nof the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." );
b9ca6e3b 1150 gtk_about_dialog_set_website ( GTK_ABOUT_DIALOG ( about_dlg ), "http://lxde.sourceforge.net/gpicview/" );
1d48a247
HJYP
1151 gtk_about_dialog_set_authors ( GTK_ABOUT_DIALOG ( about_dlg ), authors );
1152 gtk_about_dialog_set_translator_credits ( GTK_ABOUT_DIALOG ( about_dlg ), translators );
1153 gtk_window_set_transient_for( GTK_WINDOW( about_dlg ), GTK_WINDOW( self ) );
1154
1155 gtk_dialog_run( GTK_DIALOG( about_dlg ) );
1156 gtk_widget_destroy( about_dlg );
1157}
1158
1159void MainWin::on_drag_data_received( GtkWidget* widget, GdkDragContext *drag_context,
1160 int x, int y, GtkSelectionData* data, guint info, guint time, MainWin* self )
1161{
1162 if( ! data || data->length <= 0)
1163 return;
1164
1165 // g_debug("drag data receved, info = %d", info);
1166 char* file = NULL;
1167 if( info == 0 ) // text/uri-list
1168 {
1169 char** uris = gtk_selection_data_get_uris( data );
1170 if( uris )
1171 {
1172 file = g_filename_from_uri(*uris, NULL, NULL);
1173 g_strfreev( uris );
1174 }
1175 }
1176 else if( info == 1 ) // text/plain
1177 {
1178 file = (char*)gtk_selection_data_get_text( data );
1179 }
1180 if( file )
1181 {
1182 self->open( file );
1183 g_free( file );
1184 }
1185}