20 | 20 |
"""
|
21 | 21 |
|
22 | 22 |
import pygtk
|
23 | |
pygtk.require('2.0')
|
|
23 |
|
|
24 |
pygtk.require("2.0")
|
24 | 25 |
import gtk
|
25 | 26 |
import os, sys, getopt, configparser, string, gc
|
26 | 27 |
import random, urllib.request, gobject, gettext, locale
|
27 | 28 |
import stat, time, subprocess, shutil, filecmp
|
28 | 29 |
import tempfile, socket, threading
|
|
30 |
|
29 | 31 |
try:
|
30 | |
import hashlib
|
31 | |
HAS_HASHLIB = True
|
|
32 |
import hashlib
|
|
33 |
|
|
34 |
HAS_HASHLIB = True
|
32 | 35 |
except:
|
33 | |
HAS_HASHLIB= False
|
34 | |
import md5
|
|
36 |
HAS_HASHLIB = False
|
|
37 |
import md5
|
|
38 |
|
35 | 39 |
try:
|
36 | |
import imgfuncs
|
37 | |
HAS_IMGFUNCS = True
|
|
40 |
import imgfuncs
|
|
41 |
|
|
42 |
HAS_IMGFUNCS = True
|
38 | 43 |
except:
|
39 | |
HAS_IMGFUNCS = False
|
40 | |
print("imgfuncs.so module not found, rotating/flipping images will be disabled.")
|
|
44 |
HAS_IMGFUNCS = False
|
|
45 |
print("imgfuncs.so module not found, rotating/flipping images will be disabled.")
|
|
46 |
|
41 | 47 |
try:
|
42 | |
import xmouse
|
43 | |
HAS_XMOUSE = True
|
|
48 |
import xmouse
|
|
49 |
|
|
50 |
HAS_XMOUSE = True
|
44 | 51 |
except:
|
45 | |
HAS_XMOUSE = False
|
46 | |
print("xmouse.so module not found, some screenshot capabilities will be disabled.")
|
|
52 |
HAS_XMOUSE = False
|
|
53 |
print("xmouse.so module not found, some screenshot capabilities will be disabled.")
|
|
54 |
|
47 | 55 |
try:
|
48 | |
import gconf
|
|
56 |
import gconf
|
49 | 57 |
except:
|
50 | |
pass
|
|
58 |
pass
|
51 | 59 |
|
52 | 60 |
if gtk.gtk_version < (2, 10, 0):
|
53 | |
sys.stderr.write("Mirage requires GTK+ 2.10.0 or newer..\n")
|
54 | |
sys.exit(1)
|
|
61 |
sys.stderr.write("Mirage requires GTK+ 2.10.0 or newer..\n")
|
|
62 |
sys.exit(1)
|
55 | 63 |
if gtk.pygtk_version < (2, 12, 0):
|
56 | |
sys.stderr.write("Mirage requires PyGTK 2.12.0 or newer.\n")
|
57 | |
sys.exit(1)
|
58 | |
|
|
64 |
sys.stderr.write("Mirage requires PyGTK 2.12.0 or newer.\n")
|
|
65 |
sys.exit(1)
|
|
66 |
|
|
67 |
|
59 | 68 |
def valid_int(inputstring):
|
60 | |
try:
|
61 | |
x = int(inputstring)
|
62 | |
return True
|
63 | |
except:
|
64 | |
return False
|
|
69 |
try:
|
|
70 |
x = int(inputstring)
|
|
71 |
return True
|
|
72 |
except:
|
|
73 |
return False
|
|
74 |
|
65 | 75 |
|
66 | 76 |
class Base:
|
67 | |
|
68 | |
def __init__(self):
|
69 | |
|
70 | |
gtk.gdk.threads_init()
|
71 | |
|
72 | |
# FIX THIS! Does not work on windows and what happens if mo-files exists
|
73 | |
# in both dirs?
|
74 | |
gettext.install('mirage', '/usr/share/locale')
|
75 | |
gettext.install('mirage', '/usr/local/share/locale')
|
76 | |
|
77 | |
# Constants
|
78 | |
self.open_mode_smart = 0
|
79 | |
self.open_mode_fit = 1
|
80 | |
self.open_mode_1to1 = 2
|
81 | |
self.open_mode_last = 3
|
82 | |
self.min_zoomratio = 0.02
|
83 | |
|
84 | |
# Initialize vars:
|
85 | |
width=600
|
86 | |
height=400
|
87 | |
bgcolor_found = False
|
88 | |
self.simple_bgcolor = False
|
89 | |
# Current image:
|
90 | |
self.curr_img_in_list = 0
|
91 | |
self.currimg_name = ""
|
92 | |
self.currimg_width = 0
|
93 | |
self.currimg_height = 0
|
94 | |
self.currimg_pixbuf = None
|
95 | |
self.currimg_pixbuf_original = None
|
96 | |
self.currimg_zoomratio = 1
|
97 | |
self.currimg_is_animation = False
|
98 | |
# This is the actual pixbuf that is loaded in Mirage. This will
|
99 | |
# usually be the same as self.curr_img_in_list except for scenarios
|
100 | |
# like when the user presses 'next image' multiple times in a row.
|
101 | |
# In this case, self.curr_img_in_list will increment while
|
102 | |
# self.loaded_img_in_list will retain the current loaded image.
|
103 | |
self.loaded_img_in_list = 0
|
104 | |
# Next preloaded image:
|
105 | |
self.preloadimg_next_in_list = -1
|
106 | |
self.preloadimg_next_name = ""
|
107 | |
self.preloadimg_next_width = 0
|
108 | |
self.preloadimg_next_height = 0
|
109 | |
self.preloadimg_next_pixbuf = None
|
110 | |
self.preloadimg_next_pixbuf_original = None
|
111 | |
self.preloadimg_next_zoomratio = 1
|
112 | |
self.preloadimg_next_is_animation = False
|
113 | |
# Previous preloaded image:
|
114 | |
self.preloadimg_prev_in_list = -1
|
115 | |
self.preloadimg_prev_name = ""
|
116 | |
self.preloadimg_prev_width = 0
|
117 | |
self.preloadimg_prev_height = 0
|
118 | |
self.preloadimg_prev_pixbuf = None
|
119 | |
self.preloadimg_prev_pixbuf_original = None
|
120 | |
self.preloadimg_prev_zoomratio = 1
|
121 | |
self.preloadimg_prev_is_animation = False
|
122 | |
# Settings, misc:
|
123 | |
self.toolbar_show = True
|
124 | |
self.thumbpane_show = True
|
125 | |
self.statusbar_show = True
|
126 | |
self.fullscreen_mode = False
|
127 | |
self.opendialogpath = ""
|
128 | |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
129 | |
self.recursive = False
|
130 | |
self.verbose = False
|
131 | |
self.image_loaded = False
|
132 | |
self.open_all_images = True # open all images in the directory(ies)
|
133 | |
self.use_last_dir = True
|
134 | |
self.last_dir = os.path.expanduser("~")
|
135 | |
self.fixed_dir = os.path.expanduser("~")
|
136 | |
self.image_list = []
|
137 | |
self.open_mode = self.open_mode_smart
|
138 | |
self.last_mode = self.open_mode_smart
|
139 | |
self.listwrap_mode = 0 # 0=no, 1=yes, 2=ask
|
140 | |
self.user_prompt_visible = False # the "wrap?" prompt
|
141 | |
self.slideshow_delay = 1 # seconds
|
142 | |
self.slideshow_mode = False
|
143 | |
self.slideshow_random = False
|
144 | |
self.slideshow_controls_visible = False # fullscreen slideshow controls
|
145 | |
self.controls_moving = False
|
146 | |
self.zoomvalue = 2
|
147 | |
self.quality_save = 90
|
148 | |
self.updating_adjustments = False
|
149 | |
self.disable_screensaver = False
|
150 | |
self.slideshow_in_fullscreen = False
|
151 | |
self.closing_app = False
|
152 | |
self.confirm_delete = True
|
153 | |
self.preloading_images = True
|
154 | |
self.action_names = ["Open in GIMP", "Create Thumbnail", "Create Thumbnails", "Move to Favorites"]
|
155 | |
self.action_shortcuts = ["<Control>e", "<Alt>t", "<Control><Alt>t", "<Control><Alt>f"]
|
156 | |
self.action_commands = ["gimp-remote-2.4 %F", "convert %F -thumbnail 150x150 %Pt_%N.jpg", "convert %F -thumbnail 150x150 %Pt_%N.jpg", "mkdir -p ~/mirage-favs; mv %F ~/mirage-favs; [NEXT]"]
|
157 | |
self.action_batch = [False, False, True, False]
|
158 | |
self.onload_cmd = None
|
159 | |
self.searching_for_images = False
|
160 | |
self.preserve_aspect = True
|
161 | |
self.ignore_preserve_aspect_callback = False
|
162 | |
self.savemode = 2
|
163 | |
self.image_modified = False
|
164 | |
self.image_zoomed = False
|
165 | |
self.start_in_fullscreen = False
|
166 | |
self.running_custom_actions = False
|
167 | |
self.merge_id = None
|
168 | |
self.actionGroupCustom = None
|
169 | |
self.merge_id_recent = None
|
170 | |
self.actionGroupRecent = None
|
171 | |
self.open_hidden_files = False
|
172 | |
self.thumbnail_sizes = ["128", "96", "72", "64", "48", "32"]
|
173 | |
self.thumbnail_size = 128 # Default to 128 x 128
|
174 | |
self.thumbnail_loaded = []
|
175 | |
self.thumbpane_updating = False
|
176 | |
self.recentfiles = ["", "", "", "", ""]
|
177 | |
self.screenshot_delay = 2
|
178 | |
self.thumbpane_bottom_coord_loaded = 0
|
179 | |
|
180 | |
# Read any passed options/arguments:
|
181 | |
try:
|
182 | |
opts, args = getopt.getopt(sys.argv[1:], "hRvVsfo:", ["help", "version", "recursive", "verbose", "slideshow", "fullscreen", "onload="])
|
183 | |
except getopt.GetoptError:
|
184 | |
# print help information and exit:
|
185 | |
self.print_usage()
|
186 | |
sys.exit(2)
|
187 | |
# If options were passed, perform action on them.
|
188 | |
if opts != []:
|
189 | |
for o, a in opts:
|
190 | |
if o in ("-v", "--version"):
|
191 | |
self.print_version()
|
192 | |
sys.exit(2)
|
193 | |
elif o in ("-h", "--help"):
|
194 | |
self.print_usage()
|
195 | |
sys.exit(2)
|
196 | |
elif o in ("-R", "--recursive"):
|
197 | |
self.recursive = True
|
198 | |
elif o in ("-V", "--verbose"):
|
199 | |
self.verbose = True
|
200 | |
elif o in ("-s", "--slideshow", "-f", "--fullscreen"):
|
201 | |
#This will be handled later
|
202 | |
None
|
203 | |
elif o in ("-o", "--onload"):
|
204 | |
self.onload_cmd = a
|
205 | |
else:
|
206 | |
self.print_usage()
|
207 | |
sys.exit(2)
|
208 | |
|
209 | |
|
210 | |
# Determine config dir, first try the environment variable XDG_CONFIG_HOME
|
211 | |
# according to XDG specification and as a fallback use ~/.config/mirage
|
212 | |
self.config_dir = (os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config')) + '/mirage'
|
213 | |
# Load config from disk:
|
214 | |
conf = configparser.ConfigParser()
|
215 | |
if os.path.isfile(self.config_dir + '/miragerc'):
|
216 | |
conf.read(self.config_dir + '/miragerc')
|
217 | |
if conf.has_option('window', 'w'):
|
218 | |
width = conf.getint('window', 'w')
|
219 | |
if conf.has_option('window', 'h'):
|
220 | |
height = conf.getint('window', 'h')
|
221 | |
if conf.has_option('window', 'toolbar'):
|
222 | |
self.toolbar_show = conf.getboolean('window', 'toolbar')
|
223 | |
if conf.has_option('window', 'statusbar'):
|
224 | |
self.statusbar_show = conf.getboolean('window', 'statusbar')
|
225 | |
if conf.has_option('window', 'thumbpane'):
|
226 | |
self.thumbpane_show = conf.getboolean('window', 'thumbpane')
|
227 | |
if conf.has_option('prefs', 'simple-bgcolor'):
|
228 | |
self.simple_bgcolor = conf.getboolean('prefs', 'simple-bgcolor')
|
229 | |
if conf.has_option('prefs', 'bgcolor-red'):
|
230 | |
bgr = conf.getint('prefs', 'bgcolor-red')
|
231 | |
bgg = conf.getint('prefs', 'bgcolor-green')
|
232 | |
bgb = conf.getint('prefs', 'bgcolor-blue')
|
233 | |
bgcolor_found = True
|
234 | |
self.bgcolor = gtk.gdk.Color(red=bgr, green=bgg, blue=bgb)
|
235 | |
if conf.has_option('prefs', 'use_last_dir'):
|
236 | |
self.use_last_dir = conf.getboolean('prefs', 'use_last_dir')
|
237 | |
if conf.has_option('prefs', 'last_dir'):
|
238 | |
self.last_dir = conf.get('prefs', 'last_dir')
|
239 | |
if conf.has_option('prefs', 'fixed_dir'):
|
240 | |
self.fixed_dir = conf.get('prefs', 'fixed_dir')
|
241 | |
if conf.has_option('prefs', 'open_all'):
|
242 | |
self.open_all_images = conf.getboolean('prefs', 'open_all')
|
243 | |
if conf.has_option('prefs', 'hidden'):
|
244 | |
self.open_hidden_files = conf.getboolean('prefs', 'hidden')
|
245 | |
if conf.has_option('prefs', 'open_mode'):
|
246 | |
self.open_mode = conf.getint('prefs', 'open_mode')
|
247 | |
if conf.has_option('prefs', 'last_mode'):
|
248 | |
self.last_mode = conf.getint('prefs', 'last_mode')
|
249 | |
if conf.has_option('prefs', 'listwrap_mode'):
|
250 | |
self.listwrap_mode = conf.getint('prefs', 'listwrap_mode')
|
251 | |
if conf.has_option('prefs', 'slideshow_delay'):
|
252 | |
self.slideshow_delay = conf.getint('prefs', 'slideshow_delay')
|
253 | |
if conf.has_option('prefs', 'slideshow_random'):
|
254 | |
self.slideshow_random = conf.getboolean('prefs', 'slideshow_random')
|
255 | |
if conf.has_option('prefs', 'zoomquality'):
|
256 | |
self.zoomvalue = conf.getint('prefs', 'zoomquality')
|
257 | |
if int(round(self.zoomvalue, 0)) == 0:
|
258 | |
self.zoom_quality = gtk.gdk.INTERP_NEAREST
|
259 | |
elif int(round(self.zoomvalue, 0)) == 1:
|
260 | |
self.zoom_quality = gtk.gdk.INTERP_TILES
|
261 | |
elif int(round(self.zoomvalue, 0)) == 2:
|
262 | |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
263 | |
elif int(round(self.zoomvalue, 0)) == 3:
|
264 | |
self.zoom_quality = gtk.gdk.INTERP_HYPER
|
265 | |
if conf.has_option('prefs', 'quality_save'):
|
266 | |
self.quality_save = conf.getint('prefs', 'quality_save')
|
267 | |
if conf.has_option('prefs', 'disable_screensaver'):
|
268 | |
self.disable_screensaver = conf.getboolean('prefs', 'disable_screensaver')
|
269 | |
if conf.has_option('prefs', 'slideshow_in_fullscreen'):
|
270 | |
self.slideshow_in_fullscreen = conf.getboolean('prefs', 'slideshow_in_fullscreen')
|
271 | |
if conf.has_option('prefs', 'preloading_images'):
|
272 | |
self.preloading_images = conf.getboolean('prefs', 'preloading_images')
|
273 | |
if conf.has_option('prefs', 'thumbsize'):
|
274 | |
self.thumbnail_size = conf.getint('prefs', 'thumbsize')
|
275 | |
if conf.has_option('prefs', 'screenshot_delay'):
|
276 | |
self.screenshot_delay = conf.getint('prefs', 'screenshot_delay')
|
277 | |
if conf.has_option('actions', 'num_actions'):
|
278 | |
num_actions = conf.getint('actions', 'num_actions')
|
279 | |
self.action_names = []
|
280 | |
self.action_commands = []
|
281 | |
self.action_shortcuts = []
|
282 | |
self.action_batch = []
|
283 | |
for i in range(num_actions):
|
284 | |
if conf.has_option('actions', 'names[' + str(i) + ']') and conf.has_option('actions', 'commands[' + str(i) + ']') and conf.has_option('actions', 'shortcuts[' + str(i) + ']') and conf.has_option('actions', 'batch[' + str(i) + ']'):
|
285 | |
self.action_names.append(conf.get('actions', 'names[' + str(i) + ']'))
|
286 | |
self.action_commands.append(conf.get('actions', 'commands[' + str(i) + ']'))
|
287 | |
self.action_shortcuts.append(conf.get('actions', 'shortcuts[' + str(i) + ']'))
|
288 | |
self.action_batch.append(conf.getboolean('actions', 'batch[' + str(i) + ']'))
|
289 | |
if conf.has_option('prefs', 'savemode'):
|
290 | |
self.savemode = conf.getint('prefs', 'savemode')
|
291 | |
if conf.has_option('prefs', 'start_in_fullscreen'):
|
292 | |
self.start_in_fullscreen = conf.getboolean('prefs', 'start_in_fullscreen')
|
293 | |
if conf.has_option('prefs', 'confirm_delete'):
|
294 | |
self.confirm_delete = conf.getboolean('prefs', 'confirm_delete')
|
295 | |
self.recentfiles = []
|
296 | |
if conf.has_option('recent', 'num_recent'):
|
297 | |
num_recent = conf.getint('recent', 'num_recent')
|
298 | |
for i in range(num_recent):
|
299 | |
self.recentfiles.append('')
|
300 | |
if conf.has_option('recent', 'urls[' + str(i) + ',0]'):
|
301 | |
self.recentfiles[i] = conf.get('recent', 'urls[' + str(i) + ',0]')
|
302 | |
# slideshow_delay is the user's preference, whereas curr_slideshow_delay is
|
303 | |
# the current delay (which can be changed without affecting the 'default')
|
304 | |
self.curr_slideshow_delay = self.slideshow_delay
|
305 | |
# Same for randomization:
|
306 | |
self.curr_slideshow_random = self.slideshow_random
|
307 | |
|
308 | |
# Read accel_map file, if it exists
|
309 | |
if os.path.isfile(self.config_dir + '/accel_map'):
|
310 | |
gtk.accel_map_load(self.config_dir + '/accel_map')
|
311 | |
|
312 | |
# Directory/ies in which to find application images/pixmaps
|
313 | |
self.resource_path_list = False
|
314 | |
|
315 | |
self.blank_image = gtk.gdk.pixbuf_new_from_file(self.find_path("mirage_blank.png"))
|
316 | |
|
317 | |
# Define the main menubar and toolbar:
|
318 | |
factory = gtk.IconFactory()
|
319 | |
iconname = 'stock_leave-fullscreen.png'
|
320 | |
iconname2 = 'stock_fullscreen.png'
|
321 | |
leave_fullscreen_icon_path = self.find_path(iconname)
|
322 | |
pixbuf = gtk.gdk.pixbuf_new_from_file(leave_fullscreen_icon_path)
|
323 | |
iconset = gtk.IconSet(pixbuf)
|
324 | |
factory.add('leave-fullscreen', iconset)
|
325 | |
factory.add_default()
|
326 | |
fullscreen_icon_path = self.find_path(iconname2)
|
327 | |
pixbuf = gtk.gdk.pixbuf_new_from_file(fullscreen_icon_path)
|
328 | |
iconset = gtk.IconSet(pixbuf)
|
329 | |
factory.add('fullscreen', iconset)
|
330 | |
factory.add_default()
|
331 | |
try:
|
332 | |
test = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
|
333 | |
leave_fullscreen_icon = gtk.STOCK_LEAVE_FULLSCREEN
|
334 | |
fullscreen_icon = gtk.STOCK_FULLSCREEN
|
335 | |
except:
|
336 | |
# This will allow gtk 2.6 users to run Mirage
|
337 | |
leave_fullscreen_icon = 'leave-fullscreen'
|
338 | |
fullscreen_icon = 'fullscreen'
|
339 | |
actions = (
|
340 | |
('FileMenu', None, _('_File')),
|
341 | |
('EditMenu', None, _('_Edit')),
|
342 | |
('ViewMenu', None, _('_View')),
|
343 | |
('GoMenu', None, _('_Go')),
|
344 | |
('HelpMenu', None, _('_Help')),
|
345 | |
('ActionSubMenu', None, _('Custom _Actions')),
|
346 | |
('Open Image', gtk.STOCK_FILE, _('_Open Image...'), '<Ctrl>O', _('Open Image'), self.open_file),
|
347 | |
('Open Remote Image', gtk.STOCK_NETWORK, _('Open _Remote image...'), None, _('Open Remote Image'), self.open_file_remote),
|
348 | |
('Open Folder', gtk.STOCK_DIRECTORY, _('Open _Folder...'), '<Ctrl>F', _('Open Folder'), self.open_folder),
|
349 | |
('Save', gtk.STOCK_SAVE, _('_Save Image'), '<Ctrl>S', _('Save Image'), self.save_image),
|
350 | |
('Save As', gtk.STOCK_SAVE, _('Save Image _As...'), '<Shift><Ctrl>S', _('Save Image As'), self.save_image_as),
|
351 | |
('Crop', None, _('_Crop...'), None, _('Crop Image'), self.crop_image),
|
352 | |
('Resize', None, _('R_esize...'), None, _('Resize Image'), self.resize_image),
|
353 | |
('Saturation', None, _('_Saturation...'), None, _('Modify saturation'), self.saturation),
|
354 | |
('Quit', gtk.STOCK_QUIT, _('_Quit'), '<Ctrl>Q', _('Quit'), self.exit_app),
|
355 | |
('Previous Image', gtk.STOCK_GO_BACK, _('_Previous Image'), 'Left', _('Previous Image'), self.goto_prev_image),
|
356 | |
('Next Image', gtk.STOCK_GO_FORWARD, _('_Next Image'), 'Right', _('Next Image'), self.goto_next_image),
|
357 | |
('Previous2', gtk.STOCK_GO_BACK, _('_Previous'), 'Left', _('Previous'), self.goto_prev_image),
|
358 | |
('Next2', gtk.STOCK_GO_FORWARD, _('_Next'), 'Right', _('Next'), self.goto_next_image),
|
359 | |
('Random Image', None, _('_Random Image'), 'R', _('Random Image'), self.goto_random_image),
|
360 | |
('First Image', gtk.STOCK_GOTO_FIRST, _('_First Image'), 'Home', _('First Image'), self.goto_first_image),
|
361 | |
('Last Image', gtk.STOCK_GOTO_LAST, _('_Last Image'), 'End', _('Last Image'), self.goto_last_image),
|
362 | |
('In', gtk.STOCK_ZOOM_IN, _('Zoom _In'), '<Ctrl>Up', _('Zoom In'), self.zoom_in),
|
363 | |
('Out', gtk.STOCK_ZOOM_OUT, _('Zoom _Out'), '<Ctrl>Down', _('Zoom Out'), self.zoom_out),
|
364 | |
('Fit', gtk.STOCK_ZOOM_FIT, _('Zoom To _Fit'), '<Ctrl>0', _('Fit'), self.zoom_to_fit_window_action),
|
365 | |
('1:1', gtk.STOCK_ZOOM_100, _('_1:1'), '<Ctrl>1', _('1:1'), self.zoom_1_to_1_action),
|
366 | |
('Rotate Left', None, _('Rotate _Left'), '<Ctrl>Left', _('Rotate Left'), self.rotate_left),
|
367 | |
('Rotate Right', None, _('Rotate _Right'), '<Ctrl>Right', _('Rotate Right'), self.rotate_right),
|
368 | |
('Flip Vertically', None, _('Flip _Vertically'), '<Ctrl>V', _('Flip Vertically'), self.flip_image_vert),
|
369 | |
('Flip Horizontally', None, _('Flip _Horizontally'), '<Ctrl>H', _('Flip Horizontally'), self.flip_image_horiz),
|
370 | |
('About', gtk.STOCK_ABOUT, _('_About'), None, _('About'), self.show_about),
|
371 | |
('Contents', gtk.STOCK_HELP, _('_Contents'), 'F1', _('Contents'), self.show_help),
|
372 | |
('Preferences', gtk.STOCK_PREFERENCES, _('_Preferences...'), '<Ctrl>P', _('Preferences'), self.show_prefs),
|
373 | |
('Full Screen', fullscreen_icon, _('_Full Screen'), 'F11', _('Full Screen'), self.enter_fullscreen),
|
374 | |
('Exit Full Screen', leave_fullscreen_icon, _('E_xit Full Screen'), None, _('Exit Full Screen'), self.leave_fullscreen),
|
375 | |
('Start Slideshow', gtk.STOCK_MEDIA_PLAY, _('_Start Slideshow'), 'F5', _('Start Slideshow'), self.toggle_slideshow),
|
376 | |
('Stop Slideshow', gtk.STOCK_MEDIA_STOP, _('_Stop Slideshow'), 'F5', _('Stop Slideshow'), self.toggle_slideshow),
|
377 | |
('Delete Image', gtk.STOCK_DELETE, _('_Delete...'), 'Delete', _('Delete Image'), self.delete_image),
|
378 | |
('Rename Image', None, _('Re_name...'), 'F2', _('Rename Image'), self.rename_image),
|
379 | |
('Take Screenshot', None, _('_Take Screenshot...'), None, _('Take Screenshot'), self.screenshot),
|
380 | |
('Properties', gtk.STOCK_PROPERTIES, _('_Properties...'), None, _('Properties'), self.show_properties),
|
381 | |
('Custom Actions', None, _('_Configure...'), None, _('Custom Actions'), self.show_custom_actions),
|
382 | |
('MiscKeysMenuHidden', None, 'Keys'),
|
383 | |
('Escape', None, '', 'Escape', _('Exit Full Screen'), self.leave_fullscreen),
|
384 | |
('Minus', None, '', 'minus', _('Zoom Out'), self.zoom_out),
|
385 | |
('Plus', None, '', 'plus', _('Zoom In'), self.zoom_in),
|
386 | |
('Equal', None, '', 'equal', _('Zoom In'), self.zoom_in),
|
387 | |
('Space', None, '', 'space', _('Next Image'), self.goto_next_image),
|
388 | |
('Ctrl-KP_Insert', None, '', '<Ctrl>KP_Insert', _('Fit'), self.zoom_to_fit_window_action),
|
389 | |
('Ctrl-KP_End', None, '', '<Ctrl>KP_End', _('1:1'), self.zoom_1_to_1_action),
|
390 | |
('Ctrl-KP_Subtract', None, '', '<Ctrl>KP_Subtract', _('Zoom Out'), self.zoom_out),
|
391 | |
('Ctrl-KP_Add', None, '', '<Ctrl>KP_Add', _('Zoom In'), self.zoom_in),
|
392 | |
('Ctrl-KP_0', None, '', '<Ctrl>KP_0', _('Fit'), self.zoom_to_fit_window_action),
|
393 | |
('Ctrl-KP_1', None, '', '<Ctrl>KP_1', _('1:1'), self.zoom_1_to_1_action),
|
394 | |
('Full Screen Key', None, '', '<Shift>Return', None, self.enter_fullscreen),
|
395 | |
('Prev', None, '', 'Up', _('Previous Image'), self.goto_prev_image),
|
396 | |
('Next', None, '', 'Down', _('Next Image'), self.goto_next_image),
|
397 | |
('PgUp', None, '', 'Page_Up', _('Previous Image'), self.goto_prev_image),
|
398 | |
('PgDn', None, '', 'Page_Down', _('Next Image'), self.goto_next_image),
|
399 | |
('BackSpace', None, '', 'BackSpace', _('Previous Image'), self.goto_prev_image),
|
400 | |
('OriginalSize', None, '', '1', _('1:1'), self.zoom_1_to_1_action),
|
401 | |
('ZoomIn', None, '', 'KP_Add', _('Zoom In'), self.zoom_in),
|
402 | |
('ZoomOut', None, '', 'KP_Subtract', _('Zoom Out'), self.zoom_out)
|
403 | |
)
|
404 | |
toggle_actions = (
|
405 | |
('Status Bar', None, _('_Status Bar'), None, _('Status Bar'), self.toggle_status_bar, self.statusbar_show),
|
406 | |
('Toolbar', None, _('_Toolbar'), None, _('Toolbar'), self.toggle_toolbar, self.toolbar_show),
|
407 | |
('Thumbnails Pane', None, _('Thumbnails _Pane'), None, _('Thumbnails Pane'), self.toggle_thumbpane, self.thumbpane_show)
|
408 | |
)
|
409 | |
|
410 | |
# Populate keys[]:
|
411 | |
self.keys=[]
|
412 | |
for i in range(len(actions)):
|
413 | |
if len(actions[i]) > 3:
|
414 | |
if actions[i][3] != None:
|
415 | |
self.keys.append([actions[i][4], actions[i][3]])
|
416 | |
|
417 | |
uiDescription = """
|
|
77 |
def __init__(self):
|
|
78 |
|
|
79 |
gtk.gdk.threads_init()
|
|
80 |
|
|
81 |
# FIX THIS! Does not work on windows and what happens if mo-files exists
|
|
82 |
# in both dirs?
|
|
83 |
gettext.install("mirage", "/usr/share/locale")
|
|
84 |
gettext.install("mirage", "/usr/local/share/locale")
|
|
85 |
|
|
86 |
# Constants
|
|
87 |
self.open_mode_smart = 0
|
|
88 |
self.open_mode_fit = 1
|
|
89 |
self.open_mode_1to1 = 2
|
|
90 |
self.open_mode_last = 3
|
|
91 |
self.min_zoomratio = 0.02
|
|
92 |
|
|
93 |
# Initialize vars:
|
|
94 |
width = 600
|
|
95 |
height = 400
|
|
96 |
bgcolor_found = False
|
|
97 |
self.simple_bgcolor = False
|
|
98 |
# Current image:
|
|
99 |
self.curr_img_in_list = 0
|
|
100 |
self.currimg_name = ""
|
|
101 |
self.currimg_width = 0
|
|
102 |
self.currimg_height = 0
|
|
103 |
self.currimg_pixbuf = None
|
|
104 |
self.currimg_pixbuf_original = None
|
|
105 |
self.currimg_zoomratio = 1
|
|
106 |
self.currimg_is_animation = False
|
|
107 |
# This is the actual pixbuf that is loaded in Mirage. This will
|
|
108 |
# usually be the same as self.curr_img_in_list except for scenarios
|
|
109 |
# like when the user presses 'next image' multiple times in a row.
|
|
110 |
# In this case, self.curr_img_in_list will increment while
|
|
111 |
# self.loaded_img_in_list will retain the current loaded image.
|
|
112 |
self.loaded_img_in_list = 0
|
|
113 |
# Next preloaded image:
|
|
114 |
self.preloadimg_next_in_list = -1
|
|
115 |
self.preloadimg_next_name = ""
|
|
116 |
self.preloadimg_next_width = 0
|
|
117 |
self.preloadimg_next_height = 0
|
|
118 |
self.preloadimg_next_pixbuf = None
|
|
119 |
self.preloadimg_next_pixbuf_original = None
|
|
120 |
self.preloadimg_next_zoomratio = 1
|
|
121 |
self.preloadimg_next_is_animation = False
|
|
122 |
# Previous preloaded image:
|
|
123 |
self.preloadimg_prev_in_list = -1
|
|
124 |
self.preloadimg_prev_name = ""
|
|
125 |
self.preloadimg_prev_width = 0
|
|
126 |
self.preloadimg_prev_height = 0
|
|
127 |
self.preloadimg_prev_pixbuf = None
|
|
128 |
self.preloadimg_prev_pixbuf_original = None
|
|
129 |
self.preloadimg_prev_zoomratio = 1
|
|
130 |
self.preloadimg_prev_is_animation = False
|
|
131 |
# Settings, misc:
|
|
132 |
self.toolbar_show = True
|
|
133 |
self.thumbpane_show = True
|
|
134 |
self.statusbar_show = True
|
|
135 |
self.fullscreen_mode = False
|
|
136 |
self.opendialogpath = ""
|
|
137 |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
|
138 |
self.recursive = False
|
|
139 |
self.verbose = False
|
|
140 |
self.image_loaded = False
|
|
141 |
self.open_all_images = True # open all images in the directory(ies)
|
|
142 |
self.use_last_dir = True
|
|
143 |
self.last_dir = os.path.expanduser("~")
|
|
144 |
self.fixed_dir = os.path.expanduser("~")
|
|
145 |
self.image_list = []
|
|
146 |
self.open_mode = self.open_mode_smart
|
|
147 |
self.last_mode = self.open_mode_smart
|
|
148 |
self.listwrap_mode = 0 # 0=no, 1=yes, 2=ask
|
|
149 |
self.user_prompt_visible = False # the "wrap?" prompt
|
|
150 |
self.slideshow_delay = 1 # seconds
|
|
151 |
self.slideshow_mode = False
|
|
152 |
self.slideshow_random = False
|
|
153 |
self.slideshow_controls_visible = False # fullscreen slideshow controls
|
|
154 |
self.controls_moving = False
|
|
155 |
self.zoomvalue = 2
|
|
156 |
self.quality_save = 90
|
|
157 |
self.updating_adjustments = False
|
|
158 |
self.disable_screensaver = False
|
|
159 |
self.slideshow_in_fullscreen = False
|
|
160 |
self.closing_app = False
|
|
161 |
self.confirm_delete = True
|
|
162 |
self.preloading_images = True
|
|
163 |
self.action_names = [
|
|
164 |
"Open in GIMP",
|
|
165 |
"Create Thumbnail",
|
|
166 |
"Create Thumbnails",
|
|
167 |
"Move to Favorites",
|
|
168 |
]
|
|
169 |
self.action_shortcuts = [
|
|
170 |
"<Control>e",
|
|
171 |
"<Alt>t",
|
|
172 |
"<Control><Alt>t",
|
|
173 |
"<Control><Alt>f",
|
|
174 |
]
|
|
175 |
self.action_commands = [
|
|
176 |
"gimp-remote-2.4 %F",
|
|
177 |
"convert %F -thumbnail 150x150 %Pt_%N.jpg",
|
|
178 |
"convert %F -thumbnail 150x150 %Pt_%N.jpg",
|
|
179 |
"mkdir -p ~/mirage-favs; mv %F ~/mirage-favs; [NEXT]",
|
|
180 |
]
|
|
181 |
self.action_batch = [False, False, True, False]
|
|
182 |
self.onload_cmd = None
|
|
183 |
self.searching_for_images = False
|
|
184 |
self.preserve_aspect = True
|
|
185 |
self.ignore_preserve_aspect_callback = False
|
|
186 |
self.savemode = 2
|
|
187 |
self.image_modified = False
|
|
188 |
self.image_zoomed = False
|
|
189 |
self.start_in_fullscreen = False
|
|
190 |
self.running_custom_actions = False
|
|
191 |
self.merge_id = None
|
|
192 |
self.actionGroupCustom = None
|
|
193 |
self.merge_id_recent = None
|
|
194 |
self.actionGroupRecent = None
|
|
195 |
self.open_hidden_files = False
|
|
196 |
self.thumbnail_sizes = ["128", "96", "72", "64", "48", "32"]
|
|
197 |
self.thumbnail_size = 128 # Default to 128 x 128
|
|
198 |
self.thumbnail_loaded = []
|
|
199 |
self.thumbpane_updating = False
|
|
200 |
self.recentfiles = ["", "", "", "", ""]
|
|
201 |
self.screenshot_delay = 2
|
|
202 |
self.thumbpane_bottom_coord_loaded = 0
|
|
203 |
|
|
204 |
# Read any passed options/arguments:
|
|
205 |
try:
|
|
206 |
opts, args = getopt.getopt(
|
|
207 |
sys.argv[1:],
|
|
208 |
"hRvVsfo:",
|
|
209 |
[
|
|
210 |
"help",
|
|
211 |
"version",
|
|
212 |
"recursive",
|
|
213 |
"verbose",
|
|
214 |
"slideshow",
|
|
215 |
"fullscreen",
|
|
216 |
"onload=",
|
|
217 |
],
|
|
218 |
)
|
|
219 |
except getopt.GetoptError:
|
|
220 |
# print help information and exit:
|
|
221 |
self.print_usage()
|
|
222 |
sys.exit(2)
|
|
223 |
# If options were passed, perform action on them.
|
|
224 |
if opts != []:
|
|
225 |
for o, a in opts:
|
|
226 |
if o in ("-v", "--version"):
|
|
227 |
self.print_version()
|
|
228 |
sys.exit(2)
|
|
229 |
elif o in ("-h", "--help"):
|
|
230 |
self.print_usage()
|
|
231 |
sys.exit(2)
|
|
232 |
elif o in ("-R", "--recursive"):
|
|
233 |
self.recursive = True
|
|
234 |
elif o in ("-V", "--verbose"):
|
|
235 |
self.verbose = True
|
|
236 |
elif o in ("-s", "--slideshow", "-f", "--fullscreen"):
|
|
237 |
# This will be handled later
|
|
238 |
None
|
|
239 |
elif o in ("-o", "--onload"):
|
|
240 |
self.onload_cmd = a
|
|
241 |
else:
|
|
242 |
self.print_usage()
|
|
243 |
sys.exit(2)
|
|
244 |
|
|
245 |
# Determine config dir, first try the environment variable XDG_CONFIG_HOME
|
|
246 |
# according to XDG specification and as a fallback use ~/.config/mirage
|
|
247 |
self.config_dir = (
|
|
248 |
os.getenv("XDG_CONFIG_HOME") or os.path.expanduser("~/.config")
|
|
249 |
) + "/mirage"
|
|
250 |
# Load config from disk:
|
|
251 |
conf = configparser.ConfigParser()
|
|
252 |
if os.path.isfile(self.config_dir + "/miragerc"):
|
|
253 |
conf.read(self.config_dir + "/miragerc")
|
|
254 |
if conf.has_option("window", "w"):
|
|
255 |
width = conf.getint("window", "w")
|
|
256 |
if conf.has_option("window", "h"):
|
|
257 |
height = conf.getint("window", "h")
|
|
258 |
if conf.has_option("window", "toolbar"):
|
|
259 |
self.toolbar_show = conf.getboolean("window", "toolbar")
|
|
260 |
if conf.has_option("window", "statusbar"):
|
|
261 |
self.statusbar_show = conf.getboolean("window", "statusbar")
|
|
262 |
if conf.has_option("window", "thumbpane"):
|
|
263 |
self.thumbpane_show = conf.getboolean("window", "thumbpane")
|
|
264 |
if conf.has_option("prefs", "simple-bgcolor"):
|
|
265 |
self.simple_bgcolor = conf.getboolean("prefs", "simple-bgcolor")
|
|
266 |
if conf.has_option("prefs", "bgcolor-red"):
|
|
267 |
bgr = conf.getint("prefs", "bgcolor-red")
|
|
268 |
bgg = conf.getint("prefs", "bgcolor-green")
|
|
269 |
bgb = conf.getint("prefs", "bgcolor-blue")
|
|
270 |
bgcolor_found = True
|
|
271 |
self.bgcolor = gtk.gdk.Color(red=bgr, green=bgg, blue=bgb)
|
|
272 |
if conf.has_option("prefs", "use_last_dir"):
|
|
273 |
self.use_last_dir = conf.getboolean("prefs", "use_last_dir")
|
|
274 |
if conf.has_option("prefs", "last_dir"):
|
|
275 |
self.last_dir = conf.get("prefs", "last_dir")
|
|
276 |
if conf.has_option("prefs", "fixed_dir"):
|
|
277 |
self.fixed_dir = conf.get("prefs", "fixed_dir")
|
|
278 |
if conf.has_option("prefs", "open_all"):
|
|
279 |
self.open_all_images = conf.getboolean("prefs", "open_all")
|
|
280 |
if conf.has_option("prefs", "hidden"):
|
|
281 |
self.open_hidden_files = conf.getboolean("prefs", "hidden")
|
|
282 |
if conf.has_option("prefs", "open_mode"):
|
|
283 |
self.open_mode = conf.getint("prefs", "open_mode")
|
|
284 |
if conf.has_option("prefs", "last_mode"):
|
|
285 |
self.last_mode = conf.getint("prefs", "last_mode")
|
|
286 |
if conf.has_option("prefs", "listwrap_mode"):
|
|
287 |
self.listwrap_mode = conf.getint("prefs", "listwrap_mode")
|
|
288 |
if conf.has_option("prefs", "slideshow_delay"):
|
|
289 |
self.slideshow_delay = conf.getint("prefs", "slideshow_delay")
|
|
290 |
if conf.has_option("prefs", "slideshow_random"):
|
|
291 |
self.slideshow_random = conf.getboolean("prefs", "slideshow_random")
|
|
292 |
if conf.has_option("prefs", "zoomquality"):
|
|
293 |
self.zoomvalue = conf.getint("prefs", "zoomquality")
|
|
294 |
if int(round(self.zoomvalue, 0)) == 0:
|
|
295 |
self.zoom_quality = gtk.gdk.INTERP_NEAREST
|
|
296 |
elif int(round(self.zoomvalue, 0)) == 1:
|
|
297 |
self.zoom_quality = gtk.gdk.INTERP_TILES
|
|
298 |
elif int(round(self.zoomvalue, 0)) == 2:
|
|
299 |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
|
300 |
elif int(round(self.zoomvalue, 0)) == 3:
|
|
301 |
self.zoom_quality = gtk.gdk.INTERP_HYPER
|
|
302 |
if conf.has_option("prefs", "quality_save"):
|
|
303 |
self.quality_save = conf.getint("prefs", "quality_save")
|
|
304 |
if conf.has_option("prefs", "disable_screensaver"):
|
|
305 |
self.disable_screensaver = conf.getboolean("prefs", "disable_screensaver")
|
|
306 |
if conf.has_option("prefs", "slideshow_in_fullscreen"):
|
|
307 |
self.slideshow_in_fullscreen = conf.getboolean(
|
|
308 |
"prefs", "slideshow_in_fullscreen"
|
|
309 |
)
|
|
310 |
if conf.has_option("prefs", "preloading_images"):
|
|
311 |
self.preloading_images = conf.getboolean("prefs", "preloading_images")
|
|
312 |
if conf.has_option("prefs", "thumbsize"):
|
|
313 |
self.thumbnail_size = conf.getint("prefs", "thumbsize")
|
|
314 |
if conf.has_option("prefs", "screenshot_delay"):
|
|
315 |
self.screenshot_delay = conf.getint("prefs", "screenshot_delay")
|
|
316 |
if conf.has_option("actions", "num_actions"):
|
|
317 |
num_actions = conf.getint("actions", "num_actions")
|
|
318 |
self.action_names = []
|
|
319 |
self.action_commands = []
|
|
320 |
self.action_shortcuts = []
|
|
321 |
self.action_batch = []
|
|
322 |
for i in range(num_actions):
|
|
323 |
if (
|
|
324 |
conf.has_option("actions", "names[" + str(i) + "]")
|
|
325 |
and conf.has_option("actions", "commands[" + str(i) + "]")
|
|
326 |
and conf.has_option("actions", "shortcuts[" + str(i) + "]")
|
|
327 |
and conf.has_option("actions", "batch[" + str(i) + "]")
|
|
328 |
):
|
|
329 |
self.action_names.append(
|
|
330 |
conf.get("actions", "names[" + str(i) + "]")
|
|
331 |
)
|
|
332 |
self.action_commands.append(
|
|
333 |
conf.get("actions", "commands[" + str(i) + "]")
|
|
334 |
)
|
|
335 |
self.action_shortcuts.append(
|
|
336 |
conf.get("actions", "shortcuts[" + str(i) + "]")
|
|
337 |
)
|
|
338 |
self.action_batch.append(
|
|
339 |
conf.getboolean("actions", "batch[" + str(i) + "]")
|
|
340 |
)
|
|
341 |
if conf.has_option("prefs", "savemode"):
|
|
342 |
self.savemode = conf.getint("prefs", "savemode")
|
|
343 |
if conf.has_option("prefs", "start_in_fullscreen"):
|
|
344 |
self.start_in_fullscreen = conf.getboolean("prefs", "start_in_fullscreen")
|
|
345 |
if conf.has_option("prefs", "confirm_delete"):
|
|
346 |
self.confirm_delete = conf.getboolean("prefs", "confirm_delete")
|
|
347 |
self.recentfiles = []
|
|
348 |
if conf.has_option("recent", "num_recent"):
|
|
349 |
num_recent = conf.getint("recent", "num_recent")
|
|
350 |
for i in range(num_recent):
|
|
351 |
self.recentfiles.append("")
|
|
352 |
if conf.has_option("recent", "urls[" + str(i) + ",0]"):
|
|
353 |
self.recentfiles[i] = conf.get("recent", "urls[" + str(i) + ",0]")
|
|
354 |
# slideshow_delay is the user's preference, whereas curr_slideshow_delay is
|
|
355 |
# the current delay (which can be changed without affecting the 'default')
|
|
356 |
self.curr_slideshow_delay = self.slideshow_delay
|
|
357 |
# Same for randomization:
|
|
358 |
self.curr_slideshow_random = self.slideshow_random
|
|
359 |
|
|
360 |
# Read accel_map file, if it exists
|
|
361 |
if os.path.isfile(self.config_dir + "/accel_map"):
|
|
362 |
gtk.accel_map_load(self.config_dir + "/accel_map")
|
|
363 |
|
|
364 |
# Directory/ies in which to find application images/pixmaps
|
|
365 |
self.resource_path_list = False
|
|
366 |
|
|
367 |
self.blank_image = gtk.gdk.pixbuf_new_from_file(
|
|
368 |
self.find_path("mirage_blank.png")
|
|
369 |
)
|
|
370 |
|
|
371 |
# Define the main menubar and toolbar:
|
|
372 |
factory = gtk.IconFactory()
|
|
373 |
iconname = "stock_leave-fullscreen.png"
|
|
374 |
iconname2 = "stock_fullscreen.png"
|
|
375 |
leave_fullscreen_icon_path = self.find_path(iconname)
|
|
376 |
pixbuf = gtk.gdk.pixbuf_new_from_file(leave_fullscreen_icon_path)
|
|
377 |
iconset = gtk.IconSet(pixbuf)
|
|
378 |
factory.add("leave-fullscreen", iconset)
|
|
379 |
factory.add_default()
|
|
380 |
fullscreen_icon_path = self.find_path(iconname2)
|
|
381 |
pixbuf = gtk.gdk.pixbuf_new_from_file(fullscreen_icon_path)
|
|
382 |
iconset = gtk.IconSet(pixbuf)
|
|
383 |
factory.add("fullscreen", iconset)
|
|
384 |
factory.add_default()
|
|
385 |
try:
|
|
386 |
test = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
|
|
387 |
leave_fullscreen_icon = gtk.STOCK_LEAVE_FULLSCREEN
|
|
388 |
fullscreen_icon = gtk.STOCK_FULLSCREEN
|
|
389 |
except:
|
|
390 |
# This will allow gtk 2.6 users to run Mirage
|
|
391 |
leave_fullscreen_icon = "leave-fullscreen"
|
|
392 |
fullscreen_icon = "fullscreen"
|
|
393 |
actions = (
|
|
394 |
("FileMenu", None, _("_File")),
|
|
395 |
("EditMenu", None, _("_Edit")),
|
|
396 |
("ViewMenu", None, _("_View")),
|
|
397 |
("GoMenu", None, _("_Go")),
|
|
398 |
("HelpMenu", None, _("_Help")),
|
|
399 |
("ActionSubMenu", None, _("Custom _Actions")),
|
|
400 |
(
|
|
401 |
"Open Image",
|
|
402 |
gtk.STOCK_FILE,
|
|
403 |
_("_Open Image..."),
|
|
404 |
"<Ctrl>O",
|
|
405 |
_("Open Image"),
|
|
406 |
self.open_file,
|
|
407 |
),
|
|
408 |
(
|
|
409 |
"Open Remote Image",
|
|
410 |
gtk.STOCK_NETWORK,
|
|
411 |
_("Open _Remote image..."),
|
|
412 |
None,
|
|
413 |
_("Open Remote Image"),
|
|
414 |
self.open_file_remote,
|
|
415 |
),
|
|
416 |
(
|
|
417 |
"Open Folder",
|
|
418 |
gtk.STOCK_DIRECTORY,
|
|
419 |
_("Open _Folder..."),
|
|
420 |
"<Ctrl>F",
|
|
421 |
_("Open Folder"),
|
|
422 |
self.open_folder,
|
|
423 |
),
|
|
424 |
(
|
|
425 |
"Save",
|
|
426 |
gtk.STOCK_SAVE,
|
|
427 |
_("_Save Image"),
|
|
428 |
"<Ctrl>S",
|
|
429 |
_("Save Image"),
|
|
430 |
self.save_image,
|
|
431 |
),
|
|
432 |
(
|
|
433 |
"Save As",
|
|
434 |
gtk.STOCK_SAVE,
|
|
435 |
_("Save Image _As..."),
|
|
436 |
"<Shift><Ctrl>S",
|
|
437 |
_("Save Image As"),
|
|
438 |
self.save_image_as,
|
|
439 |
),
|
|
440 |
("Crop", None, _("_Crop..."), None, _("Crop Image"), self.crop_image),
|
|
441 |
(
|
|
442 |
"Resize",
|
|
443 |
None,
|
|
444 |
_("R_esize..."),
|
|
445 |
None,
|
|
446 |
_("Resize Image"),
|
|
447 |
self.resize_image,
|
|
448 |
),
|
|
449 |
(
|
|
450 |
"Saturation",
|
|
451 |
None,
|
|
452 |
_("_Saturation..."),
|
|
453 |
None,
|
|
454 |
_("Modify saturation"),
|
|
455 |
self.saturation,
|
|
456 |
),
|
|
457 |
("Quit", gtk.STOCK_QUIT, _("_Quit"), "<Ctrl>Q", _("Quit"), self.exit_app),
|
|
458 |
(
|
|
459 |
"Previous Image",
|
|
460 |
gtk.STOCK_GO_BACK,
|
|
461 |
_("_Previous Image"),
|
|
462 |
"Left",
|
|
463 |
_("Previous Image"),
|
|
464 |
self.goto_prev_image,
|
|
465 |
),
|
|
466 |
(
|
|
467 |
"Next Image",
|
|
468 |
gtk.STOCK_GO_FORWARD,
|
|
469 |
_("_Next Image"),
|
|
470 |
"Right",
|
|
471 |
_("Next Image"),
|
|
472 |
self.goto_next_image,
|
|
473 |
),
|
|
474 |
(
|
|
475 |
"Previous2",
|
|
476 |
gtk.STOCK_GO_BACK,
|
|
477 |
_("_Previous"),
|
|
478 |
"Left",
|
|
479 |
_("Previous"),
|
|
480 |
self.goto_prev_image,
|
|
481 |
),
|
|
482 |
(
|
|
483 |
"Next2",
|
|
484 |
gtk.STOCK_GO_FORWARD,
|
|
485 |
_("_Next"),
|
|
486 |
"Right",
|
|
487 |
_("Next"),
|
|
488 |
self.goto_next_image,
|
|
489 |
),
|
|
490 |
(
|
|
491 |
"Random Image",
|
|
492 |
None,
|
|
493 |
_("_Random Image"),
|
|
494 |
"R",
|
|
495 |
_("Random Image"),
|
|
496 |
self.goto_random_image,
|
|
497 |
),
|
|
498 |
(
|
|
499 |
"First Image",
|
|
500 |
gtk.STOCK_GOTO_FIRST,
|
|
501 |
_("_First Image"),
|
|
502 |
"Home",
|
|
503 |
_("First Image"),
|
|
504 |
self.goto_first_image,
|
|
505 |
),
|
|
506 |
(
|
|
507 |
"Last Image",
|
|
508 |
gtk.STOCK_GOTO_LAST,
|
|
509 |
_("_Last Image"),
|
|
510 |
"End",
|
|
511 |
_("Last Image"),
|
|
512 |
self.goto_last_image,
|
|
513 |
),
|
|
514 |
(
|
|
515 |
"In",
|
|
516 |
gtk.STOCK_ZOOM_IN,
|
|
517 |
_("Zoom _In"),
|
|
518 |
"<Ctrl>Up",
|
|
519 |
_("Zoom In"),
|
|
520 |
self.zoom_in,
|
|
521 |
),
|
|
522 |
(
|
|
523 |
"Out",
|
|
524 |
gtk.STOCK_ZOOM_OUT,
|
|
525 |
_("Zoom _Out"),
|
|
526 |
"<Ctrl>Down",
|
|
527 |
_("Zoom Out"),
|
|
528 |
self.zoom_out,
|
|
529 |
),
|
|
530 |
(
|
|
531 |
"Fit",
|
|
532 |
gtk.STOCK_ZOOM_FIT,
|
|
533 |
_("Zoom To _Fit"),
|
|
534 |
"<Ctrl>0",
|
|
535 |
_("Fit"),
|
|
536 |
self.zoom_to_fit_window_action,
|
|
537 |
),
|
|
538 |
(
|
|
539 |
"1:1",
|
|
540 |
gtk.STOCK_ZOOM_100,
|
|
541 |
_("_1:1"),
|
|
542 |
"<Ctrl>1",
|
|
543 |
_("1:1"),
|
|
544 |
self.zoom_1_to_1_action,
|
|
545 |
),
|
|
546 |
(
|
|
547 |
"Rotate Left",
|
|
548 |
None,
|
|
549 |
_("Rotate _Left"),
|
|
550 |
"<Ctrl>Left",
|
|
551 |
_("Rotate Left"),
|
|
552 |
self.rotate_left,
|
|
553 |
),
|
|
554 |
(
|
|
555 |
"Rotate Right",
|
|
556 |
None,
|
|
557 |
_("Rotate _Right"),
|
|
558 |
"<Ctrl>Right",
|
|
559 |
_("Rotate Right"),
|
|
560 |
self.rotate_right,
|
|
561 |
),
|
|
562 |
(
|
|
563 |
"Flip Vertically",
|
|
564 |
None,
|
|
565 |
_("Flip _Vertically"),
|
|
566 |
"<Ctrl>V",
|
|
567 |
_("Flip Vertically"),
|
|
568 |
self.flip_image_vert,
|
|
569 |
),
|
|
570 |
(
|
|
571 |
"Flip Horizontally",
|
|
572 |
None,
|
|
573 |
_("Flip _Horizontally"),
|
|
574 |
"<Ctrl>H",
|
|
575 |
_("Flip Horizontally"),
|
|
576 |
self.flip_image_horiz,
|
|
577 |
),
|
|
578 |
("About", gtk.STOCK_ABOUT, _("_About"), None, _("About"), self.show_about),
|
|
579 |
(
|
|
580 |
"Contents",
|
|
581 |
gtk.STOCK_HELP,
|
|
582 |
_("_Contents"),
|
|
583 |
"F1",
|
|
584 |
_("Contents"),
|
|
585 |
self.show_help,
|
|
586 |
),
|
|
587 |
(
|
|
588 |
"Preferences",
|
|
589 |
gtk.STOCK_PREFERENCES,
|
|
590 |
_("_Preferences..."),
|
|
591 |
"<Ctrl>P",
|
|
592 |
_("Preferences"),
|
|
593 |
self.show_prefs,
|
|
594 |
),
|
|
595 |
(
|
|
596 |
"Full Screen",
|
|
597 |
fullscreen_icon,
|
|
598 |
_("_Full Screen"),
|
|
599 |
"F11",
|
|
600 |
_("Full Screen"),
|
|
601 |
self.enter_fullscreen,
|
|
602 |
),
|
|
603 |
(
|
|
604 |
"Exit Full Screen",
|
|
605 |
leave_fullscreen_icon,
|
|
606 |
_("E_xit Full Screen"),
|
|
607 |
None,
|
|
608 |
_("Exit Full Screen"),
|
|
609 |
self.leave_fullscreen,
|
|
610 |
),
|
|
611 |
(
|
|
612 |
"Start Slideshow",
|
|
613 |
gtk.STOCK_MEDIA_PLAY,
|
|
614 |
_("_Start Slideshow"),
|
|
615 |
"F5",
|
|
616 |
_("Start Slideshow"),
|
|
617 |
self.toggle_slideshow,
|
|
618 |
),
|
|
619 |
(
|
|
620 |
"Stop Slideshow",
|
|
621 |
gtk.STOCK_MEDIA_STOP,
|
|
622 |
_("_Stop Slideshow"),
|
|
623 |
"F5",
|
|
624 |
_("Stop Slideshow"),
|
|
625 |
self.toggle_slideshow,
|
|
626 |
),
|
|
627 |
(
|
|
628 |
"Delete Image",
|
|
629 |
gtk.STOCK_DELETE,
|
|
630 |
_("_Delete..."),
|
|
631 |
"Delete",
|
|
632 |
_("Delete Image"),
|
|
633 |
self.delete_image,
|
|
634 |
),
|
|
635 |
(
|
|
636 |
"Rename Image",
|
|
637 |
None,
|
|
638 |
_("Re_name..."),
|
|
639 |
"F2",
|
|
640 |
_("Rename Image"),
|
|
641 |
self.rename_image,
|
|
642 |
),
|
|
643 |
(
|
|
644 |
"Take Screenshot",
|
|
645 |
None,
|
|
646 |
_("_Take Screenshot..."),
|
|
647 |
None,
|
|
648 |
_("Take Screenshot"),
|
|
649 |
self.screenshot,
|
|
650 |
),
|
|
651 |
(
|
|
652 |
"Properties",
|
|
653 |
gtk.STOCK_PROPERTIES,
|
|
654 |
_("_Properties..."),
|
|
655 |
None,
|
|
656 |
_("Properties"),
|
|
657 |
self.show_properties,
|
|
658 |
),
|
|
659 |
(
|
|
660 |
"Custom Actions",
|
|
661 |
None,
|
|
662 |
_("_Configure..."),
|
|
663 |
None,
|
|
664 |
_("Custom Actions"),
|
|
665 |
self.show_custom_actions,
|
|
666 |
),
|
|
667 |
("MiscKeysMenuHidden", None, "Keys"),
|
|
668 |
(
|
|
669 |
"Escape",
|
|
670 |
None,
|
|
671 |
"",
|
|
672 |
"Escape",
|
|
673 |
_("Exit Full Screen"),
|
|
674 |
self.leave_fullscreen,
|
|
675 |
),
|
|
676 |
("Minus", None, "", "minus", _("Zoom Out"), self.zoom_out),
|
|
677 |
("Plus", None, "", "plus", _("Zoom In"), self.zoom_in),
|
|
678 |
("Equal", None, "", "equal", _("Zoom In"), self.zoom_in),
|
|
679 |
("Space", None, "", "space", _("Next Image"), self.goto_next_image),
|
|
680 |
(
|
|
681 |
"Ctrl-KP_Insert",
|
|
682 |
None,
|
|
683 |
"",
|
|
684 |
"<Ctrl>KP_Insert",
|
|
685 |
_("Fit"),
|
|
686 |
self.zoom_to_fit_window_action,
|
|
687 |
),
|
|
688 |
(
|
|
689 |
"Ctrl-KP_End",
|
|
690 |
None,
|
|
691 |
"",
|
|
692 |
"<Ctrl>KP_End",
|
|
693 |
_("1:1"),
|
|
694 |
self.zoom_1_to_1_action,
|
|
695 |
),
|
|
696 |
(
|
|
697 |
"Ctrl-KP_Subtract",
|
|
698 |
None,
|
|
699 |
"",
|
|
700 |
"<Ctrl>KP_Subtract",
|
|
701 |
_("Zoom Out"),
|
|
702 |
self.zoom_out,
|
|
703 |
),
|
|
704 |
("Ctrl-KP_Add", None, "", "<Ctrl>KP_Add", _("Zoom In"), self.zoom_in),
|
|
705 |
(
|
|
706 |
"Ctrl-KP_0",
|
|
707 |
None,
|
|
708 |
"",
|
|
709 |
"<Ctrl>KP_0",
|
|
710 |
_("Fit"),
|
|
711 |
self.zoom_to_fit_window_action,
|
|
712 |
),
|
|
713 |
("Ctrl-KP_1", None, "", "<Ctrl>KP_1", _("1:1"), self.zoom_1_to_1_action),
|
|
714 |
("Full Screen Key", None, "", "<Shift>Return", None, self.enter_fullscreen),
|
|
715 |
("Prev", None, "", "Up", _("Previous Image"), self.goto_prev_image),
|
|
716 |
("Next", None, "", "Down", _("Next Image"), self.goto_next_image),
|
|
717 |
("PgUp", None, "", "Page_Up", _("Previous Image"), self.goto_prev_image),
|
|
718 |
("PgDn", None, "", "Page_Down", _("Next Image"), self.goto_next_image),
|
|
719 |
(
|
|
720 |
"BackSpace",
|
|
721 |
None,
|
|
722 |
"",
|
|
723 |
"BackSpace",
|
|
724 |
_("Previous Image"),
|
|
725 |
self.goto_prev_image,
|
|
726 |
),
|
|
727 |
("OriginalSize", None, "", "1", _("1:1"), self.zoom_1_to_1_action),
|
|
728 |
("ZoomIn", None, "", "KP_Add", _("Zoom In"), self.zoom_in),
|
|
729 |
("ZoomOut", None, "", "KP_Subtract", _("Zoom Out"), self.zoom_out),
|
|
730 |
)
|
|
731 |
toggle_actions = (
|
|
732 |
(
|
|
733 |
"Status Bar",
|
|
734 |
None,
|
|
735 |
_("_Status Bar"),
|
|
736 |
None,
|
|
737 |
_("Status Bar"),
|
|
738 |
self.toggle_status_bar,
|
|
739 |
self.statusbar_show,
|
|
740 |
),
|
|
741 |
(
|
|
742 |
"Toolbar",
|
|
743 |
None,
|
|
744 |
_("_Toolbar"),
|
|
745 |
None,
|
|
746 |
_("Toolbar"),
|
|
747 |
self.toggle_toolbar,
|
|
748 |
self.toolbar_show,
|
|
749 |
),
|
|
750 |
(
|
|
751 |
"Thumbnails Pane",
|
|
752 |
None,
|
|
753 |
_("Thumbnails _Pane"),
|
|
754 |
None,
|
|
755 |
_("Thumbnails Pane"),
|
|
756 |
self.toggle_thumbpane,
|
|
757 |
self.thumbpane_show,
|
|
758 |
),
|
|
759 |
)
|
|
760 |
|
|
761 |
# Populate keys[]:
|
|
762 |
self.keys = []
|
|
763 |
for i in range(len(actions)):
|
|
764 |
if len(actions[i]) > 3:
|
|
765 |
if actions[i][3] != None:
|
|
766 |
self.keys.append([actions[i][4], actions[i][3]])
|
|
767 |
|
|
768 |
uiDescription = """
|
418 | 769 |
<ui>
|
419 | 770 |
<popup name="Popup">
|
420 | 771 |
<menuitem action="Next Image"/>
|
|
532 | 883 |
</ui>
|
533 | 884 |
"""
|
534 | 885 |
|
535 | |
# Create interface
|
536 | |
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
537 | |
self.update_title()
|
538 | |
icon_path = self.find_path('mirage.png')
|
539 | |
try:
|
540 | |
gtk.window_set_default_icon_from_file(icon_path)
|
541 | |
except:
|
542 | |
pass
|
543 | |
vbox = gtk.VBox(False, 0)
|
544 | |
self.UIManager = gtk.UIManager()
|
545 | |
actionGroup = gtk.ActionGroup('Actions')
|
546 | |
actionGroup.add_actions(actions)
|
547 | |
actionGroup.add_toggle_actions(toggle_actions)
|
548 | |
self.UIManager.insert_action_group(actionGroup, 0)
|
549 | |
self.UIManager.add_ui_from_string(uiDescription)
|
550 | |
self.refresh_custom_actions_menu()
|
551 | |
self.refresh_recent_files_menu()
|
552 | |
self.window.add_accel_group(self.UIManager.get_accel_group())
|
553 | |
self.menubar = self.UIManager.get_widget('/MainMenu')
|
554 | |
vbox.pack_start(self.menubar, False, False, 0)
|
555 | |
self.toolbar = self.UIManager.get_widget('/MainToolbar')
|
556 | |
vbox.pack_start(self.toolbar, False, False, 0)
|
557 | |
self.layout = gtk.Layout()
|
558 | |
self.vscroll = gtk.VScrollbar(None)
|
559 | |
self.vscroll.set_adjustment(self.layout.get_vadjustment())
|
560 | |
self.hscroll = gtk.HScrollbar(None)
|
561 | |
self.hscroll.set_adjustment(self.layout.get_hadjustment())
|
562 | |
self.table = gtk.Table(3, 2, False)
|
563 | |
|
564 | |
self.thumblist = gtk.ListStore(gtk.gdk.Pixbuf)
|
565 | |
self.thumbpane = gtk.TreeView(self.thumblist)
|
566 | |
self.thumbcolumn = gtk.TreeViewColumn(None)
|
567 | |
self.thumbcell = gtk.CellRendererPixbuf()
|
568 | |
self.thumbcolumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
569 | |
self.thumbpane_set_size()
|
570 | |
self.thumbpane.append_column(self.thumbcolumn)
|
571 | |
self.thumbcolumn.pack_start(self.thumbcell, True)
|
572 | |
self.thumbcolumn.set_attributes(self.thumbcell, pixbuf=0)
|
573 | |
self.thumbpane.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
574 | |
self.thumbpane.set_headers_visible(False)
|
575 | |
self.thumbpane.set_property('can-focus', False)
|
576 | |
self.thumbscroll = gtk.ScrolledWindow()
|
577 | |
self.thumbscroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
578 | |
self.thumbscroll.add(self.thumbpane)
|
579 | |
|
580 | |
self.table.attach(self.thumbscroll, 0, 1, 0, 1, 0, gtk.FILL|gtk.EXPAND, 0, 0)
|
581 | |
self.table.attach(self.layout, 1, 2, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
582 | |
self.table.attach(self.hscroll, 1, 2, 1, 2, gtk.FILL|gtk.SHRINK, gtk.FILL|gtk.SHRINK, 0, 0)
|
583 | |
self.table.attach(self.vscroll, 2, 3, 0, 1, gtk.FILL|gtk.SHRINK, gtk.FILL|gtk.SHRINK, 0, 0)
|
584 | |
vbox.pack_start(self.table, True, True, 0)
|
585 | |
if not bgcolor_found:
|
586 | |
self.bgcolor = gtk.gdk.Color(0, 0, 0) # Default to black
|
587 | |
if self.simple_bgcolor:
|
588 | |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
589 | |
else:
|
590 | |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
591 | |
self.imageview = gtk.Image()
|
592 | |
self.layout.add(self.imageview)
|
593 | |
|
594 | |
self.statusbar = gtk.Statusbar()
|
595 | |
self.statusbar2 = gtk.Statusbar()
|
596 | |
self.statusbar.set_has_resize_grip(False)
|
597 | |
self.statusbar2.set_has_resize_grip(True)
|
598 | |
self.statusbar2.set_size_request(200, -1)
|
599 | |
hbox_statusbar = gtk.HBox()
|
600 | |
hbox_statusbar.pack_start(self.statusbar, expand=True)
|
601 | |
hbox_statusbar.pack_start(self.statusbar2, expand=False)
|
602 | |
vbox.pack_start(hbox_statusbar, False, False, 0)
|
603 | |
self.window.add(vbox)
|
604 | |
self.window.set_property('allow-shrink', False)
|
605 | |
self.window.set_default_size(width,height)
|
606 | |
|
607 | |
# Slideshow control:
|
608 | |
self.slideshow_window = gtk.Window(gtk.WINDOW_POPUP)
|
609 | |
self.slideshow_controls = gtk.HBox()
|
610 | |
self.ss_back = gtk.Button()
|
611 | |
self.ss_back.add(gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON))
|
612 | |
self.ss_back.set_property('can-focus', False)
|
613 | |
self.ss_back.connect('clicked', self.goto_prev_image)
|
614 | |
self.ss_start = gtk.Button("", gtk.STOCK_MEDIA_PLAY)
|
615 | |
self.ss_start.get_child().get_child().get_children()[1].set_text('')
|
616 | |
self.ss_start.set_property('can-focus', False)
|
617 | |
self.ss_start.connect('clicked', self.toggle_slideshow)
|
618 | |
self.ss_stop = gtk.Button("", gtk.STOCK_MEDIA_STOP)
|
619 | |
self.ss_stop.get_child().get_child().get_children()[1].set_text('')
|
620 | |
self.ss_stop.set_property('can-focus', False)
|
621 | |
self.ss_stop.connect('clicked', self.toggle_slideshow)
|
622 | |
self.ss_forward = gtk.Button("", gtk.STOCK_GO_FORWARD)
|
623 | |
self.ss_forward.get_child().get_child().get_children()[1].set_text('')
|
624 | |
self.ss_forward.set_property('can-focus', False)
|
625 | |
self.ss_forward.connect('clicked', self.goto_next_image)
|
626 | |
self.slideshow_controls.pack_start(self.ss_back, False, False, 0)
|
627 | |
self.slideshow_controls.pack_start(self.ss_start, False, False, 0)
|
628 | |
self.slideshow_controls.pack_start(self.ss_stop, False, False, 0)
|
629 | |
self.slideshow_controls.pack_start(self.ss_forward, False, False, 0)
|
630 | |
self.slideshow_window.add(self.slideshow_controls)
|
631 | |
if self.simple_bgcolor:
|
632 | |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, None)
|
633 | |
else:
|
634 | |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
635 | |
self.slideshow_window2 = gtk.Window(gtk.WINDOW_POPUP)
|
636 | |
self.slideshow_controls2 = gtk.HBox()
|
637 | |
try:
|
638 | |
self.ss_exit = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
|
639 | |
self.ss_exit.get_child().get_child().get_children()[1].set_text('')
|
640 | |
except:
|
641 | |
self.ss_exit = gtk.Button()
|
642 | |
self.ss_exit.set_image(gtk.image_new_from_stock('leave-fullscreen', gtk.ICON_SIZE_MENU))
|
643 | |
self.ss_exit.set_property('can-focus', False)
|
644 | |
self.ss_exit.connect('clicked', self.leave_fullscreen)
|
645 | |
self.ss_randomize = gtk.ToggleButton()
|
646 | |
icon_path = self.find_path('stock_shuffle.png')
|
647 | |
try:
|
648 | |
pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
|
649 | |
iconset = gtk.IconSet(pixbuf)
|
650 | |
factory.add('stock-shuffle', iconset)
|
651 | |
factory.add_default()
|
652 | |
self.ss_randomize.set_image(gtk.image_new_from_stock('stock-shuffle', gtk.ICON_SIZE_MENU))
|
653 | |
except:
|
654 | |
self.ss_randomize.set_label("Rand")
|
655 | |
self.ss_randomize.connect('toggled', self.random_changed)
|
656 | |
|
657 | |
spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1,100, 0)
|
658 | |
self.ss_delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
|
659 | |
self.ss_delayspin.set_numeric(True)
|
660 | |
self.ss_delayspin.connect('changed', self.delay_changed)
|
661 | |
self.slideshow_controls2.pack_start(self.ss_randomize, False, False, 0)
|
662 | |
self.slideshow_controls2.pack_start(self.ss_delayspin, False, False, 0)
|
663 | |
self.slideshow_controls2.pack_start(self.ss_exit, False, False, 0)
|
664 | |
self.slideshow_window2.add(self.slideshow_controls2)
|
665 | |
if self.simple_bgcolor:
|
666 | |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, None)
|
667 | |
else:
|
668 | |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
669 | |
|
670 | |
# Connect signals
|
671 | |
self.window.connect("delete_event", self.delete_event)
|
672 | |
self.window.connect("destroy", self.destroy)
|
673 | |
self.window.connect("size-allocate", self.window_resized)
|
674 | |
self.window.connect('key-press-event', self.topwindow_keypress)
|
675 | |
self.toolbar.connect('focus', self.toolbar_focused)
|
676 | |
self.layout.drag_dest_set(gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, [("text/uri-list", 0, 80)], gtk.gdk.ACTION_DEFAULT)
|
677 | |
self.layout.connect('drag_motion', self.motion_cb)
|
678 | |
self.layout.connect('drag_data_received', self.drop_cb)
|
679 | |
self.layout.add_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.SCROLL_MASK)
|
680 | |
self.layout.connect("scroll-event", self.mousewheel_scrolled)
|
681 | |
self.layout.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.KEY_PRESS_MASK)
|
682 | |
self.layout.connect("button_press_event", self.button_pressed)
|
683 | |
self.layout.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
|
684 | |
self.layout.connect("motion-notify-event", self.mouse_moved)
|
685 | |
self.layout.connect("button-release-event", self.button_released)
|
686 | |
self.imageview.connect("expose-event", self.expose_event)
|
687 | |
self.thumb_sel_handler = self.thumbpane.get_selection().connect('changed', self.thumbpane_selection_changed)
|
688 | |
self.thumb_scroll_handler = self.thumbscroll.get_vscrollbar().connect("value-changed", self.thumbpane_scrolled)
|
689 | |
|
690 | |
# Since GNOME does its own thing for the toolbar style...
|
691 | |
# Requires gnome-python installed to work (but optional)
|
692 | |
try:
|
693 | |
client = gconf.client_get_default()
|
694 | |
style = client.get_string('/desktop/gnome/interface/toolbar_style')
|
695 | |
if style == "both":
|
696 | |
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
697 | |
elif style == "both-horiz":
|
698 | |
self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
|
699 | |
elif style == "icons":
|
700 | |
self.toolbar.set_style(gtk.TOOLBAR_ICONS)
|
701 | |
elif style == "text":
|
702 | |
self.toolbar.set_style(gtk.TOOLBAR_TEXT)
|
703 | |
client.add_dir("/desktop/gnome/interface", gconf.CLIENT_PRELOAD_NONE)
|
704 | |
client.notify_add("/desktop/gnome/interface/toolbar_style", self.gconf_key_changed)
|
705 | |
except:
|
706 | |
pass
|
707 | |
|
708 | |
# Show GUI:
|
709 | |
if not self.toolbar_show:
|
710 | |
self.toolbar.set_property('visible', False)
|
711 | |
self.toolbar.set_no_show_all(True)
|
712 | |
if not self.statusbar_show:
|
713 | |
self.statusbar.set_property('visible', False)
|
714 | |
self.statusbar.set_no_show_all(True)
|
715 | |
self.statusbar2.set_property('visible', False)
|
716 | |
self.statusbar2.set_no_show_all(True)
|
717 | |
if not self.thumbpane_show:
|
718 | |
self.thumbscroll.set_property('visible', False)
|
719 | |
self.thumbscroll.set_no_show_all(True)
|
720 | |
self.hscroll.set_no_show_all(True)
|
721 | |
self.vscroll.set_no_show_all(True)
|
722 | |
go_into_fullscreen = False
|
723 | |
if opts != []:
|
724 | |
for o, a in opts:
|
725 | |
if (o in ("-f", "--fullscreen")) or ((o in ("-s", "--slideshow")) and self.slideshow_in_fullscreen):
|
726 | |
go_into_fullscreen = True
|
727 | |
if go_into_fullscreen or self.start_in_fullscreen:
|
728 | |
self.enter_fullscreen(None)
|
729 | |
self.statusbar.set_no_show_all(True)
|
730 | |
self.statusbar2.set_no_show_all(True)
|
731 | |
self.toolbar.set_no_show_all(True)
|
732 | |
self.menubar.set_no_show_all(True)
|
733 | |
self.thumbscroll.set_no_show_all(True)
|
734 | |
self.window.show_all()
|
735 | |
self.ss_exit.set_size_request(self.ss_start.size_request()[0], self.ss_stop.size_request()[1])
|
736 | |
self.ss_randomize.set_size_request(self.ss_start.size_request()[0], -1)
|
737 | |
self.ss_start.set_size_request(self.ss_start.size_request()[0]*2, -1)
|
738 | |
self.ss_stop.set_size_request(self.ss_stop.size_request()[0]*2, -1)
|
739 | |
self.UIManager.get_widget('/Popup/Exit Full Screen').hide()
|
740 | |
self.layout.set_flags(gtk.CAN_FOCUS)
|
741 | |
self.window.set_focus(self.layout)
|
742 | |
|
743 | |
#sets the visibility of some menu entries
|
744 | |
self.set_slideshow_sensitivities()
|
745 | |
self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
|
746 | |
if opts != []:
|
747 | |
for o, a in opts:
|
748 | |
if o in ("-f", "--fullscreen"):
|
749 | |
self.UIManager.get_widget('/Popup/Exit Full Screen').show()
|
750 | |
|
751 | |
# If arguments (filenames) were passed, try to open them:
|
752 | |
self.image_list = []
|
753 | |
if args != []:
|
754 | |
for i in range(len(args)):
|
755 | |
args[i] = urllib.request.url2pathname(args[i])
|
756 | |
self.expand_filelist_and_load_image(args)
|
757 | |
else:
|
758 | |
self.set_go_sensitivities(False)
|
759 | |
self.set_image_sensitivities(False)
|
760 | |
|
761 | |
if opts != []:
|
762 | |
for o, a in opts:
|
763 | |
if o in ("-s", "--slideshow"):
|
764 | |
self.toggle_slideshow(None)
|
765 | |
|
766 | |
def refresh_recent_files_menu(self):
|
767 | |
if self.merge_id_recent:
|
768 | |
self.UIManager.remove_ui(self.merge_id_recent)
|
769 | |
if self.actionGroupRecent:
|
770 | |
self.UIManager.remove_action_group(self.actionGroupRecent)
|
771 | |
self.actionGroupRecent = None
|
772 | |
self.actionGroupRecent = gtk.ActionGroup('RecentFiles')
|
773 | |
self.UIManager.ensure_update()
|
774 | |
for i in range(len(self.recentfiles)):
|
775 | |
if len(self.recentfiles[i]) > 0:
|
776 | |
filename = self.recentfiles[i].split("/")[-1]
|
777 | |
if len(filename) > 0:
|
778 | |
if len(filename) > 27:
|
779 | |
# Replace end of file name (excluding extension) with ..
|
780 | |
try:
|
781 | |
menu_name = filename[:25] + '..' + os.path.splitext(filename)[1]
|
782 | |
except:
|
783 | |
menu_name = filename[0]
|
784 | |
else:
|
785 | |
menu_name = filename
|
786 | |
menu_name = menu_name.replace('_','__')
|
787 | |
action = [(str(i), None, menu_name, '<Alt>' + str(i+1), None, self.recent_action_click)]
|
788 | |
self.actionGroupRecent.add_actions(action)
|
789 | |
uiDescription = """
|
|
886 |
# Create interface
|
|
887 |
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
|
888 |
self.update_title()
|
|
889 |
icon_path = self.find_path("mirage.png")
|
|
890 |
try:
|
|
891 |
gtk.window_set_default_icon_from_file(icon_path)
|
|
892 |
except:
|
|
893 |
pass
|
|
894 |
vbox = gtk.VBox(False, 0)
|
|
895 |
self.UIManager = gtk.UIManager()
|
|
896 |
actionGroup = gtk.ActionGroup("Actions")
|
|
897 |
actionGroup.add_actions(actions)
|
|
898 |
actionGroup.add_toggle_actions(toggle_actions)
|
|
899 |
self.UIManager.insert_action_group(actionGroup, 0)
|
|
900 |
self.UIManager.add_ui_from_string(uiDescription)
|
|
901 |
self.refresh_custom_actions_menu()
|
|
902 |
self.refresh_recent_files_menu()
|
|
903 |
self.window.add_accel_group(self.UIManager.get_accel_group())
|
|
904 |
self.menubar = self.UIManager.get_widget("/MainMenu")
|
|
905 |
vbox.pack_start(self.menubar, False, False, 0)
|
|
906 |
self.toolbar = self.UIManager.get_widget("/MainToolbar")
|
|
907 |
vbox.pack_start(self.toolbar, False, False, 0)
|
|
908 |
self.layout = gtk.Layout()
|
|
909 |
self.vscroll = gtk.VScrollbar(None)
|
|
910 |
self.vscroll.set_adjustment(self.layout.get_vadjustment())
|
|
911 |
self.hscroll = gtk.HScrollbar(None)
|
|
912 |
self.hscroll.set_adjustment(self.layout.get_hadjustment())
|
|
913 |
self.table = gtk.Table(3, 2, False)
|
|
914 |
|
|
915 |
self.thumblist = gtk.ListStore(gtk.gdk.Pixbuf)
|
|
916 |
self.thumbpane = gtk.TreeView(self.thumblist)
|
|
917 |
self.thumbcolumn = gtk.TreeViewColumn(None)
|
|
918 |
self.thumbcell = gtk.CellRendererPixbuf()
|
|
919 |
self.thumbcolumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
|
920 |
self.thumbpane_set_size()
|
|
921 |
self.thumbpane.append_column(self.thumbcolumn)
|
|
922 |
self.thumbcolumn.pack_start(self.thumbcell, True)
|
|
923 |
self.thumbcolumn.set_attributes(self.thumbcell, pixbuf=0)
|
|
924 |
self.thumbpane.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
|
925 |
self.thumbpane.set_headers_visible(False)
|
|
926 |
self.thumbpane.set_property("can-focus", False)
|
|
927 |
self.thumbscroll = gtk.ScrolledWindow()
|
|
928 |
self.thumbscroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
|
929 |
self.thumbscroll.add(self.thumbpane)
|
|
930 |
|
|
931 |
self.table.attach(self.thumbscroll, 0, 1, 0, 1, 0, gtk.FILL | gtk.EXPAND, 0, 0)
|
|
932 |
self.table.attach(
|
|
933 |
self.layout, 1, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
934 |
)
|
|
935 |
self.table.attach(
|
|
936 |
self.hscroll, 1, 2, 1, 2, gtk.FILL | gtk.SHRINK, gtk.FILL | gtk.SHRINK, 0, 0
|
|
937 |
)
|
|
938 |
self.table.attach(
|
|
939 |
self.vscroll, 2, 3, 0, 1, gtk.FILL | gtk.SHRINK, gtk.FILL | gtk.SHRINK, 0, 0
|
|
940 |
)
|
|
941 |
vbox.pack_start(self.table, True, True, 0)
|
|
942 |
if not bgcolor_found:
|
|
943 |
self.bgcolor = gtk.gdk.Color(0, 0, 0) # Default to black
|
|
944 |
if self.simple_bgcolor:
|
|
945 |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
|
946 |
else:
|
|
947 |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
948 |
self.imageview = gtk.Image()
|
|
949 |
self.layout.add(self.imageview)
|
|
950 |
|
|
951 |
self.statusbar = gtk.Statusbar()
|
|
952 |
self.statusbar2 = gtk.Statusbar()
|
|
953 |
self.statusbar.set_has_resize_grip(False)
|
|
954 |
self.statusbar2.set_has_resize_grip(True)
|
|
955 |
self.statusbar2.set_size_request(200, -1)
|
|
956 |
hbox_statusbar = gtk.HBox()
|
|
957 |
hbox_statusbar.pack_start(self.statusbar, expand=True)
|
|
958 |
hbox_statusbar.pack_start(self.statusbar2, expand=False)
|
|
959 |
vbox.pack_start(hbox_statusbar, False, False, 0)
|
|
960 |
self.window.add(vbox)
|
|
961 |
self.window.set_property("allow-shrink", False)
|
|
962 |
self.window.set_default_size(width, height)
|
|
963 |
|
|
964 |
# Slideshow control:
|
|
965 |
self.slideshow_window = gtk.Window(gtk.WINDOW_POPUP)
|
|
966 |
self.slideshow_controls = gtk.HBox()
|
|
967 |
self.ss_back = gtk.Button()
|
|
968 |
self.ss_back.add(
|
|
969 |
gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
|
|
970 |
)
|
|
971 |
self.ss_back.set_property("can-focus", False)
|
|
972 |
self.ss_back.connect("clicked", self.goto_prev_image)
|
|
973 |
self.ss_start = gtk.Button("", gtk.STOCK_MEDIA_PLAY)
|
|
974 |
self.ss_start.get_child().get_child().get_children()[1].set_text("")
|
|
975 |
self.ss_start.set_property("can-focus", False)
|
|
976 |
self.ss_start.connect("clicked", self.toggle_slideshow)
|
|
977 |
self.ss_stop = gtk.Button("", gtk.STOCK_MEDIA_STOP)
|
|
978 |
self.ss_stop.get_child().get_child().get_children()[1].set_text("")
|
|
979 |
self.ss_stop.set_property("can-focus", False)
|
|
980 |
self.ss_stop.connect("clicked", self.toggle_slideshow)
|
|
981 |
self.ss_forward = gtk.Button("", gtk.STOCK_GO_FORWARD)
|
|
982 |
self.ss_forward.get_child().get_child().get_children()[1].set_text("")
|
|
983 |
self.ss_forward.set_property("can-focus", False)
|
|
984 |
self.ss_forward.connect("clicked", self.goto_next_image)
|
|
985 |
self.slideshow_controls.pack_start(self.ss_back, False, False, 0)
|
|
986 |
self.slideshow_controls.pack_start(self.ss_start, False, False, 0)
|
|
987 |
self.slideshow_controls.pack_start(self.ss_stop, False, False, 0)
|
|
988 |
self.slideshow_controls.pack_start(self.ss_forward, False, False, 0)
|
|
989 |
self.slideshow_window.add(self.slideshow_controls)
|
|
990 |
if self.simple_bgcolor:
|
|
991 |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, None)
|
|
992 |
else:
|
|
993 |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
994 |
self.slideshow_window2 = gtk.Window(gtk.WINDOW_POPUP)
|
|
995 |
self.slideshow_controls2 = gtk.HBox()
|
|
996 |
try:
|
|
997 |
self.ss_exit = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
|
|
998 |
self.ss_exit.get_child().get_child().get_children()[1].set_text("")
|
|
999 |
except:
|
|
1000 |
self.ss_exit = gtk.Button()
|
|
1001 |
self.ss_exit.set_image(
|
|
1002 |
gtk.image_new_from_stock("leave-fullscreen", gtk.ICON_SIZE_MENU)
|
|
1003 |
)
|
|
1004 |
self.ss_exit.set_property("can-focus", False)
|
|
1005 |
self.ss_exit.connect("clicked", self.leave_fullscreen)
|
|
1006 |
self.ss_randomize = gtk.ToggleButton()
|
|
1007 |
icon_path = self.find_path("stock_shuffle.png")
|
|
1008 |
try:
|
|
1009 |
pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
|
|
1010 |
iconset = gtk.IconSet(pixbuf)
|
|
1011 |
factory.add("stock-shuffle", iconset)
|
|
1012 |
factory.add_default()
|
|
1013 |
self.ss_randomize.set_image(
|
|
1014 |
gtk.image_new_from_stock("stock-shuffle", gtk.ICON_SIZE_MENU)
|
|
1015 |
)
|
|
1016 |
except:
|
|
1017 |
self.ss_randomize.set_label("Rand")
|
|
1018 |
self.ss_randomize.connect("toggled", self.random_changed)
|
|
1019 |
|
|
1020 |
spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1, 100, 0)
|
|
1021 |
self.ss_delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
|
|
1022 |
self.ss_delayspin.set_numeric(True)
|
|
1023 |
self.ss_delayspin.connect("changed", self.delay_changed)
|
|
1024 |
self.slideshow_controls2.pack_start(self.ss_randomize, False, False, 0)
|
|
1025 |
self.slideshow_controls2.pack_start(self.ss_delayspin, False, False, 0)
|
|
1026 |
self.slideshow_controls2.pack_start(self.ss_exit, False, False, 0)
|
|
1027 |
self.slideshow_window2.add(self.slideshow_controls2)
|
|
1028 |
if self.simple_bgcolor:
|
|
1029 |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, None)
|
|
1030 |
else:
|
|
1031 |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
1032 |
|
|
1033 |
# Connect signals
|
|
1034 |
self.window.connect("delete_event", self.delete_event)
|
|
1035 |
self.window.connect("destroy", self.destroy)
|
|
1036 |
self.window.connect("size-allocate", self.window_resized)
|
|
1037 |
self.window.connect("key-press-event", self.topwindow_keypress)
|
|
1038 |
self.toolbar.connect("focus", self.toolbar_focused)
|
|
1039 |
self.layout.drag_dest_set(
|
|
1040 |
gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP,
|
|
1041 |
[("text/uri-list", 0, 80)],
|
|
1042 |
gtk.gdk.ACTION_DEFAULT,
|
|
1043 |
)
|
|
1044 |
self.layout.connect("drag_motion", self.motion_cb)
|
|
1045 |
self.layout.connect("drag_data_received", self.drop_cb)
|
|
1046 |
self.layout.add_events(
|
|
1047 |
gtk.gdk.KEY_PRESS_MASK
|
|
1048 |
| gtk.gdk.POINTER_MOTION_MASK
|
|
1049 |
| gtk.gdk.BUTTON_PRESS_MASK
|
|
1050 |
| gtk.gdk.BUTTON_MOTION_MASK
|
|
1051 |
| gtk.gdk.SCROLL_MASK
|
|
1052 |
)
|
|
1053 |
self.layout.connect("scroll-event", self.mousewheel_scrolled)
|
|
1054 |
self.layout.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.KEY_PRESS_MASK)
|
|
1055 |
self.layout.connect("button_press_event", self.button_pressed)
|
|
1056 |
self.layout.add_events(
|
|
1057 |
gtk.gdk.POINTER_MOTION_MASK
|
|
1058 |
| gtk.gdk.POINTER_MOTION_HINT_MASK
|
|
1059 |
| gtk.gdk.BUTTON_RELEASE_MASK
|
|
1060 |
)
|
|
1061 |
self.layout.connect("motion-notify-event", self.mouse_moved)
|
|
1062 |
self.layout.connect("button-release-event", self.button_released)
|
|
1063 |
self.imageview.connect("expose-event", self.expose_event)
|
|
1064 |
self.thumb_sel_handler = self.thumbpane.get_selection().connect(
|
|
1065 |
"changed", self.thumbpane_selection_changed
|
|
1066 |
)
|
|
1067 |
self.thumb_scroll_handler = self.thumbscroll.get_vscrollbar().connect(
|
|
1068 |
"value-changed", self.thumbpane_scrolled
|
|
1069 |
)
|
|
1070 |
|
|
1071 |
# Since GNOME does its own thing for the toolbar style...
|
|
1072 |
# Requires gnome-python installed to work (but optional)
|
|
1073 |
try:
|
|
1074 |
client = gconf.client_get_default()
|
|
1075 |
style = client.get_string("/desktop/gnome/interface/toolbar_style")
|
|
1076 |
if style == "both":
|
|
1077 |
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
|
1078 |
elif style == "both-horiz":
|
|
1079 |
self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
|
|
1080 |
elif style == "icons":
|
|
1081 |
self.toolbar.set_style(gtk.TOOLBAR_ICONS)
|
|
1082 |
elif style == "text":
|
|
1083 |
self.toolbar.set_style(gtk.TOOLBAR_TEXT)
|
|
1084 |
client.add_dir("/desktop/gnome/interface", gconf.CLIENT_PRELOAD_NONE)
|
|
1085 |
client.notify_add(
|
|
1086 |
"/desktop/gnome/interface/toolbar_style", self.gconf_key_changed
|
|
1087 |
)
|
|
1088 |
except:
|
|
1089 |
pass
|
|
1090 |
|
|
1091 |
# Show GUI:
|
|
1092 |
if not self.toolbar_show:
|
|
1093 |
self.toolbar.set_property("visible", False)
|
|
1094 |
self.toolbar.set_no_show_all(True)
|
|
1095 |
if not self.statusbar_show:
|
|
1096 |
self.statusbar.set_property("visible", False)
|
|
1097 |
self.statusbar.set_no_show_all(True)
|
|
1098 |
self.statusbar2.set_property("visible", False)
|
|
1099 |
self.statusbar2.set_no_show_all(True)
|
|
1100 |
if not self.thumbpane_show:
|
|
1101 |
self.thumbscroll.set_property("visible", False)
|
|
1102 |
self.thumbscroll.set_no_show_all(True)
|
|
1103 |
self.hscroll.set_no_show_all(True)
|
|
1104 |
self.vscroll.set_no_show_all(True)
|
|
1105 |
go_into_fullscreen = False
|
|
1106 |
if opts != []:
|
|
1107 |
for o, a in opts:
|
|
1108 |
if (o in ("-f", "--fullscreen")) or (
|
|
1109 |
(o in ("-s", "--slideshow")) and self.slideshow_in_fullscreen
|
|
1110 |
):
|
|
1111 |
go_into_fullscreen = True
|
|
1112 |
if go_into_fullscreen or self.start_in_fullscreen:
|
|
1113 |
self.enter_fullscreen(None)
|
|
1114 |
self.statusbar.set_no_show_all(True)
|
|
1115 |
self.statusbar2.set_no_show_all(True)
|
|
1116 |
self.toolbar.set_no_show_all(True)
|
|
1117 |
self.menubar.set_no_show_all(True)
|
|
1118 |
self.thumbscroll.set_no_show_all(True)
|
|
1119 |
self.window.show_all()
|
|
1120 |
self.ss_exit.set_size_request(
|
|
1121 |
self.ss_start.size_request()[0], self.ss_stop.size_request()[1]
|
|
1122 |
)
|
|
1123 |
self.ss_randomize.set_size_request(self.ss_start.size_request()[0], -1)
|
|
1124 |
self.ss_start.set_size_request(self.ss_start.size_request()[0] * 2, -1)
|
|
1125 |
self.ss_stop.set_size_request(self.ss_stop.size_request()[0] * 2, -1)
|
|
1126 |
self.UIManager.get_widget("/Popup/Exit Full Screen").hide()
|
|
1127 |
self.layout.set_flags(gtk.CAN_FOCUS)
|
|
1128 |
self.window.set_focus(self.layout)
|
|
1129 |
|
|
1130 |
# sets the visibility of some menu entries
|
|
1131 |
self.set_slideshow_sensitivities()
|
|
1132 |
self.UIManager.get_widget("/MainMenu/MiscKeysMenuHidden").set_property(
|
|
1133 |
"visible", False
|
|
1134 |
)
|
|
1135 |
if opts != []:
|
|
1136 |
for o, a in opts:
|
|
1137 |
if o in ("-f", "--fullscreen"):
|
|
1138 |
self.UIManager.get_widget("/Popup/Exit Full Screen").show()
|
|
1139 |
|
|
1140 |
# If arguments (filenames) were passed, try to open them:
|
|
1141 |
self.image_list = []
|
|
1142 |
if args != []:
|
|
1143 |
for i in range(len(args)):
|
|
1144 |
args[i] = urllib.request.url2pathname(args[i])
|
|
1145 |
self.expand_filelist_and_load_image(args)
|
|
1146 |
else:
|
|
1147 |
self.set_go_sensitivities(False)
|
|
1148 |
self.set_image_sensitivities(False)
|
|
1149 |
|
|
1150 |
if opts != []:
|
|
1151 |
for o, a in opts:
|
|
1152 |
if o in ("-s", "--slideshow"):
|
|
1153 |
self.toggle_slideshow(None)
|
|
1154 |
|
|
1155 |
def refresh_recent_files_menu(self):
|
|
1156 |
if self.merge_id_recent:
|
|
1157 |
self.UIManager.remove_ui(self.merge_id_recent)
|
|
1158 |
if self.actionGroupRecent:
|
|
1159 |
self.UIManager.remove_action_group(self.actionGroupRecent)
|
|
1160 |
self.actionGroupRecent = None
|
|
1161 |
self.actionGroupRecent = gtk.ActionGroup("RecentFiles")
|
|
1162 |
self.UIManager.ensure_update()
|
|
1163 |
for i in range(len(self.recentfiles)):
|
|
1164 |
if len(self.recentfiles[i]) > 0:
|
|
1165 |
filename = self.recentfiles[i].split("/")[-1]
|
|
1166 |
if len(filename) > 0:
|
|
1167 |
if len(filename) > 27:
|
|
1168 |
# Replace end of file name (excluding extension) with ..
|
|
1169 |
try:
|
|
1170 |
menu_name = (
|
|
1171 |
filename[:25] + ".." + os.path.splitext(filename)[1]
|
|
1172 |
)
|
|
1173 |
except:
|
|
1174 |
menu_name = filename[0]
|
|
1175 |
else:
|
|
1176 |
menu_name = filename
|
|
1177 |
menu_name = menu_name.replace("_", "__")
|
|
1178 |
action = [
|
|
1179 |
(
|
|
1180 |
str(i),
|
|
1181 |
None,
|
|
1182 |
menu_name,
|
|
1183 |
"<Alt>" + str(i + 1),
|
|
1184 |
None,
|
|
1185 |
self.recent_action_click,
|
|
1186 |
)
|
|
1187 |
]
|
|
1188 |
self.actionGroupRecent.add_actions(action)
|
|
1189 |
uiDescription = """
|
790 | 1190 |
<ui>
|
791 | 1191 |
<menubar name="MainMenu">
|
792 | 1192 |
<menu action="FileMenu">
|
793 | 1193 |
<placeholder name="Recent Files">
|
794 | 1194 |
"""
|
795 | |
for i in range(len(self.recentfiles)):
|
796 | |
if len(self.recentfiles[i]) > 0:
|
797 | |
uiDescription = uiDescription + """<menuitem action=\"""" + str(i) + """\"/>"""
|
798 | |
uiDescription = uiDescription + """</placeholder></menu></menubar></ui>"""
|
799 | |
self.merge_id_recent = self.UIManager.add_ui_from_string(uiDescription)
|
800 | |
self.UIManager.insert_action_group(self.actionGroupRecent, 0)
|
801 | |
self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
|
802 | |
|
803 | |
def refresh_custom_actions_menu(self):
|
804 | |
if self.merge_id:
|
805 | |
self.UIManager.remove_ui(self.merge_id)
|
806 | |
if self.actionGroupCustom:
|
807 | |
self.UIManager.remove_action_group(self.actionGroupCustom)
|
808 | |
self.actionGroupCustom = None
|
809 | |
self.actionGroupCustom = gtk.ActionGroup('CustomActions')
|
810 | |
self.UIManager.ensure_update()
|
811 | |
for i in range(len(self.action_names)):
|
812 | |
action = [(self.action_names[i], None, self.action_names[i], self.action_shortcuts[i], None, self.custom_action_click)]
|
813 | |
self.actionGroupCustom.add_actions(action)
|
814 | |
uiDescription = """
|
|
1195 |
for i in range(len(self.recentfiles)):
|
|
1196 |
if len(self.recentfiles[i]) > 0:
|
|
1197 |
uiDescription = (
|
|
1198 |
uiDescription + """<menuitem action=\"""" + str(i) + """\"/>"""
|
|
1199 |
)
|
|
1200 |
uiDescription = uiDescription + """</placeholder></menu></menubar></ui>"""
|
|
1201 |
self.merge_id_recent = self.UIManager.add_ui_from_string(uiDescription)
|
|
1202 |
self.UIManager.insert_action_group(self.actionGroupRecent, 0)
|
|
1203 |
self.UIManager.get_widget("/MainMenu/MiscKeysMenuHidden").set_property(
|
|
1204 |
"visible", False
|
|
1205 |
)
|
|
1206 |
|
|
1207 |
def refresh_custom_actions_menu(self):
|
|
1208 |
if self.merge_id:
|
|
1209 |
self.UIManager.remove_ui(self.merge_id)
|
|
1210 |
if self.actionGroupCustom:
|
|
1211 |
self.UIManager.remove_action_group(self.actionGroupCustom)
|
|
1212 |
self.actionGroupCustom = None
|
|
1213 |
self.actionGroupCustom = gtk.ActionGroup("CustomActions")
|
|
1214 |
self.UIManager.ensure_update()
|
|
1215 |
for i in range(len(self.action_names)):
|
|
1216 |
action = [
|
|
1217 |
(
|
|
1218 |
self.action_names[i],
|
|
1219 |
None,
|
|
1220 |
self.action_names[i],
|
|
1221 |
self.action_shortcuts[i],
|
|
1222 |
None,
|
|
1223 |
self.custom_action_click,
|
|
1224 |
)
|
|
1225 |
]
|
|
1226 |
self.actionGroupCustom.add_actions(action)
|
|
1227 |
uiDescription = """
|
815 | 1228 |
<ui>
|
816 | 1229 |
<menubar name="MainMenu">
|
817 | 1230 |
<menu action="EditMenu">
|
818 | 1231 |
<menu action="ActionSubMenu">
|
819 | 1232 |
"""
|
820 | |
for i in range(len(self.action_names)):
|
821 | |
uiDescription = uiDescription + """<menuitem action=\"""" + self.action_names[len(self.action_names)-i-1].replace('&','&') + """\" position="top"/>"""
|
822 | |
uiDescription = uiDescription + """</menu></menu></menubar></ui>"""
|
823 | |
self.merge_id = self.UIManager.add_ui_from_string(uiDescription)
|
824 | |
self.UIManager.insert_action_group(self.actionGroupCustom, 0)
|
825 | |
self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
|
826 | |
|
827 | |
def thumbpane_update_images(self, clear_first=False, force_upto_imgnum=-1):
|
828 | |
self.stop_now = False
|
829 | |
# When first populating the thumbpane, make sure we go up to at least
|
830 | |
# force_upto_imgnum so that we can show this image selected:
|
831 | |
if clear_first:
|
832 | |
self.thumbpane_clear_list()
|
833 | |
# Load all images up to the bottom ofo the visible thumbpane rect:
|
834 | |
rect = self.thumbpane.get_visible_rect()
|
835 | |
bottom_coord = rect.y + rect.height + self.thumbnail_size
|
836 | |
if bottom_coord > self.thumbpane_bottom_coord_loaded:
|
837 | |
self.thumbpane_bottom_coord_loaded = bottom_coord
|
838 | |
# update images:
|
839 | |
if not self.thumbpane_updating:
|
840 | |
thread = threading.Thread(target=self.thumbpane_update_pending_images, args=(force_upto_imgnum, None))
|
841 | |
thread.setDaemon(True)
|
842 | |
thread.start()
|
843 | |
|
844 | |
def thumbpane_create_dir(self):
|
845 | |
if not os.path.exists(os.path.expanduser('~/.thumbnails/')):
|
846 | |
os.mkdir(os.path.expanduser('~/.thumbnails/'))
|
847 | |
if not os.path.exists(os.path.expanduser('~/.thumbnails/normal/')):
|
848 | |
os.mkdir(os.path.expanduser('~/.thumbnails/normal/'))
|
849 | |
|
850 | |
def thumbpane_update_pending_images(self, force_upto_imgnum, foo):
|
851 | |
self.thumbpane_updating = True
|
852 | |
self.thumbpane_create_dir()
|
853 | |
# Check to see if any images need their thumbnails generated.
|
854 | |
curr_coord = 0
|
855 | |
imgnum = 0
|
856 | |
while curr_coord < self.thumbpane_bottom_coord_loaded or imgnum <= force_upto_imgnum:
|
857 | |
if self.closing_app or self.stop_now or not self.thumbpane_show:
|
858 | |
break
|
859 | |
if imgnum >= len(self.image_list):
|
860 | |
break
|
861 | |
self.thumbpane_set_image(self.image_list[imgnum], imgnum)
|
862 | |
curr_coord += self.thumbpane.get_background_area((imgnum,),self.thumbcolumn).height
|
863 | |
if force_upto_imgnum == imgnum:
|
864 | |
# Verify that the user hasn't switched images while we're loading thumbnails:
|
865 | |
if force_upto_imgnum == self.curr_img_in_list:
|
866 | |
gobject.idle_add(self.thumbpane_select, force_upto_imgnum)
|
867 | |
imgnum += 1
|
868 | |
self.thumbpane_updating = False
|
869 | |
|
870 | |
def thumbpane_clear_list(self):
|
871 | |
self.thumbpane_bottom_coord_loaded = 0
|
872 | |
self.thumbscroll.get_vscrollbar().handler_block(self.thumb_scroll_handler)
|
873 | |
self.thumblist.clear()
|
874 | |
self.thumbscroll.get_vscrollbar().handler_unblock(self.thumb_scroll_handler)
|
875 | |
for image in self.image_list:
|
876 | |
blank_pix = self.get_blank_pix_for_image(image)
|
877 | |
self.thumblist.append([blank_pix])
|
878 | |
self.thumbnail_loaded = [False]*len(self.image_list)
|
879 | |
|
880 | |
def thumbpane_set_image(self, image_name, imgnum, force_update=False):
|
881 | |
if self.thumbpane_show:
|
882 | |
if not self.thumbnail_loaded[imgnum] or force_update:
|
883 | |
filename, thumbfile = self.thumbnail_get_name(image_name)
|
884 | |
pix = self.thumbpane_get_pixbuf(thumbfile, filename, force_update)
|
885 | |
if pix:
|
886 | |
if self.thumbnail_size != 128:
|
887 | |
# 128 is the size of the saved thumbnail, so convert if different:
|
888 | |
pix, image_width, image_height = self.get_pixbuf_of_size(pix, self.thumbnail_size, gtk.gdk.INTERP_TILES)
|
889 | |
self.thumbnail_loaded[imgnum] = True
|
890 | |
self.thumbscroll.get_vscrollbar().handler_block(self.thumb_scroll_handler)
|
891 | |
pix = self.pixbuf_add_border(pix)
|
892 | |
try:
|
893 | |
self.thumblist[imgnum] = [pix]
|
894 | |
except:
|
895 | |
pass
|
896 | |
self.thumbscroll.get_vscrollbar().handler_unblock(self.thumb_scroll_handler)
|
897 | |
|
898 | |
def thumbnail_get_name(self, image_name):
|
899 | |
filename = os.path.expanduser('file://' + image_name)
|
900 | |
uriname = os.path.expanduser('file://' + urllib.request.pathname2url(image_name))
|
901 | |
if HAS_HASHLIB:
|
902 | |
m = hashlib.md5()
|
903 | |
else:
|
904 | |
m = md5.new()
|
905 | |
m.update(uriname)
|
906 | |
mhex = m.hexdigest()
|
907 | |
mhex_filename = os.path.expanduser('~/.thumbnails/normal/' + mhex + '.png')
|
908 | |
return filename, mhex_filename
|
909 | |
|
910 | |
def thumbpane_get_pixbuf(self, thumb_url, image_url, force_generation):
|
911 | |
# Returns a valid pixbuf or None if a pixbuf cannot be generated. Tries to re-use
|
912 | |
# a thumbnail from ~/.thumbails/normal/, otherwise generates one with the
|
913 | |
# XDG filename: md5(file:///full/path/to/image).png
|
914 | |
imgfile = image_url
|
915 | |
if imgfile[:7] == 'file://':
|
916 | |
imgfile = imgfile[7:]
|
917 | |
try:
|
918 | |
if os.path.exists(thumb_url) and not force_generation:
|
919 | |
pix = gtk.gdk.pixbuf_new_from_file(thumb_url)
|
920 | |
pix_mtime = pix.get_option('tEXt::Thumb::MTime')
|
921 | |
if pix_mtime:
|
922 | |
st = os.stat(imgfile)
|
923 | |
file_mtime = str(st[stat.ST_MTIME])
|
924 | |
# If the mtimes match, we're good. if not, regenerate the thumbnail..
|
925 | |
if pix_mtime == file_mtime:
|
926 | |
return pix
|
927 | |
# Create the 128x128 thumbnail:
|
928 | |
uri = 'file://' + urllib.request.pathname2url(imgfile)
|
929 | |
pix = gtk.gdk.pixbuf_new_from_file(imgfile)
|
930 | |
pix, image_width, image_height = self.get_pixbuf_of_size(pix, 128, gtk.gdk.INTERP_TILES)
|
931 | |
st = os.stat(imgfile)
|
932 | |
file_mtime = str(st[stat.ST_MTIME])
|
933 | |
# Save image to .thumbnails:
|
934 | |
pix.save(thumb_url, "png", {'tEXt::Thumb::URI':uri, 'tEXt::Thumb::MTime':file_mtime, 'tEXt::Software':'Mirage' + __version__})
|
935 | |
return pix
|
936 | |
except:
|
937 | |
return None
|
938 | |
|
939 | |
def thumbpane_load_image(self, treeview, imgnum):
|
940 | |
if imgnum != self.curr_img_in_list:
|
941 | |
gobject.idle_add(self.goto_image, str(imgnum), None)
|
942 | |
|
943 | |
def thumbpane_selection_changed(self, treeview):
|
944 | |
cancel = self.autosave_image()
|
945 | |
if cancel:
|
946 | |
# Revert selection...
|
947 | |
gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
|
948 | |
return True
|
949 | |
try:
|
950 | |
model, paths = self.thumbpane.get_selection().get_selected_rows()
|
951 | |
imgnum = paths[0][0]
|
952 | |
if not self.thumbnail_loaded[imgnum]:
|
953 | |
self.thumbpane_set_image(self.image_list[imgnum], imgnum)
|
954 | |
gobject.idle_add(self.thumbpane_load_image, treeview, imgnum)
|
955 | |
except:
|
956 | |
pass
|
957 | |
|
958 | |
def thumbpane_select(self, imgnum):
|
959 | |
if self.thumbpane_show:
|
960 | |
self.thumbpane.get_selection().handler_block(self.thumb_sel_handler)
|
961 | |
try:
|
962 | |
self.thumbpane.get_selection().select_path((imgnum,))
|
963 | |
self.thumbpane.scroll_to_cell((imgnum,))
|
964 | |
except:
|
965 | |
pass
|
966 | |
self.thumbpane.get_selection().handler_unblock(self.thumb_sel_handler)
|
967 | |
|
968 | |
def thumbpane_set_size(self):
|
969 | |
self.thumbcolumn.set_fixed_width(self.thumbpane_get_size())
|
970 | |
self.window_resized(None, self.window.allocation, True)
|
971 | |
|
972 | |
def thumbpane_get_size(self):
|
973 | |
return int(self.thumbnail_size * 1.3)
|
974 | |
|
975 | |
def thumbpane_scrolled(self, range):
|
976 | |
self.thumbpane_update_images()
|
977 | |
|
978 | |
def get_blank_pix_for_image(self, image):
|
979 | |
# Sizes the "blank image" icon for the thumbpane. This will ensure that we don't
|
980 | |
# load a humongous icon for a small pix, for example, and will keep the thumbnails
|
981 | |
# from shifting around when they are actually loaded.
|
982 | |
try:
|
983 | |
info = gtk.gdk.pixbuf_get_file_info(image)
|
984 | |
imgwidth = float(info[1])
|
985 | |
imgheight = float(info[2])
|
986 | |
if imgheight > self.thumbnail_size:
|
987 | |
if imgheight > imgwidth:
|
988 | |
imgheight = self.thumbnail_size
|
989 | |
else:
|
990 | |
imgheight = (imgheight // imgwidth) * self.thumbnail_size
|
991 | |
imgheight = 2 + int(imgheight) # Account for border that will be added to thumbnails..
|
992 | |
imgwidth = self.thumbnail_size
|
993 | |
except:
|
994 | |
imgheight = 2 + self.thumbnail_size
|
995 | |
imgwidth = self.thumbnail_size
|
996 | |
blank_pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, imgwidth, imgheight)
|
997 | |
blank_pix.fill(0x00000000)
|
998 | |
imgwidth2 = int(imgheight*0.8)
|
999 | |
imgheight2 = int(imgheight*0.8)
|
1000 | |
composite_pix = self.blank_image.scale_simple(imgwidth2, imgheight2, gtk.gdk.INTERP_BILINEAR)
|
1001 | |
leftcoord = int((imgwidth - imgwidth2) // 2)
|
1002 | |
topcoord = int((imgheight - imgheight2) // 2)
|
1003 | |
composite_pix.copy_area(0, 0, imgwidth2, imgheight2, blank_pix, leftcoord, topcoord)
|
1004 | |
return blank_pix
|
1005 | |
|
1006 | |
def find_path(self, filename, exit_on_fail=True):
|
1007 | |
""" Find a pixmap or icon by looking through standard dirs.
|
|
1233 |
for i in range(len(self.action_names)):
|
|
1234 |
uiDescription = (
|
|
1235 |
uiDescription
|
|
1236 |
+ """<menuitem action=\""""
|
|
1237 |
+ self.action_names[len(self.action_names) - i - 1].replace(
|
|
1238 |
"&", "&"
|
|
1239 |
)
|
|
1240 |
+ """\" position="top"/>"""
|
|
1241 |
)
|
|
1242 |
uiDescription = uiDescription + """</menu></menu></menubar></ui>"""
|
|
1243 |
self.merge_id = self.UIManager.add_ui_from_string(uiDescription)
|
|
1244 |
self.UIManager.insert_action_group(self.actionGroupCustom, 0)
|
|
1245 |
self.UIManager.get_widget("/MainMenu/MiscKeysMenuHidden").set_property(
|
|
1246 |
"visible", False
|
|
1247 |
)
|
|
1248 |
|
|
1249 |
def thumbpane_update_images(self, clear_first=False, force_upto_imgnum=-1):
|
|
1250 |
self.stop_now = False
|
|
1251 |
# When first populating the thumbpane, make sure we go up to at least
|
|
1252 |
# force_upto_imgnum so that we can show this image selected:
|
|
1253 |
if clear_first:
|
|
1254 |
self.thumbpane_clear_list()
|
|
1255 |
# Load all images up to the bottom ofo the visible thumbpane rect:
|
|
1256 |
rect = self.thumbpane.get_visible_rect()
|
|
1257 |
bottom_coord = rect.y + rect.height + self.thumbnail_size
|
|
1258 |
if bottom_coord > self.thumbpane_bottom_coord_loaded:
|
|
1259 |
self.thumbpane_bottom_coord_loaded = bottom_coord
|
|
1260 |
# update images:
|
|
1261 |
if not self.thumbpane_updating:
|
|
1262 |
thread = threading.Thread(
|
|
1263 |
target=self.thumbpane_update_pending_images,
|
|
1264 |
args=(force_upto_imgnum, None),
|
|
1265 |
)
|
|
1266 |
thread.setDaemon(True)
|
|
1267 |
thread.start()
|
|
1268 |
|
|
1269 |
def thumbpane_create_dir(self):
|
|
1270 |
if not os.path.exists(os.path.expanduser("~/.thumbnails/")):
|
|
1271 |
os.mkdir(os.path.expanduser("~/.thumbnails/"))
|
|
1272 |
if not os.path.exists(os.path.expanduser("~/.thumbnails/normal/")):
|
|
1273 |
os.mkdir(os.path.expanduser("~/.thumbnails/normal/"))
|
|
1274 |
|
|
1275 |
def thumbpane_update_pending_images(self, force_upto_imgnum, foo):
|
|
1276 |
self.thumbpane_updating = True
|
|
1277 |
self.thumbpane_create_dir()
|
|
1278 |
# Check to see if any images need their thumbnails generated.
|
|
1279 |
curr_coord = 0
|
|
1280 |
imgnum = 0
|
|
1281 |
while (
|
|
1282 |
curr_coord < self.thumbpane_bottom_coord_loaded
|
|
1283 |
or imgnum <= force_upto_imgnum
|
|
1284 |
):
|
|
1285 |
if self.closing_app or self.stop_now or not self.thumbpane_show:
|
|
1286 |
break
|
|
1287 |
if imgnum >= len(self.image_list):
|
|
1288 |
break
|
|
1289 |
self.thumbpane_set_image(self.image_list[imgnum], imgnum)
|
|
1290 |
curr_coord += self.thumbpane.get_background_area(
|
|
1291 |
(imgnum,), self.thumbcolumn
|
|
1292 |
).height
|
|
1293 |
if force_upto_imgnum == imgnum:
|
|
1294 |
# Verify that the user hasn't switched images while we're loading thumbnails:
|
|
1295 |
if force_upto_imgnum == self.curr_img_in_list:
|
|
1296 |
gobject.idle_add(self.thumbpane_select, force_upto_imgnum)
|
|
1297 |
imgnum += 1
|
|
1298 |
self.thumbpane_updating = False
|
|
1299 |
|
|
1300 |
def thumbpane_clear_list(self):
|
|
1301 |
self.thumbpane_bottom_coord_loaded = 0
|
|
1302 |
self.thumbscroll.get_vscrollbar().handler_block(self.thumb_scroll_handler)
|
|
1303 |
self.thumblist.clear()
|
|
1304 |
self.thumbscroll.get_vscrollbar().handler_unblock(self.thumb_scroll_handler)
|
|
1305 |
for image in self.image_list:
|
|
1306 |
blank_pix = self.get_blank_pix_for_image(image)
|
|
1307 |
self.thumblist.append([blank_pix])
|
|
1308 |
self.thumbnail_loaded = [False] * len(self.image_list)
|
|
1309 |
|
|
1310 |
def thumbpane_set_image(self, image_name, imgnum, force_update=False):
|
|
1311 |
if self.thumbpane_show:
|
|
1312 |
if not self.thumbnail_loaded[imgnum] or force_update:
|
|
1313 |
filename, thumbfile = self.thumbnail_get_name(image_name)
|
|
1314 |
pix = self.thumbpane_get_pixbuf(thumbfile, filename, force_update)
|
|
1315 |
if pix:
|
|
1316 |
if self.thumbnail_size != 128:
|
|
1317 |
# 128 is the size of the saved thumbnail, so convert if different:
|
|
1318 |
pix, image_width, image_height = self.get_pixbuf_of_size(
|
|
1319 |
pix, self.thumbnail_size, gtk.gdk.INTERP_TILES
|
|
1320 |
)
|
|
1321 |
self.thumbnail_loaded[imgnum] = True
|
|
1322 |
self.thumbscroll.get_vscrollbar().handler_block(
|
|
1323 |
self.thumb_scroll_handler
|
|
1324 |
)
|
|
1325 |
pix = self.pixbuf_add_border(pix)
|
|
1326 |
try:
|
|
1327 |
self.thumblist[imgnum] = [pix]
|
|
1328 |
except:
|
|
1329 |
pass
|
|
1330 |
self.thumbscroll.get_vscrollbar().handler_unblock(
|
|
1331 |
self.thumb_scroll_handler
|
|
1332 |
)
|
|
1333 |
|
|
1334 |
def thumbnail_get_name(self, image_name):
|
|
1335 |
filename = os.path.expanduser("file://" + image_name)
|
|
1336 |
uriname = os.path.expanduser(
|
|
1337 |
"file://" + urllib.request.pathname2url(image_name)
|
|
1338 |
)
|
|
1339 |
if HAS_HASHLIB:
|
|
1340 |
m = hashlib.md5()
|
|
1341 |
else:
|
|
1342 |
m = md5.new()
|
|
1343 |
m.update(uriname)
|
|
1344 |
mhex = m.hexdigest()
|
|
1345 |
mhex_filename = os.path.expanduser("~/.thumbnails/normal/" + mhex + ".png")
|
|
1346 |
return filename, mhex_filename
|
|
1347 |
|
|
1348 |
def thumbpane_get_pixbuf(self, thumb_url, image_url, force_generation):
|
|
1349 |
# Returns a valid pixbuf or None if a pixbuf cannot be generated. Tries to re-use
|
|
1350 |
# a thumbnail from ~/.thumbails/normal/, otherwise generates one with the
|
|
1351 |
# XDG filename: md5(file:///full/path/to/image).png
|
|
1352 |
imgfile = image_url
|
|
1353 |
if imgfile[:7] == "file://":
|
|
1354 |
imgfile = imgfile[7:]
|
|
1355 |
try:
|
|
1356 |
if os.path.exists(thumb_url) and not force_generation:
|
|
1357 |
pix = gtk.gdk.pixbuf_new_from_file(thumb_url)
|
|
1358 |
pix_mtime = pix.get_option("tEXt::Thumb::MTime")
|
|
1359 |
if pix_mtime:
|
|
1360 |
st = os.stat(imgfile)
|
|
1361 |
file_mtime = str(st[stat.ST_MTIME])
|
|
1362 |
# If the mtimes match, we're good. if not, regenerate the thumbnail..
|
|
1363 |
if pix_mtime == file_mtime:
|
|
1364 |
return pix
|
|
1365 |
# Create the 128x128 thumbnail:
|
|
1366 |
uri = "file://" + urllib.request.pathname2url(imgfile)
|
|
1367 |
pix = gtk.gdk.pixbuf_new_from_file(imgfile)
|
|
1368 |
pix, image_width, image_height = self.get_pixbuf_of_size(
|
|
1369 |
pix, 128, gtk.gdk.INTERP_TILES
|
|
1370 |
)
|
|
1371 |
st = os.stat(imgfile)
|
|
1372 |
file_mtime = str(st[stat.ST_MTIME])
|
|
1373 |
# Save image to .thumbnails:
|
|
1374 |
pix.save(
|
|
1375 |
thumb_url,
|
|
1376 |
"png",
|
|
1377 |
{
|
|
1378 |
"tEXt::Thumb::URI": uri,
|
|
1379 |
"tEXt::Thumb::MTime": file_mtime,
|
|
1380 |
"tEXt::Software": "Mirage" + __version__,
|
|
1381 |
},
|
|
1382 |
)
|
|
1383 |
return pix
|
|
1384 |
except:
|
|
1385 |
return None
|
|
1386 |
|
|
1387 |
def thumbpane_load_image(self, treeview, imgnum):
|
|
1388 |
if imgnum != self.curr_img_in_list:
|
|
1389 |
gobject.idle_add(self.goto_image, str(imgnum), None)
|
|
1390 |
|
|
1391 |
def thumbpane_selection_changed(self, treeview):
|
|
1392 |
cancel = self.autosave_image()
|
|
1393 |
if cancel:
|
|
1394 |
# Revert selection...
|
|
1395 |
gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
|
|
1396 |
return True
|
|
1397 |
try:
|
|
1398 |
model, paths = self.thumbpane.get_selection().get_selected_rows()
|
|
1399 |
imgnum = paths[0][0]
|
|
1400 |
if not self.thumbnail_loaded[imgnum]:
|
|
1401 |
self.thumbpane_set_image(self.image_list[imgnum], imgnum)
|
|
1402 |
gobject.idle_add(self.thumbpane_load_image, treeview, imgnum)
|
|
1403 |
except:
|
|
1404 |
pass
|
|
1405 |
|
|
1406 |
def thumbpane_select(self, imgnum):
|
|
1407 |
if self.thumbpane_show:
|
|
1408 |
self.thumbpane.get_selection().handler_block(self.thumb_sel_handler)
|
|
1409 |
try:
|
|
1410 |
self.thumbpane.get_selection().select_path((imgnum,))
|
|
1411 |
self.thumbpane.scroll_to_cell((imgnum,))
|
|
1412 |
except:
|
|
1413 |
pass
|
|
1414 |
self.thumbpane.get_selection().handler_unblock(self.thumb_sel_handler)
|
|
1415 |
|
|
1416 |
def thumbpane_set_size(self):
|
|
1417 |
self.thumbcolumn.set_fixed_width(self.thumbpane_get_size())
|
|
1418 |
self.window_resized(None, self.window.allocation, True)
|
|
1419 |
|
|
1420 |
def thumbpane_get_size(self):
|
|
1421 |
return int(self.thumbnail_size * 1.3)
|
|
1422 |
|
|
1423 |
def thumbpane_scrolled(self, range):
|
|
1424 |
self.thumbpane_update_images()
|
|
1425 |
|
|
1426 |
def get_blank_pix_for_image(self, image):
|
|
1427 |
# Sizes the "blank image" icon for the thumbpane. This will ensure that we don't
|
|
1428 |
# load a humongous icon for a small pix, for example, and will keep the thumbnails
|
|
1429 |
# from shifting around when they are actually loaded.
|
|
1430 |
try:
|
|
1431 |
info = gtk.gdk.pixbuf_get_file_info(image)
|
|
1432 |
imgwidth = float(info[1])
|
|
1433 |
imgheight = float(info[2])
|
|
1434 |
if imgheight > self.thumbnail_size:
|
|
1435 |
if imgheight > imgwidth:
|
|
1436 |
imgheight = self.thumbnail_size
|
|
1437 |
else:
|
|
1438 |
imgheight = (imgheight // imgwidth) * self.thumbnail_size
|
|
1439 |
imgheight = 2 + int(
|
|
1440 |
imgheight
|
|
1441 |
) # Account for border that will be added to thumbnails..
|
|
1442 |
imgwidth = self.thumbnail_size
|
|
1443 |
except:
|
|
1444 |
imgheight = 2 + self.thumbnail_size
|
|
1445 |
imgwidth = self.thumbnail_size
|
|
1446 |
blank_pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, imgwidth, imgheight)
|
|
1447 |
blank_pix.fill(0x00000000)
|
|
1448 |
imgwidth2 = int(imgheight * 0.8)
|
|
1449 |
imgheight2 = int(imgheight * 0.8)
|
|
1450 |
composite_pix = self.blank_image.scale_simple(
|
|
1451 |
imgwidth2, imgheight2, gtk.gdk.INTERP_BILINEAR
|
|
1452 |
)
|
|
1453 |
leftcoord = int((imgwidth - imgwidth2) // 2)
|
|
1454 |
topcoord = int((imgheight - imgheight2) // 2)
|
|
1455 |
composite_pix.copy_area(
|
|
1456 |
0, 0, imgwidth2, imgheight2, blank_pix, leftcoord, topcoord
|
|
1457 |
)
|
|
1458 |
return blank_pix
|
|
1459 |
|
|
1460 |
def find_path(self, filename, exit_on_fail=True):
|
|
1461 |
""" Find a pixmap or icon by looking through standard dirs.
|
1008 | 1462 |
If the image isn't found exit with error status 1 unless
|
1009 | 1463 |
exit_on_fail is set to False, then return None """
|
1010 | |
if not self.resource_path_list:
|
1011 | |
#If executed from mirage in bin this points to the basedir
|
1012 | |
basedir_mirage = os.path.split(sys.path[0])[0]
|
1013 | |
#If executed from mirage.py module in python lib this points to the basedir
|
1014 | |
f0 = os.path.split(__file__)[0].split('/lib')[0]
|
1015 | |
self.resource_path_list = list(set(filter(os.path.isdir, [
|
1016 | |
os.path.join(basedir_mirage, 'share', 'mirage'),
|
1017 | |
os.path.join(basedir_mirage, 'share', 'pixmaps'),
|
1018 | |
os.path.join(sys.prefix, 'share', 'mirage'),
|
1019 | |
os.path.join(sys.prefix, 'share', 'pixmaps'),
|
1020 | |
os.path.join(sys.prefix, 'local', 'share', 'mirage'),
|
1021 | |
os.path.join(sys.prefix, 'local', 'share', 'pixmaps'),
|
1022 | |
sys.path[0], #If it's run non-installed
|
1023 | |
os.path.join(f0, 'share', 'mirage'),
|
1024 | |
os.path.join(f0, 'share', 'pixmaps'),
|
1025 | |
])))
|
1026 | |
for path in self.resource_path_list:
|
1027 | |
pix = os.path.join(path, filename)
|
1028 | |
if os.path.exists(pix):
|
1029 | |
return pix
|
1030 | |
# If we reached here, we didn't find the pixmap
|
1031 | |
if exit_on_fail:
|
1032 | |
print(_("Couldn't find the image %s. Please check your installation.") % filename)
|
1033 | |
sys.exit(1)
|
1034 | |
else:
|
1035 | |
return None
|
1036 | |
|
1037 | |
def gconf_key_changed(self, client, cnxn_id, entry, label):
|
1038 | |
if entry.value.type == gconf.VALUE_STRING:
|
1039 | |
style = entry.value.to_string()
|
1040 | |
if style == "both":
|
1041 | |
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
1042 | |
elif style == "both-horiz":
|
1043 | |
self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
|
1044 | |
elif style == "icons":
|
1045 | |
self.toolbar.set_style(gtk.TOOLBAR_ICONS)
|
1046 | |
elif style == "text":
|
1047 | |
self.toolbar.set_style(gtk.TOOLBAR_TEXT)
|
1048 | |
if self.image_loaded and self.last_image_action_was_fit:
|
1049 | |
if self.last_image_action_was_smart_fit:
|
1050 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
1051 | |
else:
|
1052 | |
self.zoom_to_fit_window(None, False, False)
|
1053 | |
|
1054 | |
def toolbar_focused(self, widget, direction):
|
1055 | |
self.layout.grab_focus()
|
1056 | |
return True
|
1057 | |
|
1058 | |
def topwindow_keypress(self, widget, event):
|
1059 | |
# For whatever reason, 'Left' and 'Right' cannot be used as menu
|
1060 | |
# accelerators so we will manually check for them here:
|
1061 | |
if (not (event.state & gtk.gdk.SHIFT_MASK)) and not (event.state & gtk.gdk.CONTROL_MASK) and not (event.state & gtk.gdk.MOD1_MASK) and not (event.state & gtk.gdk.MOD2_MASK) and not (event.state & gtk.gdk.CONTROL_MASK):
|
1062 | |
if event.keyval == gtk.gdk.keyval_from_name('Left') or event.keyval == gtk.gdk.keyval_from_name('Up'):
|
1063 | |
self.goto_prev_image(None)
|
1064 | |
return
|
1065 | |
elif event.keyval == gtk.gdk.keyval_from_name('Right') or event.keyval == gtk.gdk.keyval_from_name('Down'):
|
1066 | |
self.goto_next_image(None)
|
1067 | |
return
|
1068 | |
shortcut = gtk.accelerator_name(event.keyval, event.state)
|
1069 | |
if "Escape" in shortcut:
|
1070 | |
self.stop_now = True
|
1071 | |
self.searching_for_images = False
|
1072 | |
while gtk.events_pending():
|
1073 | |
gtk.main_iteration()
|
1074 | |
self.update_title()
|
1075 | |
return
|
1076 | |
|
1077 | |
def parse_action_command(self, command, batchmode):
|
1078 | |
self.running_custom_actions = True
|
1079 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
1080 | |
while gtk.events_pending():
|
1081 | |
gtk.main_iteration()
|
1082 | |
self.curr_custom_action = 0
|
1083 | |
if batchmode:
|
1084 | |
self.num_custom_actions = len(self.image_list)
|
1085 | |
for i in range(self.num_custom_actions):
|
1086 | |
self.curr_custom_action += 1
|
1087 | |
self.update_statusbar()
|
1088 | |
while gtk.events_pending():
|
1089 | |
gtk.main_iteration()
|
1090 | |
imagename = self.image_list[i]
|
1091 | |
self.parse_action_command2(command, imagename)
|
1092 | |
else:
|
1093 | |
self.num_custom_actions = 1
|
1094 | |
self.curr_custom_action = 1
|
1095 | |
self.update_statusbar()
|
1096 | |
while gtk.events_pending():
|
1097 | |
gtk.main_iteration()
|
1098 | |
self.parse_action_command2(command, self.currimg_name)
|
1099 | |
gc.collect()
|
1100 | |
self.change_cursor(None)
|
1101 | |
# Refresh the current image or any preloaded needed if they have changed:
|
1102 | |
if not os.path.exists(self.currimg_name):
|
1103 | |
self.currimg_pixbuf_original = None
|
1104 | |
self.image_load_failed(False)
|
1105 | |
else:
|
1106 | |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
1107 | |
if animtest.is_static_image():
|
1108 | |
if self.images_are_different(animtest.get_static_image(), self.currimg_pixbuf_original):
|
1109 | |
self.load_new_image2(False, False, True, False)
|
1110 | |
else:
|
1111 | |
if self.images_are_different(animtest, self.currimg_pixbuf_original):
|
1112 | |
self.load_new_image2(False, False, True, False)
|
1113 | |
self.running_custom_actions = False
|
1114 | |
self.update_statusbar()
|
1115 | |
while gtk.events_pending():
|
1116 | |
gtk.main_iteration()
|
1117 | |
if not os.path.exists(self.preloadimg_prev_name):
|
1118 | |
self.preloadimg_prev_in_list = -1
|
1119 | |
else:
|
1120 | |
animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
|
1121 | |
if animtest.is_static_image():
|
1122 | |
if self.images_are_different(animtest.get_static_image(), self.preloadimg_prev_pixbuf_original):
|
1123 | |
self.preloadimg_prev_in_list = -1
|
1124 | |
self.preload_when_idle = gobject.idle_add(self.preload_prev_image, False)
|
1125 | |
else:
|
1126 | |
if self.images_are_different(animtest, self.preloadimg_prev_pixbuf_original):
|
1127 | |
self.preloadimg_prev_in_list = -1
|
1128 | |
self.preload_when_idle = gobject.idle_add(self.preload_prev_image, False)
|
1129 | |
if not os.path.exists(self.preloadimg_next_name):
|
1130 | |
self.preloadimg_next_in_list = -1
|
1131 | |
else:
|
1132 | |
animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
|
1133 | |
if animtest.is_static_image():
|
1134 | |
if self.images_are_different(animtest.get_static_image(), self.preloadimg_next_pixbuf_original):
|
1135 | |
self.preloadimg_next_in_list = -1
|
1136 | |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
|
1137 | |
else:
|
1138 | |
if self.images_are_different(animtest, self.preloadimg_next_pixbuf_original):
|
1139 | |
self.preloadimg_next_in_list = -1
|
1140 | |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
|
1141 | |
self.stop_now = False
|
1142 | |
if batchmode:
|
1143 | |
# Update all thumbnails:
|
1144 | |
gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
|
1145 | |
else:
|
1146 | |
# Update only the current thumbnail:
|
1147 | |
gobject.idle_add(self.thumbpane_set_image, self.image_list[self.curr_img_in_list], self.curr_img_in_list, True)
|
1148 | |
|
1149 | |
def images_are_different(self, pixbuf1, pixbuf2):
|
1150 | |
if pixbuf1.get_pixels() == pixbuf2.get_pixels():
|
1151 | |
return False
|
1152 | |
else:
|
1153 | |
return True
|
1154 | |
|
1155 | |
def recent_action_click(self, action):
|
1156 | |
self.stop_now = True
|
1157 | |
while gtk.events_pending():
|
1158 | |
gtk.main_iteration()
|
1159 | |
cancel = self.autosave_image()
|
1160 | |
if cancel:
|
1161 | |
return
|
1162 | |
index = int(action.get_name())
|
1163 | |
if os.path.isfile(self.recentfiles[index]) or os.path.exists(self.recentfiles[index]) or self.recentfiles[index].startswith('http://') or self.recentfiles[index].startswith('ftp://'):
|
1164 | |
self.expand_filelist_and_load_image([self.recentfiles[index]])
|
1165 | |
else:
|
1166 | |
self.image_list = []
|
1167 | |
self.curr_img_in_list = 0
|
1168 | |
self.image_list.append(self.recentfiles[index])
|
1169 | |
self.image_load_failed(False)
|
1170 | |
self.recent_file_remove_and_refresh(index)
|
1171 | |
|
1172 | |
def recent_file_remove_and_refresh_name(self, rmfile):
|
1173 | |
index_num = 0
|
1174 | |
for imgfile in self.recentfiles:
|
1175 | |
if imgfile == rmfile:
|
1176 | |
self.recent_file_remove_and_refresh(index_num)
|
1177 | |
break
|
1178 | |
index_num += index_num
|
1179 | |
|
1180 | |
def recent_file_remove_and_refresh(self, index_num):
|
1181 | |
i = index_num
|
1182 | |
while i < len(self.recentfiles)-1:
|
1183 | |
self.recentfiles[i] = self.recentfiles[i+1]
|
1184 | |
i = i + 1
|
1185 | |
# Set last item empty:
|
1186 | |
self.recentfiles[len(self.recentfiles)-1] = ''
|
1187 | |
self.refresh_recent_files_menu()
|
1188 | |
|
1189 | |
def recent_file_add_and_refresh(self, addfile):
|
1190 | |
# First check if the filename is already in the list:
|
1191 | |
for i in range(len(self.recentfiles)):
|
1192 | |
if len(self.recentfiles[i]) > 0:
|
1193 | |
if addfile == self.recentfiles[i]:
|
1194 | |
# If found in list, put to position 1 and decrement the rest:
|
1195 | |
j = i
|
1196 | |
while j > 0:
|
1197 | |
self.recentfiles[j] = self.recentfiles[j-1]
|
1198 | |
j = j - 1
|
1199 | |
self.recentfiles[0] = addfile
|
1200 | |
self.refresh_recent_files_menu()
|
1201 | |
return
|
1202 | |
# If not found, put to position 1, decrement the rest:
|
1203 | |
j = len(self.recentfiles)-1
|
1204 | |
while j > 0:
|
1205 | |
self.recentfiles[j] = self.recentfiles[j-1]
|
1206 | |
j = j - 1
|
1207 | |
if len(self.recentfiles) > 0:
|
1208 | |
self.recentfiles[0] = addfile
|
1209 | |
self.refresh_recent_files_menu()
|
1210 | |
|
1211 | |
def custom_action_click(self, action):
|
1212 | |
if self.UIManager.get_widget('/MainMenu/EditMenu/ActionSubMenu/' + action.get_name()).get_property('sensitive'):
|
1213 | |
for i in range(len(self.action_shortcuts)):
|
1214 | |
try:
|
1215 | |
if action.get_name() == self.action_names[i]:
|
1216 | |
self.parse_action_command(self.action_commands[i], self.action_batch[i])
|
1217 | |
except:
|
1218 | |
pass
|
1219 | |
|
1220 | |
|
1221 | |
def parse_action_command2(self, cmd, imagename):
|
1222 | |
# Executes the given command using ``os.system``, substituting "%"-macros approprately.
|
1223 | |
def sh_esc(s):
|
1224 | |
import re
|
1225 | |
return re.sub(r'[^/._a-zA-Z0-9-]', lambda c: '\\'+c.group(), s)
|
1226 | |
cmd = cmd.strip()
|
1227 | |
# [NEXT] and [PREV] are only valid alone or at the end of the command
|
1228 | |
if cmd == "[NEXT]":
|
1229 | |
self.goto_next_image(None)
|
1230 | |
return
|
1231 | |
elif cmd == "[PREV]":
|
1232 | |
self.goto_prev_image(None)
|
1233 | |
return
|
1234 | |
# -1=go to previous, 1=go to next, 0=don't change
|
1235 | |
prev_or_next=0
|
1236 | |
if cmd[-6:] == "[NEXT]":
|
1237 | |
prev_or_next=1
|
1238 | |
cmd = cmd[:-6]
|
1239 | |
elif cmd[-6:] == "[PREV]":
|
1240 | |
prev_or_next=-1
|
1241 | |
cmd = cmd[:-6]
|
1242 | |
if "%F" in cmd:
|
1243 | |
cmd = cmd.replace("%F", sh_esc(imagename))
|
1244 | |
if "%N" in cmd:
|
1245 | |
cmd = cmd.replace("%N", sh_esc(os.path.splitext(os.path.basename(imagename))[0]))
|
1246 | |
if "%P" in cmd:
|
1247 | |
cmd = cmd.replace("%P", sh_esc(os.path.dirname(imagename) + "/"))
|
1248 | |
if "%E" in cmd:
|
1249 | |
cmd = cmd.replace("%E", sh_esc(os.path.splitext(os.path.basename(imagename))[1]))
|
1250 | |
if "%L" in cmd:
|
1251 | |
cmd = cmd.replace("%L", " ".join([sh_esc(s) for s in self.image_list]))
|
1252 | |
if self.verbose:
|
1253 | |
print(_("Action: %s") % cmd)
|
1254 | |
shell_rc = os.system(cmd) >> 8
|
1255 | |
if self.verbose:
|
1256 | |
print(_("Action return code: %s") % shell_rc)
|
1257 | |
if shell_rc != 0:
|
1258 | |
msg = _('Unable to launch \"%s\". Please specify a valid command from Edit > Custom Actions.') % cmd
|
1259 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, msg)
|
1260 | |
error_dialog.set_title(_("Invalid Custom Action"))
|
1261 | |
error_dialog.run()
|
1262 | |
error_dialog.destroy()
|
1263 | |
elif prev_or_next == 1:
|
1264 | |
self.goto_next_image(None)
|
1265 | |
elif prev_or_next == -1:
|
1266 | |
self.goto_prev_image(None)
|
1267 | |
self.running_custom_actions = False
|
1268 | |
|
1269 | |
def set_go_sensitivities(self, enable):
|
1270 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Previous Image').set_sensitive(enable)
|
1271 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Next Image').set_sensitive(enable)
|
1272 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Random Image').set_sensitive(enable)
|
1273 | |
self.UIManager.get_widget('/MainMenu/GoMenu/First Image').set_sensitive(enable)
|
1274 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Last Image').set_sensitive(enable)
|
1275 | |
self.UIManager.get_widget('/Popup/Previous Image').set_sensitive(enable)
|
1276 | |
self.UIManager.get_widget('/Popup/Next Image').set_sensitive(enable)
|
1277 | |
self.UIManager.get_widget('/MainToolbar/Previous2').set_sensitive(enable)
|
1278 | |
self.UIManager.get_widget('/MainToolbar/Next2').set_sensitive(enable)
|
1279 | |
self.ss_forward.set_sensitive(enable)
|
1280 | |
self.ss_back.set_sensitive(enable)
|
1281 | |
|
1282 | |
def set_image_sensitivities(self, enable):
|
1283 | |
self.set_zoom_in_sensitivities(enable)
|
1284 | |
self.set_zoom_out_sensitivities(enable)
|
1285 | |
self.UIManager.get_widget('/MainMenu/ViewMenu/1:1').set_sensitive(enable)
|
1286 | |
self.UIManager.get_widget('/MainMenu/ViewMenu/Fit').set_sensitive(enable)
|
1287 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Delete Image').set_sensitive(enable)
|
1288 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Rename Image').set_sensitive(enable)
|
1289 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Crop').set_sensitive(enable)
|
1290 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Resize').set_sensitive(enable)
|
1291 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Saturation').set_sensitive(enable)
|
1292 | |
self.UIManager.get_widget('/MainToolbar/1:1').set_sensitive(enable)
|
1293 | |
self.UIManager.get_widget('/MainToolbar/Fit').set_sensitive(enable)
|
1294 | |
self.UIManager.get_widget('/Popup/1:1').set_sensitive(enable)
|
1295 | |
self.UIManager.get_widget('/Popup/Fit').set_sensitive(enable)
|
1296 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save As').set_sensitive(enable)
|
1297 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(False)
|
1298 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Properties').set_sensitive(False)
|
1299 | |
# Only jpeg, png, and bmp images are currently supported for saving
|
1300 | |
if len(self.image_list) > 0:
|
1301 | |
try:
|
1302 | |
filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name']
|
1303 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Properties').set_sensitive(True)
|
1304 | |
if self.filetype_is_writable(filetype):
|
1305 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(enable)
|
1306 | |
except:
|
1307 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(False)
|
1308 | |
if self.actionGroupCustom:
|
1309 | |
for action in self.action_names:
|
1310 | |
self.UIManager.get_widget('/MainMenu/EditMenu/ActionSubMenu/' + action).set_sensitive(enable)
|
1311 | |
if not HAS_IMGFUNCS:
|
1312 | |
enable = False
|
1313 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Left').set_sensitive(enable)
|
1314 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Right').set_sensitive(enable)
|
1315 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Flip Vertically').set_sensitive(enable)
|
1316 | |
self.UIManager.get_widget('/MainMenu/EditMenu/Flip Horizontally').set_sensitive(enable)
|
1317 | |
|
1318 | |
def set_zoom_in_sensitivities(self, enable):
|
1319 | |
self.UIManager.get_widget('/MainMenu/ViewMenu/In').set_sensitive(enable)
|
1320 | |
self.UIManager.get_widget('/MainToolbar/In').set_sensitive(enable)
|
1321 | |
self.UIManager.get_widget('/Popup/In').set_sensitive(enable)
|
1322 | |
|
1323 | |
def set_zoom_out_sensitivities(self, enable):
|
1324 | |
self.UIManager.get_widget('/MainMenu/ViewMenu/Out').set_sensitive(enable)
|
1325 | |
self.UIManager.get_widget('/MainToolbar/Out').set_sensitive(enable)
|
1326 | |
self.UIManager.get_widget('/Popup/Out').set_sensitive(enable)
|
1327 | |
|
1328 | |
def set_next_image_sensitivities(self, enable):
|
1329 | |
self.UIManager.get_widget('/MainToolbar/Next2').set_sensitive(enable)
|
1330 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Next Image').set_sensitive(enable)
|
1331 | |
self.UIManager.get_widget('/Popup/Next Image').set_sensitive(enable)
|
1332 | |
self.ss_forward.set_sensitive(enable)
|
1333 | |
|
1334 | |
def set_previous_image_sensitivities(self, enable):
|
1335 | |
self.UIManager.get_widget('/MainToolbar/Previous2').set_sensitive(enable)
|
1336 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Previous Image').set_sensitive(enable)
|
1337 | |
self.UIManager.get_widget('/Popup/Previous Image').set_sensitive(enable)
|
1338 | |
self.ss_back.set_sensitive(enable)
|
1339 | |
|
1340 | |
def set_first_image_sensitivities(self, enable):
|
1341 | |
self.UIManager.get_widget('/MainMenu/GoMenu/First Image').set_sensitive(enable)
|
1342 | |
|
1343 | |
def set_last_image_sensitivities(self, enable):
|
1344 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Last Image').set_sensitive(enable)
|
1345 | |
|
1346 | |
def set_random_image_sensitivities(self, enable):
|
1347 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Random Image').set_sensitive(enable)
|
1348 | |
|
1349 | |
def set_slideshow_sensitivities(self):
|
1350 | |
if len(self.image_list) <=1:
|
1351 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').show()
|
1352 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(False)
|
1353 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').hide()
|
1354 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(False)
|
1355 | |
elif self.slideshow_mode:
|
1356 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').hide()
|
1357 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(False)
|
1358 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').show()
|
1359 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(True)
|
1360 | |
else:
|
1361 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').show()
|
1362 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(True)
|
1363 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').hide()
|
1364 | |
self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(False)
|
1365 | |
if self.slideshow_mode:
|
1366 | |
self.UIManager.get_widget('/Popup/Start Slideshow').hide()
|
1367 | |
self.UIManager.get_widget('/Popup/Stop Slideshow').show()
|
1368 | |
else:
|
1369 | |
self.UIManager.get_widget('/Popup/Start Slideshow').show()
|
1370 | |
self.UIManager.get_widget('/Popup/Stop Slideshow').hide()
|
1371 | |
if len(self.image_list) <=1:
|
1372 | |
self.UIManager.get_widget('/Popup/Start Slideshow').set_sensitive(False)
|
1373 | |
else:
|
1374 | |
self.UIManager.get_widget('/Popup/Start Slideshow').set_sensitive(True)
|
1375 | |
|
1376 | |
def set_zoom_sensitivities(self):
|
1377 | |
if not self.currimg_is_animation:
|
1378 | |
self.set_zoom_out_sensitivities(True)
|
1379 | |
self.set_zoom_in_sensitivities(True)
|
1380 | |
else:
|
1381 | |
self.set_zoom_out_sensitivities(False)
|
1382 | |
self.set_zoom_in_sensitivities(False)
|
1383 | |
|
1384 | |
def print_version(self):
|
1385 | |
print(_("Version: Mirage"), __version__)
|
1386 | |
print(_("Website: http://mirageiv.berlios.de"))
|
1387 | |
|
1388 | |
def print_usage(self):
|
1389 | |
self.print_version()
|
1390 | |
print("")
|
1391 | |
print(_("Usage: mirage [OPTION]... FILES|FOLDERS..."))
|
1392 | |
print("")
|
1393 | |
print(_("Options") + ":")
|
1394 | |
print(" -h, --help " + _("Show this help and exit"))
|
1395 | |
print(" -v, --version " + _("Show version information and exit"))
|
1396 | |
print(" -V, --verbose " + _("Show more detailed information"))
|
1397 | |
print(" -R, --recursive " + _("Recursively include all images found in"))
|
1398 | |
print(" " + _("subdirectories of FOLDERS"))
|
1399 | |
print(" -s, --slideshow " + _("Start in slideshow mode"))
|
1400 | |
print(" -f, --fullscreen " + _("Start in fullscreen mode"))
|
1401 | |
print(" -o, --onload 'cmd' " + _("Execute 'cmd' when an image is loaded"))
|
1402 | |
print(" " + _("uses same syntax as custom actions,\n"))
|
1403 | |
print(" " + _("i.e. mirage -o 'echo file is %F'"))
|
1404 | |
|
1405 | |
def delay_changed(self, action):
|
1406 | |
self.curr_slideshow_delay = self.ss_delayspin.get_value()
|
1407 | |
if self.slideshow_mode:
|
1408 | |
gobject.source_remove(self.timer_delay)
|
1409 | |
if self.curr_slideshow_random:
|
1410 | |
self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
|
1411 | |
else:
|
1412 | |
self.timer_delay = gobject.timeout_add((self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
|
1413 | |
self.window.set_focus(self.layout)
|
1414 | |
|
1415 | |
def random_changed(self, action):
|
1416 | |
self.curr_slideshow_random = self.ss_randomize.get_active()
|
1417 | |
|
1418 | |
def motion_cb(self, widget, context, x, y, time):
|
1419 | |
context.drag_status(gtk.gdk.ACTION_COPY, time)
|
1420 | |
return True
|
1421 | |
|
1422 | |
def drop_cb(self, widget, context, x, y, selection, info, time):
|
1423 | |
uri = selection.data.strip()
|
1424 | |
path = urllib.request.url2pathname(uri)
|
1425 | |
paths = path.rsplit('\n')
|
1426 | |
for i, path in enumerate(paths):
|
1427 | |
paths[i] = path.rstrip('\r')
|
1428 | |
self.expand_filelist_and_load_image(paths)
|
1429 | |
|
1430 | |
def put_error_image_to_window(self):
|
1431 | |
self.imageview.set_from_stock(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR)
|
1432 | |
self.currimg_width = self.imageview.size_request()[0]
|
1433 | |
self.currimg_height = self.imageview.size_request()[1]
|
1434 | |
self.center_image()
|
1435 | |
self.set_go_sensitivities(False)
|
1436 | |
self.set_image_sensitivities(False)
|
1437 | |
self.update_statusbar()
|
1438 | |
self.loaded_img_in_list = -1
|
1439 | |
return
|
1440 | |
|
1441 | |
def expose_event(self, widget, event):
|
1442 | |
if self.updating_adjustments:
|
1443 | |
return
|
1444 | |
self.updating_adjustments = True
|
1445 | |
if self.hscroll.get_property('visible'):
|
1446 | |
try:
|
1447 | |
zoomratio = float(self.currimg_width)/self.previmg_width
|
1448 | |
newvalue = abs(self.layout.get_hadjustment().get_value() * zoomratio + ((self.available_image_width()) * (zoomratio - 1)) // 2)
|
1449 | |
if newvalue >= self.layout.get_hadjustment().lower and newvalue <= (self.layout.get_hadjustment().upper - self.layout.get_hadjustment().page_size):
|
1450 | |
self.layout.get_hadjustment().set_value(newvalue)
|
1451 | |
except:
|
1452 | |
pass
|
1453 | |
if self.vscroll.get_property('visible'):
|
1454 | |
try:
|
1455 | |
newvalue = abs(self.layout.get_vadjustment().get_value() * zoomratio + ((self.available_image_height()) * (zoomratio - 1)) // 2)
|
1456 | |
if newvalue >= self.layout.get_vadjustment().lower and newvalue <= (self.layout.get_vadjustment().upper - self.layout.get_vadjustment().page_size):
|
1457 | |
self.layout.get_vadjustment().set_value(newvalue)
|
1458 | |
self.previmg_width = self.currimg_width
|
1459 | |
except:
|
1460 | |
pass
|
1461 | |
self.updating_adjustments = False
|
1462 | |
|
1463 | |
def window_resized(self, widget, allocation, force_update=False):
|
1464 | |
# Update the image size on window resize if the current image was last fit:
|
1465 | |
if self.image_loaded:
|
1466 | |
if force_update or allocation.width != self.prevwinwidth or allocation.height != self.prevwinheight:
|
1467 | |
if self.last_image_action_was_fit:
|
1468 | |
if self.last_image_action_was_smart_fit:
|
1469 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
1470 | |
else:
|
1471 | |
self.zoom_to_fit_window(None, False, False)
|
1472 | |
else:
|
1473 | |
self.center_image()
|
1474 | |
self.load_new_image_stop_now()
|
1475 | |
self.show_scrollbars_if_needed()
|
1476 | |
# Also, regenerate preloaded image for new window size:
|
1477 | |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, True)
|
1478 | |
self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, True)
|
1479 | |
self.prevwinwidth = allocation.width
|
1480 | |
self.prevwinheight = allocation.height
|
1481 | |
return
|
1482 | |
|
1483 | |
def save_settings(self):
|
1484 | |
conf = configparser.ConfigParser()
|
1485 | |
conf.add_section('window')
|
1486 | |
conf.set('window', 'w', self.window.get_allocation().width)
|
1487 | |
conf.set('window', 'h', self.window.get_allocation().height)
|
1488 | |
conf.set('window', 'toolbar', self.toolbar_show)
|
1489 | |
conf.set('window', 'statusbar', self.statusbar_show)
|
1490 | |
conf.set('window', 'thumbpane', self.thumbpane_show)
|
1491 | |
conf.add_section('prefs')
|
1492 | |
conf.set('prefs', 'simple-bgcolor', self.simple_bgcolor)
|
1493 | |
conf.set('prefs', 'bgcolor-red', self.bgcolor.red)
|
1494 | |
conf.set('prefs', 'bgcolor-green', self.bgcolor.green)
|
1495 | |
conf.set('prefs', 'bgcolor-blue', self.bgcolor.blue)
|
1496 | |
conf.set('prefs', 'open_all', self.open_all_images)
|
1497 | |
conf.set('prefs', 'hidden', self.open_hidden_files)
|
1498 | |
conf.set('prefs', 'use_last_dir', self.use_last_dir)
|
1499 | |
conf.set('prefs', 'last_dir', self.last_dir)
|
1500 | |
conf.set('prefs', 'fixed_dir', self.fixed_dir)
|
1501 | |
conf.set('prefs', 'open_mode', self.open_mode)
|
1502 | |
conf.set('prefs', 'last_mode', self.last_mode)
|
1503 | |
conf.set('prefs', 'listwrap_mode', self.listwrap_mode)
|
1504 | |
conf.set('prefs', 'slideshow_delay', int(self.slideshow_delay))
|
1505 | |
conf.set('prefs', 'slideshow_random', self.slideshow_random)
|
1506 | |
conf.set('prefs', 'zoomquality', self.zoomvalue)
|
1507 | |
conf.set('prefs', 'quality_save', int(self.quality_save))
|
1508 | |
conf.set('prefs', 'disable_screensaver', self.disable_screensaver)
|
1509 | |
conf.set('prefs', 'slideshow_in_fullscreen', self.slideshow_in_fullscreen)
|
1510 | |
conf.set('prefs', 'confirm_delete', self.confirm_delete)
|
1511 | |
conf.set('prefs', 'preloading_images', self.preloading_images)
|
1512 | |
conf.set('prefs', 'savemode', self.savemode)
|
1513 | |
conf.set('prefs', 'start_in_fullscreen', self.start_in_fullscreen)
|
1514 | |
conf.set('prefs', 'thumbsize', self.thumbnail_size)
|
1515 | |
conf.set('prefs', 'screenshot_delay', self.screenshot_delay)
|
1516 | |
conf.add_section('actions')
|
1517 | |
conf.set('actions', 'num_actions', len(self.action_names))
|
1518 | |
for i in range(len(self.action_names)):
|
1519 | |
conf.set('actions', 'names[' + str(i) + ']', self.action_names[i])
|
1520 | |
conf.set('actions', 'commands[' + str(i) + ']', self.action_commands[i])
|
1521 | |
conf.set('actions', 'shortcuts[' + str(i) + ']', self.action_shortcuts[i])
|
1522 | |
conf.set('actions', 'batch[' + str(i) + ']', self.action_batch[i])
|
1523 | |
conf.add_section('recent')
|
1524 | |
conf.set('recent', 'num_recent', len(self.recentfiles))
|
1525 | |
for i in range(len(self.recentfiles)):
|
1526 | |
conf.set('recent', 'num[' + str(i) + ']', len(self.recentfiles[i]))
|
1527 | |
conf.set('recent', 'urls[' + str(i) + ',0]', self.recentfiles[i])
|
1528 | |
if not os.path.exists(self.config_dir):
|
1529 | |
os.makedirs(self.config_dir)
|
1530 | |
conf.write(file(self.config_dir + '/miragerc', 'w'))
|
1531 | |
|
1532 | |
# Also, save accel_map:
|
1533 | |
gtk.accel_map_save(self.config_dir + '/accel_map')
|
1534 | |
|
1535 | |
return
|
1536 | |
|
1537 | |
def delete_event(self, widget, event, data=None):
|
1538 | |
cancel = self.autosave_image()
|
1539 | |
if cancel:
|
1540 | |
return True
|
1541 | |
self.stop_now = True
|
1542 | |
self.closing_app = True
|
1543 | |
self.save_settings()
|
1544 | |
sys.exit(0)
|
1545 | |
|
1546 | |
def destroy(self, event, data=None):
|
1547 | |
cancel = self.autosave_image()
|
1548 | |
if cancel:
|
1549 | |
return True
|
1550 | |
self.stop_now = True
|
1551 | |
self.closing_app = True
|
1552 | |
self.save_settings()
|
1553 | |
|
1554 | |
def exit_app(self, action):
|
1555 | |
cancel = self.autosave_image()
|
1556 | |
if cancel:
|
1557 | |
return True
|
1558 | |
self.stop_now = True
|
1559 | |
self.closing_app = True
|
1560 | |
self.save_settings()
|
1561 | |
sys.exit(0)
|
1562 | |
|
1563 | |
def put_zoom_image_to_window(self, currimg_preloaded):
|
1564 | |
self.window.window.freeze_updates()
|
1565 | |
if not currimg_preloaded:
|
1566 | |
# Always start with the original image to preserve quality!
|
1567 | |
# Calculate image size:
|
1568 | |
finalimg_width = int(self.currimg_pixbuf_original.get_width() * self.currimg_zoomratio)
|
1569 | |
finalimg_height = int(self.currimg_pixbuf_original.get_height() * self.currimg_zoomratio)
|
1570 | |
if not self.currimg_is_animation:
|
1571 | |
# Scale image:
|
1572 | |
if not self.currimg_pixbuf_original.get_has_alpha():
|
1573 | |
self.currimg_pixbuf = self.currimg_pixbuf_original.scale_simple(finalimg_width, finalimg_height, self.zoom_quality)
|
1574 | |
else:
|
1575 | |
colormap = self.imageview.get_colormap()
|
1576 | |
light_grey = colormap.alloc_color('#666666', True, True)
|
1577 | |
dark_grey = colormap.alloc_color('#999999', True, True)
|
1578 | |
self.currimg_pixbuf = self.currimg_pixbuf_original.composite_color_simple(finalimg_width, finalimg_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
|
1579 | |
else:
|
1580 | |
self.currimg_pixbuf = self.currimg_pixbuf_original
|
1581 | |
self.currimg_width, self.currimg_height = finalimg_width, finalimg_height
|
1582 | |
self.layout.set_size(self.currimg_width, self.currimg_height)
|
1583 | |
self.center_image()
|
1584 | |
self.show_scrollbars_if_needed()
|
1585 | |
if not self.currimg_is_animation:
|
1586 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
1587 | |
self.previmage_is_animation = False
|
1588 | |
else:
|
1589 | |
self.imageview.set_from_animation(self.currimg_pixbuf)
|
1590 | |
self.previmage_is_animation = True
|
1591 | |
# Clean up (free memory) because I'm lazy
|
1592 | |
gc.collect()
|
1593 | |
self.window.window.thaw_updates()
|
1594 | |
self.loaded_img_in_list = self.curr_img_in_list
|
1595 | |
|
1596 | |
def show_scrollbars_if_needed(self):
|
1597 | |
if self.currimg_width > self.available_image_width():
|
1598 | |
self.hscroll.show()
|
1599 | |
else:
|
1600 | |
self.hscroll.hide()
|
1601 | |
if self.currimg_height > self.available_image_height():
|
1602 | |
self.vscroll.show()
|
1603 | |
else:
|
1604 | |
self.vscroll.hide()
|
1605 | |
|
1606 | |
def center_image(self):
|
1607 | |
x_shift = int((self.available_image_width() - self.currimg_width) // 2)
|
1608 | |
if x_shift < 0:
|
1609 | |
x_shift = 0
|
1610 | |
y_shift = int((self.available_image_height() - self.currimg_height) // 2)
|
1611 | |
if y_shift < 0:
|
1612 | |
y_shift = 0
|
1613 | |
self.layout.move(self.imageview, x_shift, y_shift)
|
1614 | |
|
1615 | |
def available_image_width(self):
|
1616 | |
width = self.window.get_size()[0]
|
1617 | |
if not self.fullscreen_mode:
|
1618 | |
if self.thumbpane_show:
|
1619 | |
width -= self.thumbscroll.size_request()[0]
|
1620 | |
return width
|
1621 | |
|
1622 | |
def available_image_height(self):
|
1623 | |
height = self.window.get_size()[1]
|
1624 | |
if not self.fullscreen_mode:
|
1625 | |
height -= self.menubar.size_request()[1]
|
1626 | |
if self.toolbar_show:
|
1627 | |
height -= self.toolbar.size_request()[1]
|
1628 | |
if self.statusbar_show:
|
1629 | |
height -= self.statusbar.size_request()[1]
|
1630 | |
return height
|
1631 | |
|
1632 | |
def save_image(self, action):
|
1633 | |
if self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive'):
|
1634 | |
self.save_image_now(self.currimg_name, gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name'])
|
1635 | |
|
1636 | |
def save_image_as(self, action):
|
1637 | |
dialog = gtk.FileChooserDialog(title=_("Save As"),action=gtk.FILE_CHOOSER_ACTION_SAVE,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
|
1638 | |
dialog.set_default_response(gtk.RESPONSE_OK)
|
1639 | |
filename = os.path.basename(self.currimg_name)
|
1640 | |
filetype = None
|
1641 | |
dialog.set_current_folder(os.path.dirname(self.currimg_name))
|
1642 | |
dialog.set_current_name(filename)
|
1643 | |
dialog.set_do_overwrite_confirmation(True)
|
1644 | |
response = dialog.run()
|
1645 | |
if response == gtk.RESPONSE_OK:
|
1646 | |
prev_name = self.currimg_name
|
1647 | |
filename = dialog.get_filename()
|
1648 | |
dialog.destroy()
|
1649 | |
fileext = os.path.splitext(os.path.basename(filename))[1].lower()
|
1650 | |
if len(fileext) > 0:
|
1651 | |
fileext = fileext[1:]
|
1652 | |
# Override filetype if user typed a filename with a different extension:
|
1653 | |
for i in gtk.gdk.pixbuf_get_formats():
|
1654 | |
if fileext in i['extensions']:
|
1655 | |
filetype = i['name']
|
1656 | |
self.save_image_now(filename, filetype)
|
1657 | |
self.register_file_with_recent_docs(filename)
|
1658 | |
else:
|
1659 | |
dialog.destroy()
|
1660 | |
|
1661 | |
def save_image_now(self, dest_name, filetype):
|
1662 | |
try:
|
1663 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
1664 | |
while gtk.events_pending():
|
1665 | |
gtk.main_iteration()
|
1666 | |
if filetype == None:
|
1667 | |
filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name']
|
1668 | |
if self.filetype_is_writable(filetype):
|
1669 | |
self.currimg_pixbuf_original.save(dest_name, filetype, {'quality': str(self.quality_save)})
|
1670 | |
self.currimg_name = dest_name
|
1671 | |
self.image_list[self.curr_img_in_list] = dest_name
|
1672 | |
self.update_title()
|
1673 | |
self.update_statusbar()
|
1674 | |
# Update thumbnail:
|
1675 | |
gobject.idle_add(self.thumbpane_set_image, dest_name, self.curr_img_in_list, True)
|
1676 | |
self.image_modified = False
|
1677 | |
else:
|
1678 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, _('The %s format is not supported for saving. Do you wish to save the file in a different format?') % filetype)
|
1679 | |
error_dialog.set_title(_("Save"))
|
1680 | |
response = error_dialog.run()
|
1681 | |
if response == gtk.RESPONSE_YES:
|
1682 | |
error_dialog.destroy()
|
1683 | |
while gtk.events_pending():
|
1684 | |
gtk.main_iteration()
|
1685 | |
self.save_image_as(None)
|
1686 | |
else:
|
1687 | |
error_dialog.destroy()
|
1688 | |
except:
|
1689 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Unable to save %s') % dest_name)
|
1690 | |
error_dialog.set_title(_("Save"))
|
1691 | |
error_dialog.run()
|
1692 | |
error_dialog.destroy()
|
1693 | |
self.change_cursor(None)
|
1694 | |
|
1695 | |
def autosave_image(self):
|
1696 | |
# Returns True if the user has canceled out of the dialog
|
1697 | |
# Never call this function from an idle or timeout loop! That will cause
|
1698 | |
# the app to freeze.
|
1699 | |
if self.image_modified:
|
1700 | |
if self.savemode == 1:
|
1701 | |
temp = self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive')
|
1702 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', True)
|
1703 | |
self.save_image(None)
|
1704 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', temp)
|
1705 | |
elif self.savemode == 2:
|
1706 | |
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, _("The current image has been modified. Save changes?"))
|
1707 | |
dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
1708 | |
dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
|
1709 | |
dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_YES)
|
1710 | |
dialog.set_title(_("Save?"))
|
1711 | |
dialog.set_default_response(gtk.RESPONSE_YES)
|
1712 | |
response = dialog.run()
|
1713 | |
dialog.destroy()
|
1714 | |
if response == gtk.RESPONSE_YES:
|
1715 | |
temp = self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive')
|
1716 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', True)
|
1717 | |
self.save_image(None)
|
1718 | |
self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', temp)
|
1719 | |
self.image_modified = False
|
1720 | |
elif response == gtk.RESPONSE_NO:
|
1721 | |
self.image_modified = False
|
1722 | |
# Ensures that we don't use the current pixbuf for any preload pixbufs if we are in
|
1723 | |
# the process of loading the previous or next image in the list:
|
1724 | |
self.currimg_pixbuf = self.currimg_pixbuf_original
|
1725 | |
self.preloadimg_next_in_list = -1
|
1726 | |
self.preloadimg_prev_in_list = -1
|
1727 | |
self.loaded_img_in_list = -1
|
1728 | |
else:
|
1729 | |
return True
|
1730 | |
|
1731 | |
def filetype_is_writable(self, filetype):
|
1732 | |
# Determine if filetype is a writable format
|
1733 | |
filetype_is_writable = True
|
1734 | |
for i in gtk.gdk.pixbuf_get_formats():
|
1735 | |
if filetype in i['extensions']:
|
1736 | |
if i['is_writable']:
|
1737 | |
return True
|
1738 | |
return False
|
1739 | |
|
1740 | |
def open_file(self, action):
|
1741 | |
self.stop_now = True
|
1742 | |
while gtk.events_pending():
|
1743 | |
gtk.main_iteration()
|
1744 | |
self.open_file_or_folder(action, True)
|
1745 | |
|
1746 | |
def open_file_remote(self, action):
|
1747 | |
# Prompt user for the url:
|
1748 | |
dialog = gtk.Dialog(_("Open Remote"), self.window, gtk.DIALOG_MODAL, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
1749 | |
location = gtk.Entry()
|
1750 | |
location.set_size_request(300, -1)
|
1751 | |
location.set_activates_default(True)
|
1752 | |
hbox = gtk.HBox()
|
1753 | |
hbox.pack_start(gtk.Label(_("Image Location (URL):")), False, False, 5)
|
1754 | |
hbox.pack_start(location, True, True, 5)
|
1755 | |
dialog.vbox.pack_start(hbox, True, True, 10)
|
1756 | |
dialog.set_default_response(gtk.RESPONSE_OK)
|
1757 | |
dialog.vbox.show_all()
|
1758 | |
dialog.connect('response', self.open_file_remote_response, location)
|
1759 | |
response = dialog.show()
|
1760 | |
|
1761 | |
def open_file_remote_response(self, dialog, response, location):
|
1762 | |
if response == gtk.RESPONSE_OK:
|
1763 | |
filenames = []
|
1764 | |
filenames.append(location.get_text())
|
1765 | |
dialog.destroy()
|
1766 | |
while gtk.events_pending():
|
1767 | |
gtk.main_iteration()
|
1768 | |
self.expand_filelist_and_load_image(filenames)
|
1769 | |
else:
|
1770 | |
dialog.destroy()
|
1771 | |
|
1772 | |
def open_folder(self, action):
|
1773 | |
self.stop_now = True
|
1774 | |
while gtk.events_pending():
|
1775 | |
gtk.main_iteration()
|
1776 | |
self.open_file_or_folder(action, False)
|
1777 | |
|
1778 | |
def open_file_or_folder(self, action, isfile):
|
1779 | |
self.thumbpane_create_dir()
|
1780 | |
cancel = self.autosave_image()
|
1781 | |
if cancel:
|
1782 | |
return
|
1783 | |
# If isfile = True, file; If isfile = False, folder
|
1784 | |
dialog = gtk.FileChooserDialog(title=_("Open"),action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
1785 | |
if isfile:
|
1786 | |
filter = gtk.FileFilter()
|
1787 | |
filter.set_name(_("Images"))
|
1788 | |
filter.add_pixbuf_formats()
|
1789 | |
dialog.add_filter(filter)
|
1790 | |
filter = gtk.FileFilter()
|
1791 | |
filter.set_name(_("All files"))
|
1792 | |
filter.add_pattern("*")
|
1793 | |
dialog.add_filter(filter)
|
1794 | |
preview = gtk.Image()
|
1795 | |
dialog.set_preview_widget(preview)
|
1796 | |
dialog.set_use_preview_label(False)
|
1797 | |
dialog.connect("update-preview", self.update_preview, preview)
|
1798 | |
recursivebutton = None
|
1799 | |
else:
|
1800 | |
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
1801 | |
recursivebutton = gtk.CheckButton(label=_("Include images in subdirectories"))
|
1802 | |
dialog.set_extra_widget(recursivebutton)
|
1803 | |
dialog.set_default_response(gtk.RESPONSE_OK)
|
1804 | |
dialog.set_select_multiple(True)
|
1805 | |
if self.use_last_dir:
|
1806 | |
if self.last_dir != None:
|
1807 | |
dialog.set_current_folder(self.last_dir)
|
1808 | |
else:
|
1809 | |
if self.fixed_dir != None:
|
1810 | |
dialog.set_current_folder(self.fixed_dir)
|
1811 | |
dialog.connect("response", self.open_file_or_folder_response, isfile, recursivebutton)
|
1812 | |
response = dialog.show()
|
1813 | |
|
1814 | |
def open_file_or_folder_response(self, dialog, response, isfile, recursivebutton):
|
1815 | |
if response == gtk.RESPONSE_OK:
|
1816 | |
if self.use_last_dir:
|
1817 | |
self.last_dir = dialog.get_current_folder()
|
1818 | |
if not isfile and recursivebutton.get_property('active'):
|
1819 | |
self.recursive = True
|
1820 | |
filenames = dialog.get_filenames()
|
1821 | |
dialog.destroy()
|
1822 | |
while gtk.events_pending():
|
1823 | |
gtk.main_iteration()
|
1824 | |
self.expand_filelist_and_load_image(filenames)
|
1825 | |
else:
|
1826 | |
dialog.destroy()
|
1827 | |
|
1828 | |
def update_preview(self, file_chooser, preview):
|
1829 | |
filename = file_chooser.get_preview_filename()
|
1830 | |
if not filename:
|
1831 | |
return
|
1832 | |
filename, thumbfile = self.thumbnail_get_name(filename)
|
1833 | |
pixbuf = self.thumbpane_get_pixbuf(thumbfile, filename, False)
|
1834 | |
if pixbuf:
|
1835 | |
preview.set_from_pixbuf(pixbuf)
|
1836 | |
else:
|
1837 | |
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 1, 8, 128, 128)
|
1838 | |
pixbuf.fill(0x00000000)
|
1839 | |
preview.set_from_pixbuf(pixbuf)
|
1840 | |
have_preview = True
|
1841 | |
file_chooser.set_preview_widget_active(have_preview)
|
1842 | |
del pixbuf
|
1843 | |
gc.collect()
|
1844 | |
|
1845 | |
def hide_cursor(self):
|
1846 | |
if self.fullscreen_mode and not self.user_prompt_visible and not self.slideshow_controls_visible:
|
1847 | |
pix_data = """/* XPM */
|
|
1464 |
if not self.resource_path_list:
|
|
1465 |
# If executed from mirage in bin this points to the basedir
|
|
1466 |
basedir_mirage = os.path.split(sys.path[0])[0]
|
|
1467 |
# If executed from mirage.py module in python lib this points to the basedir
|
|
1468 |
f0 = os.path.split(__file__)[0].split("/lib")[0]
|
|
1469 |
self.resource_path_list = list(
|
|
1470 |
set(
|
|
1471 |
filter(
|
|
1472 |
os.path.isdir,
|
|
1473 |
[
|
|
1474 |
os.path.join(basedir_mirage, "share", "mirage"),
|
|
1475 |
os.path.join(basedir_mirage, "share", "pixmaps"),
|
|
1476 |
os.path.join(sys.prefix, "share", "mirage"),
|
|
1477 |
os.path.join(sys.prefix, "share", "pixmaps"),
|
|
1478 |
os.path.join(sys.prefix, "local", "share", "mirage"),
|
|
1479 |
os.path.join(sys.prefix, "local", "share", "pixmaps"),
|
|
1480 |
sys.path[0], # If it's run non-installed
|
|
1481 |
os.path.join(f0, "share", "mirage"),
|
|
1482 |
os.path.join(f0, "share", "pixmaps"),
|
|
1483 |
],
|
|
1484 |
)
|
|
1485 |
)
|
|
1486 |
)
|
|
1487 |
for path in self.resource_path_list:
|
|
1488 |
pix = os.path.join(path, filename)
|
|
1489 |
if os.path.exists(pix):
|
|
1490 |
return pix
|
|
1491 |
# If we reached here, we didn't find the pixmap
|
|
1492 |
if exit_on_fail:
|
|
1493 |
print(
|
|
1494 |
_("Couldn't find the image %s. Please check your installation.")
|
|
1495 |
% filename
|
|
1496 |
)
|
|
1497 |
sys.exit(1)
|
|
1498 |
else:
|
|
1499 |
return None
|
|
1500 |
|
|
1501 |
def gconf_key_changed(self, client, cnxn_id, entry, label):
|
|
1502 |
if entry.value.type == gconf.VALUE_STRING:
|
|
1503 |
style = entry.value.to_string()
|
|
1504 |
if style == "both":
|
|
1505 |
self.toolbar.set_style(gtk.TOOLBAR_BOTH)
|
|
1506 |
elif style == "both-horiz":
|
|
1507 |
self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
|
|
1508 |
elif style == "icons":
|
|
1509 |
self.toolbar.set_style(gtk.TOOLBAR_ICONS)
|
|
1510 |
elif style == "text":
|
|
1511 |
self.toolbar.set_style(gtk.TOOLBAR_TEXT)
|
|
1512 |
if self.image_loaded and self.last_image_action_was_fit:
|
|
1513 |
if self.last_image_action_was_smart_fit:
|
|
1514 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
1515 |
else:
|
|
1516 |
self.zoom_to_fit_window(None, False, False)
|
|
1517 |
|
|
1518 |
def toolbar_focused(self, widget, direction):
|
|
1519 |
self.layout.grab_focus()
|
|
1520 |
return True
|
|
1521 |
|
|
1522 |
def topwindow_keypress(self, widget, event):
|
|
1523 |
# For whatever reason, 'Left' and 'Right' cannot be used as menu
|
|
1524 |
# accelerators so we will manually check for them here:
|
|
1525 |
if (
|
|
1526 |
(not (event.state & gtk.gdk.SHIFT_MASK))
|
|
1527 |
and not (event.state & gtk.gdk.CONTROL_MASK)
|
|
1528 |
and not (event.state & gtk.gdk.MOD1_MASK)
|
|
1529 |
and not (event.state & gtk.gdk.MOD2_MASK)
|
|
1530 |
and not (event.state & gtk.gdk.CONTROL_MASK)
|
|
1531 |
):
|
|
1532 |
if event.keyval == gtk.gdk.keyval_from_name(
|
|
1533 |
"Left"
|
|
1534 |
) or event.keyval == gtk.gdk.keyval_from_name("Up"):
|
|
1535 |
self.goto_prev_image(None)
|
|
1536 |
return
|
|
1537 |
elif event.keyval == gtk.gdk.keyval_from_name(
|
|
1538 |
"Right"
|
|
1539 |
) or event.keyval == gtk.gdk.keyval_from_name("Down"):
|
|
1540 |
self.goto_next_image(None)
|
|
1541 |
return
|
|
1542 |
shortcut = gtk.accelerator_name(event.keyval, event.state)
|
|
1543 |
if "Escape" in shortcut:
|
|
1544 |
self.stop_now = True
|
|
1545 |
self.searching_for_images = False
|
|
1546 |
while gtk.events_pending():
|
|
1547 |
gtk.main_iteration()
|
|
1548 |
self.update_title()
|
|
1549 |
return
|
|
1550 |
|
|
1551 |
def parse_action_command(self, command, batchmode):
|
|
1552 |
self.running_custom_actions = True
|
|
1553 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
1554 |
while gtk.events_pending():
|
|
1555 |
gtk.main_iteration()
|
|
1556 |
self.curr_custom_action = 0
|
|
1557 |
if batchmode:
|
|
1558 |
self.num_custom_actions = len(self.image_list)
|
|
1559 |
for i in range(self.num_custom_actions):
|
|
1560 |
self.curr_custom_action += 1
|
|
1561 |
self.update_statusbar()
|
|
1562 |
while gtk.events_pending():
|
|
1563 |
gtk.main_iteration()
|
|
1564 |
imagename = self.image_list[i]
|
|
1565 |
self.parse_action_command2(command, imagename)
|
|
1566 |
else:
|
|
1567 |
self.num_custom_actions = 1
|
|
1568 |
self.curr_custom_action = 1
|
|
1569 |
self.update_statusbar()
|
|
1570 |
while gtk.events_pending():
|
|
1571 |
gtk.main_iteration()
|
|
1572 |
self.parse_action_command2(command, self.currimg_name)
|
|
1573 |
gc.collect()
|
|
1574 |
self.change_cursor(None)
|
|
1575 |
# Refresh the current image or any preloaded needed if they have changed:
|
|
1576 |
if not os.path.exists(self.currimg_name):
|
|
1577 |
self.currimg_pixbuf_original = None
|
|
1578 |
self.image_load_failed(False)
|
|
1579 |
else:
|
|
1580 |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
|
1581 |
if animtest.is_static_image():
|
|
1582 |
if self.images_are_different(
|
|
1583 |
animtest.get_static_image(), self.currimg_pixbuf_original
|
|
1584 |
):
|
|
1585 |
self.load_new_image2(False, False, True, False)
|
|
1586 |
else:
|
|
1587 |
if self.images_are_different(animtest, self.currimg_pixbuf_original):
|
|
1588 |
self.load_new_image2(False, False, True, False)
|
|
1589 |
self.running_custom_actions = False
|
|
1590 |
self.update_statusbar()
|
|
1591 |
while gtk.events_pending():
|
|
1592 |
gtk.main_iteration()
|
|
1593 |
if not os.path.exists(self.preloadimg_prev_name):
|
|
1594 |
self.preloadimg_prev_in_list = -1
|
|
1595 |
else:
|
|
1596 |
animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
|
|
1597 |
if animtest.is_static_image():
|
|
1598 |
if self.images_are_different(
|
|
1599 |
animtest.get_static_image(), self.preloadimg_prev_pixbuf_original
|
|
1600 |
):
|
|
1601 |
self.preloadimg_prev_in_list = -1
|
|
1602 |
self.preload_when_idle = gobject.idle_add(
|
|
1603 |
self.preload_prev_image, False
|
|
1604 |
)
|
|
1605 |
else:
|
|
1606 |
if self.images_are_different(
|
|
1607 |
animtest, self.preloadimg_prev_pixbuf_original
|
|
1608 |
):
|
|
1609 |
self.preloadimg_prev_in_list = -1
|
|
1610 |
self.preload_when_idle = gobject.idle_add(
|
|
1611 |
self.preload_prev_image, False
|
|
1612 |
)
|
|
1613 |
if not os.path.exists(self.preloadimg_next_name):
|
|
1614 |
self.preloadimg_next_in_list = -1
|
|
1615 |
else:
|
|
1616 |
animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
|
|
1617 |
if animtest.is_static_image():
|
|
1618 |
if self.images_are_different(
|
|
1619 |
animtest.get_static_image(), self.preloadimg_next_pixbuf_original
|
|
1620 |
):
|
|
1621 |
self.preloadimg_next_in_list = -1
|
|
1622 |
self.preload_when_idle = gobject.idle_add(
|
|
1623 |
self.preload_next_image, False
|
|
1624 |
)
|
|
1625 |
else:
|
|
1626 |
if self.images_are_different(
|
|
1627 |
animtest, self.preloadimg_next_pixbuf_original
|
|
1628 |
):
|
|
1629 |
self.preloadimg_next_in_list = -1
|
|
1630 |
self.preload_when_idle = gobject.idle_add(
|
|
1631 |
self.preload_next_image, False
|
|
1632 |
)
|
|
1633 |
self.stop_now = False
|
|
1634 |
if batchmode:
|
|
1635 |
# Update all thumbnails:
|
|
1636 |
gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
|
|
1637 |
else:
|
|
1638 |
# Update only the current thumbnail:
|
|
1639 |
gobject.idle_add(
|
|
1640 |
self.thumbpane_set_image,
|
|
1641 |
self.image_list[self.curr_img_in_list],
|
|
1642 |
self.curr_img_in_list,
|
|
1643 |
True,
|
|
1644 |
)
|
|
1645 |
|
|
1646 |
def images_are_different(self, pixbuf1, pixbuf2):
|
|
1647 |
if pixbuf1.get_pixels() == pixbuf2.get_pixels():
|
|
1648 |
return False
|
|
1649 |
else:
|
|
1650 |
return True
|
|
1651 |
|
|
1652 |
def recent_action_click(self, action):
|
|
1653 |
self.stop_now = True
|
|
1654 |
while gtk.events_pending():
|
|
1655 |
gtk.main_iteration()
|
|
1656 |
cancel = self.autosave_image()
|
|
1657 |
if cancel:
|
|
1658 |
return
|
|
1659 |
index = int(action.get_name())
|
|
1660 |
if (
|
|
1661 |
os.path.isfile(self.recentfiles[index])
|
|
1662 |
or os.path.exists(self.recentfiles[index])
|
|
1663 |
or self.recentfiles[index].startswith("http://")
|
|
1664 |
or self.recentfiles[index].startswith("ftp://")
|
|
1665 |
):
|
|
1666 |
self.expand_filelist_and_load_image([self.recentfiles[index]])
|
|
1667 |
else:
|
|
1668 |
self.image_list = []
|
|
1669 |
self.curr_img_in_list = 0
|
|
1670 |
self.image_list.append(self.recentfiles[index])
|
|
1671 |
self.image_load_failed(False)
|
|
1672 |
self.recent_file_remove_and_refresh(index)
|
|
1673 |
|
|
1674 |
def recent_file_remove_and_refresh_name(self, rmfile):
|
|
1675 |
index_num = 0
|
|
1676 |
for imgfile in self.recentfiles:
|
|
1677 |
if imgfile == rmfile:
|
|
1678 |
self.recent_file_remove_and_refresh(index_num)
|
|
1679 |
break
|
|
1680 |
index_num += index_num
|
|
1681 |
|
|
1682 |
def recent_file_remove_and_refresh(self, index_num):
|
|
1683 |
i = index_num
|
|
1684 |
while i < len(self.recentfiles) - 1:
|
|
1685 |
self.recentfiles[i] = self.recentfiles[i + 1]
|
|
1686 |
i = i + 1
|
|
1687 |
# Set last item empty:
|
|
1688 |
self.recentfiles[len(self.recentfiles) - 1] = ""
|
|
1689 |
self.refresh_recent_files_menu()
|
|
1690 |
|
|
1691 |
def recent_file_add_and_refresh(self, addfile):
|
|
1692 |
# First check if the filename is already in the list:
|
|
1693 |
for i in range(len(self.recentfiles)):
|
|
1694 |
if len(self.recentfiles[i]) > 0:
|
|
1695 |
if addfile == self.recentfiles[i]:
|
|
1696 |
# If found in list, put to position 1 and decrement the rest:
|
|
1697 |
j = i
|
|
1698 |
while j > 0:
|
|
1699 |
self.recentfiles[j] = self.recentfiles[j - 1]
|
|
1700 |
j = j - 1
|
|
1701 |
self.recentfiles[0] = addfile
|
|
1702 |
self.refresh_recent_files_menu()
|
|
1703 |
return
|
|
1704 |
# If not found, put to position 1, decrement the rest:
|
|
1705 |
j = len(self.recentfiles) - 1
|
|
1706 |
while j > 0:
|
|
1707 |
self.recentfiles[j] = self.recentfiles[j - 1]
|
|
1708 |
j = j - 1
|
|
1709 |
if len(self.recentfiles) > 0:
|
|
1710 |
self.recentfiles[0] = addfile
|
|
1711 |
self.refresh_recent_files_menu()
|
|
1712 |
|
|
1713 |
def custom_action_click(self, action):
|
|
1714 |
if self.UIManager.get_widget(
|
|
1715 |
"/MainMenu/EditMenu/ActionSubMenu/" + action.get_name()
|
|
1716 |
).get_property("sensitive"):
|
|
1717 |
for i in range(len(self.action_shortcuts)):
|
|
1718 |
try:
|
|
1719 |
if action.get_name() == self.action_names[i]:
|
|
1720 |
self.parse_action_command(
|
|
1721 |
self.action_commands[i], self.action_batch[i]
|
|
1722 |
)
|
|
1723 |
except:
|
|
1724 |
pass
|
|
1725 |
|
|
1726 |
def parse_action_command2(self, cmd, imagename):
|
|
1727 |
# Executes the given command using ``os.system``, substituting "%"-macros approprately.
|
|
1728 |
def sh_esc(s):
|
|
1729 |
import re
|
|
1730 |
|
|
1731 |
return re.sub(r"[^/._a-zA-Z0-9-]", lambda c: "\\" + c.group(), s)
|
|
1732 |
|
|
1733 |
cmd = cmd.strip()
|
|
1734 |
# [NEXT] and [PREV] are only valid alone or at the end of the command
|
|
1735 |
if cmd == "[NEXT]":
|
|
1736 |
self.goto_next_image(None)
|
|
1737 |
return
|
|
1738 |
elif cmd == "[PREV]":
|
|
1739 |
self.goto_prev_image(None)
|
|
1740 |
return
|
|
1741 |
# -1=go to previous, 1=go to next, 0=don't change
|
|
1742 |
prev_or_next = 0
|
|
1743 |
if cmd[-6:] == "[NEXT]":
|
|
1744 |
prev_or_next = 1
|
|
1745 |
cmd = cmd[:-6]
|
|
1746 |
elif cmd[-6:] == "[PREV]":
|
|
1747 |
prev_or_next = -1
|
|
1748 |
cmd = cmd[:-6]
|
|
1749 |
if "%F" in cmd:
|
|
1750 |
cmd = cmd.replace("%F", sh_esc(imagename))
|
|
1751 |
if "%N" in cmd:
|
|
1752 |
cmd = cmd.replace(
|
|
1753 |
"%N", sh_esc(os.path.splitext(os.path.basename(imagename))[0])
|
|
1754 |
)
|
|
1755 |
if "%P" in cmd:
|
|
1756 |
cmd = cmd.replace("%P", sh_esc(os.path.dirname(imagename) + "/"))
|
|
1757 |
if "%E" in cmd:
|
|
1758 |
cmd = cmd.replace(
|
|
1759 |
"%E", sh_esc(os.path.splitext(os.path.basename(imagename))[1])
|
|
1760 |
)
|
|
1761 |
if "%L" in cmd:
|
|
1762 |
cmd = cmd.replace("%L", " ".join([sh_esc(s) for s in self.image_list]))
|
|
1763 |
if self.verbose:
|
|
1764 |
print(_("Action: %s") % cmd)
|
|
1765 |
shell_rc = os.system(cmd) >> 8
|
|
1766 |
if self.verbose:
|
|
1767 |
print(_("Action return code: %s") % shell_rc)
|
|
1768 |
if shell_rc != 0:
|
|
1769 |
msg = (
|
|
1770 |
_(
|
|
1771 |
'Unable to launch "%s". Please specify a valid command from Edit > Custom Actions.'
|
|
1772 |
)
|
|
1773 |
% cmd
|
|
1774 |
)
|
|
1775 |
error_dialog = gtk.MessageDialog(
|
|
1776 |
self.window,
|
|
1777 |
gtk.DIALOG_MODAL,
|
|
1778 |
gtk.MESSAGE_WARNING,
|
|
1779 |
gtk.BUTTONS_CLOSE,
|
|
1780 |
msg,
|
|
1781 |
)
|
|
1782 |
error_dialog.set_title(_("Invalid Custom Action"))
|
|
1783 |
error_dialog.run()
|
|
1784 |
error_dialog.destroy()
|
|
1785 |
elif prev_or_next == 1:
|
|
1786 |
self.goto_next_image(None)
|
|
1787 |
elif prev_or_next == -1:
|
|
1788 |
self.goto_prev_image(None)
|
|
1789 |
self.running_custom_actions = False
|
|
1790 |
|
|
1791 |
def set_go_sensitivities(self, enable):
|
|
1792 |
self.UIManager.get_widget("/MainMenu/GoMenu/Previous Image").set_sensitive(
|
|
1793 |
enable
|
|
1794 |
)
|
|
1795 |
self.UIManager.get_widget("/MainMenu/GoMenu/Next Image").set_sensitive(enable)
|
|
1796 |
self.UIManager.get_widget("/MainMenu/GoMenu/Random Image").set_sensitive(enable)
|
|
1797 |
self.UIManager.get_widget("/MainMenu/GoMenu/First Image").set_sensitive(enable)
|
|
1798 |
self.UIManager.get_widget("/MainMenu/GoMenu/Last Image").set_sensitive(enable)
|
|
1799 |
self.UIManager.get_widget("/Popup/Previous Image").set_sensitive(enable)
|
|
1800 |
self.UIManager.get_widget("/Popup/Next Image").set_sensitive(enable)
|
|
1801 |
self.UIManager.get_widget("/MainToolbar/Previous2").set_sensitive(enable)
|
|
1802 |
self.UIManager.get_widget("/MainToolbar/Next2").set_sensitive(enable)
|
|
1803 |
self.ss_forward.set_sensitive(enable)
|
|
1804 |
self.ss_back.set_sensitive(enable)
|
|
1805 |
|
|
1806 |
def set_image_sensitivities(self, enable):
|
|
1807 |
self.set_zoom_in_sensitivities(enable)
|
|
1808 |
self.set_zoom_out_sensitivities(enable)
|
|
1809 |
self.UIManager.get_widget("/MainMenu/ViewMenu/1:1").set_sensitive(enable)
|
|
1810 |
self.UIManager.get_widget("/MainMenu/ViewMenu/Fit").set_sensitive(enable)
|
|
1811 |
self.UIManager.get_widget("/MainMenu/EditMenu/Delete Image").set_sensitive(
|
|
1812 |
enable
|
|
1813 |
)
|
|
1814 |
self.UIManager.get_widget("/MainMenu/EditMenu/Rename Image").set_sensitive(
|
|
1815 |
enable
|
|
1816 |
)
|
|
1817 |
self.UIManager.get_widget("/MainMenu/EditMenu/Crop").set_sensitive(enable)
|
|
1818 |
self.UIManager.get_widget("/MainMenu/EditMenu/Resize").set_sensitive(enable)
|
|
1819 |
self.UIManager.get_widget("/MainMenu/EditMenu/Saturation").set_sensitive(enable)
|
|
1820 |
self.UIManager.get_widget("/MainToolbar/1:1").set_sensitive(enable)
|
|
1821 |
self.UIManager.get_widget("/MainToolbar/Fit").set_sensitive(enable)
|
|
1822 |
self.UIManager.get_widget("/Popup/1:1").set_sensitive(enable)
|
|
1823 |
self.UIManager.get_widget("/Popup/Fit").set_sensitive(enable)
|
|
1824 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save As").set_sensitive(enable)
|
|
1825 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_sensitive(False)
|
|
1826 |
self.UIManager.get_widget("/MainMenu/FileMenu/Properties").set_sensitive(False)
|
|
1827 |
# Only jpeg, png, and bmp images are currently supported for saving
|
|
1828 |
if len(self.image_list) > 0:
|
|
1829 |
try:
|
|
1830 |
filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]["name"]
|
|
1831 |
self.UIManager.get_widget(
|
|
1832 |
"/MainMenu/FileMenu/Properties"
|
|
1833 |
).set_sensitive(True)
|
|
1834 |
if self.filetype_is_writable(filetype):
|
|
1835 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_sensitive(
|
|
1836 |
enable
|
|
1837 |
)
|
|
1838 |
except:
|
|
1839 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_sensitive(
|
|
1840 |
False
|
|
1841 |
)
|
|
1842 |
if self.actionGroupCustom:
|
|
1843 |
for action in self.action_names:
|
|
1844 |
self.UIManager.get_widget(
|
|
1845 |
"/MainMenu/EditMenu/ActionSubMenu/" + action
|
|
1846 |
).set_sensitive(enable)
|
|
1847 |
if not HAS_IMGFUNCS:
|
|
1848 |
enable = False
|
|
1849 |
self.UIManager.get_widget("/MainMenu/EditMenu/Rotate Left").set_sensitive(
|
|
1850 |
enable
|
|
1851 |
)
|
|
1852 |
self.UIManager.get_widget("/MainMenu/EditMenu/Rotate Right").set_sensitive(
|
|
1853 |
enable
|
|
1854 |
)
|
|
1855 |
self.UIManager.get_widget("/MainMenu/EditMenu/Flip Vertically").set_sensitive(
|
|
1856 |
enable
|
|
1857 |
)
|
|
1858 |
self.UIManager.get_widget("/MainMenu/EditMenu/Flip Horizontally").set_sensitive(
|
|
1859 |
enable
|
|
1860 |
)
|
|
1861 |
|
|
1862 |
def set_zoom_in_sensitivities(self, enable):
|
|
1863 |
self.UIManager.get_widget("/MainMenu/ViewMenu/In").set_sensitive(enable)
|
|
1864 |
self.UIManager.get_widget("/MainToolbar/In").set_sensitive(enable)
|
|
1865 |
self.UIManager.get_widget("/Popup/In").set_sensitive(enable)
|
|
1866 |
|
|
1867 |
def set_zoom_out_sensitivities(self, enable):
|
|
1868 |
self.UIManager.get_widget("/MainMenu/ViewMenu/Out").set_sensitive(enable)
|
|
1869 |
self.UIManager.get_widget("/MainToolbar/Out").set_sensitive(enable)
|
|
1870 |
self.UIManager.get_widget("/Popup/Out").set_sensitive(enable)
|
|
1871 |
|
|
1872 |
def set_next_image_sensitivities(self, enable):
|
|
1873 |
self.UIManager.get_widget("/MainToolbar/Next2").set_sensitive(enable)
|
|
1874 |
self.UIManager.get_widget("/MainMenu/GoMenu/Next Image").set_sensitive(enable)
|
|
1875 |
self.UIManager.get_widget("/Popup/Next Image").set_sensitive(enable)
|
|
1876 |
self.ss_forward.set_sensitive(enable)
|
|
1877 |
|
|
1878 |
def set_previous_image_sensitivities(self, enable):
|
|
1879 |
self.UIManager.get_widget("/MainToolbar/Previous2").set_sensitive(enable)
|
|
1880 |
self.UIManager.get_widget("/MainMenu/GoMenu/Previous Image").set_sensitive(
|
|
1881 |
enable
|
|
1882 |
)
|
|
1883 |
self.UIManager.get_widget("/Popup/Previous Image").set_sensitive(enable)
|
|
1884 |
self.ss_back.set_sensitive(enable)
|
|
1885 |
|
|
1886 |
def set_first_image_sensitivities(self, enable):
|
|
1887 |
self.UIManager.get_widget("/MainMenu/GoMenu/First Image").set_sensitive(enable)
|
|
1888 |
|
|
1889 |
def set_last_image_sensitivities(self, enable):
|
|
1890 |
self.UIManager.get_widget("/MainMenu/GoMenu/Last Image").set_sensitive(enable)
|
|
1891 |
|
|
1892 |
def set_random_image_sensitivities(self, enable):
|
|
1893 |
self.UIManager.get_widget("/MainMenu/GoMenu/Random Image").set_sensitive(enable)
|
|
1894 |
|
|
1895 |
def set_slideshow_sensitivities(self):
|
|
1896 |
if len(self.image_list) <= 1:
|
|
1897 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").show()
|
|
1898 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").set_sensitive(
|
|
1899 |
False
|
|
1900 |
)
|
|
1901 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").hide()
|
|
1902 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").set_sensitive(
|
|
1903 |
False
|
|
1904 |
)
|
|
1905 |
elif self.slideshow_mode:
|
|
1906 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").hide()
|
|
1907 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").set_sensitive(
|
|
1908 |
False
|
|
1909 |
)
|
|
1910 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").show()
|
|
1911 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").set_sensitive(
|
|
1912 |
True
|
|
1913 |
)
|
|
1914 |
else:
|
|
1915 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").show()
|
|
1916 |
self.UIManager.get_widget("/MainMenu/GoMenu/Start Slideshow").set_sensitive(
|
|
1917 |
True
|
|
1918 |
)
|
|
1919 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").hide()
|
|
1920 |
self.UIManager.get_widget("/MainMenu/GoMenu/Stop Slideshow").set_sensitive(
|
|
1921 |
False
|
|
1922 |
)
|
|
1923 |
if self.slideshow_mode:
|
|
1924 |
self.UIManager.get_widget("/Popup/Start Slideshow").hide()
|
|
1925 |
self.UIManager.get_widget("/Popup/Stop Slideshow").show()
|
|
1926 |
else:
|
|
1927 |
self.UIManager.get_widget("/Popup/Start Slideshow").show()
|
|
1928 |
self.UIManager.get_widget("/Popup/Stop Slideshow").hide()
|
|
1929 |
if len(self.image_list) <= 1:
|
|
1930 |
self.UIManager.get_widget("/Popup/Start Slideshow").set_sensitive(False)
|
|
1931 |
else:
|
|
1932 |
self.UIManager.get_widget("/Popup/Start Slideshow").set_sensitive(True)
|
|
1933 |
|
|
1934 |
def set_zoom_sensitivities(self):
|
|
1935 |
if not self.currimg_is_animation:
|
|
1936 |
self.set_zoom_out_sensitivities(True)
|
|
1937 |
self.set_zoom_in_sensitivities(True)
|
|
1938 |
else:
|
|
1939 |
self.set_zoom_out_sensitivities(False)
|
|
1940 |
self.set_zoom_in_sensitivities(False)
|
|
1941 |
|
|
1942 |
def print_version(self):
|
|
1943 |
print(_("Version: Mirage"), __version__)
|
|
1944 |
print(_("Website: http://mirageiv.berlios.de"))
|
|
1945 |
|
|
1946 |
def print_usage(self):
|
|
1947 |
self.print_version()
|
|
1948 |
print("")
|
|
1949 |
print(_("Usage: mirage [OPTION]... FILES|FOLDERS..."))
|
|
1950 |
print("")
|
|
1951 |
print(_("Options") + ":")
|
|
1952 |
print(" -h, --help " + _("Show this help and exit"))
|
|
1953 |
print(" -v, --version " + _("Show version information and exit"))
|
|
1954 |
print(" -V, --verbose " + _("Show more detailed information"))
|
|
1955 |
print(" -R, --recursive " + _("Recursively include all images found in"))
|
|
1956 |
print(" " + _("subdirectories of FOLDERS"))
|
|
1957 |
print(" -s, --slideshow " + _("Start in slideshow mode"))
|
|
1958 |
print(" -f, --fullscreen " + _("Start in fullscreen mode"))
|
|
1959 |
print(" -o, --onload 'cmd' " + _("Execute 'cmd' when an image is loaded"))
|
|
1960 |
print(" " + _("uses same syntax as custom actions,\n"))
|
|
1961 |
print(" " + _("i.e. mirage -o 'echo file is %F'"))
|
|
1962 |
|
|
1963 |
def delay_changed(self, action):
|
|
1964 |
self.curr_slideshow_delay = self.ss_delayspin.get_value()
|
|
1965 |
if self.slideshow_mode:
|
|
1966 |
gobject.source_remove(self.timer_delay)
|
|
1967 |
if self.curr_slideshow_random:
|
|
1968 |
self.timer_delay = gobject.timeout_add(
|
|
1969 |
int(self.curr_slideshow_delay * 1000), self.goto_random_image, "ss"
|
|
1970 |
)
|
|
1971 |
else:
|
|
1972 |
self.timer_delay = gobject.timeout_add(
|
|
1973 |
(self.curr_slideshow_delay * 1000), self.goto_next_image, "ss"
|
|
1974 |
)
|
|
1975 |
self.window.set_focus(self.layout)
|
|
1976 |
|
|
1977 |
def random_changed(self, action):
|
|
1978 |
self.curr_slideshow_random = self.ss_randomize.get_active()
|
|
1979 |
|
|
1980 |
def motion_cb(self, widget, context, x, y, time):
|
|
1981 |
context.drag_status(gtk.gdk.ACTION_COPY, time)
|
|
1982 |
return True
|
|
1983 |
|
|
1984 |
def drop_cb(self, widget, context, x, y, selection, info, time):
|
|
1985 |
uri = selection.data.strip()
|
|
1986 |
path = urllib.request.url2pathname(uri)
|
|
1987 |
paths = path.rsplit("\n")
|
|
1988 |
for i, path in enumerate(paths):
|
|
1989 |
paths[i] = path.rstrip("\r")
|
|
1990 |
self.expand_filelist_and_load_image(paths)
|
|
1991 |
|
|
1992 |
def put_error_image_to_window(self):
|
|
1993 |
self.imageview.set_from_stock(
|
|
1994 |
gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR
|
|
1995 |
)
|
|
1996 |
self.currimg_width = self.imageview.size_request()[0]
|
|
1997 |
self.currimg_height = self.imageview.size_request()[1]
|
|
1998 |
self.center_image()
|
|
1999 |
self.set_go_sensitivities(False)
|
|
2000 |
self.set_image_sensitivities(False)
|
|
2001 |
self.update_statusbar()
|
|
2002 |
self.loaded_img_in_list = -1
|
|
2003 |
return
|
|
2004 |
|
|
2005 |
def expose_event(self, widget, event):
|
|
2006 |
if self.updating_adjustments:
|
|
2007 |
return
|
|
2008 |
self.updating_adjustments = True
|
|
2009 |
if self.hscroll.get_property("visible"):
|
|
2010 |
try:
|
|
2011 |
zoomratio = float(self.currimg_width) / self.previmg_width
|
|
2012 |
newvalue = abs(
|
|
2013 |
self.layout.get_hadjustment().get_value() * zoomratio
|
|
2014 |
+ ((self.available_image_width()) * (zoomratio - 1)) // 2
|
|
2015 |
)
|
|
2016 |
if newvalue >= self.layout.get_hadjustment().lower and newvalue <= (
|
|
2017 |
self.layout.get_hadjustment().upper
|
|
2018 |
- self.layout.get_hadjustment().page_size
|
|
2019 |
):
|
|
2020 |
self.layout.get_hadjustment().set_value(newvalue)
|
|
2021 |
except:
|
|
2022 |
pass
|
|
2023 |
if self.vscroll.get_property("visible"):
|
|
2024 |
try:
|
|
2025 |
newvalue = abs(
|
|
2026 |
self.layout.get_vadjustment().get_value() * zoomratio
|
|
2027 |
+ ((self.available_image_height()) * (zoomratio - 1)) // 2
|
|
2028 |
)
|
|
2029 |
if newvalue >= self.layout.get_vadjustment().lower and newvalue <= (
|
|
2030 |
self.layout.get_vadjustment().upper
|
|
2031 |
- self.layout.get_vadjustment().page_size
|
|
2032 |
):
|
|
2033 |
self.layout.get_vadjustment().set_value(newvalue)
|
|
2034 |
self.previmg_width = self.currimg_width
|
|
2035 |
except:
|
|
2036 |
pass
|
|
2037 |
self.updating_adjustments = False
|
|
2038 |
|
|
2039 |
def window_resized(self, widget, allocation, force_update=False):
|
|
2040 |
# Update the image size on window resize if the current image was last fit:
|
|
2041 |
if self.image_loaded:
|
|
2042 |
if (
|
|
2043 |
force_update
|
|
2044 |
or allocation.width != self.prevwinwidth
|
|
2045 |
or allocation.height != self.prevwinheight
|
|
2046 |
):
|
|
2047 |
if self.last_image_action_was_fit:
|
|
2048 |
if self.last_image_action_was_smart_fit:
|
|
2049 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
2050 |
else:
|
|
2051 |
self.zoom_to_fit_window(None, False, False)
|
|
2052 |
else:
|
|
2053 |
self.center_image()
|
|
2054 |
self.load_new_image_stop_now()
|
|
2055 |
self.show_scrollbars_if_needed()
|
|
2056 |
# Also, regenerate preloaded image for new window size:
|
|
2057 |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, True)
|
|
2058 |
self.preload_when_idle2 = gobject.idle_add(
|
|
2059 |
self.preload_prev_image, True
|
|
2060 |
)
|
|
2061 |
self.prevwinwidth = allocation.width
|
|
2062 |
self.prevwinheight = allocation.height
|
|
2063 |
return
|
|
2064 |
|
|
2065 |
def save_settings(self):
|
|
2066 |
conf = configparser.ConfigParser()
|
|
2067 |
conf.add_section("window")
|
|
2068 |
conf.set("window", "w", self.window.get_allocation().width)
|
|
2069 |
conf.set("window", "h", self.window.get_allocation().height)
|
|
2070 |
conf.set("window", "toolbar", self.toolbar_show)
|
|
2071 |
conf.set("window", "statusbar", self.statusbar_show)
|
|
2072 |
conf.set("window", "thumbpane", self.thumbpane_show)
|
|
2073 |
conf.add_section("prefs")
|
|
2074 |
conf.set("prefs", "simple-bgcolor", self.simple_bgcolor)
|
|
2075 |
conf.set("prefs", "bgcolor-red", self.bgcolor.red)
|
|
2076 |
conf.set("prefs", "bgcolor-green", self.bgcolor.green)
|
|
2077 |
conf.set("prefs", "bgcolor-blue", self.bgcolor.blue)
|
|
2078 |
conf.set("prefs", "open_all", self.open_all_images)
|
|
2079 |
conf.set("prefs", "hidden", self.open_hidden_files)
|
|
2080 |
conf.set("prefs", "use_last_dir", self.use_last_dir)
|
|
2081 |
conf.set("prefs", "last_dir", self.last_dir)
|
|
2082 |
conf.set("prefs", "fixed_dir", self.fixed_dir)
|
|
2083 |
conf.set("prefs", "open_mode", self.open_mode)
|
|
2084 |
conf.set("prefs", "last_mode", self.last_mode)
|
|
2085 |
conf.set("prefs", "listwrap_mode", self.listwrap_mode)
|
|
2086 |
conf.set("prefs", "slideshow_delay", int(self.slideshow_delay))
|
|
2087 |
conf.set("prefs", "slideshow_random", self.slideshow_random)
|
|
2088 |
conf.set("prefs", "zoomquality", self.zoomvalue)
|
|
2089 |
conf.set("prefs", "quality_save", int(self.quality_save))
|
|
2090 |
conf.set("prefs", "disable_screensaver", self.disable_screensaver)
|
|
2091 |
conf.set("prefs", "slideshow_in_fullscreen", self.slideshow_in_fullscreen)
|
|
2092 |
conf.set("prefs", "confirm_delete", self.confirm_delete)
|
|
2093 |
conf.set("prefs", "preloading_images", self.preloading_images)
|
|
2094 |
conf.set("prefs", "savemode", self.savemode)
|
|
2095 |
conf.set("prefs", "start_in_fullscreen", self.start_in_fullscreen)
|
|
2096 |
conf.set("prefs", "thumbsize", self.thumbnail_size)
|
|
2097 |
conf.set("prefs", "screenshot_delay", self.screenshot_delay)
|
|
2098 |
conf.add_section("actions")
|
|
2099 |
conf.set("actions", "num_actions", len(self.action_names))
|
|
2100 |
for i in range(len(self.action_names)):
|
|
2101 |
conf.set("actions", "names[" + str(i) + "]", self.action_names[i])
|
|
2102 |
conf.set("actions", "commands[" + str(i) + "]", self.action_commands[i])
|
|
2103 |
conf.set("actions", "shortcuts[" + str(i) + "]", self.action_shortcuts[i])
|
|
2104 |
conf.set("actions", "batch[" + str(i) + "]", self.action_batch[i])
|
|
2105 |
conf.add_section("recent")
|
|
2106 |
conf.set("recent", "num_recent", len(self.recentfiles))
|
|
2107 |
for i in range(len(self.recentfiles)):
|
|
2108 |
conf.set("recent", "num[" + str(i) + "]", len(self.recentfiles[i]))
|
|
2109 |
conf.set("recent", "urls[" + str(i) + ",0]", self.recentfiles[i])
|
|
2110 |
if not os.path.exists(self.config_dir):
|
|
2111 |
os.makedirs(self.config_dir)
|
|
2112 |
conf.write(file(self.config_dir + "/miragerc", "w"))
|
|
2113 |
|
|
2114 |
# Also, save accel_map:
|
|
2115 |
gtk.accel_map_save(self.config_dir + "/accel_map")
|
|
2116 |
|
|
2117 |
return
|
|
2118 |
|
|
2119 |
def delete_event(self, widget, event, data=None):
|
|
2120 |
cancel = self.autosave_image()
|
|
2121 |
if cancel:
|
|
2122 |
return True
|
|
2123 |
self.stop_now = True
|
|
2124 |
self.closing_app = True
|
|
2125 |
self.save_settings()
|
|
2126 |
sys.exit(0)
|
|
2127 |
|
|
2128 |
def destroy(self, event, data=None):
|
|
2129 |
cancel = self.autosave_image()
|
|
2130 |
if cancel:
|
|
2131 |
return True
|
|
2132 |
self.stop_now = True
|
|
2133 |
self.closing_app = True
|
|
2134 |
self.save_settings()
|
|
2135 |
|
|
2136 |
def exit_app(self, action):
|
|
2137 |
cancel = self.autosave_image()
|
|
2138 |
if cancel:
|
|
2139 |
return True
|
|
2140 |
self.stop_now = True
|
|
2141 |
self.closing_app = True
|
|
2142 |
self.save_settings()
|
|
2143 |
sys.exit(0)
|
|
2144 |
|
|
2145 |
def put_zoom_image_to_window(self, currimg_preloaded):
|
|
2146 |
self.window.window.freeze_updates()
|
|
2147 |
if not currimg_preloaded:
|
|
2148 |
# Always start with the original image to preserve quality!
|
|
2149 |
# Calculate image size:
|
|
2150 |
finalimg_width = int(
|
|
2151 |
self.currimg_pixbuf_original.get_width() * self.currimg_zoomratio
|
|
2152 |
)
|
|
2153 |
finalimg_height = int(
|
|
2154 |
self.currimg_pixbuf_original.get_height() * self.currimg_zoomratio
|
|
2155 |
)
|
|
2156 |
if not self.currimg_is_animation:
|
|
2157 |
# Scale image:
|
|
2158 |
if not self.currimg_pixbuf_original.get_has_alpha():
|
|
2159 |
self.currimg_pixbuf = self.currimg_pixbuf_original.scale_simple(
|
|
2160 |
finalimg_width, finalimg_height, self.zoom_quality
|
|
2161 |
)
|
|
2162 |
else:
|
|
2163 |
colormap = self.imageview.get_colormap()
|
|
2164 |
light_grey = colormap.alloc_color("#666666", True, True)
|
|
2165 |
dark_grey = colormap.alloc_color("#999999", True, True)
|
|
2166 |
self.currimg_pixbuf = self.currimg_pixbuf_original.composite_color_simple(
|
|
2167 |
finalimg_width,
|
|
2168 |
finalimg_height,
|
|
2169 |
self.zoom_quality,
|
|
2170 |
255,
|
|
2171 |
8,
|
|
2172 |
light_grey.pixel,
|
|
2173 |
dark_grey.pixel,
|
|
2174 |
)
|
|
2175 |
else:
|
|
2176 |
self.currimg_pixbuf = self.currimg_pixbuf_original
|
|
2177 |
self.currimg_width, self.currimg_height = finalimg_width, finalimg_height
|
|
2178 |
self.layout.set_size(self.currimg_width, self.currimg_height)
|
|
2179 |
self.center_image()
|
|
2180 |
self.show_scrollbars_if_needed()
|
|
2181 |
if not self.currimg_is_animation:
|
|
2182 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
2183 |
self.previmage_is_animation = False
|
|
2184 |
else:
|
|
2185 |
self.imageview.set_from_animation(self.currimg_pixbuf)
|
|
2186 |
self.previmage_is_animation = True
|
|
2187 |
# Clean up (free memory) because I'm lazy
|
|
2188 |
gc.collect()
|
|
2189 |
self.window.window.thaw_updates()
|
|
2190 |
self.loaded_img_in_list = self.curr_img_in_list
|
|
2191 |
|
|
2192 |
def show_scrollbars_if_needed(self):
|
|
2193 |
if self.currimg_width > self.available_image_width():
|
|
2194 |
self.hscroll.show()
|
|
2195 |
else:
|
|
2196 |
self.hscroll.hide()
|
|
2197 |
if self.currimg_height > self.available_image_height():
|
|
2198 |
self.vscroll.show()
|
|
2199 |
else:
|
|
2200 |
self.vscroll.hide()
|
|
2201 |
|
|
2202 |
def center_image(self):
|
|
2203 |
x_shift = int((self.available_image_width() - self.currimg_width) // 2)
|
|
2204 |
if x_shift < 0:
|
|
2205 |
x_shift = 0
|
|
2206 |
y_shift = int((self.available_image_height() - self.currimg_height) // 2)
|
|
2207 |
if y_shift < 0:
|
|
2208 |
y_shift = 0
|
|
2209 |
self.layout.move(self.imageview, x_shift, y_shift)
|
|
2210 |
|
|
2211 |
def available_image_width(self):
|
|
2212 |
width = self.window.get_size()[0]
|
|
2213 |
if not self.fullscreen_mode:
|
|
2214 |
if self.thumbpane_show:
|
|
2215 |
width -= self.thumbscroll.size_request()[0]
|
|
2216 |
return width
|
|
2217 |
|
|
2218 |
def available_image_height(self):
|
|
2219 |
height = self.window.get_size()[1]
|
|
2220 |
if not self.fullscreen_mode:
|
|
2221 |
height -= self.menubar.size_request()[1]
|
|
2222 |
if self.toolbar_show:
|
|
2223 |
height -= self.toolbar.size_request()[1]
|
|
2224 |
if self.statusbar_show:
|
|
2225 |
height -= self.statusbar.size_request()[1]
|
|
2226 |
return height
|
|
2227 |
|
|
2228 |
def save_image(self, action):
|
|
2229 |
if self.UIManager.get_widget("/MainMenu/FileMenu/Save").get_property(
|
|
2230 |
"sensitive"
|
|
2231 |
):
|
|
2232 |
self.save_image_now(
|
|
2233 |
self.currimg_name,
|
|
2234 |
gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]["name"],
|
|
2235 |
)
|
|
2236 |
|
|
2237 |
def save_image_as(self, action):
|
|
2238 |
dialog = gtk.FileChooserDialog(
|
|
2239 |
title=_("Save As"),
|
|
2240 |
action=gtk.FILE_CHOOSER_ACTION_SAVE,
|
|
2241 |
buttons=(
|
|
2242 |
gtk.STOCK_CANCEL,
|
|
2243 |
gtk.RESPONSE_CANCEL,
|
|
2244 |
gtk.STOCK_SAVE,
|
|
2245 |
gtk.RESPONSE_OK,
|
|
2246 |
),
|
|
2247 |
)
|
|
2248 |
dialog.set_default_response(gtk.RESPONSE_OK)
|
|
2249 |
filename = os.path.basename(self.currimg_name)
|
|
2250 |
filetype = None
|
|
2251 |
dialog.set_current_folder(os.path.dirname(self.currimg_name))
|
|
2252 |
dialog.set_current_name(filename)
|
|
2253 |
dialog.set_do_overwrite_confirmation(True)
|
|
2254 |
response = dialog.run()
|
|
2255 |
if response == gtk.RESPONSE_OK:
|
|
2256 |
prev_name = self.currimg_name
|
|
2257 |
filename = dialog.get_filename()
|
|
2258 |
dialog.destroy()
|
|
2259 |
fileext = os.path.splitext(os.path.basename(filename))[1].lower()
|
|
2260 |
if len(fileext) > 0:
|
|
2261 |
fileext = fileext[1:]
|
|
2262 |
# Override filetype if user typed a filename with a different extension:
|
|
2263 |
for i in gtk.gdk.pixbuf_get_formats():
|
|
2264 |
if fileext in i["extensions"]:
|
|
2265 |
filetype = i["name"]
|
|
2266 |
self.save_image_now(filename, filetype)
|
|
2267 |
self.register_file_with_recent_docs(filename)
|
|
2268 |
else:
|
|
2269 |
dialog.destroy()
|
|
2270 |
|
|
2271 |
def save_image_now(self, dest_name, filetype):
|
|
2272 |
try:
|
|
2273 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
2274 |
while gtk.events_pending():
|
|
2275 |
gtk.main_iteration()
|
|
2276 |
if filetype == None:
|
|
2277 |
filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]["name"]
|
|
2278 |
if self.filetype_is_writable(filetype):
|
|
2279 |
self.currimg_pixbuf_original.save(
|
|
2280 |
dest_name, filetype, {"quality": str(self.quality_save)}
|
|
2281 |
)
|
|
2282 |
self.currimg_name = dest_name
|
|
2283 |
self.image_list[self.curr_img_in_list] = dest_name
|
|
2284 |
self.update_title()
|
|
2285 |
self.update_statusbar()
|
|
2286 |
# Update thumbnail:
|
|
2287 |
gobject.idle_add(
|
|
2288 |
self.thumbpane_set_image, dest_name, self.curr_img_in_list, True
|
|
2289 |
)
|
|
2290 |
self.image_modified = False
|
|
2291 |
else:
|
|
2292 |
error_dialog = gtk.MessageDialog(
|
|
2293 |
self.window,
|
|
2294 |
gtk.DIALOG_MODAL,
|
|
2295 |
gtk.MESSAGE_WARNING,
|
|
2296 |
gtk.BUTTONS_YES_NO,
|
|
2297 |
_(
|
|
2298 |
"The %s format is not supported for saving. Do you wish to save the file in a different format?"
|
|
2299 |
)
|
|
2300 |
% filetype,
|
|
2301 |
)
|
|
2302 |
error_dialog.set_title(_("Save"))
|
|
2303 |
response = error_dialog.run()
|
|
2304 |
if response == gtk.RESPONSE_YES:
|
|
2305 |
error_dialog.destroy()
|
|
2306 |
while gtk.events_pending():
|
|
2307 |
gtk.main_iteration()
|
|
2308 |
self.save_image_as(None)
|
|
2309 |
else:
|
|
2310 |
error_dialog.destroy()
|
|
2311 |
except:
|
|
2312 |
error_dialog = gtk.MessageDialog(
|
|
2313 |
self.window,
|
|
2314 |
gtk.DIALOG_MODAL,
|
|
2315 |
gtk.MESSAGE_WARNING,
|
|
2316 |
gtk.BUTTONS_CLOSE,
|
|
2317 |
_("Unable to save %s") % dest_name,
|
|
2318 |
)
|
|
2319 |
error_dialog.set_title(_("Save"))
|
|
2320 |
error_dialog.run()
|
|
2321 |
error_dialog.destroy()
|
|
2322 |
self.change_cursor(None)
|
|
2323 |
|
|
2324 |
def autosave_image(self):
|
|
2325 |
# Returns True if the user has canceled out of the dialog
|
|
2326 |
# Never call this function from an idle or timeout loop! That will cause
|
|
2327 |
# the app to freeze.
|
|
2328 |
if self.image_modified:
|
|
2329 |
if self.savemode == 1:
|
|
2330 |
temp = self.UIManager.get_widget(
|
|
2331 |
"/MainMenu/FileMenu/Save"
|
|
2332 |
).get_property("sensitive")
|
|
2333 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_property(
|
|
2334 |
"sensitive", True
|
|
2335 |
)
|
|
2336 |
self.save_image(None)
|
|
2337 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_property(
|
|
2338 |
"sensitive", temp
|
|
2339 |
)
|
|
2340 |
elif self.savemode == 2:
|
|
2341 |
dialog = gtk.MessageDialog(
|
|
2342 |
self.window,
|
|
2343 |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
|
2344 |
gtk.MESSAGE_QUESTION,
|
|
2345 |
gtk.BUTTONS_NONE,
|
|
2346 |
_("The current image has been modified. Save changes?"),
|
|
2347 |
)
|
|
2348 |
dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
|
2349 |
dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
|
|
2350 |
dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_YES)
|
|
2351 |
dialog.set_title(_("Save?"))
|
|
2352 |
dialog.set_default_response(gtk.RESPONSE_YES)
|
|
2353 |
response = dialog.run()
|
|
2354 |
dialog.destroy()
|
|
2355 |
if response == gtk.RESPONSE_YES:
|
|
2356 |
temp = self.UIManager.get_widget(
|
|
2357 |
"/MainMenu/FileMenu/Save"
|
|
2358 |
).get_property("sensitive")
|
|
2359 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_property(
|
|
2360 |
"sensitive", True
|
|
2361 |
)
|
|
2362 |
self.save_image(None)
|
|
2363 |
self.UIManager.get_widget("/MainMenu/FileMenu/Save").set_property(
|
|
2364 |
"sensitive", temp
|
|
2365 |
)
|
|
2366 |
self.image_modified = False
|
|
2367 |
elif response == gtk.RESPONSE_NO:
|
|
2368 |
self.image_modified = False
|
|
2369 |
# Ensures that we don't use the current pixbuf for any preload pixbufs if we are in
|
|
2370 |
# the process of loading the previous or next image in the list:
|
|
2371 |
self.currimg_pixbuf = self.currimg_pixbuf_original
|
|
2372 |
self.preloadimg_next_in_list = -1
|
|
2373 |
self.preloadimg_prev_in_list = -1
|
|
2374 |
self.loaded_img_in_list = -1
|
|
2375 |
else:
|
|
2376 |
return True
|
|
2377 |
|
|
2378 |
def filetype_is_writable(self, filetype):
|
|
2379 |
# Determine if filetype is a writable format
|
|
2380 |
filetype_is_writable = True
|
|
2381 |
for i in gtk.gdk.pixbuf_get_formats():
|
|
2382 |
if filetype in i["extensions"]:
|
|
2383 |
if i["is_writable"]:
|
|
2384 |
return True
|
|
2385 |
return False
|
|
2386 |
|
|
2387 |
def open_file(self, action):
|
|
2388 |
self.stop_now = True
|
|
2389 |
while gtk.events_pending():
|
|
2390 |
gtk.main_iteration()
|
|
2391 |
self.open_file_or_folder(action, True)
|
|
2392 |
|
|
2393 |
def open_file_remote(self, action):
|
|
2394 |
# Prompt user for the url:
|
|
2395 |
dialog = gtk.Dialog(
|
|
2396 |
_("Open Remote"),
|
|
2397 |
self.window,
|
|
2398 |
gtk.DIALOG_MODAL,
|
|
2399 |
buttons=(
|
|
2400 |
gtk.STOCK_CANCEL,
|
|
2401 |
gtk.RESPONSE_CANCEL,
|
|
2402 |
gtk.STOCK_OPEN,
|
|
2403 |
gtk.RESPONSE_OK,
|
|
2404 |
),
|
|
2405 |
)
|
|
2406 |
location = gtk.Entry()
|
|
2407 |
location.set_size_request(300, -1)
|
|
2408 |
location.set_activates_default(True)
|
|
2409 |
hbox = gtk.HBox()
|
|
2410 |
hbox.pack_start(gtk.Label(_("Image Location (URL):")), False, False, 5)
|
|
2411 |
hbox.pack_start(location, True, True, 5)
|
|
2412 |
dialog.vbox.pack_start(hbox, True, True, 10)
|
|
2413 |
dialog.set_default_response(gtk.RESPONSE_OK)
|
|
2414 |
dialog.vbox.show_all()
|
|
2415 |
dialog.connect("response", self.open_file_remote_response, location)
|
|
2416 |
response = dialog.show()
|
|
2417 |
|
|
2418 |
def open_file_remote_response(self, dialog, response, location):
|
|
2419 |
if response == gtk.RESPONSE_OK:
|
|
2420 |
filenames = []
|
|
2421 |
filenames.append(location.get_text())
|
|
2422 |
dialog.destroy()
|
|
2423 |
while gtk.events_pending():
|
|
2424 |
gtk.main_iteration()
|
|
2425 |
self.expand_filelist_and_load_image(filenames)
|
|
2426 |
else:
|
|
2427 |
dialog.destroy()
|
|
2428 |
|
|
2429 |
def open_folder(self, action):
|
|
2430 |
self.stop_now = True
|
|
2431 |
while gtk.events_pending():
|
|
2432 |
gtk.main_iteration()
|
|
2433 |
self.open_file_or_folder(action, False)
|
|
2434 |
|
|
2435 |
def open_file_or_folder(self, action, isfile):
|
|
2436 |
self.thumbpane_create_dir()
|
|
2437 |
cancel = self.autosave_image()
|
|
2438 |
if cancel:
|
|
2439 |
return
|
|
2440 |
# If isfile = True, file; If isfile = False, folder
|
|
2441 |
dialog = gtk.FileChooserDialog(
|
|
2442 |
title=_("Open"),
|
|
2443 |
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
|
2444 |
buttons=(
|
|
2445 |
gtk.STOCK_CANCEL,
|
|
2446 |
gtk.RESPONSE_CANCEL,
|
|
2447 |
gtk.STOCK_OPEN,
|
|
2448 |
gtk.RESPONSE_OK,
|
|
2449 |
),
|
|
2450 |
)
|
|
2451 |
if isfile:
|
|
2452 |
filter = gtk.FileFilter()
|
|
2453 |
filter.set_name(_("Images"))
|
|
2454 |
filter.add_pixbuf_formats()
|
|
2455 |
dialog.add_filter(filter)
|
|
2456 |
filter = gtk.FileFilter()
|
|
2457 |
filter.set_name(_("All files"))
|
|
2458 |
filter.add_pattern("*")
|
|
2459 |
dialog.add_filter(filter)
|
|
2460 |
preview = gtk.Image()
|
|
2461 |
dialog.set_preview_widget(preview)
|
|
2462 |
dialog.set_use_preview_label(False)
|
|
2463 |
dialog.connect("update-preview", self.update_preview, preview)
|
|
2464 |
recursivebutton = None
|
|
2465 |
else:
|
|
2466 |
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
|
2467 |
recursivebutton = gtk.CheckButton(
|
|
2468 |
label=_("Include images in subdirectories")
|
|
2469 |
)
|
|
2470 |
dialog.set_extra_widget(recursivebutton)
|
|
2471 |
dialog.set_default_response(gtk.RESPONSE_OK)
|
|
2472 |
dialog.set_select_multiple(True)
|
|
2473 |
if self.use_last_dir:
|
|
2474 |
if self.last_dir != None:
|
|
2475 |
dialog.set_current_folder(self.last_dir)
|
|
2476 |
else:
|
|
2477 |
if self.fixed_dir != None:
|
|
2478 |
dialog.set_current_folder(self.fixed_dir)
|
|
2479 |
dialog.connect(
|
|
2480 |
"response", self.open_file_or_folder_response, isfile, recursivebutton
|
|
2481 |
)
|
|
2482 |
response = dialog.show()
|
|
2483 |
|
|
2484 |
def open_file_or_folder_response(self, dialog, response, isfile, recursivebutton):
|
|
2485 |
if response == gtk.RESPONSE_OK:
|
|
2486 |
if self.use_last_dir:
|
|
2487 |
self.last_dir = dialog.get_current_folder()
|
|
2488 |
if not isfile and recursivebutton.get_property("active"):
|
|
2489 |
self.recursive = True
|
|
2490 |
filenames = dialog.get_filenames()
|
|
2491 |
dialog.destroy()
|
|
2492 |
while gtk.events_pending():
|
|
2493 |
gtk.main_iteration()
|
|
2494 |
self.expand_filelist_and_load_image(filenames)
|
|
2495 |
else:
|
|
2496 |
dialog.destroy()
|
|
2497 |
|
|
2498 |
def update_preview(self, file_chooser, preview):
|
|
2499 |
filename = file_chooser.get_preview_filename()
|
|
2500 |
if not filename:
|
|
2501 |
return
|
|
2502 |
filename, thumbfile = self.thumbnail_get_name(filename)
|
|
2503 |
pixbuf = self.thumbpane_get_pixbuf(thumbfile, filename, False)
|
|
2504 |
if pixbuf:
|
|
2505 |
preview.set_from_pixbuf(pixbuf)
|
|
2506 |
else:
|
|
2507 |
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 1, 8, 128, 128)
|
|
2508 |
pixbuf.fill(0x00000000)
|
|
2509 |
preview.set_from_pixbuf(pixbuf)
|
|
2510 |
have_preview = True
|
|
2511 |
file_chooser.set_preview_widget_active(have_preview)
|
|
2512 |
del pixbuf
|
|
2513 |
gc.collect()
|
|
2514 |
|
|
2515 |
def hide_cursor(self):
|
|
2516 |
if (
|
|
2517 |
self.fullscreen_mode
|
|
2518 |
and not self.user_prompt_visible
|
|
2519 |
and not self.slideshow_controls_visible
|
|
2520 |
):
|
|
2521 |
pix_data = """/* XPM */
|
1848 | 2522 |
static char * invisible_xpm[] = {
|
1849 | 2523 |
"1 1 1 1",
|
1850 | 2524 |
" c None",
|
1851 | 2525 |
" "};"""
|
1852 | |
color = gtk.gdk.Color()
|
1853 | |
pix = gtk.gdk.pixmap_create_from_data(None, pix_data, 1, 1, 1, color, color)
|
1854 | |
invisible = gtk.gdk.Cursor(pix, pix, color, color, 0, 0)
|
1855 | |
self.change_cursor(invisible)
|
1856 | |
return False
|
1857 | |
|
1858 | |
def enter_fullscreen(self, action):
|
1859 | |
if not self.fullscreen_mode:
|
1860 | |
self.fullscreen_mode = True
|
1861 | |
self.UIManager.get_widget('/Popup/Full Screen').hide()
|
1862 | |
self.UIManager.get_widget('/Popup/Exit Full Screen').show()
|
1863 | |
self.statusbar.hide()
|
1864 | |
self.statusbar2.hide()
|
1865 | |
self.toolbar.hide()
|
1866 | |
self.menubar.hide()
|
1867 | |
self.thumbscroll.hide()
|
1868 | |
self.thumbpane.hide()
|
1869 | |
self.window.fullscreen()
|
1870 | |
self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
|
1871 | |
self.set_slideshow_sensitivities()
|
1872 | |
if self.simple_bgcolor:
|
1873 | |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
1874 | |
else:
|
1875 | |
if self.simple_bgcolor:
|
1876 | |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
1877 | |
self.leave_fullscreen(action)
|
1878 | |
|
1879 | |
def leave_fullscreen(self, action):
|
1880 | |
if self.fullscreen_mode:
|
1881 | |
self.slideshow_controls_visible = False
|
1882 | |
self.slideshow_window.hide_all()
|
1883 | |
self.slideshow_window2.hide_all()
|
1884 | |
self.fullscreen_mode = False
|
1885 | |
self.UIManager.get_widget('/Popup/Full Screen').show()
|
1886 | |
self.UIManager.get_widget('/Popup/Exit Full Screen').hide()
|
1887 | |
if self.toolbar_show:
|
1888 | |
self.toolbar.show()
|
1889 | |
self.menubar.show()
|
1890 | |
if self.statusbar_show:
|
1891 | |
self.statusbar.show()
|
1892 | |
self.statusbar2.show()
|
1893 | |
if self.thumbpane_show:
|
1894 | |
self.thumbscroll.show()
|
1895 | |
self.thumbpane.show()
|
1896 | |
self.thumbpane_update_images(False, self.curr_img_in_list)
|
1897 | |
self.window.unfullscreen()
|
1898 | |
self.change_cursor(None)
|
1899 | |
self.set_slideshow_sensitivities()
|
1900 | |
if self.simple_bgcolor:
|
1901 | |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
1902 | |
|
1903 | |
def toggle_status_bar(self, action):
|
1904 | |
if self.statusbar.get_property('visible'):
|
1905 | |
self.statusbar.hide()
|
1906 | |
self.statusbar2.hide()
|
1907 | |
self.statusbar_show = False
|
1908 | |
else:
|
1909 | |
self.statusbar.show()
|
1910 | |
self.statusbar2.show()
|
1911 | |
self.statusbar_show = True
|
1912 | |
if self.image_loaded and self.last_image_action_was_fit:
|
1913 | |
if self.last_image_action_was_smart_fit:
|
1914 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
1915 | |
else:
|
1916 | |
self.zoom_to_fit_window(None, False, False)
|
1917 | |
|
1918 | |
def toggle_thumbpane(self, action):
|
1919 | |
if self.thumbscroll.get_property('visible'):
|
1920 | |
self.thumbscroll.hide()
|
1921 | |
self.thumbpane.hide()
|
1922 | |
self.thumbpane_show = False
|
1923 | |
else:
|
1924 | |
self.thumbscroll.show()
|
1925 | |
self.thumbpane.show()
|
1926 | |
self.thumbpane_show = True
|
1927 | |
self.stop_now = False
|
1928 | |
gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
|
1929 | |
if self.image_loaded and self.last_image_action_was_fit:
|
1930 | |
if self.last_image_action_was_smart_fit:
|
1931 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
1932 | |
else:
|
1933 | |
self.zoom_to_fit_window(None, False, False)
|
1934 | |
|
1935 | |
def toggle_toolbar(self, action):
|
1936 | |
if self.toolbar.get_property('visible'):
|
1937 | |
self.toolbar.hide()
|
1938 | |
self.toolbar_show = False
|
1939 | |
else:
|
1940 | |
self.toolbar.show()
|
1941 | |
self.toolbar_show = True
|
1942 | |
if self.image_loaded and self.last_image_action_was_fit:
|
1943 | |
if self.last_image_action_was_smart_fit:
|
1944 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
1945 | |
else:
|
1946 | |
self.zoom_to_fit_window(None, False, False)
|
1947 | |
|
1948 | |
def update_statusbar(self):
|
1949 | |
# Update status bar:
|
1950 | |
try:
|
1951 | |
st = os.stat(self.currimg_name)
|
1952 | |
filesize = st[stat.ST_SIZE] // 1000
|
1953 | |
ratio = int(100 * self.currimg_zoomratio)
|
1954 | |
status_text = os.path.basename(self.currimg_name)+ ": " + str(self.currimg_pixbuf_original.get_width()) + "x" + str(self.currimg_pixbuf_original.get_height()) + " " + str(filesize) + "KB " + str(ratio) + "% "
|
1955 | |
except:
|
1956 | |
status_text=_("Cannot load image.")
|
1957 | |
self.statusbar.push(self.statusbar.get_context_id(""), status_text)
|
1958 | |
status_text = ""
|
1959 | |
if self.running_custom_actions:
|
1960 | |
status_text = _('Custom actions: %(current)i of %(total)i') % {'current': self.curr_custom_action,'total': self.num_custom_actions}
|
1961 | |
elif self.searching_for_images:
|
1962 | |
status_text = _('Scanning...')
|
1963 | |
self.statusbar2.push(self.statusbar2.get_context_id(""), status_text)
|
1964 | |
|
1965 | |
def show_custom_actions(self, action):
|
1966 | |
self.actions_dialog = gtk.Dialog(title=_("Configure Custom Actions"), parent=self.window)
|
1967 | |
self.actions_dialog.set_has_separator(False)
|
1968 | |
self.actions_dialog.set_resizable(False)
|
1969 | |
table_actions = gtk.Table(13, 2, False)
|
1970 | |
table_actions.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
1971 | |
actionscrollwindow = gtk.ScrolledWindow()
|
1972 | |
self.actionstore = gtk.ListStore(str, str, str)
|
1973 | |
self.actionwidget = gtk.TreeView()
|
1974 | |
self.actionwidget.set_enable_search(False)
|
1975 | |
self.actionwidget.set_rules_hint(True)
|
1976 | |
self.actionwidget.connect('row-activated', self.edit_custom_action2)
|
1977 | |
actionscrollwindow.add(self.actionwidget)
|
1978 | |
actionscrollwindow.set_shadow_type(gtk.SHADOW_IN)
|
1979 | |
actionscrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
1980 | |
actionscrollwindow.set_size_request(500, 200)
|
1981 | |
self.actionwidget.set_model(self.actionstore)
|
1982 | |
self.cell = gtk.CellRendererText()
|
1983 | |
self.cellbool = gtk.CellRendererPixbuf()
|
1984 | |
self.tvcolumn0 = gtk.TreeViewColumn(_("Batch"))
|
1985 | |
self.tvcolumn1 = gtk.TreeViewColumn(_("Action"), self.cell, markup=0)
|
1986 | |
self.tvcolumn2 = gtk.TreeViewColumn(_("Shortcut"))
|
1987 | |
self.tvcolumn1.set_max_width(self.actionwidget.size_request()[0] - self.tvcolumn0.get_width() - self.tvcolumn2.get_width())
|
1988 | |
self.actionwidget.append_column(self.tvcolumn0)
|
1989 | |
self.actionwidget.append_column(self.tvcolumn1)
|
1990 | |
self.actionwidget.append_column(self.tvcolumn2)
|
1991 | |
self.populate_treeview()
|
1992 | |
if len(self.action_names) > 0:
|
1993 | |
self.actionwidget.get_selection().select_path(0)
|
1994 | |
vbox_actions = gtk.VBox()
|
1995 | |
addbutton = gtk.Button("", gtk.STOCK_ADD)
|
1996 | |
addbutton.get_child().get_child().get_children()[1].set_text('')
|
1997 | |
addbutton.connect('clicked', self.add_custom_action, self.actionwidget)
|
1998 | |
addbutton.set_tooltip_text(_("Add action"))
|
1999 | |
editbutton = gtk.Button("", gtk.STOCK_EDIT)
|
2000 | |
editbutton.get_child().get_child().get_children()[1].set_text('')
|
2001 | |
editbutton.connect('clicked', self.edit_custom_action, self.actionwidget)
|
2002 | |
editbutton.set_tooltip_text(_("Edit selected action."))
|
2003 | |
removebutton = gtk.Button("", gtk.STOCK_REMOVE)
|
2004 | |
removebutton.get_child().get_child().get_children()[1].set_text('')
|
2005 | |
removebutton.connect('clicked', self.remove_custom_action)
|
2006 | |
removebutton.set_tooltip_text(_("Remove selected action."))
|
2007 | |
upbutton = gtk.Button("", gtk.STOCK_GO_UP)
|
2008 | |
upbutton.get_child().get_child().get_children()[1].set_text('')
|
2009 | |
upbutton.connect('clicked', self.custom_action_move_up, self.actionwidget)
|
2010 | |
upbutton.set_tooltip_text(_("Move selected action up."))
|
2011 | |
downbutton = gtk.Button("", gtk.STOCK_GO_DOWN)
|
2012 | |
downbutton.get_child().get_child().get_children()[1].set_text('')
|
2013 | |
downbutton.connect('clicked', self.custom_action_move_down, self.actionwidget)
|
2014 | |
downbutton.set_tooltip_text(_("Move selected action down."))
|
2015 | |
vbox_buttons = gtk.VBox()
|
2016 | |
propertyinfo = gtk.Label()
|
2017 | |
propertyinfo.set_markup('<small>' + _("Parameters") + ':\n<span font_family="Monospace">%F</span> - ' + _("File path, name, and extension") + '\n<span font_family="Monospace">%P</span> - ' + _("File path") + '\n<span font_family="Monospace">%N</span> - ' + _("File name without file extension") + '\n<span font_family="Monospace">%E</span> - ' + _("File extension (i.e. \".png\")") + '\n<span font_family="Monospace">%L</span> - ' + _("List of files, space-separated") + '</small>')
|
2018 | |
propertyinfo.set_alignment(0, 0)
|
2019 | |
actioninfo = gtk.Label()
|
2020 | |
actioninfo.set_markup('<small>' + _("Operations") + ':\n<span font_family="Monospace">[NEXT]</span> - ' + _("Go to next image") + '\n<span font_family="Monospace">[PREV]</span> - ' + _("Go to previous image") +'</small>')
|
2021 | |
actioninfo.set_alignment(0, 0)
|
2022 | |
hbox_info = gtk.HBox()
|
2023 | |
hbox_info.pack_start(propertyinfo, False, False, 15)
|
2024 | |
hbox_info.pack_start(actioninfo, False, False, 15)
|
2025 | |
vbox_buttons.pack_start(addbutton, False, False, 5)
|
2026 | |
vbox_buttons.pack_start(editbutton, False, False, 5)
|
2027 | |
vbox_buttons.pack_start(removebutton, False, False, 5)
|
2028 | |
vbox_buttons.pack_start(upbutton, False, False, 5)
|
2029 | |
vbox_buttons.pack_start(downbutton, False, False, 0)
|
2030 | |
hbox_top = gtk.HBox()
|
2031 | |
hbox_top.pack_start(actionscrollwindow, True, True, 5)
|
2032 | |
hbox_top.pack_start(vbox_buttons, False, False, 5)
|
2033 | |
vbox_actions.pack_start(hbox_top, True, True, 5)
|
2034 | |
vbox_actions.pack_start(hbox_info, False, False, 5)
|
2035 | |
hbox_instructions = gtk.HBox()
|
2036 | |
info_image = gtk.Image()
|
2037 | |
info_image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_BUTTON)
|
2038 | |
hbox_instructions.pack_start(info_image, False, False, 5)
|
2039 | |
instructions = gtk.Label(_("Here you can define custom actions with shortcuts. Actions use the built-in parameters and operations listed below and can have multiple statements separated by a semicolon. Batch actions apply to all images in the list."))
|
2040 | |
instructions.set_line_wrap(True)
|
2041 | |
instructions.set_alignment(0, 0.5)
|
2042 | |
hbox_instructions.pack_start(instructions, False, False, 5)
|
2043 | |
table_actions.attach(hbox_instructions, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 5, 0)
|
2044 | |
table_actions.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2045 | |
table_actions.attach(vbox_actions, 1, 3, 4, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2046 | |
table_actions.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2047 | |
self.actions_dialog.vbox.pack_start(table_actions, False, False, 0)
|
2048 | |
# Show dialog:
|
2049 | |
self.actions_dialog.vbox.show_all()
|
2050 | |
instructions.set_size_request(self.actions_dialog.size_request()[0]-50, -1)
|
2051 | |
close_button = self.actions_dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
2052 | |
close_button.grab_focus()
|
2053 | |
self.actions_dialog.run()
|
2054 | |
self.refresh_custom_actions_menu()
|
2055 | |
while gtk.events_pending():
|
2056 | |
gtk.main_iteration()
|
2057 | |
if len(self.image_list) == 0:
|
2058 | |
self.set_image_sensitivities(False)
|
2059 | |
self.actions_dialog.destroy()
|
2060 | |
|
2061 | |
def add_custom_action(self, button, treeview):
|
2062 | |
self.open_custom_action_dialog(True, '', '', 'None', False, treeview)
|
2063 | |
|
2064 | |
def edit_custom_action2(self, treeview, path, view_column):
|
2065 | |
self.edit_custom_action(None, treeview)
|
2066 | |
|
2067 | |
def edit_custom_action(self, button, treeview):
|
2068 | |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
2069 | |
if iter != None:
|
2070 | |
(row, ) = self.actionstore.get_path(iter)
|
2071 | |
self.open_custom_action_dialog(False, self.action_names[row], self.action_commands[row], self.action_shortcuts[row], self.action_batch[row], treeview)
|
2072 | |
|
2073 | |
def open_custom_action_dialog(self, add_call, name, command, shortcut, batch, treeview):
|
2074 | |
if add_call:
|
2075 | |
self.dialog_name = gtk.Dialog(_("Add Custom Action"), self.actions_dialog, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
|
2076 | |
else:
|
2077 | |
self.dialog_name = gtk.Dialog(_("Edit Custom Action"), self.actions_dialog, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
|
2078 | |
self.dialog_name.set_modal(True)
|
2079 | |
table = gtk.Table(2, 4, False)
|
2080 | |
action_name_label = gtk.Label(_("Action Name:"))
|
2081 | |
action_name_label.set_alignment(0, 0.5)
|
2082 | |
action_command_label = gtk.Label(_("Command:"))
|
2083 | |
action_command_label.set_alignment(0, 0.5)
|
2084 | |
shortcut_label = gtk.Label(_("Shortcut:"))
|
2085 | |
shortcut_label.set_alignment(0, 0.5)
|
2086 | |
table.attach(action_name_label, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2087 | |
table.attach(action_command_label, 0, 1, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2088 | |
table.attach(shortcut_label, 0, 1, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2089 | |
action_name = gtk.Entry()
|
2090 | |
action_name.set_text(name)
|
2091 | |
action_command = gtk.Entry()
|
2092 | |
action_command.set_text(command)
|
2093 | |
table.attach(action_name, 1, 2, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2094 | |
table.attach(action_command, 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2095 | |
self.shortcut = gtk.Button(shortcut)
|
2096 | |
self.shortcut.connect('clicked', self.shortcut_clicked)
|
2097 | |
table.attach(self.shortcut, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2098 | |
batchmode = gtk.CheckButton(_("Perform action on all images (Batch)"))
|
2099 | |
batchmode.set_active(batch)
|
2100 | |
table.attach(batchmode, 0, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2101 | |
self.dialog_name.vbox.pack_start(table, False, False, 5)
|
2102 | |
self.dialog_name.vbox.show_all()
|
2103 | |
self.dialog_name.connect('response', self.dialog_name_response, add_call, action_name, action_command, self.shortcut, batchmode, treeview)
|
2104 | |
self.dialog_name.run()
|
2105 | |
|
2106 | |
def dialog_name_response(self, dialog, response, add_call, action_name, action_command, shortcut, batchmode, treeview):
|
2107 | |
if response == gtk.RESPONSE_ACCEPT:
|
2108 | |
if not (action_command.get_text() == "" or action_name.get_text() == "" or self.shortcut.get_label() == "None"):
|
2109 | |
name = action_name.get_text()
|
2110 | |
command = action_command.get_text()
|
2111 | |
if ((("[NEXT]" in command.strip()) and command.strip()[-6:] != "[NEXT]") or (("[PREV]" in command.strip()) and command.strip()[-6:] != "[PREV]") ):
|
2112 | |
error_dialog = gtk.MessageDialog(self.actions_dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('[PREV] and [NEXT] are only valid alone or at the end of the command'))
|
2113 | |
error_dialog.set_title(_("Invalid Custom Action"))
|
2114 | |
error_dialog.run()
|
2115 | |
error_dialog.destroy()
|
2116 | |
return
|
2117 | |
shortcut = shortcut.get_label()
|
2118 | |
batch = batchmode.get_active()
|
2119 | |
dialog.destroy()
|
2120 | |
if add_call:
|
2121 | |
self.action_names.append(name)
|
2122 | |
self.action_commands.append(command)
|
2123 | |
self.action_shortcuts.append(shortcut)
|
2124 | |
self.action_batch.append(batch)
|
2125 | |
else:
|
2126 | |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
2127 | |
(rownum, ) = self.actionstore.get_path(iter)
|
2128 | |
self.action_names[rownum] = name
|
2129 | |
self.action_commands[rownum] = command
|
2130 | |
self.action_shortcuts[rownum] = shortcut
|
2131 | |
self.action_batch[rownum] = batch
|
2132 | |
self.populate_treeview()
|
2133 | |
if add_call:
|
2134 | |
rownum = len(self.action_names)-1
|
2135 | |
treeview.get_selection().select_path(rownum)
|
2136 | |
while gtk.events_pending():
|
2137 | |
gtk.main_iteration()
|
2138 | |
# Keep item in visible rect:
|
2139 | |
visible_rect = treeview.get_visible_rect()
|
2140 | |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
2141 | |
if row_rect.y + row_rect.height > visible_rect.height:
|
2142 | |
top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
|
2143 | |
treeview.scroll_to_point(-1, top_coord)
|
2144 | |
elif row_rect.y < 0:
|
2145 | |
treeview.scroll_to_cell(rownum)
|
2146 | |
else:
|
2147 | |
error_dialog = gtk.MessageDialog(self.actions_dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Incomplete custom action specified.'))
|
2148 | |
error_dialog.set_title(_("Invalid Custom Action"))
|
2149 | |
error_dialog.run()
|
2150 | |
error_dialog.destroy()
|
2151 | |
else:
|
2152 | |
dialog.destroy()
|
2153 | |
|
2154 | |
def custom_action_move_down(self, button, treeview):
|
2155 | |
iter = None
|
2156 | |
selection = treeview.get_selection()
|
2157 | |
model, iter = selection.get_selected()
|
2158 | |
if iter:
|
2159 | |
rownum = int(model.get_string_from_iter(iter))
|
2160 | |
if rownum < len(self.action_names)-1:
|
2161 | |
# Move item down:
|
2162 | |
temp_name = self.action_names[rownum]
|
2163 | |
temp_shortcut = self.action_shortcuts[rownum]
|
2164 | |
temp_command = self.action_commands[rownum]
|
2165 | |
temp_batch = self.action_batch[rownum]
|
2166 | |
self.action_names[rownum] = self.action_names[rownum+1]
|
2167 | |
self.action_shortcuts[rownum] = self.action_shortcuts[rownum+1]
|
2168 | |
self.action_commands[rownum] = self.action_commands[rownum+1]
|
2169 | |
self.action_batch[rownum] = self.action_batch[rownum+1]
|
2170 | |
self.action_names[rownum+1] = temp_name
|
2171 | |
self.action_shortcuts[rownum+1] = temp_shortcut
|
2172 | |
self.action_commands[rownum+1] = temp_command
|
2173 | |
self.action_batch[rownum+1] = temp_batch
|
2174 | |
# Repopulate treeview and keep item selected:
|
2175 | |
self.populate_treeview()
|
2176 | |
selection.select_path((rownum+1,))
|
2177 | |
while gtk.events_pending():
|
2178 | |
gtk.main_iteration()
|
2179 | |
# Keep item in visible rect:
|
2180 | |
rownum = rownum + 1
|
2181 | |
visible_rect = treeview.get_visible_rect()
|
2182 | |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
2183 | |
if row_rect.y + row_rect.height > visible_rect.height:
|
2184 | |
top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
|
2185 | |
treeview.scroll_to_point(-1, top_coord)
|
2186 | |
elif row_rect.y < 0:
|
2187 | |
treeview.scroll_to_cell(rownum)
|
2188 | |
|
2189 | |
def custom_action_move_up(self, button, treeview):
|
2190 | |
iter = None
|
2191 | |
selection = treeview.get_selection()
|
2192 | |
model, iter = selection.get_selected()
|
2193 | |
if iter:
|
2194 | |
rownum = int(model.get_string_from_iter(iter))
|
2195 | |
if rownum > 0:
|
2196 | |
# Move item down:
|
2197 | |
temp_name = self.action_names[rownum]
|
2198 | |
temp_shortcut = self.action_shortcuts[rownum]
|
2199 | |
temp_command = self.action_commands[rownum]
|
2200 | |
temp_batch = self.action_batch[rownum]
|
2201 | |
self.action_names[rownum] = self.action_names[rownum-1]
|
2202 | |
self.action_shortcuts[rownum] = self.action_shortcuts[rownum-1]
|
2203 | |
self.action_commands[rownum] = self.action_commands[rownum-1]
|
2204 | |
self.action_batch[rownum] = self.action_batch[rownum-1]
|
2205 | |
self.action_names[rownum-1] = temp_name
|
2206 | |
self.action_shortcuts[rownum-1] = temp_shortcut
|
2207 | |
self.action_commands[rownum-1] = temp_command
|
2208 | |
self.action_batch[rownum-1] = temp_batch
|
2209 | |
# Repopulate treeview and keep item selected:
|
2210 | |
self.populate_treeview()
|
2211 | |
selection.select_path((rownum-1,))
|
2212 | |
while gtk.events_pending():
|
2213 | |
gtk.main_iteration()
|
2214 | |
# Keep item in visible rect:
|
2215 | |
rownum = rownum - 1
|
2216 | |
visible_rect = treeview.get_visible_rect()
|
2217 | |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
2218 | |
if row_rect.y + row_rect.height > visible_rect.height:
|
2219 | |
top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
|
2220 | |
treeview.scroll_to_point(-1, top_coord)
|
2221 | |
elif row_rect.y < 0:
|
2222 | |
treeview.scroll_to_cell(rownum)
|
2223 | |
|
2224 | |
def shortcut_clicked(self, widget):
|
2225 | |
self.dialog_shortcut = gtk.Dialog(_("Action Shortcut"), self.dialog_name, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
|
2226 | |
self.shortcut_label = gtk.Label(_("Press the desired shortcut for the action."))
|
2227 | |
hbox = gtk.HBox()
|
2228 | |
hbox.pack_start(self.shortcut_label, False, False, 15)
|
2229 | |
self.dialog_shortcut.vbox.pack_start(hbox, False, False, 5)
|
2230 | |
self.dialog_shortcut.vbox.show_all()
|
2231 | |
self.dialog_shortcut.connect('key-press-event', self.shortcut_keypress)
|
2232 | |
self.dialog_shortcut.run()
|
2233 | |
self.dialog_shortcut.destroy()
|
2234 | |
|
2235 | |
def shortcut_keypress(self, widget, event):
|
2236 | |
shortcut = gtk.accelerator_name(event.keyval, event.state)
|
2237 | |
if "<Mod2>" in shortcut:
|
2238 | |
shortcut = shortcut.replace("<Mod2>", "")
|
2239 | |
if shortcut[(len(shortcut)-2):len(shortcut)] != "_L" and shortcut[(len(shortcut)-2):len(shortcut)] != "_R":
|
2240 | |
# Validate to make sure the shortcut hasn't already been used:
|
2241 | |
for i in range(len(self.keys)):
|
2242 | |
if shortcut == self.keys[i][1]:
|
2243 | |
error_dialog = gtk.MessageDialog(self.dialog_shortcut, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('The shortcut \'%(shortcut)s\' is already used for \'%(key)s\'.') % {'shortcut': shortcut, 'key': self.keys[i][0]})
|
2244 | |
error_dialog.set_title(_("Invalid Shortcut"))
|
2245 | |
error_dialog.run()
|
2246 | |
error_dialog.destroy()
|
2247 | |
return
|
2248 | |
for i in range(len(self.action_shortcuts)):
|
2249 | |
if shortcut == self.action_shortcuts[i]:
|
2250 | |
error_dialog = gtk.MessageDialog(self.dialog_shortcut, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('The shortcut \'%(shortcut)s\' is already used for \'%(key)s\'.') % {'shortcut': shortcut, 'key': self.action_names[i]})
|
2251 | |
error_dialog.set_title(_("Invalid Shortcut"))
|
2252 | |
error_dialog.run()
|
2253 | |
error_dialog.destroy()
|
2254 | |
return
|
2255 | |
self.shortcut.set_label(shortcut)
|
2256 | |
widget.destroy()
|
2257 | |
|
2258 | |
def remove_custom_action(self, button):
|
2259 | |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
2260 | |
if iter != None:
|
2261 | |
(row, ) = self.actionstore.get_path(iter)
|
2262 | |
self.action_names.pop(row)
|
2263 | |
self.action_shortcuts.pop(row)
|
2264 | |
self.action_commands.pop(row)
|
2265 | |
self.action_batch.pop(row)
|
2266 | |
self.populate_treeview()
|
2267 | |
self.actionwidget.grab_focus()
|
2268 | |
|
2269 | |
def populate_treeview(self):
|
2270 | |
self.actionstore.clear()
|
2271 | |
for i in range(len(self.action_names)):
|
2272 | |
if self.action_batch[i]:
|
2273 | |
pb = gtk.STOCK_APPLY
|
2274 | |
else:
|
2275 | |
pb = None
|
2276 | |
self.actionstore.append([pb, '<big><b>' + self.action_names[i].replace('&','&') + '</b></big>\n<small>' + self.action_commands[i].replace('&','&') + '</small>', self.action_shortcuts[i]])
|
2277 | |
self.tvcolumn0.clear()
|
2278 | |
self.tvcolumn1.clear()
|
2279 | |
self.tvcolumn2.clear()
|
2280 | |
self.tvcolumn0.pack_start(self.cellbool)
|
2281 | |
self.tvcolumn1.pack_start(self.cell)
|
2282 | |
self.tvcolumn2.pack_start(self.cell)
|
2283 | |
self.tvcolumn0.add_attribute(self.cellbool, "stock-id", 0)
|
2284 | |
self.tvcolumn1.set_attributes(self.cell, markup=1)
|
2285 | |
self.tvcolumn2.set_attributes(self.cell, text=2)
|
2286 | |
self.tvcolumn1.set_expand(True)
|
2287 | |
|
2288 | |
def screenshot(self, action):
|
2289 | |
cancel = self.autosave_image()
|
2290 | |
if cancel:
|
2291 | |
return
|
2292 | |
# Dialog:
|
2293 | |
dialog = gtk.Dialog(_("Screenshot"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
|
2294 | |
snapbutton = dialog.add_button(_("_Snap"), gtk.RESPONSE_ACCEPT)
|
2295 | |
snapimage = gtk.Image()
|
2296 | |
snapimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
2297 | |
snapbutton.set_image(snapimage)
|
2298 | |
loc = gtk.Label()
|
2299 | |
loc.set_markup('<b>' + _('Location') + '</b>')
|
2300 | |
loc.set_alignment(0, 0)
|
2301 | |
area = gtk.RadioButton()
|
2302 | |
area1 = gtk.RadioButton(group=area, label=_("Entire screen"))
|
2303 | |
area2 = gtk.RadioButton(group=area, label=_("Window under pointer"))
|
2304 | |
if not HAS_XMOUSE:
|
2305 | |
area2.set_sensitive(False)
|
2306 | |
area1.set_active(True)
|
2307 | |
de = gtk.Label()
|
2308 | |
de.set_markup('<b>' + _("Delay") + '</b>')
|
2309 | |
de.set_alignment(0, 0)
|
2310 | |
delaybox = gtk.HBox()
|
2311 | |
adj = gtk.Adjustment(self.screenshot_delay, 0, 30, 1, 10, 0)
|
2312 | |
delay = gtk.SpinButton(adj, 0, 0)
|
2313 | |
delay.set_numeric(True)
|
2314 | |
delay.set_update_policy(gtk.UPDATE_IF_VALID)
|
2315 | |
delay.set_wrap(False)
|
2316 | |
delaylabel = gtk.Label(_(" seconds"))
|
2317 | |
delaybox.pack_start(delay, False)
|
2318 | |
delaybox.pack_start(delaylabel, False)
|
2319 | |
table = gtk.Table()
|
2320 | |
table.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2321 | |
table.attach(loc, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2322 | |
table.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2323 | |
table.attach(area1, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2324 | |
table.attach(area2, 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2325 | |
table.attach(gtk.Label(), 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2326 | |
table.attach(de, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2327 | |
table.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2328 | |
table.attach(delaybox, 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2329 | |
table.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2330 | |
dialog.vbox.pack_start(table)
|
2331 | |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
2332 | |
dialog.vbox.show_all()
|
2333 | |
response = dialog.run()
|
2334 | |
if response == gtk.RESPONSE_ACCEPT:
|
2335 | |
dialog.destroy()
|
2336 | |
while gtk.events_pending():
|
2337 | |
gtk.main_iteration()
|
2338 | |
self.screenshot_delay = delay.get_value_as_int()
|
2339 | |
gobject.timeout_add(int(self.screenshot_delay*1000), self._screenshot_grab, area1.get_active())
|
2340 | |
else:
|
2341 | |
dialog.destroy()
|
2342 | |
|
2343 | |
def _screenshot_grab(self, entire_screen):
|
2344 | |
root_win = gtk.gdk.get_default_root_window()
|
2345 | |
if entire_screen:
|
2346 | |
x = 0
|
2347 | |
y = 0
|
2348 | |
width = gtk.gdk.screen_width()
|
2349 | |
height = gtk.gdk.screen_height()
|
2350 | |
else:
|
2351 | |
(x, y, width, height) = xmouse.geometry()
|
2352 | |
pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height)
|
2353 | |
pix = pix.get_from_drawable(root_win, gtk.gdk.colormap_get_system(), x, y, 0, 0, width, height)
|
2354 | |
# Save as /tmp/mirage-<random>/filename.ext
|
2355 | |
tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
|
2356 | |
tmpfile = tmpdir + "screenshot.png"
|
2357 | |
pix.save(tmpfile, 'png')
|
2358 | |
# Load file:
|
2359 | |
self.image_list = [tmpfile]
|
2360 | |
self.curr_img_in_list = 0
|
2361 | |
gobject.idle_add(self.load_new_image2, False, False, False, False, True)
|
2362 | |
self.update_statusbar()
|
2363 | |
self.set_go_navigation_sensitivities(False)
|
2364 | |
self.set_slideshow_sensitivities()
|
2365 | |
self.thumbpane_update_images(True, self.curr_img_in_list)
|
2366 | |
del pix
|
2367 | |
self.window.present()
|
2368 | |
|
2369 | |
def show_properties(self, action):
|
2370 | |
show_props = gtk.Dialog(_("Properties"), self.window)
|
2371 | |
show_props.set_has_separator(False)
|
2372 | |
show_props.set_resizable(False)
|
2373 | |
table = gtk.Table(3, 3, False)
|
2374 | |
image = gtk.Image()
|
2375 | |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
2376 | |
image_is_anim = False
|
2377 | |
if animtest.is_static_image():
|
2378 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 180, self.zoom_quality)
|
2379 | |
else:
|
2380 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 180, self.zoom_quality)
|
2381 | |
image_is_anim = True
|
2382 | |
image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
|
2383 | |
vbox_left = gtk.VBox()
|
2384 | |
filename = gtk.Label(_("File name:"))
|
2385 | |
filename.set_alignment(1, 1)
|
2386 | |
filedate = gtk.Label(_("File modified:"))
|
2387 | |
filedate.set_alignment(1, 1)
|
2388 | |
imagesize = gtk.Label(_("Dimensions:"))
|
2389 | |
imagesize.set_alignment(1, 1)
|
2390 | |
filesize = gtk.Label(_("File size:"))
|
2391 | |
filesize.set_alignment(1, 1)
|
2392 | |
filetype = gtk.Label(_("File type:"))
|
2393 | |
filetype.set_alignment(1, 1)
|
2394 | |
transparency = gtk.Label(_("Transparency:"))
|
2395 | |
transparency.set_alignment(1, 1)
|
2396 | |
animation = gtk.Label(_("Animation:"))
|
2397 | |
animation.set_alignment(1, 1)
|
2398 | |
bits = gtk.Label(_("Bits per sample:"))
|
2399 | |
bits.set_alignment(1, 1)
|
2400 | |
channels = gtk.Label(_("Channels:"))
|
2401 | |
channels.set_alignment(1, 1)
|
2402 | |
vbox_left.pack_start(filename, False, False, 2)
|
2403 | |
vbox_left.pack_start(filedate, False, False, 2)
|
2404 | |
vbox_left.pack_start(imagesize, False, False, 2)
|
2405 | |
vbox_left.pack_start(filesize, False, False, 2)
|
2406 | |
vbox_left.pack_start(filetype, False, False, 2)
|
2407 | |
vbox_left.pack_start(transparency, False, False, 2)
|
2408 | |
vbox_left.pack_start(animation, False, False, 2)
|
2409 | |
vbox_left.pack_start(bits, False, False, 2)
|
2410 | |
vbox_left.pack_start(channels, False, False, 2)
|
2411 | |
vbox_right = gtk.VBox()
|
2412 | |
filestat = os.stat(self.currimg_name)
|
2413 | |
filename2 = gtk.Label(os.path.basename(self.currimg_name))
|
2414 | |
filedate2 = gtk.Label(time.strftime('%c', time.localtime(filestat[stat.ST_MTIME])))
|
2415 | |
imagesize2 = gtk.Label(str(self.currimg_pixbuf_original.get_width()) + "x" + str(self.currimg_pixbuf_original.get_height()))
|
2416 | |
filetype2 = gtk.Label(gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['mime_types'][0])
|
2417 | |
filesize2 = gtk.Label(str(filestat[stat.ST_SIZE] // 1000) + "KB")
|
2418 | |
if not image_is_anim and pixbuf.get_has_alpha():
|
2419 | |
transparency2 = gtk.Label(_("Yes"))
|
2420 | |
else:
|
2421 | |
transparency2 = gtk.Label(_("No"))
|
2422 | |
if animtest.is_static_image():
|
2423 | |
animation2 = gtk.Label(_("No"))
|
2424 | |
else:
|
2425 | |
animation2 = gtk.Label(_("Yes"))
|
2426 | |
bits2 = gtk.Label(str(pixbuf.get_bits_per_sample()))
|
2427 | |
channels2 = gtk.Label(str(pixbuf.get_n_channels()))
|
2428 | |
filename2.set_alignment(0, 1)
|
2429 | |
filedate2.set_alignment(0, 1)
|
2430 | |
imagesize2.set_alignment(0, 1)
|
2431 | |
filesize2.set_alignment(0, 1)
|
2432 | |
filetype2.set_alignment(0, 1)
|
2433 | |
transparency2.set_alignment(0, 1)
|
2434 | |
animation2.set_alignment(0, 1)
|
2435 | |
bits2.set_alignment(0, 1)
|
2436 | |
channels2.set_alignment(0, 1)
|
2437 | |
vbox_right.pack_start(filename2, False, False, 2)
|
2438 | |
vbox_right.pack_start(filedate2, False, False, 2)
|
2439 | |
vbox_right.pack_start(imagesize2, False, False, 2)
|
2440 | |
vbox_right.pack_start(filesize2, False, False, 2)
|
2441 | |
vbox_right.pack_start(filetype2, False, False, 2)
|
2442 | |
vbox_right.pack_start(transparency2, False, False, 2)
|
2443 | |
vbox_right.pack_start(animation2, False, False, 2)
|
2444 | |
vbox_right.pack_start(bits2, False, False, 2)
|
2445 | |
vbox_right.pack_start(channels2, False, False, 2)
|
2446 | |
hbox = gtk.HBox()
|
2447 | |
hbox.pack_start(vbox_left, False, False, 3)
|
2448 | |
hbox.pack_start(vbox_right, False, False, 3)
|
2449 | |
table.attach(image, 1, 2, 1, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2450 | |
table.attach(hbox, 2, 3, 1, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2451 | |
show_props.vbox.pack_start(table, False, False, 15)
|
2452 | |
show_props.vbox.show_all()
|
2453 | |
close_button = show_props.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
2454 | |
close_button.grab_focus()
|
2455 | |
show_props.run()
|
2456 | |
show_props.destroy()
|
2457 | |
|
2458 | |
def show_prefs(self, action):
|
2459 | |
prev_thumbnail_size = self.thumbnail_size
|
2460 | |
self.prefs_dialog = gtk.Dialog(_("Mirage Preferences"), self.window)
|
2461 | |
self.prefs_dialog.set_has_separator(False)
|
2462 | |
self.prefs_dialog.set_resizable(False)
|
2463 | |
# "Interface" prefs:
|
2464 | |
table_settings = gtk.Table(14, 3, False)
|
2465 | |
bglabel = gtk.Label()
|
2466 | |
bglabel.set_markup('<b>' + _('Interface') + '</b>')
|
2467 | |
bglabel.set_alignment(0, 1)
|
2468 | |
color_hbox = gtk.HBox(False, 0)
|
2469 | |
colortext = gtk.Label(_('Background color:'))
|
2470 | |
self.colorbutton = gtk.ColorButton(self.bgcolor)
|
2471 | |
self.colorbutton.connect('color-set', self.bgcolor_selected)
|
2472 | |
self.colorbutton.set_size_request(150, -1)
|
2473 | |
self.colorbutton.set_tooltip_text(_("Sets the background color for the application."))
|
2474 | |
color_hbox.pack_start(colortext, False, False, 0)
|
2475 | |
color_hbox.pack_start(self.colorbutton, False, False, 0)
|
2476 | |
color_hbox.pack_start(gtk.Label(), True, True, 0)
|
2477 | |
|
2478 | |
simplecolor_hbox = gtk.HBox(False, 0)
|
2479 | |
simplecolortext = gtk.Label(_('Simple background color:'))
|
2480 | |
simplecolorbutton = gtk.CheckButton()
|
2481 | |
simplecolorbutton.connect('toggled', self.simple_bgcolor_selected)
|
2482 | |
simplecolor_hbox.pack_start(simplecolortext, False, False, 0)
|
2483 | |
simplecolor_hbox.pack_start(simplecolorbutton, False, False, 0)
|
2484 | |
simplecolor_hbox.pack_start(gtk.Label(), True, True, 0)
|
2485 | |
if self.simple_bgcolor:
|
2486 | |
simplecolorbutton.set_active(True)
|
2487 | |
|
2488 | |
fullscreen = gtk.CheckButton(_("Open Mirage in fullscreen mode"))
|
2489 | |
fullscreen.set_active(self.start_in_fullscreen)
|
2490 | |
thumbbox = gtk.HBox()
|
2491 | |
thumblabel = gtk.Label(_("Thumbnail size:"))
|
2492 | |
thumbbox.pack_start(thumblabel, False, False, 0)
|
2493 | |
thumbsize = gtk.combo_box_new_text()
|
2494 | |
option = 0
|
2495 | |
for size in self.thumbnail_sizes:
|
2496 | |
thumbsize.append_text(size + " x " + size)
|
2497 | |
if self.thumbnail_size == int(size):
|
2498 | |
thumbsize.set_active(option)
|
2499 | |
option += 1
|
2500 | |
thumbbox.pack_start(thumbsize, False, False, 5)
|
2501 | |
table_settings.attach(gtk.Label(), 1, 3, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2502 | |
table_settings.attach(bglabel, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2503 | |
table_settings.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2504 | |
table_settings.attach(simplecolor_hbox, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2505 | |
table_settings.attach(color_hbox, 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2506 | |
table_settings.attach(gtk.Label(), 1, 3, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2507 | |
table_settings.attach(thumbbox, 1, 3, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2508 | |
table_settings.attach(gtk.Label(), 1, 3, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2509 | |
table_settings.attach(fullscreen, 1, 3, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2510 | |
table_settings.attach(gtk.Label(), 1, 3, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2511 | |
table_settings.attach(gtk.Label(), 1, 3, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2512 | |
table_settings.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2513 | |
table_settings.attach(gtk.Label(), 1, 3, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2514 | |
table_settings.attach(gtk.Label(), 1, 3, 14, 15, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2515 | |
# "Behavior" tab:
|
2516 | |
table_behavior = gtk.Table(14, 2, False)
|
2517 | |
openlabel = gtk.Label()
|
2518 | |
openlabel.set_markup('<b>' + _('Open Behavior') + '</b>')
|
2519 | |
openlabel.set_alignment(0, 1)
|
2520 | |
hbox_openmode = gtk.HBox()
|
2521 | |
hbox_openmode.pack_start(gtk.Label(_('Open new image in:')), False, False, 0)
|
2522 | |
combobox = gtk.combo_box_new_text()
|
2523 | |
combobox.append_text(_("Smart Mode"))
|
2524 | |
combobox.append_text(_("Zoom To Fit Mode"))
|
2525 | |
combobox.append_text(_("1:1 Mode"))
|
2526 | |
combobox.append_text(_("Last Active Mode"))
|
2527 | |
combobox.set_active(self.open_mode)
|
2528 | |
hbox_openmode.pack_start(combobox, False, False, 5)
|
2529 | |
openallimages = gtk.CheckButton(_("Load all images in current directory"))
|
2530 | |
openallimages.set_active(self.open_all_images)
|
2531 | |
openallimages.set_tooltip_text(_("If enabled, opening an image in Mirage will automatically load all images found in that image's directory."))
|
2532 | |
hiddenimages = gtk.CheckButton(_("Allow loading hidden files"))
|
2533 | |
hiddenimages.set_active(self.open_hidden_files)
|
2534 | |
hiddenimages.set_tooltip_text(_("If checked, Mirage will open hidden files. Otherwise, hidden files will be ignored."))
|
2535 | |
openpref = gtk.RadioButton()
|
2536 | |
openpref1 = gtk.RadioButton(group=openpref, label=_("Use last chosen directory"))
|
2537 | |
openpref1.set_tooltip_text(_("The default 'Open' directory will be the last directory used."))
|
2538 | |
openpref2 = gtk.RadioButton(group=openpref, label=_("Use this fixed directory:"))
|
2539 | |
openpref2.connect('toggled', self.prefs_use_fixed_dir_clicked)
|
2540 | |
openpref2.set_tooltip_text(_("The default 'Open' directory will be this specified directory."))
|
2541 | |
hbox_defaultdir = gtk.HBox()
|
2542 | |
self.defaultdir = gtk.Button()
|
2543 | |
hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
|
2544 | |
hbox_defaultdir.pack_start(self.defaultdir, False, False, 0)
|
2545 | |
hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
|
2546 | |
if len(self.fixed_dir) > 25:
|
2547 | |
self.defaultdir.set_label('...' + self.fixed_dir[-22:])
|
2548 | |
else:
|
2549 | |
self.defaultdir.set_label(self.fixed_dir)
|
2550 | |
self.defaultdir.connect('clicked', self.defaultdir_clicked)
|
2551 | |
self.defaultdir.set_size_request(250, -1)
|
2552 | |
if self.use_last_dir:
|
2553 | |
openpref1.set_active(True)
|
2554 | |
self.defaultdir.set_sensitive(False)
|
2555 | |
else:
|
2556 | |
openpref2.set_active(True)
|
2557 | |
self.defaultdir.set_sensitive(True)
|
2558 | |
table_behavior.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2559 | |
table_behavior.attach(openlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2560 | |
table_behavior.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2561 | |
table_behavior.attach(hbox_openmode, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2562 | |
table_behavior.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2563 | |
table_behavior.attach(openallimages, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2564 | |
table_behavior.attach(hiddenimages, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2565 | |
table_behavior.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2566 | |
table_behavior.attach(openpref1, 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2567 | |
table_behavior.attach(openpref2, 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2568 | |
table_behavior.attach(hbox_defaultdir, 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 45, 0)
|
2569 | |
table_behavior.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 45, 0)
|
2570 | |
# "Navigation" tab:
|
2571 | |
table_navigation = gtk.Table(14, 2, False)
|
2572 | |
navlabel = gtk.Label()
|
2573 | |
navlabel.set_markup('<b>' + _('Navigation') + '</b>')
|
2574 | |
navlabel.set_alignment(0, 1)
|
2575 | |
preloadnav = gtk.CheckButton(label=_("Preload images for faster navigation"))
|
2576 | |
preloadnav.set_active(self.preloading_images)
|
2577 | |
preloadnav.set_tooltip_text(_("If enabled, the next and previous images in the list will be preloaded during idle time. Note that the speed increase comes at the expense of memory usage, so it is recommended to disable this option on machines with limited ram."))
|
2578 | |
hbox_listwrap = gtk.HBox()
|
2579 | |
hbox_listwrap.pack_start(gtk.Label(_("Wrap around imagelist:")), False, False, 0)
|
2580 | |
combobox2 = gtk.combo_box_new_text()
|
2581 | |
combobox2.append_text(_("No"))
|
2582 | |
combobox2.append_text(_("Yes"))
|
2583 | |
combobox2.append_text(_("Prompt User"))
|
2584 | |
combobox2.set_active(self.listwrap_mode)
|
2585 | |
hbox_listwrap.pack_start(combobox2, False, False, 5)
|
2586 | |
table_navigation.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2587 | |
table_navigation.attach(navlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2588 | |
table_navigation.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2589 | |
table_navigation.attach(hbox_listwrap, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2590 | |
table_navigation.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2591 | |
table_navigation.attach(preloadnav, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2592 | |
table_navigation.attach(gtk.Label(), 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2593 | |
table_navigation.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2594 | |
table_navigation.attach(gtk.Label(), 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2595 | |
table_navigation.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2596 | |
table_navigation.attach(gtk.Label(), 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2597 | |
table_navigation.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2598 | |
table_navigation.attach(gtk.Label(), 1, 2, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2599 | |
# "Slideshow" tab:
|
2600 | |
table_slideshow = gtk.Table(14, 2, False)
|
2601 | |
slideshowlabel = gtk.Label()
|
2602 | |
slideshowlabel.set_markup('<b>' + _('Slideshow Mode') + '</b>')
|
2603 | |
slideshowlabel.set_alignment(0, 1)
|
2604 | |
hbox_delay = gtk.HBox()
|
2605 | |
hbox_delay.pack_start(gtk.Label(_("Delay between images in seconds:")), False, False, 0)
|
2606 | |
spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1, 10, 0)
|
2607 | |
delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
|
2608 | |
delayspin.set_numeric(True)
|
2609 | |
hbox_delay.pack_start(delayspin, False, False, 5)
|
2610 | |
randomize = gtk.CheckButton(_("Randomize order of images"))
|
2611 | |
randomize.set_active(self.slideshow_random)
|
2612 | |
randomize.set_tooltip_text(_("If enabled, a random image will be chosen during slideshow mode (without loading any image twice)."))
|
2613 | |
disable_screensaver = gtk.CheckButton(_("Disable screensaver in slideshow mode"))
|
2614 | |
disable_screensaver.set_active(self.disable_screensaver)
|
2615 | |
disable_screensaver.set_tooltip_text(_("If enabled, xscreensaver will be temporarily disabled during slideshow mode."))
|
2616 | |
ss_in_fs = gtk.CheckButton(_("Always start in fullscreen mode"))
|
2617 | |
ss_in_fs.set_tooltip_text(_("If enabled, starting a slideshow will put the application in fullscreen mode."))
|
2618 | |
ss_in_fs.set_active(self.slideshow_in_fullscreen)
|
2619 | |
table_slideshow.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2620 | |
table_slideshow.attach(slideshowlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2621 | |
table_slideshow.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2622 | |
table_slideshow.attach(hbox_delay, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2623 | |
table_slideshow.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2624 | |
table_slideshow.attach(disable_screensaver, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2625 | |
table_slideshow.attach(ss_in_fs, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2626 | |
table_slideshow.attach(randomize, 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2627 | |
table_slideshow.attach(gtk.Label(), 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2628 | |
table_slideshow.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2629 | |
table_slideshow.attach(gtk.Label(), 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2630 | |
table_slideshow.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2631 | |
table_slideshow.attach(gtk.Label(), 1, 2, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
|
2632 | |
# "Image" tab:
|
2633 | |
table_image = gtk.Table(14, 2, False)
|
2634 | |
imagelabel = gtk.Label()
|
2635 | |
imagelabel.set_markup('<b>' + _('Image Editing') + '</b>')
|
2636 | |
imagelabel.set_alignment(0, 1)
|
2637 | |
deletebutton = gtk.CheckButton(_("Confirm image delete"))
|
2638 | |
deletebutton.set_active(self.confirm_delete)
|
2639 | |
|
2640 | |
zoom_hbox = gtk.HBox()
|
2641 | |
zoom_hbox.pack_start(gtk.Label(_('Scaling quality:')), False, False, 0)
|
2642 | |
zoomcombo = gtk.combo_box_new_text()
|
2643 | |
zoomcombo.append_text(_("Nearest (Fastest)"))
|
2644 | |
zoomcombo.append_text(_("Tiles"))
|
2645 | |
zoomcombo.append_text(_("Bilinear"))
|
2646 | |
zoomcombo.append_text(_("Hyper (Best)"))
|
2647 | |
zoomcombo.set_active(self.zoomvalue)
|
2648 | |
zoom_hbox.pack_start(zoomcombo, False, False, 0)
|
2649 | |
zoom_hbox.pack_start(gtk.Label(), True, True, 0)
|
2650 | |
|
2651 | |
hbox_save = gtk.HBox()
|
2652 | |
savelabel = gtk.Label(_("Modified images:"))
|
2653 | |
savecombo = gtk.combo_box_new_text()
|
2654 | |
savecombo.append_text(_("Ignore Changes"))
|
2655 | |
savecombo.append_text(_("Auto-Save"))
|
2656 | |
savecombo.append_text(_("Prompt For Action"))
|
2657 | |
savecombo.set_active(self.savemode)
|
2658 | |
hbox_save.pack_start(savelabel, False, False, 0)
|
2659 | |
hbox_save.pack_start(savecombo, False, False, 5)
|
2660 | |
|
2661 | |
hbox_quality = gtk.HBox()
|
2662 | |
qualitylabel = gtk.Label(_("Quality to save in:"))
|
2663 | |
qspin_adj = gtk.Adjustment(self.quality_save, 0, 100, 1, 100, 0)
|
2664 | |
qualityspin = gtk.SpinButton(qspin_adj, 1.0, 0)
|
2665 | |
qualityspin.set_numeric(True)
|
2666 | |
hbox_quality.pack_start(qualitylabel, False, False, 0)
|
2667 | |
hbox_quality.pack_start(qualityspin, False, False, 5)
|
2668 | |
table_image.attach(gtk.Label(), 1, 3, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2669 | |
table_image.attach(imagelabel, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
|
2670 | |
table_image.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2671 | |
table_image.attach(zoom_hbox, 1, 3, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2672 | |
table_image.attach(gtk.Label(), 1, 3, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2673 | |
table_image.attach(hbox_save, 1, 3, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2674 | |
table_image.attach(gtk.Label(), 1, 3, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2675 | |
table_image.attach(hbox_quality, 1, 3, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2676 | |
table_image.attach(gtk.Label(), 1, 3, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2677 | |
table_image.attach(deletebutton, 1, 3, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2678 | |
table_image.attach(gtk.Label(), 1, 3, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2679 | |
table_image.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2680 | |
table_image.attach(gtk.Label(), 1, 3, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2681 | |
table_image.attach(gtk.Label(), 1, 3, 14, 15, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
|
2682 | |
# Add tabs:
|
2683 | |
notebook = gtk.Notebook()
|
2684 | |
notebook.append_page(table_behavior, gtk.Label(_("Behavior")))
|
2685 | |
notebook.append_page(table_navigation, gtk.Label(_("Navigation")))
|
2686 | |
notebook.append_page(table_settings, gtk.Label(_("Interface")))
|
2687 | |
notebook.append_page(table_slideshow, gtk.Label(_("Slideshow")))
|
2688 | |
notebook.append_page(table_image, gtk.Label(_("Image")))
|
2689 | |
notebook.set_current_page(0)
|
2690 | |
hbox = gtk.HBox()
|
2691 | |
self.prefs_dialog.vbox.pack_start(hbox, False, False, 7)
|
2692 | |
hbox.pack_start(notebook, False, False, 7)
|
2693 | |
notebook.connect('switch-page', self.prefs_tab_switched)
|
2694 | |
# Show prefs:
|
2695 | |
self.prefs_dialog.vbox.show_all()
|
2696 | |
self.close_button = self.prefs_dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
2697 | |
self.close_button.grab_focus()
|
2698 | |
response = self.prefs_dialog.run()
|
2699 | |
if response == gtk.RESPONSE_CLOSE or response == gtk.RESPONSE_DELETE_EVENT:
|
2700 | |
self.zoomvalue = zoomcombo.get_active()
|
2701 | |
if int(round(self.zoomvalue, 0)) == 0:
|
2702 | |
self.zoom_quality = gtk.gdk.INTERP_NEAREST
|
2703 | |
elif int(round(self.zoomvalue, 0)) == 1:
|
2704 | |
self.zoom_quality = gtk.gdk.INTERP_TILES
|
2705 | |
elif int(round(self.zoomvalue, 0)) == 2:
|
2706 | |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
2707 | |
elif int(round(self.zoomvalue, 0)) == 3:
|
2708 | |
self.zoom_quality = gtk.gdk.INTERP_HYPER
|
2709 | |
self.open_all_images = openallimages.get_active()
|
2710 | |
self.open_hidden_files = hiddenimages.get_active()
|
2711 | |
if openpref1.get_active():
|
2712 | |
self.use_last_dir = True
|
2713 | |
else:
|
2714 | |
self.use_last_dir = False
|
2715 | |
open_mode_prev = self.open_mode
|
2716 | |
self.open_mode = combobox.get_active()
|
2717 | |
preloading_images_prev = self.preloading_images
|
2718 | |
self.preloading_images = preloadnav.get_active()
|
2719 | |
self.listwrap_mode = combobox2.get_active()
|
2720 | |
self.slideshow_delay = delayspin.get_value()
|
2721 | |
self.curr_slideshow_delay = self.slideshow_delay
|
2722 | |
self.slideshow_random = randomize.get_active()
|
2723 | |
self.curr_slideshow_random = self.slideshow_random
|
2724 | |
self.disable_screensaver = disable_screensaver.get_active()
|
2725 | |
self.slideshow_in_fullscreen = ss_in_fs.get_active()
|
2726 | |
self.savemode = savecombo.get_active()
|
2727 | |
self.start_in_fullscreen = fullscreen.get_active()
|
2728 | |
self.confirm_delete = deletebutton.get_active()
|
2729 | |
self.quality_save = qualityspin.get_value()
|
2730 | |
self.thumbnail_size = int(self.thumbnail_sizes[thumbsize.get_active()])
|
2731 | |
if self.thumbnail_size != prev_thumbnail_size:
|
2732 | |
gobject.idle_add(self.thumbpane_set_size)
|
2733 | |
gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
|
2734 | |
self.prefs_dialog.destroy()
|
2735 | |
self.set_go_navigation_sensitivities(False)
|
2736 | |
if (self.preloading_images and not preloading_images_prev) or (open_mode_prev != self.open_mode):
|
2737 | |
# The user just turned on preloading, so do it:
|
2738 | |
self.preloadimg_next_in_list = -1
|
2739 | |
self.preloadimg_prev_in_list = -1
|
2740 | |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
|
2741 | |
self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, False)
|
2742 | |
elif not self.preloading_images:
|
2743 | |
self.preloadimg_next_in_list = -1
|
2744 | |
self.preloadimg_prev_in_list = -1
|
2745 | |
|
2746 | |
def prefs_use_fixed_dir_clicked(self, button):
|
2747 | |
if button.get_active():
|
2748 | |
self.defaultdir.set_sensitive(True)
|
2749 | |
else:
|
2750 | |
self.defaultdir.set_sensitive(False)
|
2751 | |
|
2752 | |
def rename_image(self, action):
|
2753 | |
if len(self.image_list) > 0:
|
2754 | |
temp_slideshow_mode = self.slideshow_mode
|
2755 | |
if self.slideshow_mode:
|
2756 | |
self.toggle_slideshow(None)
|
2757 | |
rename_dialog = gtk.Dialog(_('Rename Image'), self.window, gtk.DIALOG_MODAL)
|
2758 | |
self.rename_txt = gtk.Entry()
|
2759 | |
filename = os.path.basename(self.currimg_name)
|
2760 | |
self.rename_txt.set_text(filename)
|
2761 | |
self.rename_txt.set_activates_default(True)
|
2762 | |
cancelbutton = rename_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
2763 | |
renamebutton = rename_dialog.add_button(_("_Rename"), gtk.RESPONSE_ACCEPT)
|
2764 | |
renameimage = gtk.Image()
|
2765 | |
renameimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
2766 | |
renamebutton.set_image(renameimage)
|
2767 | |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
2768 | |
if animtest.is_static_image():
|
2769 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 60, self.zoom_quality)
|
2770 | |
else:
|
2771 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 60, self.zoom_quality)
|
2772 | |
image = gtk.Image()
|
2773 | |
image.set_from_pixbuf(pixbuf)
|
2774 | |
instructions = gtk.Label(_("Enter the new name:"))
|
2775 | |
instructions.set_alignment(0, 1)
|
2776 | |
hbox = gtk.HBox()
|
2777 | |
hbox.pack_start(image, False, False, 10)
|
2778 | |
vbox_stuff = gtk.VBox()
|
2779 | |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
2780 | |
vbox_stuff.pack_start(instructions, False, False, 0)
|
2781 | |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
2782 | |
vbox_stuff.pack_start(self.rename_txt, True, True, 0)
|
2783 | |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
2784 | |
hbox.pack_start(vbox_stuff, True, True, 10)
|
2785 | |
rename_dialog.vbox.pack_start(hbox, False, False, 0)
|
2786 | |
rename_dialog.set_has_separator(True)
|
2787 | |
rename_dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
2788 | |
rename_dialog.set_size_request(300, -1)
|
2789 | |
rename_dialog.vbox.show_all()
|
2790 | |
rename_dialog.connect('show', self.select_rename_text)
|
2791 | |
response = rename_dialog.run()
|
2792 | |
if response == gtk.RESPONSE_ACCEPT:
|
2793 | |
try:
|
2794 | |
new_filename = os.path.dirname(self.currimg_name) + "/" + self.rename_txt.get_text()
|
2795 | |
shutil.move(self.currimg_name, new_filename)
|
2796 | |
# Update thumbnail filename:
|
2797 | |
try:
|
2798 | |
shutil.move(self_get_name(self.currimg_name)[1], self.thumbnail_get_name(new_filename)[1])
|
2799 | |
except:
|
2800 | |
pass
|
2801 | |
self.recent_file_remove_and_refresh_name(self.currimg_name)
|
2802 | |
self.currimg_name = new_filename
|
2803 | |
self.register_file_with_recent_docs(self.currimg_name)
|
2804 | |
self.update_title()
|
2805 | |
except:
|
2806 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _('Unable to rename %s') % self.currimg_name)
|
2807 | |
error_dialog.set_title(_("Unable to rename"))
|
2808 | |
error_dialog.run()
|
2809 | |
error_dialog.destroy()
|
2810 | |
rename_dialog.destroy()
|
2811 | |
if temp_slideshow_mode:
|
2812 | |
self.toggle_slideshow(None)
|
2813 | |
|
2814 | |
def select_rename_text(self, widget):
|
2815 | |
filename = os.path.basename(self.currimg_name)
|
2816 | |
fileext = os.path.splitext(os.path.basename(self.currimg_name))[1]
|
2817 | |
self.rename_txt.select_region(0, len(filename) - len(fileext))
|
2818 | |
|
2819 | |
def delete_image(self, action):
|
2820 | |
if len(self.image_list) > 0:
|
2821 | |
temp_slideshow_mode = self.slideshow_mode
|
2822 | |
if self.slideshow_mode:
|
2823 | |
self.toggle_slideshow(None)
|
2824 | |
delete_dialog = gtk.Dialog(_('Delete Image'), self.window, gtk.DIALOG_MODAL)
|
2825 | |
if self.confirm_delete:
|
2826 | |
permlabel = gtk.Label(_('Are you sure you wish to permanently delete %s?') % os.path.split(self.currimg_name)[1])
|
2827 | |
permlabel.set_line_wrap(True)
|
2828 | |
permlabel.set_alignment(0, 0.1)
|
2829 | |
warningicon = gtk.Image()
|
2830 | |
warningicon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
|
2831 | |
hbox = gtk.HBox()
|
2832 | |
hbox.pack_start(warningicon, False, False, 10)
|
2833 | |
hbox.pack_start(permlabel, False, False, 10)
|
2834 | |
delete_dialog.vbox.pack_start(gtk.Label(), False, False, 0)
|
2835 | |
delete_dialog.vbox.pack_start(hbox, False, False, 0)
|
2836 | |
cancelbutton = delete_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
2837 | |
deletebutton = delete_dialog.add_button(gtk.STOCK_DELETE, gtk.RESPONSE_YES)
|
2838 | |
delete_dialog.set_has_separator(False)
|
2839 | |
deletebutton.set_property('has-focus', True)
|
2840 | |
delete_dialog.set_default_response(gtk.RESPONSE_YES)
|
2841 | |
delete_dialog.vbox.show_all()
|
2842 | |
response = delete_dialog.run()
|
2843 | |
else:
|
2844 | |
response = gtk.RESPONSE_YES
|
2845 | |
if response == gtk.RESPONSE_YES:
|
2846 | |
try:
|
2847 | |
os.remove(self.currimg_name)
|
2848 | |
self.image_modified = False
|
2849 | |
try:
|
2850 | |
os.remove(self.thumbnail_get_name(self.currimg_name)[1])
|
2851 | |
except:
|
2852 | |
pass
|
2853 | |
self.recent_file_remove_and_refresh_name(self.currimg_name)
|
2854 | |
iter = self.thumblist.get_iter((self.curr_img_in_list,))
|
2855 | |
try:
|
2856 | |
self.thumbnail_loaded.pop(self.curr_img_in_list)
|
2857 | |
self.thumbpane_update_images()
|
2858 | |
except:
|
2859 | |
pass
|
2860 | |
self.thumblist.remove(iter)
|
2861 | |
templist = self.image_list
|
2862 | |
self.image_list = []
|
2863 | |
for item in templist:
|
2864 | |
if item != self.currimg_name:
|
2865 | |
self.image_list.append(item)
|
2866 | |
if len(self.image_list) >= 1:
|
2867 | |
if len(self.image_list) == 1:
|
2868 | |
self.curr_img_in_list = 0
|
2869 | |
elif self.curr_img_in_list == len(self.image_list):
|
2870 | |
self.curr_img_in_list -= 1
|
2871 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
2872 | |
self.preloadimg_prev_in_list = -1
|
2873 | |
self.preloadimg_next_in_list = -1
|
2874 | |
self.load_when_idle = gobject.idle_add(self.load_new_image, False, False, True, True, True, True)
|
2875 | |
self.set_go_navigation_sensitivities(False)
|
2876 | |
else:
|
2877 | |
self.imageview.clear()
|
2878 | |
self.update_title()
|
2879 | |
self.statusbar.push(self.statusbar.get_context_id(""), "")
|
2880 | |
self.image_loaded = False
|
2881 | |
self.set_slideshow_sensitivities()
|
2882 | |
self.set_image_sensitivities(False)
|
2883 | |
self.set_go_navigation_sensitivities(False)
|
2884 | |
# Select new item:
|
2885 | |
self.thumbpane_select(self.curr_img_in_list)
|
2886 | |
except:
|
2887 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _('Unable to delete %s') % self.currimg_name)
|
2888 | |
error_dialog.set_title(_("Unable to delete"))
|
2889 | |
error_dialog.run()
|
2890 | |
error_dialog.destroy()
|
2891 | |
delete_dialog.destroy()
|
2892 | |
if temp_slideshow_mode:
|
2893 | |
self.toggle_slideshow(None)
|
2894 | |
|
2895 | |
def defaultdir_clicked(self, button):
|
2896 | |
getdir = gtk.FileChooserDialog(title=_("Choose directory"),action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
2897 | |
getdir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
2898 | |
getdir.set_filename(self.fixed_dir)
|
2899 | |
getdir.set_default_response(gtk.RESPONSE_OK)
|
2900 | |
response = getdir.run()
|
2901 | |
if response == gtk.RESPONSE_OK:
|
2902 | |
self.fixed_dir = getdir.get_filenames()[0]
|
2903 | |
if len(self.fixed_dir) > 25:
|
2904 | |
button.set_label('...' + self.fixed_dir[-22:])
|
2905 | |
else:
|
2906 | |
button.set_label(self.fixed_dir)
|
2907 | |
getdir.destroy()
|
2908 | |
else:
|
2909 | |
getdir.destroy()
|
2910 | |
|
2911 | |
def prefs_tab_switched(self, notebook, page, page_num):
|
2912 | |
do_when_idle = gobject.idle_add(self.grab_close_button)
|
2913 | |
|
2914 | |
def grab_close_button(self):
|
2915 | |
self.close_button.grab_focus()
|
2916 | |
|
2917 | |
def bgcolor_selected(self, widget):
|
2918 | |
# When the user selects a color, store this color in self.bgcolor (which will
|
2919 | |
# later be saved to .miragerc) and set this background color:
|
2920 | |
self.bgcolor = widget.get_property('color')
|
2921 | |
if not self.simple_bgcolor:
|
2922 | |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
2923 | |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
2924 | |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
2925 | |
|
2926 | |
def simple_bgcolor_selected(self, widget):
|
2927 | |
if widget.get_active():
|
2928 | |
self.simple_bgcolor = True
|
2929 | |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
2930 | |
else:
|
2931 | |
self.simple_bgcolor = False
|
2932 | |
self.bgcolor_selected(self.colorbutton)
|
2933 | |
|
2934 | |
def show_about(self, action):
|
2935 | |
# Help > About
|
2936 | |
self.about_dialog = gtk.AboutDialog()
|
2937 | |
try:
|
2938 | |
self.about_dialog.set_transient_for(self.window)
|
2939 | |
self.about_dialog.set_modal(True)
|
2940 | |
except:
|
2941 | |
pass
|
2942 | |
self.about_dialog.set_name('Mirage')
|
2943 | |
self.about_dialog.set_version(__version__)
|
2944 | |
self.about_dialog.set_comments(_('A fast GTK+ Image Viewer.'))
|
2945 | |
self.about_dialog.set_license(__license__)
|
2946 | |
self.about_dialog.set_authors(['Scott Horowitz <stonecrest@gmail.com>', 'Fredric Johansson <fredric.miscmail@gmail.com>'])
|
2947 | |
self.about_dialog.set_artists(['William Rea <sillywilly@gmail.com>'])
|
2948 | |
self.about_dialog.set_translator_credits('cs - Petr Pisar <petr.pisar@atlas.cz>\nde - Bjoern Martensen <bjoern.martensen@gmail.com>\nes - Isidro Arribas <cdhotfire@gmail.com>\nfr - Mike Massonnet <mmassonnet@gmail.com>\nhu - Sandor Lisovszki <lisovszki@dunakanyar.net>\nnl - Pascal De Vuyst <pascal.devuyst@gmail.com>\npl - Tomasz Dominikowski <dominikowski@gmail.com>\npt_BR - Danilo Martins <mawkee@gmail.com>\nru - mavka <mavka@justos.org>\nit - Daniele Maggio <dado84@freemail.it>\nzh_CN - Jayden Suen <no.sun@163.com>')
|
2949 | |
gtk.about_dialog_set_url_hook(self.show_website, "http://mirageiv.berlios.de")
|
2950 | |
self.about_dialog.set_website_label("http://mirageiv.berlios.de")
|
2951 | |
icon_path = self.find_path('mirage.png')
|
2952 | |
try:
|
2953 | |
icon_pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
|
2954 | |
self.about_dialog.set_logo(icon_pixbuf)
|
2955 | |
except:
|
2956 | |
pass
|
2957 | |
self.about_dialog.connect('response', self.close_about)
|
2958 | |
self.about_dialog.connect('delete_event', self.close_about)
|
2959 | |
self.about_dialog.show_all()
|
2960 | |
|
2961 | |
def show_website(self, dialog, blah, link):
|
2962 | |
self.browser_load(link)
|
2963 | |
|
2964 | |
def show_help(self, action):
|
2965 | |
self.browser_load("http://mirageiv.berlios.de/docs.html")
|
2966 | |
|
2967 | |
def browser_load(self, docslink):
|
2968 | |
try:
|
2969 | |
pid = subprocess.Popen(["gnome-open", docslink]).pid
|
2970 | |
except:
|
2971 | |
try:
|
2972 | |
pid = subprocess.Popen(["exo-open", docslink]).pid
|
2973 | |
except:
|
2974 | |
try:
|
2975 | |
pid = subprocess.Popen(["kfmclient", "openURL", docslink]).pid
|
2976 | |
except:
|
2977 | |
try:
|
2978 | |
pid = subprocess.Popen(["firefox", docslink]).pid
|
2979 | |
except:
|
2980 | |
try:
|
2981 | |
pid = subprocess.Popen(["mozilla", docslink]).pid
|
2982 | |
except:
|
2983 | |
try:
|
2984 | |
pid = subprocess.Popen(["opera", docslink]).pid
|
2985 | |
except:
|
2986 | |
error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Unable to launch a suitable browser.'))
|
2987 | |
error_dialog.run()
|
2988 | |
error_dialog.destroy()
|
2989 | |
|
2990 | |
def close_about(self, event, data=None):
|
2991 | |
self.about_dialog.hide()
|
2992 | |
return True
|
2993 | |
|
2994 | |
def mousewheel_scrolled(self, widget, event):
|
2995 | |
if event.type == gtk.gdk.SCROLL:
|
2996 | |
# Zooming of the image by Ctrl-mousewheel
|
2997 | |
if event.state & gtk.gdk.CONTROL_MASK:
|
2998 | |
if event.direction == gtk.gdk.SCROLL_UP:
|
2999 | |
self.zoom_in(None)
|
3000 | |
elif event.direction == gtk.gdk.SCROLL_DOWN:
|
3001 | |
self.zoom_out(None)
|
3002 | |
return True
|
3003 | |
# Navigation of images with mousewheel:
|
3004 | |
else:
|
3005 | |
if event.direction == gtk.gdk.SCROLL_UP:
|
3006 | |
self.goto_prev_image(None)
|
3007 | |
elif event.direction == gtk.gdk.SCROLL_DOWN:
|
3008 | |
self.goto_next_image(None)
|
3009 | |
return True
|
3010 | |
|
3011 | |
def mouse_moved(self, widget, event):
|
3012 | |
# This handles the panning of the image
|
3013 | |
if event.is_hint:
|
3014 | |
x, y, state = event.window.get_pointer()
|
3015 | |
else:
|
3016 | |
state = event.state
|
3017 | |
x, y = event.x_root, event.y_root
|
3018 | |
if (state & gtk.gdk.BUTTON2_MASK) or (state & gtk.gdk.BUTTON1_MASK):
|
3019 | |
# Prevent self.expose_event() from potentially further changing the
|
3020 | |
# adjustments upon the adjustment value changes
|
3021 | |
self.updating_adjustments = True
|
3022 | |
xadjust = self.layout.get_hadjustment()
|
3023 | |
newx = xadjust.value + (self.prevmousex - x)
|
3024 | |
if newx >= xadjust.lower and newx <= xadjust.upper - xadjust.page_size:
|
3025 | |
xadjust.set_value(newx)
|
3026 | |
self.layout.set_hadjustment(xadjust)
|
3027 | |
yadjust = self.layout.get_vadjustment()
|
3028 | |
newy = yadjust.value + (self.prevmousey - y)
|
3029 | |
if newy >= yadjust.lower and newy <= yadjust.upper - yadjust.page_size:
|
3030 | |
yadjust.set_value(newy)
|
3031 | |
self.layout.set_vadjustment(yadjust)
|
3032 | |
self.updating_adjustments = False
|
3033 | |
self.prevmousex = x
|
3034 | |
self.prevmousey = y
|
3035 | |
if self.fullscreen_mode:
|
3036 | |
# Show cursor on movement, then hide after 2 seconds of no movement
|
3037 | |
self.change_cursor(None)
|
3038 | |
if not self.slideshow_controls_visible:
|
3039 | |
gobject.source_remove(self.timer_id)
|
3040 | |
if not self.closing_app:
|
3041 | |
while gtk.events_pending():
|
3042 | |
gtk.main_iteration()
|
3043 | |
self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
|
3044 | |
if y > 0.9*self.available_image_height():
|
3045 | |
self.slideshow_controls_show()
|
3046 | |
else:
|
3047 | |
self.slideshow_controls_hide()
|
3048 | |
return True
|
3049 | |
|
3050 | |
def button_pressed(self, widget, event):
|
3051 | |
if self.image_loaded:
|
3052 | |
# Changes the cursor to the 'resize' cursor, like GIMP, on a middle click:
|
3053 | |
if (event.button == 2 or event.button == 1) and (self.hscroll.get_property('visible')==True or self.vscroll.get_property('visible')==True):
|
3054 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
|
3055 | |
self.prevmousex = event.x_root
|
3056 | |
self.prevmousey = event.y_root
|
3057 | |
# Right-click popup:
|
3058 | |
elif self.image_loaded and event.button == 3:
|
3059 | |
self.UIManager.get_widget('/Popup').popup(None, None, None, event.button, event.time)
|
3060 | |
return True
|
3061 | |
|
3062 | |
def button_released(self, widget, event):
|
3063 | |
# Resets the cursor when middle mouse button is released
|
3064 | |
if event.button == 2 or event.button == 1:
|
3065 | |
self.change_cursor(None)
|
3066 | |
return True
|
3067 | |
|
3068 | |
def zoom_in(self, action):
|
3069 | |
if self.currimg_name != "" and self.UIManager.get_widget('/MainMenu/ViewMenu/In').get_property('sensitive'):
|
3070 | |
self.image_zoomed = True
|
3071 | |
self.currimg_zoomratio = self.currimg_zoomratio * 1.25
|
3072 | |
self.set_zoom_sensitivities()
|
3073 | |
self.last_image_action_was_fit = False
|
3074 | |
self.put_zoom_image_to_window(False)
|
3075 | |
self.update_statusbar()
|
3076 | |
|
3077 | |
def zoom_out(self, action):
|
3078 | |
if self.currimg_name != "" and self.UIManager.get_widget('/MainMenu/ViewMenu/Out').get_property('sensitive'):
|
3079 | |
if self.currimg_zoomratio == self.min_zoomratio:
|
3080 | |
# No point in proceeding..
|
3081 | |
return
|
3082 | |
self.image_zoomed = True
|
3083 | |
self.currimg_zoomratio = self.currimg_zoomratio * 1/1.25
|
3084 | |
if self.currimg_zoomratio < self.min_zoomratio:
|
3085 | |
self.currimg_zoomratio = self.min_zoomratio
|
3086 | |
self.set_zoom_sensitivities()
|
3087 | |
self.last_image_action_was_fit = False
|
3088 | |
self.put_zoom_image_to_window(False)
|
3089 | |
self.update_statusbar()
|
3090 | |
|
3091 | |
def zoom_to_fit_window_action(self, action):
|
3092 | |
self.zoom_to_fit_window(action, False, False)
|
3093 | |
|
3094 | |
def zoom_to_fit_window(self, action, is_preloadimg_next, is_preloadimg_prev):
|
3095 | |
if is_preloadimg_next:
|
3096 | |
if self.preloading_images and self.preloadimg_next_in_list != -1:
|
3097 | |
win_width = self.available_image_width()
|
3098 | |
win_height = self.available_image_height()
|
3099 | |
preimg_width = self.preloadimg_next_pixbuf_original.get_width()
|
3100 | |
preimg_height = self.preloadimg_next_pixbuf_original.get_height()
|
3101 | |
prewidth_ratio = float(preimg_width)/win_width
|
3102 | |
preheight_ratio = float(preimg_height)/win_height
|
3103 | |
if prewidth_ratio < preheight_ratio:
|
3104 | |
premax_ratio = preheight_ratio
|
3105 | |
else:
|
3106 | |
premax_ratio = prewidth_ratio
|
3107 | |
self.preloadimg_next_zoomratio = 1/float(max_ratio)
|
3108 | |
elif is_preloadimg_prev:
|
3109 | |
if self.preloading_images and self.preloadimg_prev_in_list != -1:
|
3110 | |
win_width = self.available_image_width()
|
3111 | |
win_height = self.available_image_height()
|
3112 | |
preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
|
3113 | |
preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
|
3114 | |
prewidth_ratio = float(preimg_width)/win_width
|
3115 | |
preheight_ratio = float(preimg_height)/win_height
|
3116 | |
if prewidth_ratio < preheight_ratio:
|
3117 | |
premax_ratio = preheight_ratio
|
3118 | |
else:
|
3119 | |
premax_ratio = prewidth_ratio
|
3120 | |
self.preloadimg_prev_zoomratio = 1/float(max_ratio)
|
3121 | |
else:
|
3122 | |
if self.currimg_name != "" and (self.slideshow_mode or self.UIManager.get_widget('/MainMenu/ViewMenu/Fit').get_property('sensitive')):
|
3123 | |
self.image_zoomed = True
|
3124 | |
self.last_mode = self.open_mode_fit
|
3125 | |
self.last_image_action_was_fit = True
|
3126 | |
self.last_image_action_was_smart_fit = False
|
3127 | |
# Calculate zoomratio needed to fit to window:
|
3128 | |
win_width = self.available_image_width()
|
3129 | |
win_height = self.available_image_height()
|
3130 | |
img_width = self.currimg_pixbuf_original.get_width()
|
3131 | |
img_height = self.currimg_pixbuf_original.get_height()
|
3132 | |
width_ratio = float(img_width)/win_width
|
3133 | |
height_ratio = float(img_height)/win_height
|
3134 | |
if width_ratio < height_ratio:
|
3135 | |
max_ratio = height_ratio
|
3136 | |
else:
|
3137 | |
max_ratio = width_ratio
|
3138 | |
self.currimg_zoomratio = 1/float(max_ratio)
|
3139 | |
self.set_zoom_sensitivities()
|
3140 | |
self.put_zoom_image_to_window(False)
|
3141 | |
self.update_statusbar()
|
3142 | |
|
3143 | |
def zoom_to_fit_or_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
|
3144 | |
if is_preloadimg_next:
|
3145 | |
if self.preloading_images and self.preloadimg_next_in_list != -1:
|
3146 | |
win_width = self.available_image_width()
|
3147 | |
win_height = self.available_image_height()
|
3148 | |
preimg_width = self.preloadimg_next_pixbuf_original.get_width()
|
3149 | |
preimg_height = self.preloadimg_next_pixbuf_original.get_height()
|
3150 | |
prewidth_ratio = float(preimg_width)/win_width
|
3151 | |
preheight_ratio = float(preimg_height)/win_height
|
3152 | |
if prewidth_ratio < preheight_ratio:
|
3153 | |
premax_ratio = preheight_ratio
|
3154 | |
else:
|
3155 | |
premax_ratio = prewidth_ratio
|
3156 | |
self.preloadimg_next_zoomratio = 1/float(premax_ratio)
|
3157 | |
if self.preloadimg_next_zoomratio > 1:
|
3158 | |
self.preloadimg_next_zoomratio = 1
|
3159 | |
elif is_preloadimg_prev:
|
3160 | |
if self.preloading_images and self.preloadimg_prev_in_list != -1:
|
3161 | |
win_width = self.available_image_width()
|
3162 | |
win_height = self.available_image_height()
|
3163 | |
preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
|
3164 | |
preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
|
3165 | |
prewidth_ratio = float(preimg_width)/win_width
|
3166 | |
preheight_ratio = float(preimg_height)/win_height
|
3167 | |
if prewidth_ratio < preheight_ratio:
|
3168 | |
premax_ratio = preheight_ratio
|
3169 | |
else:
|
3170 | |
premax_ratio = prewidth_ratio
|
3171 | |
self.preloadimg_prev_zoomratio = 1/float(premax_ratio)
|
3172 | |
if self.preloadimg_prev_zoomratio > 1:
|
3173 | |
self.preloadimg_prev_zoomratio = 1
|
3174 | |
else:
|
3175 | |
if self.currimg_name != "":
|
3176 | |
self.image_zoomed = True
|
3177 | |
# Calculate zoomratio needed to fit to window:
|
3178 | |
win_width = self.available_image_width()
|
3179 | |
win_height = self.available_image_height()
|
3180 | |
img_width = self.currimg_pixbuf_original.get_width()
|
3181 | |
img_height = self.currimg_pixbuf_original.get_height()
|
3182 | |
width_ratio = float(img_width)/win_width
|
3183 | |
height_ratio = float(img_height)/win_height
|
3184 | |
if width_ratio < height_ratio:
|
3185 | |
max_ratio = height_ratio
|
3186 | |
else:
|
3187 | |
max_ratio = width_ratio
|
3188 | |
self.currimg_zoomratio = 1/float(max_ratio)
|
3189 | |
self.set_zoom_sensitivities()
|
3190 | |
if self.currimg_zoomratio > 1:
|
3191 | |
# Revert to 1:1 zoom
|
3192 | |
self.zoom_1_to_1(action, False, False)
|
3193 | |
else:
|
3194 | |
self.put_zoom_image_to_window(False)
|
3195 | |
self.update_statusbar()
|
3196 | |
self.last_image_action_was_fit = True
|
3197 | |
self.last_image_action_was_smart_fit = True
|
3198 | |
|
3199 | |
def zoom_1_to_1_action(self, action):
|
3200 | |
self.zoom_1_to_1(action, False, False)
|
3201 | |
|
3202 | |
def zoom_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
|
3203 | |
if is_preloadimg_next:
|
3204 | |
if self.preloading_images:
|
3205 | |
self.preloadimg_next_zoomratio = 1
|
3206 | |
elif is_preloadimg_prev:
|
3207 | |
if self.preloading_images:
|
3208 | |
self.preloadimg_prev_zoomratio = 1
|
3209 | |
else:
|
3210 | |
if self.currimg_name != "" and (self.slideshow_mode or self.currimg_is_animation or (not self.currimg_is_animation and self.UIManager.get_widget('/MainMenu/ViewMenu/1:1').get_property('sensitive'))):
|
3211 | |
self.image_zoomed = True
|
3212 | |
self.last_mode = self.open_mode_1to1
|
3213 | |
self.last_image_action_was_fit = False
|
3214 | |
self.currimg_zoomratio = 1
|
3215 | |
self.put_zoom_image_to_window(False)
|
3216 | |
self.update_statusbar()
|
3217 | |
|
3218 | |
def rotate_left(self, action):
|
3219 | |
self.rotate_left_or_right(self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Left'), 90)
|
3220 | |
|
3221 | |
def rotate_right(self, action):
|
3222 | |
self.rotate_left_or_right(self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Right'), 270)
|
3223 | |
|
3224 | |
def rotate_left_or_right(self, widget, angle):
|
3225 | |
if self.currimg_name != "" and widget.get_property('sensitive'):
|
3226 | |
self.currimg_pixbuf_original = self.image_rotate(self.currimg_pixbuf_original, angle)
|
3227 | |
if self.last_image_action_was_fit:
|
3228 | |
if self.last_image_action_was_smart_fit:
|
3229 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
3230 | |
else:
|
3231 | |
self.zoom_to_fit_window(None, False, False)
|
3232 | |
else:
|
3233 | |
self.currimg_width, self.currimg_height = self.currimg_height, self.currimg_width
|
3234 | |
self.layout.set_size(self.currimg_width, self.currimg_height)
|
3235 | |
self.currimg_pixbuf = self.image_rotate(self.currimg_pixbuf, angle)
|
3236 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
3237 | |
self.show_scrollbars_if_needed()
|
3238 | |
self.center_image()
|
3239 | |
self.update_statusbar()
|
3240 | |
self.image_modified = True
|
3241 | |
|
3242 | |
|
3243 | |
def flip_image_vert(self, action):
|
3244 | |
self.flip_image_vert_or_horiz(self.UIManager.get_widget('/MainMenu/EditMenu/Flip Vertically'), True)
|
3245 | |
|
3246 | |
def flip_image_horiz(self, action):
|
3247 | |
self.flip_image_vert_or_horiz(self.UIManager.get_widget('/MainMenu/EditMenu/Flip Horizontally'), False)
|
3248 | |
|
3249 | |
def flip_image_vert_or_horiz(self, widget, vertical):
|
3250 | |
if self.currimg_name != "" and widget.get_property('sensitive'):
|
3251 | |
self.currimg_pixbuf = self.image_flip(self.currimg_pixbuf, vertical)
|
3252 | |
self.currimg_pixbuf_original = self.image_flip(self.currimg_pixbuf_original, vertical)
|
3253 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
3254 | |
self.image_modified = True
|
3255 | |
|
3256 | |
def get_pixbuf_of_size(self, pixbuf, size, zoom_quality):
|
3257 | |
# Creates a pixbuf that fits in the specified square of sizexsize
|
3258 | |
# while preserving the aspect ratio
|
3259 | |
# Returns tuple: (scaled_pixbuf, actual_width, actual_height)
|
3260 | |
image_width = pixbuf.get_width()
|
3261 | |
image_height = pixbuf.get_height()
|
3262 | |
if image_width-size > image_height-size:
|
3263 | |
if image_width > size:
|
3264 | |
image_height = int(size/float(image_width)*image_height)
|
3265 | |
image_width = size
|
3266 | |
else:
|
3267 | |
if image_height > size:
|
3268 | |
image_width = int(size/float(image_height)*image_width)
|
3269 | |
image_height = size
|
3270 | |
if not pixbuf.get_has_alpha():
|
3271 | |
crop_pixbuf = pixbuf.scale_simple(image_width, image_height, zoom_quality)
|
3272 | |
else:
|
3273 | |
colormap = self.imageview.get_colormap()
|
3274 | |
light_grey = colormap.alloc_color('#666666', True, True)
|
3275 | |
dark_grey = colormap.alloc_color('#999999', True, True)
|
3276 | |
crop_pixbuf = pixbuf.composite_color_simple(image_width, image_height, zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
|
3277 | |
return (crop_pixbuf, image_width, image_height)
|
3278 | |
|
3279 | |
def pixbuf_add_border(self, pix):
|
3280 | |
# Add a gray outline to pix. This will increase the pixbuf size by
|
3281 | |
# 2 pixels lengthwise and heightwise, 1 on each side. Returns pixbuf.
|
3282 | |
try:
|
3283 | |
width = pix.get_width()
|
3284 | |
height = pix.get_height()
|
3285 | |
newpix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width+2, height+2)
|
3286 | |
newpix.fill(0x858585ff)
|
3287 | |
pix.copy_area(0, 0, width, height, newpix, 1, 1)
|
3288 | |
return newpix
|
3289 | |
except:
|
3290 | |
return pix
|
3291 | |
|
3292 | |
def crop_image(self, action):
|
3293 | |
dialog = gtk.Dialog(_("Crop Image"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
|
3294 | |
cropbutton = dialog.add_button(_("C_rop"), gtk.RESPONSE_ACCEPT)
|
3295 | |
cropimage = gtk.Image()
|
3296 | |
cropimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
3297 | |
cropbutton.set_image(cropimage)
|
3298 | |
image = gtk.DrawingArea()
|
3299 | |
crop_pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 400, self.zoom_quality)
|
3300 | |
image.set_size_request(image_width, image_height)
|
3301 | |
hbox = gtk.HBox()
|
3302 | |
hbox.pack_start(gtk.Label(), expand=True)
|
3303 | |
hbox.pack_start(image, expand=False)
|
3304 | |
hbox.pack_start(gtk.Label(), expand=True)
|
3305 | |
vbox_left = gtk.VBox()
|
3306 | |
x_adj = gtk.Adjustment(0, 0, self.currimg_pixbuf_original.get_width(), 1, 10, 0)
|
3307 | |
x = gtk.SpinButton(x_adj, 0, 0)
|
3308 | |
x.set_numeric(True)
|
3309 | |
x.set_update_policy(gtk.UPDATE_IF_VALID)
|
3310 | |
x.set_wrap(False)
|
3311 | |
x_label = gtk.Label("X:")
|
3312 | |
x_label.set_alignment(0, 0.7)
|
3313 | |
y_adj = gtk.Adjustment(0, 0, self.currimg_pixbuf_original.get_height(), 1, 10, 0)
|
3314 | |
y = gtk.SpinButton(y_adj, 0, 0)
|
3315 | |
y.set_numeric(True)
|
3316 | |
y.set_update_policy(gtk.UPDATE_IF_VALID)
|
3317 | |
y.set_wrap(False)
|
3318 | |
y_label = gtk.Label("Y:")
|
3319 | |
x_label.set_size_request(y_label.size_request()[0], -1)
|
3320 | |
hbox_x = gtk.HBox()
|
3321 | |
hbox_y = gtk.HBox()
|
3322 | |
hbox_x.pack_start(x_label, False, False, 10)
|
3323 | |
hbox_x.pack_start(x, False, False, 0)
|
3324 | |
hbox_x.pack_start(gtk.Label(), False, False, 3)
|
3325 | |
hbox_y.pack_start(y_label, False, False, 10)
|
3326 | |
hbox_y.pack_start(y, False, False, 0)
|
3327 | |
hbox_y.pack_start(gtk.Label(), False, False, 3)
|
3328 | |
vbox_left.pack_start(hbox_x, False, False, 0)
|
3329 | |
vbox_left.pack_start(hbox_y, False, False, 0)
|
3330 | |
vbox_right = gtk.VBox()
|
3331 | |
width_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_width(), 1, self.currimg_pixbuf_original.get_width(), 1, 10, 0)
|
3332 | |
width = gtk.SpinButton(width_adj, 0, 0)
|
3333 | |
width.set_numeric(True)
|
3334 | |
width.set_update_policy(gtk.UPDATE_IF_VALID)
|
3335 | |
width.set_wrap(False)
|
3336 | |
width_label = gtk.Label(_("Width:"))
|
3337 | |
width_label.set_alignment(0, 0.7)
|
3338 | |
height_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_height(), 1, self.currimg_pixbuf_original.get_height(), 1, 10, 0)
|
3339 | |
height = gtk.SpinButton(height_adj, 0, 0)
|
3340 | |
height.set_numeric(True)
|
3341 | |
height.set_update_policy(gtk.UPDATE_IF_VALID)
|
3342 | |
height.set_wrap(False)
|
3343 | |
height_label = gtk.Label(_("Height:"))
|
3344 | |
width_label.set_size_request(height_label.size_request()[0], -1)
|
3345 | |
height_label.set_alignment(0, 0.7)
|
3346 | |
hbox_width = gtk.HBox()
|
3347 | |
hbox_height = gtk.HBox()
|
3348 | |
hbox_width.pack_start(width_label, False, False, 10)
|
3349 | |
hbox_width.pack_start(width, False, False, 0)
|
3350 | |
hbox_height.pack_start(height_label, False, False, 10)
|
3351 | |
hbox_height.pack_start(height, False, False, 0)
|
3352 | |
vbox_right.pack_start(hbox_width, False, False, 0)
|
3353 | |
vbox_right.pack_start(hbox_height, False, False, 0)
|
3354 | |
hbox2 = gtk.HBox()
|
3355 | |
hbox2.pack_start(gtk.Label(), expand=True)
|
3356 | |
hbox2.pack_start(vbox_left, False, False, 0)
|
3357 | |
hbox2.pack_start(vbox_right, False, False, 0)
|
3358 | |
hbox2.pack_start(gtk.Label(), expand=True)
|
3359 | |
dialog.vbox.pack_start(hbox, False, False, 0)
|
3360 | |
dialog.vbox.pack_start(hbox2, False, False, 15)
|
3361 | |
dialog.set_resizable(False)
|
3362 | |
dialog.vbox.show_all()
|
3363 | |
image.set_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
|
3364 | |
image.connect("expose-event", self.crop_image_expose_cb, crop_pixbuf, image_width, image_height)
|
3365 | |
image.connect("motion_notify_event", self.crop_image_mouse_moved, image, 0, 0, x, y, width, height, image_width, image_height, width_adj, height_adj)
|
3366 | |
image.connect("button_press_event", self.crop_image_button_press, image)
|
3367 | |
image.connect("button_release_event", self.crop_image_button_release)
|
3368 | |
self.x_changed = x.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 0)
|
3369 | |
self.y_changed = y.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 1)
|
3370 | |
self.width_changed = width.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 2)
|
3371 | |
self.height_changed = height.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 3)
|
3372 | |
image.realize()
|
3373 | |
self.crop_rectangle = [0, 0]
|
3374 | |
self.drawing_crop_rectangle = False
|
3375 | |
self.update_rectangle = False
|
3376 | |
self.rect = None
|
3377 | |
response = dialog.run()
|
3378 | |
if response == gtk.RESPONSE_ACCEPT:
|
3379 | |
dialog.destroy()
|
3380 | |
if self.rect != None:
|
3381 | |
temp_pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, self.currimg_pixbuf_original.get_has_alpha(), 8, self.coords[2], self.coords[3])
|
3382 | |
self.currimg_pixbuf_original.copy_area(self.coords[0], self.coords[1], self.coords[2], self.coords[3], temp_pixbuf, 0, 0)
|
3383 | |
self.currimg_pixbuf_original = temp_pixbuf
|
3384 | |
del temp_pixbuf
|
3385 | |
gc.collect()
|
3386 | |
self.load_new_image2(False, True, False, False)
|
3387 | |
self.image_modified = True
|
3388 | |
else:
|
3389 | |
dialog.destroy()
|
3390 | |
|
3391 | |
def crop_value_changed(self, currspinbox, x, y, width, height, width_adj, height_adj, image_width, image_height, image, type):
|
3392 | |
if type == 0: # X
|
3393 | |
if x.get_value() + width.get_value() > self.currimg_pixbuf_original.get_width():
|
3394 | |
width.handler_block(self.width_changed)
|
3395 | |
width.set_value(self.currimg_pixbuf_original.get_width() - x.get_value())
|
3396 | |
width.handler_unblock(self.width_changed)
|
3397 | |
elif type == 1: # Y
|
3398 | |
if y.get_value() + height.get_value() > self.currimg_pixbuf_original.get_height():
|
3399 | |
height.handler_block(self.height_changed)
|
3400 | |
height.set_value(self.currimg_pixbuf_original.get_height() - y.get_value())
|
3401 | |
height.handler_unblock(self.height_changed)
|
3402 | |
self.coords = [int(x.get_value()), int(y.get_value()), int(width.get_value()), int(height.get_value())]
|
3403 | |
self.crop_rectangle[0] = int(round(float(self.coords[0])/self.currimg_pixbuf_original.get_width()*image_width, 0))
|
3404 | |
self.crop_rectangle[1] = int(round(float(self.coords[1])/self.currimg_pixbuf_original.get_height()*image_height, 0))
|
3405 | |
x2 = int(round(float(self.coords[2])/self.currimg_pixbuf_original.get_width()*image_width, 0)) + self.crop_rectangle[0]
|
3406 | |
y2 = int(round(float(self.coords[3])/self.currimg_pixbuf_original.get_height()*image_height, 0)) + self.crop_rectangle[1]
|
3407 | |
self.drawing_crop_rectangle = True
|
3408 | |
self.update_rectangle = True
|
3409 | |
self.crop_image_mouse_moved(None, None, image, x2, y2, x, y, width, height, image_width, image_height, width_adj, height_adj)
|
3410 | |
self.update_rectangle = False
|
3411 | |
self.drawing_crop_rectangle = False
|
3412 | |
|
3413 | |
def crop_image_expose_cb(self, image, event, pixbuf, width, height):
|
3414 | |
image.window.draw_pixbuf(None, pixbuf, 0, 0, 0, 0, width, height)
|
3415 | |
|
3416 | |
def crop_image_mouse_moved(self, widget, event, image, x2, y2, x, y, width, height, image_width, image_height, width_adj, height_adj):
|
3417 | |
if event != None:
|
3418 | |
x2, y2, state = event.window.get_pointer()
|
3419 | |
if self.drawing_crop_rectangle:
|
3420 | |
if self.crop_rectangle != None or self.update_rectangle:
|
3421 | |
gc = image.window.new_gc(function=gtk.gdk.INVERT)
|
3422 | |
if self.rect != None:
|
3423 | |
# Get rid of the previous drawn rectangle:
|
3424 | |
image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
|
3425 | |
self.rect = [0, 0, 0, 0]
|
3426 | |
if self.crop_rectangle[0] > x2:
|
3427 | |
self.rect[0] = x2
|
3428 | |
self.rect[2] = self.crop_rectangle[0]-x2
|
3429 | |
else:
|
3430 | |
self.rect[0] = self.crop_rectangle[0]
|
3431 | |
self.rect[2] = x2-self.crop_rectangle[0]
|
3432 | |
if self.crop_rectangle[1] > y2:
|
3433 | |
self.rect[1] = y2
|
3434 | |
self.rect[3] = self.crop_rectangle[1]-y2
|
3435 | |
else:
|
3436 | |
self.rect[1] = self.crop_rectangle[1]
|
3437 | |
self.rect[3] = y2-self.crop_rectangle[1]
|
3438 | |
image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
|
3439 | |
# Convert the rectangle coordinates of the current image
|
3440 | |
# to coordinates of pixbuf_original
|
3441 | |
if self.rect[0] < 0:
|
3442 | |
self.rect[2] = self.rect[2] + self.rect[0]
|
3443 | |
self.rect[0] = 0
|
3444 | |
if self.rect[1] < 0:
|
3445 | |
self.rect[3] = self.rect[3] + self.rect[1]
|
3446 | |
self.rect[1] = 0
|
3447 | |
if event != None:
|
3448 | |
self.coords = [0,0,0,0]
|
3449 | |
self.coords[0] = int(round(float(self.rect[0])/image_width*self.currimg_pixbuf_original.get_width(), 0))
|
3450 | |
self.coords[1] = int(round(float(self.rect[1])/image_height*self.currimg_pixbuf_original.get_height(), 0))
|
3451 | |
self.coords[2] = int(round(float(self.rect[2])/image_width*self.currimg_pixbuf_original.get_width(), 0))
|
3452 | |
self.coords[3] = int(round(float(self.rect[3])/image_height*self.currimg_pixbuf_original.get_height(), 0))
|
3453 | |
if self.coords[0] + self.coords[2] > self.currimg_pixbuf_original.get_width():
|
3454 | |
self.coords[2] = self.currimg_pixbuf_original.get_width() - self.coords[0]
|
3455 | |
if self.coords[1] + self.coords[3] > self.currimg_pixbuf_original.get_height():
|
3456 | |
self.coords[3] = self.currimg_pixbuf_original.get_height() - self.coords[1]
|
3457 | |
x.handler_block(self.x_changed)
|
3458 | |
y.handler_block(self.y_changed)
|
3459 | |
width.handler_block(self.width_changed)
|
3460 | |
height.handler_block(self.height_changed)
|
3461 | |
x.set_value(self.coords[0])
|
3462 | |
y.set_value(self.coords[1])
|
3463 | |
width.set_value(self.coords[2])
|
3464 | |
height.set_value(self.coords[3])
|
3465 | |
x.handler_unblock(self.x_changed)
|
3466 | |
y.handler_unblock(self.y_changed)
|
3467 | |
width_adj.set_property('upper', self.currimg_pixbuf_original.get_width() - self.coords[0])
|
3468 | |
height_adj.set_property('upper', self.currimg_pixbuf_original.get_height() - self.coords[1])
|
3469 | |
width.handler_unblock(self.width_changed)
|
3470 | |
height.handler_unblock(self.height_changed)
|
3471 | |
|
3472 | |
def crop_image_button_press(self, widget, event, image):
|
3473 | |
x, y, state = event.window.get_pointer()
|
3474 | |
if (state & gtk.gdk.BUTTON1_MASK):
|
3475 | |
self.drawing_crop_rectangle = True
|
3476 | |
self.crop_rectangle = [x, y]
|
3477 | |
gc = image.window.new_gc(function=gtk.gdk.INVERT)
|
3478 | |
if self.rect != None:
|
3479 | |
# Get rid of the previous drawn rectangle:
|
3480 | |
image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
|
3481 | |
self.rect = None
|
3482 | |
|
3483 | |
def crop_image_button_release(self, widget, event):
|
3484 | |
x, y, state = event.window.get_pointer()
|
3485 | |
if not (state & gtk.gdk.BUTTON1_MASK):
|
3486 | |
self.drawing_crop_rectangle = False
|
3487 | |
|
3488 | |
def saturation(self, action):
|
3489 | |
dialog = gtk.Dialog(_("Saturation"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
|
3490 | |
resizebutton = dialog.add_button(_("_Saturate"), gtk.RESPONSE_ACCEPT)
|
3491 | |
resizeimage = gtk.Image()
|
3492 | |
resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
3493 | |
resizebutton.set_image(resizeimage)
|
3494 | |
scale = gtk.HScale()
|
3495 | |
scale.set_draw_value(False)
|
3496 | |
scale.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
|
3497 | |
scale.set_range(0, 2)
|
3498 | |
scale.set_increments(0.1, 0.5)
|
3499 | |
scale.set_value(1)
|
3500 | |
scale.connect('value-changed', self.saturation_preview)
|
3501 | |
label = gtk.Label(_("Saturation level:"))
|
3502 | |
label.set_alignment(0, 0.5)
|
3503 | |
hbox1 = gtk.HBox()
|
3504 | |
hbox1.pack_start(label, True, True, 10)
|
3505 | |
hbox2 = gtk.HBox()
|
3506 | |
hbox2.pack_start(scale, True, True, 20)
|
3507 | |
dialog.vbox.pack_start(gtk.Label(" "))
|
3508 | |
dialog.vbox.pack_start(hbox1, False)
|
3509 | |
dialog.vbox.pack_start(hbox2, True, True, 10)
|
3510 | |
dialog.vbox.pack_start(gtk.Label(" "))
|
3511 | |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
3512 | |
dialog.vbox.show_all()
|
3513 | |
response = dialog.run()
|
3514 | |
if response == gtk.RESPONSE_ACCEPT:
|
3515 | |
self.currimg_pixbuf_original.saturate_and_pixelate(self.currimg_pixbuf_original, scale.get_value(), False)
|
3516 | |
self.currimg_pixbuf.saturate_and_pixelate(self.currimg_pixbuf, scale.get_value(), False)
|
3517 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
3518 | |
self.image_modified = True
|
3519 | |
dialog.destroy()
|
3520 | |
else:
|
3521 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
3522 | |
dialog.destroy()
|
3523 | |
|
3524 | |
def saturation_preview(self, range):
|
3525 | |
while gtk.events_pending():
|
3526 | |
gtk.main_iteration()
|
3527 | |
try:
|
3528 | |
bak = self.currimg_pixbuf.copy()
|
3529 | |
self.currimg_pixbuf.saturate_and_pixelate(self.currimg_pixbuf, range.get_value(), False)
|
3530 | |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
3531 | |
self.currimg_pixbuf = bak.copy()
|
3532 | |
del bak
|
3533 | |
except:
|
3534 | |
pass
|
3535 | |
gc.collect()
|
3536 | |
|
3537 | |
def resize_image(self, action):
|
3538 | |
dialog = gtk.Dialog(_("Resize Image"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
|
3539 | |
resizebutton = dialog.add_button(_("_Resize"), gtk.RESPONSE_ACCEPT)
|
3540 | |
resizeimage = gtk.Image()
|
3541 | |
resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
3542 | |
resizebutton.set_image(resizeimage)
|
3543 | |
hbox_width = gtk.HBox()
|
3544 | |
width_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_width(), 1, 100000000000, 1, 10, 0)
|
3545 | |
width = gtk.SpinButton(width_adj, 0, 0)
|
3546 | |
width.set_numeric(True)
|
3547 | |
width.set_update_policy(gtk.UPDATE_IF_VALID)
|
3548 | |
width.set_wrap(False)
|
3549 | |
width_label = gtk.Label(_("Width:"))
|
3550 | |
width_label.set_alignment(0, 0.7)
|
3551 | |
hbox_width.pack_start(width_label, False, False, 10)
|
3552 | |
hbox_width.pack_start(width, False, False, 0)
|
3553 | |
hbox_width.pack_start(gtk.Label(_("pixels")), False, False, 10)
|
3554 | |
hbox_height = gtk.HBox()
|
3555 | |
height_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_height(), 1, 100000000000, 1, 10, 0)
|
3556 | |
height = gtk.SpinButton(height_adj, 0, 0)
|
3557 | |
height.set_numeric(True)
|
3558 | |
height.set_update_policy(gtk.UPDATE_IF_VALID)
|
3559 | |
height.set_wrap(False)
|
3560 | |
height_label = gtk.Label(_("Height:"))
|
3561 | |
width_label.set_size_request(height_label.size_request()[0], -1)
|
3562 | |
height_label.set_alignment(0, 0.7)
|
3563 | |
hbox_height.pack_start(height_label, False, False, 10)
|
3564 | |
hbox_height.pack_start(height, False, False, 0)
|
3565 | |
hbox_height.pack_start(gtk.Label(_("pixels")), False, False, 10)
|
3566 | |
hbox_aspect = gtk.HBox()
|
3567 | |
aspect_checkbox = gtk.CheckButton(_("Preserve aspect ratio"))
|
3568 | |
aspect_checkbox.set_active(self.preserve_aspect)
|
3569 | |
hbox_aspect.pack_start(aspect_checkbox, False, False, 10)
|
3570 | |
vbox = gtk.VBox()
|
3571 | |
vbox.pack_start(gtk.Label(), False, False, 0)
|
3572 | |
vbox.pack_start(hbox_width, False, False, 0)
|
3573 | |
vbox.pack_start(hbox_height, False, False, 0)
|
3574 | |
vbox.pack_start(gtk.Label(), False, False, 0)
|
3575 | |
vbox.pack_start(hbox_aspect, False, False, 0)
|
3576 | |
vbox.pack_start(gtk.Label(), False, False, 0)
|
3577 | |
hbox_total = gtk.HBox()
|
3578 | |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
3579 | |
if animtest.is_static_image():
|
3580 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 96, self.zoom_quality)
|
3581 | |
else:
|
3582 | |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 96, self.zoom_quality)
|
3583 | |
image = gtk.Image()
|
3584 | |
image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
|
3585 | |
hbox_total.pack_start(image, False, False, 10)
|
3586 | |
hbox_total.pack_start(vbox, False, False, 10)
|
3587 | |
dialog.vbox.pack_start(hbox_total, False, False, 0)
|
3588 | |
width.connect('value-changed', self.preserve_image_aspect, "width", height)
|
3589 | |
height.connect('value-changed', self.preserve_image_aspect, "height", width)
|
3590 | |
aspect_checkbox.connect('toggled', self.aspect_ratio_toggled, width, height)
|
3591 | |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
3592 | |
dialog.vbox.show_all()
|
3593 | |
response = dialog.run()
|
3594 | |
if response == gtk.RESPONSE_ACCEPT:
|
3595 | |
pixelheight = height.get_value_as_int()
|
3596 | |
pixelwidth = width.get_value_as_int()
|
3597 | |
dialog.destroy()
|
3598 | |
self.currimg_pixbuf_original = self.currimg_pixbuf_original.scale_simple(pixelwidth, pixelheight, self.zoom_quality)
|
3599 | |
self.load_new_image2(False, True, False, False)
|
3600 | |
self.image_modified = True
|
3601 | |
else:
|
3602 | |
dialog.destroy()
|
3603 | |
|
3604 | |
def aspect_ratio_toggled(self, togglebutton, width, height):
|
3605 | |
self.preserve_aspect = togglebutton.get_active()
|
3606 | |
if self.preserve_aspect:
|
3607 | |
# Set height based on width and aspect ratio
|
3608 | |
target_value = float(width.get_value_as_int())/self.currimg_pixbuf_original.get_width()
|
3609 | |
target_value = int(target_value * self.currimg_pixbuf_original.get_height())
|
3610 | |
self.ignore_preserve_aspect_callback = True
|
3611 | |
height.set_value(target_value)
|
3612 | |
self.ignore_preserve_aspect_callback = False
|
3613 | |
|
3614 | |
def preserve_image_aspect(self, currspinbox, type, otherspinbox):
|
3615 | |
if not self.preserve_aspect:
|
3616 | |
return
|
3617 | |
if self.ignore_preserve_aspect_callback:
|
3618 | |
return
|
3619 | |
if type == "width":
|
3620 | |
target_value = float(currspinbox.get_value_as_int())/self.currimg_pixbuf_original.get_width()
|
3621 | |
target_value = int(target_value * self.currimg_pixbuf_original.get_height())
|
3622 | |
else:
|
3623 | |
target_value = float(currspinbox.get_value_as_int())/self.currimg_pixbuf_original.get_height()
|
3624 | |
target_value = int(target_value * self.currimg_pixbuf_original.get_width())
|
3625 | |
self.ignore_preserve_aspect_callback = True
|
3626 | |
otherspinbox.set_value(target_value)
|
3627 | |
self.ignore_preserve_aspect_callback = False
|
3628 | |
|
3629 | |
def goto_prev_image(self, action):
|
3630 | |
self.goto_image("PREV", action)
|
3631 | |
|
3632 | |
def goto_next_image(self, action):
|
3633 | |
self.goto_image("NEXT", action)
|
3634 | |
|
3635 | |
def goto_random_image(self, action):
|
3636 | |
self.goto_image("RANDOM", action)
|
3637 | |
|
3638 | |
def goto_first_image(self, action):
|
3639 | |
self.goto_image("FIRST", action)
|
3640 | |
|
3641 | |
def goto_last_image(self, action):
|
3642 | |
self.goto_image("LAST", action)
|
3643 | |
|
3644 | |
def goto_image(self, location, action):
|
3645 | |
# location can be "LAST", "FIRST", "NEXT", "PREV", "RANDOM", or a number
|
3646 | |
if self.slideshow_mode and action != "ss":
|
3647 | |
gobject.source_remove(self.timer_delay)
|
3648 | |
if ((location=="PREV" or location=="NEXT" or location=="RANDOM") and len(self.image_list) > 1) or (location=="FIRST" and (len(self.image_list) > 1 and self.curr_img_in_list != 0)) or (location=="LAST" and (len(self.image_list) > 1 and self.curr_img_in_list != len(self.image_list)-1)) or valid_int(location):
|
3649 | |
self.load_new_image_stop_now()
|
3650 | |
cancel = self.autosave_image()
|
3651 | |
if cancel:
|
3652 | |
return
|
3653 | |
check_wrap = False
|
3654 | |
if location != "RANDOM":
|
3655 | |
self.randomlist = []
|
3656 | |
if location == "FIRST":
|
3657 | |
self.curr_img_in_list = 0
|
3658 | |
elif location == "RANDOM":
|
3659 | |
if self.randomlist == []:
|
3660 | |
self.reinitialize_randomlist()
|
3661 | |
else:
|
3662 | |
# check if we have seen every image; if so, reinitialize array and repeat:
|
3663 | |
all_items_are_true = True
|
3664 | |
for item in self.randomlist:
|
3665 | |
if not item:
|
3666 | |
all_items_are_true = False
|
3667 | |
if all_items_are_true:
|
3668 | |
if not self.slideshow_mode or (self.slideshow_mode and self.listwrap_mode == 1):
|
3669 | |
self.reinitialize_randomlist()
|
3670 | |
else:
|
3671 | |
check_wrap = True
|
3672 | |
elif location == "LAST":
|
3673 | |
self.curr_img_in_list = len(self.image_list)-1
|
3674 | |
elif location == "PREV":
|
3675 | |
if self.curr_img_in_list > 0:
|
3676 | |
self.curr_img_in_list -= 1
|
3677 | |
else:
|
3678 | |
check_wrap = True
|
3679 | |
elif location == "NEXT":
|
3680 | |
if self.curr_img_in_list < len(self.image_list) - 1:
|
3681 | |
self.curr_img_in_list += 1
|
3682 | |
else:
|
3683 | |
check_wrap = True
|
3684 | |
if check_wrap:
|
3685 | |
if self.listwrap_mode == 0:
|
3686 | |
if location == "NEXT":
|
3687 | |
if self.slideshow_mode:
|
3688 | |
self.toggle_slideshow(None)
|
3689 | |
return
|
3690 | |
elif (location == "PREV" or location == "NEXT") and self.listwrap_mode == 1:
|
3691 | |
if location == "PREV":
|
3692 | |
self.curr_img_in_list = len(self.image_list) - 1
|
3693 | |
elif location == "NEXT":
|
3694 | |
self.curr_img_in_list = 0
|
3695 | |
else:
|
3696 | |
if self.curr_img_in_list != self.loaded_img_in_list:
|
3697 | |
# Ensure that the user is looking at the correct "last" image before
|
3698 | |
# they are asked the wrap question:
|
3699 | |
if location == "PREV":
|
3700 | |
self.load_new_image(True, False, True, True, True, True)
|
3701 | |
else:
|
3702 | |
self.load_new_image(False, False, True, True, True, True)
|
3703 | |
self.set_go_navigation_sensitivities(False)
|
3704 | |
self.thumbpane_select(self.curr_img_in_list)
|
3705 | |
if self.fullscreen_mode:
|
3706 | |
self.change_cursor(None)
|
3707 | |
if location == "PREV":
|
3708 | |
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("You are viewing the first image in the list. Wrap around to the last image?"))
|
3709 | |
elif location == "NEXT":
|
3710 | |
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("You are viewing the last image in the list. Wrap around to the first image?"))
|
3711 | |
elif location == "RANDOM":
|
3712 | |
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("All images have been viewed. Would you like to cycle through the images again?"))
|
3713 | |
dialog.set_title(_("Wrap?"))
|
3714 | |
dialog.label.set_property('can-focus', False)
|
3715 | |
dialog.set_default_response(gtk.RESPONSE_YES)
|
3716 | |
self.user_prompt_visible = True
|
3717 | |
response = dialog.run()
|
3718 | |
if response == gtk.RESPONSE_YES:
|
3719 | |
if location == "PREV":
|
3720 | |
self.curr_img_in_list = len(self.image_list)-1
|
3721 | |
elif location == "NEXT":
|
3722 | |
self.curr_img_in_list = 0
|
3723 | |
elif location == "RANDOM":
|
3724 | |
self.reinitialize_randomlist()
|
3725 | |
dialog.destroy()
|
3726 | |
self.user_prompt_visible = False
|
3727 | |
if self.fullscreen_mode:
|
3728 | |
self.hide_cursor
|
3729 | |
else:
|
3730 | |
dialog.destroy()
|
3731 | |
self.user_prompt_visible = False
|
3732 | |
if self.fullscreen_mode:
|
3733 | |
self.hide_cursor
|
3734 | |
else:
|
3735 | |
self.change_cursor(None)
|
3736 | |
if self.slideshow_mode:
|
3737 | |
self.toggle_slideshow(None)
|
3738 | |
return
|
3739 | |
if location == "RANDOM":
|
3740 | |
# Find random image that hasn't already been chosen:
|
3741 | |
j = random.randint(0, len(self.image_list)-1)
|
3742 | |
while self.randomlist[j]:
|
3743 | |
j = random.randint(0, len(self.image_list)-1)
|
3744 | |
self.curr_img_in_list = j
|
3745 | |
self.randomlist[j] = True
|
3746 | |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
3747 | |
if valid_int(location):
|
3748 | |
prev_img = self.curr_img_in_list
|
3749 | |
self.curr_img_in_list = int(location)
|
3750 | |
if not self.fullscreen_mode and (not self.slideshow_mode or (self.slideshow_mode and action != "ss")):
|
3751 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
3752 | |
if location == "PREV" or (valid_int(location) and int(location) == prev_img-1):
|
3753 | |
self.load_when_idle = gobject.idle_add(self.load_new_image, True, False, True, True, True, True)
|
3754 | |
else:
|
3755 | |
self.load_when_idle = gobject.idle_add(self.load_new_image, False, False, True, True, True, True)
|
3756 | |
self.set_go_navigation_sensitivities(False)
|
3757 | |
if self.slideshow_mode:
|
3758 | |
if self.curr_slideshow_random:
|
3759 | |
self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
|
3760 | |
else:
|
3761 | |
self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
|
3762 | |
gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
|
3763 | |
|
3764 | |
def set_go_navigation_sensitivities(self, skip_initial_check):
|
3765 | |
# setting skip_image_list_check to True is useful when calling from
|
3766 | |
# expand_filelist_and_load_image() for example, as self.image_list has not
|
3767 | |
# yet fully populated
|
3768 | |
if (not self.image_loaded or len(self.image_list) == 1) and not skip_initial_check:
|
3769 | |
self.set_previous_image_sensitivities(False)
|
3770 | |
self.set_first_image_sensitivities(False)
|
3771 | |
self.set_next_image_sensitivities(False)
|
3772 | |
self.set_last_image_sensitivities(False)
|
3773 | |
self.set_random_image_sensitivities(False)
|
3774 | |
elif self.curr_img_in_list == 0:
|
3775 | |
if self.listwrap_mode == 0:
|
3776 | |
self.set_previous_image_sensitivities(False)
|
3777 | |
else:
|
3778 | |
self.set_previous_image_sensitivities(True)
|
3779 | |
self.set_first_image_sensitivities(False)
|
3780 | |
self.set_next_image_sensitivities(True)
|
3781 | |
self.set_last_image_sensitivities(True)
|
3782 | |
self.set_random_image_sensitivities(True)
|
3783 | |
elif self.curr_img_in_list == len(self.image_list)-1:
|
3784 | |
self.set_previous_image_sensitivities(True)
|
3785 | |
self.set_first_image_sensitivities(True)
|
3786 | |
if self.listwrap_mode == 0:
|
3787 | |
self.set_next_image_sensitivities(False)
|
3788 | |
else:
|
3789 | |
self.set_next_image_sensitivities(True)
|
3790 | |
self.set_last_image_sensitivities(False)
|
3791 | |
self.set_random_image_sensitivities(True)
|
3792 | |
else:
|
3793 | |
self.set_previous_image_sensitivities(True)
|
3794 | |
self.set_first_image_sensitivities(True)
|
3795 | |
self.set_next_image_sensitivities(True)
|
3796 | |
self.set_last_image_sensitivities(True)
|
3797 | |
self.set_random_image_sensitivities(True)
|
3798 | |
|
3799 | |
def reinitialize_randomlist(self):
|
3800 | |
self.randomlist = []
|
3801 | |
for i in range(len(self.image_list)):
|
3802 | |
self.randomlist.append(False)
|
3803 | |
self.randomlist[self.curr_img_in_list] = True
|
3804 | |
|
3805 | |
def image_load_failed(self, reset_cursor, filename=""):
|
3806 | |
# If a filename is provided, use it for display:
|
3807 | |
if len(filename) == 0:
|
3808 | |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
3809 | |
else:
|
3810 | |
self.currmg_name = filename
|
3811 | |
if self.verbose and self.currimg_name != "":
|
3812 | |
print(_("Loading: %s") % self.currimg_name)
|
3813 | |
self.update_title()
|
3814 | |
self.put_error_image_to_window()
|
3815 | |
self.image_loaded = False
|
3816 | |
self.currimg_pixbuf_original = None
|
3817 | |
if reset_cursor:
|
3818 | |
if not self.fullscreen_mode:
|
3819 | |
self.change_cursor(None)
|
3820 | |
|
3821 | |
def load_new_image_stop_now(self):
|
3822 | |
try:
|
3823 | |
gobject.source_remove(self.load_when_idle)
|
3824 | |
except:
|
3825 | |
pass
|
3826 | |
try:
|
3827 | |
gobject.source_remove(self.preload_when_idle)
|
3828 | |
except:
|
3829 | |
pass
|
3830 | |
try:
|
3831 | |
gobject.source_remove(self.preload_when_idle2)
|
3832 | |
except:
|
3833 | |
pass
|
3834 | |
|
3835 | |
def load_new_image(self, check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action, preload_next_image_after, preload_prev_image_after):
|
3836 | |
try:
|
3837 | |
self.load_new_image2(check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action)
|
3838 | |
except:
|
3839 | |
self.image_load_failed(True)
|
3840 | |
if preload_next_image_after:
|
3841 | |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
|
3842 | |
if preload_prev_image_after:
|
3843 | |
self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, False)
|
3844 | |
|
3845 | |
def check_preloadimg_prev_for_existing(self, prev_index, reset_preloadimg_prev_in_list):
|
3846 | |
# Determines if preloadimg_prev needs to be updated; if so,
|
3847 | |
# checks if the image is already stored in self.currimg
|
3848 | |
# or self.preloadimg_next and can be reused.
|
3849 | |
reset_preloadimg_prev_in_list = False
|
3850 | |
if prev_index != self.preloadimg_prev_in_list and prev_index != -1:
|
3851 | |
# Need to update preloadimg_prev:
|
3852 | |
if prev_index == self.loaded_img_in_list and not self.image_modified and not self.image_zoomed:
|
3853 | |
self.preloadimg_prev_in_list = self.loaded_img_in_list
|
3854 | |
self.preloadimg_prev_name = self.currimg_name
|
3855 | |
self.preloadimg_prev_width = self.currimg_width
|
3856 | |
self.preloadimg_prev_height = self.currimg_height
|
3857 | |
self.preloadimg_prev_pixbuf = self.currimg_pixbuf
|
3858 | |
self.preloadimg_prev_pixbuf_original = self.currimg_pixbuf_original
|
3859 | |
self.preloadimg_prev_zoomratio = self.currimg_zoomratio
|
3860 | |
self.preloadimg_prev_is_animation = self.currimg_is_animation
|
3861 | |
elif prev_index == self.preloadimg_next_in_list:
|
3862 | |
self.preloadimg_prev_in_list = self.preloadimg_next_in_list
|
3863 | |
self.preloadimg_prev_name = self.preloadimg_next_name
|
3864 | |
self.preloadimg_prev_width = self.preloadimg_next_width
|
3865 | |
self.preloadimg_prev_height = self.preloadimg_next_height
|
3866 | |
self.preloadimg_prev_pixbuf = self.preloadimg_next_pixbuf
|
3867 | |
self.preloadimg_prev_pixbuf_original = self.preloadimg_next_pixbuf_original
|
3868 | |
self.preloadimg_prev_zoomratio = self.preloadimg_next_zoomratio
|
3869 | |
self.preloadimg_prev_is_animation = self.preloadimg_next_is_animation
|
3870 | |
else:
|
3871 | |
reset_preloadimg_prev_in_list = True
|
3872 | |
elif prev_index == -1:
|
3873 | |
reset_preloadimg_prev_in_list = True
|
3874 | |
|
3875 | |
def check_preloadimg_next_for_existing(self, next_index, reset_preloadimg_next_in_list):
|
3876 | |
# Determines if preloadimg_next needs to be updated; if so,
|
3877 | |
# checks if the image is already stored in self.currimg
|
3878 | |
# or self.preloadimg_prev and can be reused.
|
3879 | |
reset_preloadimg_next_in_list = False
|
3880 | |
if next_index != self.preloadimg_next_in_list and next_index != -1:
|
3881 | |
# Need to update preloadimg_next:
|
3882 | |
if next_index == self.loaded_img_in_list and not self.image_modified and not self.image_zoomed:
|
3883 | |
self.preloadimg_next_in_list = self.loaded_img_in_list
|
3884 | |
self.preloadimg_next_name = self.currimg_name
|
3885 | |
self.preloadimg_next_width = self.currimg_width
|
3886 | |
self.preloadimg_next_height = self.currimg_height
|
3887 | |
self.preloadimg_next_pixbuf = self.currimg_pixbuf
|
3888 | |
self.preloadimg_next_pixbuf_original = self.currimg_pixbuf_original
|
3889 | |
self.preloadimg_next_zoomratio = self.currimg_zoomratio
|
3890 | |
self.preloadimg_next_is_animation = self.currimg_is_animation
|
3891 | |
elif next_index == self.preloadimg_prev_in_list:
|
3892 | |
self.preloadimg_next_in_list = self.preloadimg_prev_in_list
|
3893 | |
self.preloadimg_next_name = self.preloadimg_prev_name
|
3894 | |
self.preloadimg_next_width = self.preloadimg_prev_width
|
3895 | |
self.preloadimg_next_height = self.preloadimg_prev_height
|
3896 | |
self.preloadimg_next_pixbuf = self.preloadimg_prev_pixbuf
|
3897 | |
self.preloadimg_next_pixbuf_original = self.preloadimg_prev_pixbuf_original
|
3898 | |
self.preloadimg_next_zoomratio = self.preloadimg_prev_zoomratio
|
3899 | |
self.preloadimg_next_is_animation = self.preloadimg_prev_is_animation
|
3900 | |
else:
|
3901 | |
reset_preloadimg_next_in_list = True
|
3902 | |
elif next_index == -1:
|
3903 | |
reset_preloadimg_next_in_list = True
|
3904 | |
|
3905 | |
def check_currimg_for_existing(self):
|
3906 | |
# Determines if currimg needs to be updated; if so,
|
3907 | |
# checks if the image is already stored in self.preloadimg_next
|
3908 | |
# or self.preloadimg_prev and can be reused (the whole point of
|
3909 | |
# preloading!)
|
3910 | |
used_prev = False
|
3911 | |
used_next = False
|
3912 | |
if self.curr_img_in_list != self.loaded_img_in_list:
|
3913 | |
# Need to update currimg:
|
3914 | |
if self.curr_img_in_list == self.preloadimg_prev_in_list:
|
3915 | |
# Set preload_prev_image as current image
|
3916 | |
self.currimg_name = self.preloadimg_prev_name
|
3917 | |
self.currimg_width = self.preloadimg_prev_width
|
3918 | |
self.currimg_height = self.preloadimg_prev_height
|
3919 | |
self.currimg_pixbuf = self.preloadimg_prev_pixbuf
|
3920 | |
self.currimg_pixbuf_original = self.preloadimg_prev_pixbuf_original
|
3921 | |
self.currimg_zoomratio = self.preloadimg_prev_zoomratio
|
3922 | |
self.currimg_is_animation = self.preloadimg_prev_is_animation
|
3923 | |
used_prev = True
|
3924 | |
if self.verbose and self.currimg_name != "":
|
3925 | |
print(_("Loading: %s") % self.currimg_name)
|
3926 | |
self.put_zoom_image_to_window(True)
|
3927 | |
if not self.currimg_is_animation:
|
3928 | |
self.set_image_sensitivities(True)
|
3929 | |
else:
|
3930 | |
self.set_image_sensitivities(False)
|
3931 | |
elif self.curr_img_in_list == self.preloadimg_next_in_list:
|
3932 | |
# Use preload_next_image as current image
|
3933 | |
self.currimg_name = self.preloadimg_next_name
|
3934 | |
self.currimg_width = self.preloadimg_next_width
|
3935 | |
self.currimg_height = self.preloadimg_next_height
|
3936 | |
self.currimg_pixbuf = self.preloadimg_next_pixbuf
|
3937 | |
self.currimg_pixbuf_original = self.preloadimg_next_pixbuf_original
|
3938 | |
self.currimg_zoomratio = self.preloadimg_next_zoomratio
|
3939 | |
self.currimg_is_animation = self.preloadimg_next_is_animation
|
3940 | |
used_next = True
|
3941 | |
if self.verbose and self.currimg_name != "":
|
3942 | |
print(_("Loading: %s") % self.currimg_name)
|
3943 | |
self.put_zoom_image_to_window(True)
|
3944 | |
if not self.currimg_is_animation:
|
3945 | |
self.set_image_sensitivities(True)
|
3946 | |
else:
|
3947 | |
self.set_image_sensitivities(False)
|
3948 | |
return used_prev, used_next
|
3949 | |
|
3950 | |
def load_new_image2(self, check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action, skip_recentfiles=False):
|
3951 | |
# check_prev_last is used to determine if we should check whether
|
3952 | |
# preloadimg_prev can be reused last. This should really only
|
3953 | |
# be done if the user just clicked the previous image button in
|
3954 | |
# order to reduce the number of image loads.
|
3955 | |
# If use_current_pixbuf_original == True, do not reload the
|
3956 | |
# self.currimg_pixbuf_original from the file; instead, use the existing
|
3957 | |
# one. This is only currently useful for resizing images.
|
3958 | |
# Determine the indices in the self.image_list array for the
|
3959 | |
# previous and next preload images.
|
3960 | |
next_index = self.curr_img_in_list + 1
|
3961 | |
if next_index > len(self.image_list)-1:
|
3962 | |
if self.listwrap_mode == 0:
|
3963 | |
next_index = -1
|
3964 | |
else:
|
3965 | |
next_index = 0
|
3966 | |
prev_index = self.curr_img_in_list - 1
|
3967 | |
if prev_index < 0:
|
3968 | |
if self.listwrap_mode == 0:
|
3969 | |
prev_index = -1
|
3970 | |
else:
|
3971 | |
prev_index = len(self.image_list)-1
|
3972 | |
if self.preloading_images:
|
3973 | |
reset_preloadimg_next_in_list = False
|
3974 | |
reset_preloadimg_prev_in_list = False
|
3975 | |
if check_prev_last:
|
3976 | |
self.check_preloadimg_next_for_existing(next_index, reset_preloadimg_next_in_list)
|
3977 | |
else:
|
3978 | |
self.check_preloadimg_prev_for_existing(prev_index, reset_preloadimg_prev_in_list)
|
3979 | |
used_prev, used_next = self.check_currimg_for_existing()
|
3980 | |
if self.preloading_images:
|
3981 | |
if check_prev_last:
|
3982 | |
self.check_preloadimg_prev_for_existing(prev_index, reset_preloadimg_prev_in_list)
|
3983 | |
else:
|
3984 | |
self.check_preloadimg_next_for_existing(next_index, reset_preloadimg_next_in_list)
|
3985 | |
if reset_preloadimg_prev_in_list:
|
3986 | |
self.preloadimg_prev_in_list = -1
|
3987 | |
if reset_preloadimg_next_in_list:
|
3988 | |
self.preloadimg_next_in_list = -1
|
3989 | |
if used_prev or used_next:
|
3990 | |
# If we used a preload image, set the correct boolean variables
|
3991 | |
if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
|
3992 | |
self.last_image_action_was_fit = True
|
3993 | |
self.last_image_action_was_smart_fit = True
|
3994 | |
elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
|
3995 | |
self.last_image_action_was_fit = True
|
3996 | |
self.last_image_action_was_smart_fit = False
|
3997 | |
elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
|
3998 | |
self.last_image_action_was_fit = False
|
3999 | |
else:
|
4000 | |
# Need to load the current image
|
4001 | |
self.currimg_pixbuf = None
|
4002 | |
self.currimg_zoomratio = 1
|
4003 | |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
4004 | |
if self.verbose and self.currimg_name != "":
|
4005 | |
print(_("Loading: %s") % self.currimg_name)
|
4006 | |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
4007 | |
if animtest.is_static_image() or (use_current_pixbuf_original and not self.currimg_is_animation):
|
4008 | |
self.currimg_is_animation = False
|
4009 | |
if not use_current_pixbuf_original:
|
4010 | |
self.currimg_pixbuf_original = animtest.get_static_image()
|
4011 | |
self.set_image_sensitivities(True)
|
4012 | |
if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
|
4013 | |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
4014 | |
elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
|
4015 | |
self.zoom_to_fit_window(None, False, False)
|
4016 | |
elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
|
4017 | |
self.zoom_1_to_1(None, False, False)
|
4018 | |
else:
|
4019 | |
self.currimg_is_animation = True
|
4020 | |
if not use_current_pixbuf_original:
|
4021 | |
self.currimg_pixbuf_original = animtest
|
4022 | |
self.zoom_1_to_1(None, False, False)
|
4023 | |
self.set_image_sensitivities(False)
|
4024 | |
if self.onload_cmd != None and perform_onload_action:
|
4025 | |
self.parse_action_command(self.onload_cmd, False)
|
4026 | |
self.update_statusbar()
|
4027 | |
self.update_title()
|
4028 | |
self.image_loaded = True
|
4029 | |
self.image_modified = False
|
4030 | |
self.image_zoomed = False
|
4031 | |
self.set_slideshow_sensitivities()
|
4032 | |
if not skip_recentfiles:
|
4033 | |
self.register_file_with_recent_docs(self.currimg_name)
|
4034 | |
if reset_cursor:
|
4035 | |
if not self.fullscreen_mode:
|
4036 | |
self.change_cursor(None)
|
4037 | |
|
4038 | |
def preload_next_image(self, use_existing_image):
|
4039 | |
try:
|
4040 | |
if self.preloading_images and len(self.image_list) > 1:
|
4041 | |
if not use_existing_image:
|
4042 | |
next_index = self.curr_img_in_list + 1
|
4043 | |
if next_index > len(self.image_list)-1:
|
4044 | |
if self.listwrap_mode == 0:
|
4045 | |
self.preloadimg_next_in_list == -1
|
4046 | |
return
|
4047 | |
else:
|
4048 | |
next_index = 0
|
4049 | |
if next_index == self.preloadimg_next_in_list:
|
4050 | |
return
|
4051 | |
self.preloadimg_next_in_list = next_index
|
4052 | |
self.preloadimg_next_name = str(self.image_list[next_index])
|
4053 | |
pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
|
4054 | |
if pre_animtest.is_static_image():
|
4055 | |
self.preloadimg_next_is_animation = False
|
4056 | |
self.preloadimg_next_pixbuf_original = pre_animtest.get_static_image()
|
4057 | |
else:
|
4058 | |
self.preloadimg_next_is_animation = True
|
4059 | |
self.preloadimg_next_pixbuf_original = pre_animtest
|
4060 | |
if self.preloadimg_next_in_list == -1:
|
4061 | |
return
|
4062 | |
# Determine self.preloadimg_next_zoomratio
|
4063 | |
if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
|
4064 | |
self.zoom_to_fit_or_1_to_1(None, True, False)
|
4065 | |
elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
|
4066 | |
self.zoom_to_fit_window(None, True, False)
|
4067 | |
elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
|
4068 | |
self.zoom_1_to_1(None, True, False)
|
4069 | |
# Always start with the original image to preserve quality!
|
4070 | |
# Calculate image size:
|
4071 | |
self.preloadimg_next_width = int(self.preloadimg_next_pixbuf_original.get_width() * self.preloadimg_next_zoomratio)
|
4072 | |
self.preloadimg_next_height = int(self.preloadimg_next_pixbuf_original.get_height() * self.preloadimg_next_zoomratio)
|
4073 | |
if not self.preloadimg_next_is_animation:
|
4074 | |
# Scale image:
|
4075 | |
if not self.preloadimg_next_pixbuf_original.get_has_alpha():
|
4076 | |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.scale_simple(self.preloadimg_next_width, self.preloadimg_next_height, self.zoom_quality)
|
4077 | |
else:
|
4078 | |
colormap = self.imageview.get_colormap()
|
4079 | |
light_grey = colormap.alloc_color('#666666', True, True)
|
4080 | |
dark_grey = colormap.alloc_color('#999999', True, True)
|
4081 | |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.composite_color_simple(self.preloadimg_next_width, self.preloadimg_next_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
|
4082 | |
else:
|
4083 | |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original
|
4084 | |
gc.collect()
|
4085 | |
if self.verbose:
|
4086 | |
print(_("Preloading: %s") % self.preloadimg_next_name)
|
4087 | |
except:
|
4088 | |
self.preloadimg_next_in_list = -1
|
4089 | |
|
4090 | |
def preload_prev_image(self, use_existing_image):
|
4091 | |
try:
|
4092 | |
if self.preloading_images and len(self.image_list) > 1:
|
4093 | |
if not use_existing_image:
|
4094 | |
prev_index = self.curr_img_in_list - 1
|
4095 | |
if prev_index < 0:
|
4096 | |
if self.listwrap_mode == 0:
|
4097 | |
self.preloadimg_prev_in_list == -1
|
4098 | |
return
|
4099 | |
else:
|
4100 | |
prev_index = len(self.image_list)-1
|
4101 | |
if prev_index == self.preloadimg_prev_in_list:
|
4102 | |
return
|
4103 | |
self.preloadimg_prev_in_list = prev_index
|
4104 | |
self.preloadimg_prev_name = str(self.image_list[prev_index])
|
4105 | |
pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
|
4106 | |
if pre_animtest.is_static_image():
|
4107 | |
self.preloadimg_prev_is_animation = False
|
4108 | |
self.preloadimg_prev_pixbuf_original = pre_animtest.get_static_image()
|
4109 | |
else:
|
4110 | |
self.preloadimg_prev_is_animation = True
|
4111 | |
self.preloadimg_prev_pixbuf_original = pre_animtest
|
4112 | |
if self.preloadimg_prev_in_list == -1:
|
4113 | |
return
|
4114 | |
# Determine self.preloadimg_prev_zoomratio
|
4115 | |
if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
|
4116 | |
self.zoom_to_fit_or_1_to_1(None, False, True)
|
4117 | |
elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
|
4118 | |
self.zoom_to_fit_window(None, False, True)
|
4119 | |
elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
|
4120 | |
self.zoom_1_to_1(None, False, True)
|
4121 | |
# Always start with the original image to preserve quality!
|
4122 | |
# Calculate image size:
|
4123 | |
self.preloadimg_prev_width = int(self.preloadimg_prev_pixbuf_original.get_width() * self.preloadimg_prev_zoomratio)
|
4124 | |
self.preloadimg_prev_height = int(self.preloadimg_prev_pixbuf_original.get_height() * self.preloadimg_prev_zoomratio)
|
4125 | |
if not self.preloadimg_prev_is_animation:
|
4126 | |
# Scale image:
|
4127 | |
if not self.preloadimg_prev_pixbuf_original.get_has_alpha():
|
4128 | |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.scale_simple(self.preloadimg_prev_width, self.preloadimg_prev_height, self.zoom_quality)
|
4129 | |
else:
|
4130 | |
colormap = self.imageview.get_colormap()
|
4131 | |
light_grey = colormap.alloc_color('#666666', True, True)
|
4132 | |
dark_grey = colormap.alloc_color('#999999', True, True)
|
4133 | |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.composite_color_simple(self.preloadimg_prev_width, self.preloadimg_prev_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
|
4134 | |
else:
|
4135 | |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original
|
4136 | |
gc.collect()
|
4137 | |
if self.verbose:
|
4138 | |
print(_("Preloading: %s") % self.preloadimg_prev_name)
|
4139 | |
except:
|
4140 | |
self.preloadimg_prev_in_list = -1
|
4141 | |
|
4142 | |
def change_cursor(self, type):
|
4143 | |
for i in gtk.gdk.window_get_toplevels():
|
4144 | |
if i.get_window_type() != gtk.gdk.WINDOW_TEMP and i.get_window_type() != gtk.gdk.WINDOW_CHILD:
|
4145 | |
i.set_cursor(type)
|
4146 | |
self.layout.window.set_cursor(type)
|
4147 | |
|
4148 | |
def expand_filelist_and_load_image(self, inputlist):
|
4149 | |
# Takes the current list (i.e. ["pic.jpg", "pic2.gif", "../images"]) and
|
4150 | |
# expands it into a list of all pictures found
|
4151 | |
self.thumblist.clear()
|
4152 | |
first_image_loaded_successfully = False
|
4153 | |
self.images_found = 0
|
4154 | |
self.stop_now = True # Make sure that any previous search process is stopped
|
4155 | |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
4156 | |
# Reset preload images:
|
4157 | |
self.preloadimg_next_in_list = -1
|
4158 | |
self.preloadimg_prev_in_list = -1
|
4159 | |
# If any directories were passed, display "Searching..." in statusbar:
|
4160 | |
self.searching_for_images = False
|
4161 | |
for item in inputlist:
|
4162 | |
if os.path.isdir(item):
|
4163 | |
self.searching_for_images = True
|
4164 | |
self.update_statusbar()
|
4165 | |
if not self.closing_app:
|
4166 | |
while gtk.events_pending():
|
4167 | |
gtk.main_iteration()
|
4168 | |
first_image = ""
|
4169 | |
first_image_found = False
|
4170 | |
first_image_loaded = False
|
4171 | |
second_image = ""
|
4172 | |
second_image_found = False
|
4173 | |
second_image_preloaded = False
|
4174 | |
self.randomlist = []
|
4175 | |
folderlist = []
|
4176 | |
self.image_list = []
|
4177 | |
self.curr_img_in_list = 0
|
4178 | |
go_buttons_enabled = False
|
4179 | |
self.set_go_sensitivities(False)
|
4180 | |
# Clean up list (remove preceding "file://" or "file:" and trailing "/")
|
4181 | |
for itemnum in range(len(inputlist)):
|
4182 | |
# Strip off preceding file..
|
4183 | |
if inputlist[itemnum].startswith('file://'):
|
4184 | |
inputlist[itemnum] = inputlist[itemnum][7:]
|
4185 | |
elif inputlist[itemnum].startswith('file:'):
|
4186 | |
inputlist[itemnum] = inputlist[itemnum][5:]
|
4187 | |
# Strip off trailing "/" if it exists:
|
4188 | |
if inputlist[itemnum][len(inputlist[itemnum])-1] == "/":
|
4189 | |
inputlist[itemnum] = inputlist[itemnum][:(len(inputlist[itemnum])-1)]
|
4190 | |
if not (inputlist[itemnum].startswith('http://') or inputlist[itemnum].startswith('ftp://')):
|
4191 | |
inputlist[itemnum] = os.path.abspath(inputlist[itemnum])
|
4192 | |
else:
|
4193 | |
try:
|
4194 | |
# Remote file. Save as /tmp/mirage-<random>/filename.ext
|
4195 | |
tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
|
4196 | |
tmpfile = tmpdir + os.path.basename(inputlist[itemnum])
|
4197 | |
socket.setdefaulttimeout(5)
|
4198 | |
urllib.request.urlretrieve(inputlist[itemnum], tmpfile)
|
4199 | |
inputlist[itemnum] = tmpfile
|
4200 | |
except:
|
4201 | |
pass
|
4202 | |
# Remove hidden files from list:
|
4203 | |
if not self.open_hidden_files:
|
4204 | |
tmplist = []
|
4205 | |
for item in inputlist:
|
4206 | |
if os.path.basename(item)[0] != '.':
|
4207 | |
tmplist.append(item)
|
4208 | |
elif self.verbose:
|
4209 | |
print(_("Skipping: %s") % item)
|
4210 | |
inputlist = tmplist
|
4211 | |
if len(inputlist) == 0:
|
4212 | |
# All files/dirs were hidden, exit..
|
4213 | |
self.currimg_name = ""
|
4214 | |
self.searching_for_images = False
|
4215 | |
self.set_go_navigation_sensitivities(False)
|
4216 | |
self.set_slideshow_sensitivities()
|
4217 | |
if not self.closing_app:
|
4218 | |
self.change_cursor(None)
|
4219 | |
self.recursive = False
|
4220 | |
self.put_error_image_to_window()
|
4221 | |
self.update_title()
|
4222 | |
return
|
4223 | |
init_image = os.path.abspath(inputlist[0])
|
4224 | |
self.stop_now = False
|
4225 | |
# If open all images in dir...
|
4226 | |
if self.open_all_images:
|
4227 | |
temp = inputlist
|
4228 | |
inputlist = []
|
4229 | |
for item in temp:
|
4230 | |
if os.path.isfile(item):
|
4231 | |
itempath = os.path.dirname(os.path.abspath(item))
|
4232 | |
temp = self.recursive
|
4233 | |
self.recursive = False
|
4234 | |
self.stop_now = False
|
4235 | |
self.expand_directory(itempath, False, go_buttons_enabled, False, False)
|
4236 | |
self.recursive = temp
|
4237 | |
else:
|
4238 | |
inputlist.append(item)
|
4239 | |
for item in self.image_list:
|
4240 | |
inputlist.append(item)
|
4241 | |
if first_image_found and not second_image_found:
|
4242 | |
second_image_found = True
|
4243 | |
second_image = item
|
4244 | |
second_image_came_from_dir = False
|
4245 | |
if item == init_image:
|
4246 | |
first_image_found = True
|
4247 | |
first_image = item
|
4248 | |
first_image_came_from_dir = False
|
4249 | |
self.curr_img_in_list = len(inputlist)-1
|
4250 | |
self.image_list = []
|
4251 | |
for item in inputlist:
|
4252 | |
if not self.closing_app:
|
4253 | |
if os.path.isfile(item):
|
4254 | |
if self.valid_image(item):
|
4255 | |
if not second_image_found and first_image_found:
|
4256 | |
second_image_found = True
|
4257 | |
second_image = item
|
4258 | |
second_image_came_from_dir = False
|
4259 | |
if not first_image_found:
|
4260 | |
first_image_found = True
|
4261 | |
first_image = item
|
4262 | |
first_image_came_from_dir = False
|
4263 | |
self.image_list.append(item)
|
4264 | |
if self.verbose:
|
4265 | |
self.images_found += 1
|
4266 | |
print(_("Found: %(item)s [%(number)i]") % {'item': item, 'number': self.images_found})
|
4267 | |
else:
|
4268 | |
# If it's a directory that was explicitly selected or passed to
|
4269 | |
# the program, get all the files in the dir.
|
4270 | |
# Retrieve only images in the top directory specified by the user
|
4271 | |
# unless explicitly told to recurse (via -R or in Settings>Preferences)
|
4272 | |
folderlist.append(item)
|
4273 | |
if not second_image_found:
|
4274 | |
# See if we can find an image in this directory:
|
4275 | |
self.stop_now = False
|
4276 | |
self.expand_directory(item, True, go_buttons_enabled, False, False)
|
4277 | |
itemnum = 0
|
4278 | |
while itemnum < len(self.image_list) and not second_image_found:
|
4279 | |
if os.path.isfile(self.image_list[itemnum]):
|
4280 | |
if not second_image_found and first_image_found:
|
4281 | |
second_image_found = True
|
4282 | |
second_image_came_from_dir = True
|
4283 | |
second_image = self.image_list[itemnum]
|
4284 | |
self.set_go_navigation_sensitivities(True)
|
4285 | |
go_buttons_enabled = True
|
4286 | |
while gtk.events_pending():
|
4287 | |
gtk.main_iteration(True)
|
4288 | |
if not first_image_found:
|
4289 | |
first_image_found = True
|
4290 | |
first_image = self.image_list[itemnum]
|
4291 | |
first_image_came_from_dir = True
|
4292 | |
itemnum += 1
|
4293 | |
# Load first image and display:
|
4294 | |
if first_image_found and not first_image_loaded and self.curr_img_in_list <= len(self.image_list)-1:
|
4295 | |
first_image_loaded = True
|
4296 | |
if self.slideshow_mode:
|
4297 | |
self.toggle_slideshow(None)
|
4298 | |
if self.verbose and self.currimg_name != "":
|
4299 | |
print(_("Loading: %s") % self.currimg_name)
|
4300 | |
try:
|
4301 | |
self.load_new_image2(False, False, True, True)
|
4302 | |
# Calling load_new_image2 will reset the following two vars
|
4303 | |
# to 0, so ensure they are -1 again (no images preloaded)
|
4304 | |
self.preloadimg_prev_in_list = -1
|
4305 | |
self.preloadimg_next_in_list = -1
|
4306 | |
if not self.currimg_is_animation:
|
4307 | |
self.previmg_width = self.currimg_pixbuf.get_width()
|
4308 | |
else:
|
4309 | |
self.previmg_width = self.currimg_pixbuf.get_static_image().get_width()
|
4310 | |
self.image_loaded = True
|
4311 | |
first_image_loaded_successfully = True
|
4312 | |
if not self.closing_app:
|
4313 | |
while gtk.events_pending():
|
4314 | |
gtk.main_iteration(True)
|
4315 | |
except:
|
4316 | |
pass
|
4317 | |
if first_image_came_from_dir:
|
4318 | |
self.image_list = []
|
4319 | |
# Pre-load second image:
|
4320 | |
if second_image_found and not second_image_preloaded and ((not second_image_came_from_dir and self.curr_img_in_list+1 <= len(self.image_list)-1) or second_image_came_from_dir):
|
4321 | |
second_image_preloaded = True
|
4322 | |
temp = self.image_list
|
4323 | |
self.image_list = []
|
4324 | |
while len(self.image_list) < self.curr_img_in_list+1:
|
4325 | |
self.image_list.append(first_image)
|
4326 | |
self.image_list.append(second_image)
|
4327 | |
self.preload_next_image(False)
|
4328 | |
self.image_list = temp
|
4329 | |
if first_image_found:
|
4330 | |
# Sort the filelist and folderlist alphabetically, and recurse into folderlist:
|
4331 | |
if first_image_came_from_dir:
|
4332 | |
self.add_folderlist_images(folderlist, go_buttons_enabled)
|
4333 | |
self.do_image_list_stuff(first_image, second_image)
|
4334 | |
else:
|
4335 | |
self.do_image_list_stuff(first_image, second_image)
|
4336 | |
self.add_folderlist_images(folderlist, go_buttons_enabled)
|
4337 | |
self.update_title()
|
4338 | |
if not self.closing_app:
|
4339 | |
while gtk.events_pending():
|
4340 | |
gtk.main_iteration(True)
|
4341 | |
if not first_image_loaded_successfully:
|
4342 | |
self.image_load_failed(False, init_image)
|
4343 | |
self.searching_for_images = False
|
4344 | |
self.update_statusbar()
|
4345 | |
self.set_go_navigation_sensitivities(False)
|
4346 | |
self.set_slideshow_sensitivities()
|
4347 | |
self.thumbpane_update_images(True, self.curr_img_in_list)
|
4348 | |
if not self.closing_app:
|
4349 | |
self.change_cursor(None)
|
4350 | |
self.recursive = False
|
4351 | |
|
4352 | |
def add_folderlist_images(self, folderlist, go_buttons_enabled):
|
4353 | |
if len(folderlist) > 0:
|
4354 | |
folderlist.sort(locale.strcoll)
|
4355 | |
folderlist = list(set(folderlist))
|
4356 | |
for item in folderlist:
|
4357 | |
if not self.closing_app:
|
4358 | |
if (not self.open_hidden_files and os.path.basename(item)[0] != '.') or self.open_hidden_files:
|
4359 | |
self.stop_now = False
|
4360 | |
self.expand_directory(item, False, go_buttons_enabled, True, True)
|
4361 | |
|
4362 | |
def do_image_list_stuff(self, first_image, second_image):
|
4363 | |
if len(self.image_list) > 0:
|
4364 | |
self.set_go_navigation_sensitivities(True)
|
4365 | |
self.image_list = list(set(self.image_list))
|
4366 | |
self.image_list.sort(locale.strcoll)
|
4367 | |
|
4368 | |
def expand_directory(self, item, stop_when_second_image_found, go_buttons_enabled, update_window_title, print_found_msg):
|
4369 | |
if not self.stop_now and not self.closing_app:
|
4370 | |
folderlist = []
|
4371 | |
filelist = []
|
4372 | |
if not os.access(item, os.R_OK):
|
4373 | |
return False
|
4374 | |
for item2 in os.listdir(item):
|
4375 | |
if not self.closing_app and not self.stop_now:
|
4376 | |
while gtk.events_pending():
|
4377 | |
gtk.main_iteration(True)
|
4378 | |
item2 = item + os.sep + item2
|
4379 | |
item_fullpath2 = os.path.abspath(item2)
|
4380 | |
if (not self.open_hidden_files and os.path.basename(item_fullpath2)[0] != '.') or self.open_hidden_files:
|
4381 | |
if os.path.isfile(item_fullpath2) and self.valid_image(item_fullpath2):
|
4382 | |
filelist.append(item2)
|
4383 | |
if self.verbose and print_found_msg:
|
4384 | |
self.images_found += 1
|
4385 | |
print(_("Found: %(fullpath)s [%(number)i]") % {'fullpath': item_fullpath2, 'number': self.images_found})
|
4386 | |
elif os.path.isdir(item_fullpath2) and self.recursive:
|
4387 | |
folderlist.append(item_fullpath2)
|
4388 | |
elif self.verbose:
|
4389 | |
print(_("Skipping: %s") % item_fullpath2)
|
4390 | |
if len(self.image_list)>0 and update_window_title:
|
4391 | |
self.update_title()
|
4392 | |
# Sort the filelist and folderlist alphabetically:
|
4393 | |
if len(filelist) > 0:
|
4394 | |
filelist.sort(locale.strcoll)
|
4395 | |
for item2 in filelist:
|
4396 | |
if not item2 in self.image_list:
|
4397 | |
self.image_list.append(item2)
|
4398 | |
if stop_when_second_image_found and len(self.image_list)==2:
|
4399 | |
return
|
4400 | |
if not go_buttons_enabled and len(self.image_list) > 1:
|
4401 | |
self.set_go_navigation_sensitivities(True)
|
4402 | |
go_buttons_enabled = True
|
4403 | |
# Recurse into the folderlist:
|
4404 | |
if len(folderlist) > 0:
|
4405 | |
folderlist.sort(locale.strcoll)
|
4406 | |
for item2 in folderlist:
|
4407 | |
if not self.stop_now:
|
4408 | |
self.expand_directory(item2, stop_when_second_image_found, go_buttons_enabled, update_window_title, print_found_msg)
|
4409 | |
|
4410 | |
def register_file_with_recent_docs(self, imgfile):
|
4411 | |
self.recent_file_add_and_refresh(imgfile)
|
4412 | |
if os.path.isfile(imgfile) and gtk.check_version(2, 10, 0) == None:
|
4413 | |
try:
|
4414 | |
gtk_recent_manager = gtk.recent_manager_get_default()
|
4415 | |
uri = ''
|
4416 | |
if imgfile[:7] != 'file://':
|
4417 | |
uri = 'file://'
|
4418 | |
uri = uri + urllib.request.pathname2url(os.path.abspath(imgfile))
|
4419 | |
gtk_recent_manager.add_item(uri)
|
4420 | |
except:
|
4421 | |
#Isnt currently functional on win32
|
4422 | |
if sys.platform == "win32":
|
4423 | |
pass
|
4424 | |
else:
|
4425 | |
raise
|
4426 | |
|
4427 | |
def valid_image(self, file):
|
4428 | |
test = gtk.gdk.pixbuf_get_file_info(file)
|
4429 | |
if test == None:
|
4430 | |
return False
|
4431 | |
elif test[0]['name'] == "wbmp":
|
4432 | |
# some regular files are thought to be wbmp for whatever reason,
|
4433 | |
# so let's check further.. :(
|
4434 | |
try:
|
4435 | |
test2 = gtk.gdk.pixbuf_new_from_file(file)
|
4436 | |
return True
|
4437 | |
except:
|
4438 | |
return False
|
4439 | |
else:
|
4440 | |
return True
|
4441 | |
|
4442 | |
def image_flip(self, old_pix, vertical):
|
4443 | |
width = old_pix.get_width()
|
4444 | |
height = old_pix.get_height()
|
4445 | |
d = None
|
4446 | |
if vertical:
|
4447 | |
d, w, h, rws = imgfuncs.vert(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
|
4448 | |
else:
|
4449 | |
d, w, h, rws = imgfuncs.horiz(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
|
4450 | |
if d:
|
4451 | |
new_pix = gtk.gdk.pixbuf_new_from_data(d, old_pix.get_colorspace(), old_pix.get_has_alpha(), old_pix.get_bits_per_sample(), w, h, rws)
|
4452 | |
return new_pix
|
4453 | |
return old_pix
|
4454 | |
|
4455 | |
def image_rotate(self, old_pix, full_angle):
|
4456 | |
width = old_pix.get_width()
|
4457 | |
height = old_pix.get_height()
|
4458 | |
angle = full_angle - (int(full_angle) // 360) * 360
|
4459 | |
if angle:
|
4460 | |
d = None
|
4461 | |
if angle % 270 == 0:
|
4462 | |
d, w, h, rws = imgfuncs.right(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
|
4463 | |
elif angle % 180 == 0:
|
4464 | |
d, w, h, rws = imgfuncs.mirror(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
|
4465 | |
elif angle % 90 == 0:
|
4466 | |
d, w, h, rws = imgfuncs.left(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
|
4467 | |
if d:
|
4468 | |
new_pix = gtk.gdk.pixbuf_new_from_data(d, old_pix.get_colorspace(), old_pix.get_has_alpha(), old_pix.get_bits_per_sample(), w, h, rws)
|
4469 | |
return new_pix
|
4470 | |
return old_pix
|
4471 | |
|
4472 | |
def toggle_slideshow(self, action):
|
4473 | |
if len(self.image_list) > 1:
|
4474 | |
if not self.slideshow_mode:
|
4475 | |
if self.slideshow_in_fullscreen and not self.fullscreen_mode:
|
4476 | |
self.enter_fullscreen(None)
|
4477 | |
self.slideshow_mode = True
|
4478 | |
self.update_title()
|
4479 | |
self.set_slideshow_sensitivities()
|
4480 | |
if not self.curr_slideshow_random:
|
4481 | |
self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
|
4482 | |
else:
|
4483 | |
self.reinitialize_randomlist()
|
4484 | |
self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
|
4485 | |
self.ss_start.hide()
|
4486 | |
self.ss_stop.show()
|
4487 | |
timer_screensaver = gobject.timeout_add(1000, self.disable_screensaver_in_slideshow_mode)
|
4488 | |
else:
|
4489 | |
self.slideshow_mode = False
|
4490 | |
gobject.source_remove(self.timer_delay)
|
4491 | |
self.update_title()
|
4492 | |
self.set_slideshow_sensitivities()
|
4493 | |
self.set_zoom_sensitivities()
|
4494 | |
self.ss_stop.hide()
|
4495 | |
self.ss_start.show()
|
4496 | |
|
4497 | |
def update_title(self):
|
4498 | |
if len(self.image_list) == 0:
|
4499 | |
title = "Mirage"
|
4500 | |
else:
|
4501 | |
title = "Mirage - " +_("[%(current)i of %(total)i]") % {'current': self.curr_img_in_list+1, 'total': len(self.image_list)} + ' ' + os.path.basename(self.currimg_name)
|
4502 | |
if self.slideshow_mode:
|
4503 | |
title = title + ' - ' + _('Slideshow Mode')
|
4504 | |
self.window.set_title(title)
|
4505 | |
|
4506 | |
def slideshow_controls_show(self):
|
4507 | |
if not self.slideshow_controls_visible and not self.controls_moving:
|
4508 | |
self.slideshow_controls_visible = True
|
4509 | |
|
4510 | |
self.ss_delayspin.set_value(self.curr_slideshow_delay)
|
4511 | |
self.ss_randomize.set_active(self.curr_slideshow_random)
|
4512 | |
|
4513 | |
if self.slideshow_mode:
|
4514 | |
self.ss_start.set_no_show_all(True)
|
4515 | |
self.ss_stop.set_no_show_all(False)
|
4516 | |
else:
|
4517 | |
self.ss_start.set_no_show_all(False)
|
4518 | |
self.ss_stop.set_no_show_all(True)
|
4519 | |
|
4520 | |
(xpos, ypos) = self.window.get_position()
|
4521 | |
screen = self.window.get_screen()
|
4522 | |
self.slideshow_window.set_screen(screen)
|
4523 | |
self.slideshow_window2.set_screen(screen)
|
4524 | |
|
4525 | |
self.slideshow_window.show_all()
|
4526 | |
self.slideshow_window2.show_all()
|
4527 | |
if not self.closing_app:
|
4528 | |
while gtk.events_pending():
|
4529 | |
gtk.main_iteration()
|
4530 | |
|
4531 | |
ss_winheight = self.slideshow_window.allocation.height
|
4532 | |
ss_win2width = self.slideshow_window2.allocation.width
|
4533 | |
winheight = self.window.allocation.height
|
4534 | |
winwidth = self.window.allocation.width
|
4535 | |
y = -3.0
|
4536 | |
self.controls_moving = True
|
4537 | |
while y < ss_winheight:
|
4538 | |
self.slideshow_window.move(2+xpos, int(winheight-y-2))
|
4539 | |
self.slideshow_window2.move(winwidth-ss_win2width-2+xpos, int(winheight-y-2))
|
4540 | |
y += 0.05
|
4541 | |
if not self.closing_app:
|
4542 | |
while gtk.events_pending():
|
4543 | |
gtk.main_iteration()
|
4544 | |
self.controls_moving = False
|
4545 | |
|
4546 | |
def slideshow_controls_hide(self):
|
4547 | |
if self.slideshow_controls_visible and not self.controls_moving:
|
4548 | |
self.slideshow_controls_visible = False
|
4549 | |
|
4550 | |
(xpos, ypos) = self.window.get_position()
|
4551 | |
|
4552 | |
ss_winheight = self.slideshow_window.allocation.height
|
4553 | |
ss_win2width = self.slideshow_window2.allocation.width
|
4554 | |
winheight = self.window.allocation.height
|
4555 | |
winwidth = self.window.allocation.width
|
4556 | |
y = float(self.slideshow_window.allocation.height*1.0)
|
4557 | |
self.controls_moving = True
|
4558 | |
while y > -3:
|
4559 | |
self.slideshow_window.move(2+xpos, int(winheight-y-2))
|
4560 | |
self.slideshow_window2.move(winwidth-ss_win2width-2+xpos, int(winheight-y-2))
|
4561 | |
y -= 0.05
|
4562 | |
if not self.closing_app:
|
4563 | |
while gtk.events_pending():
|
4564 | |
gtk.main_iteration()
|
4565 | |
self.controls_moving = False
|
4566 | |
|
4567 | |
def disable_screensaver_in_slideshow_mode(self):
|
4568 | |
if self.slideshow_mode and self.disable_screensaver:
|
4569 | |
test = os.spawnlp(os.P_WAIT, "/usr/bin/xscreensaver-command", "xscreensaver-command", "-deactivate")
|
4570 | |
if test != 127:
|
4571 | |
timer_screensaver = gobject.timeout_add(1000, self.disable_screensaver_in_slideshow_mode)
|
4572 | |
|
4573 | |
def main(self):
|
4574 | |
gtk.main()
|
|
2526 |
color = gtk.gdk.Color()
|
|
2527 |
pix = gtk.gdk.pixmap_create_from_data(None, pix_data, 1, 1, 1, color, color)
|
|
2528 |
invisible = gtk.gdk.Cursor(pix, pix, color, color, 0, 0)
|
|
2529 |
self.change_cursor(invisible)
|
|
2530 |
return False
|
|
2531 |
|
|
2532 |
def enter_fullscreen(self, action):
|
|
2533 |
if not self.fullscreen_mode:
|
|
2534 |
self.fullscreen_mode = True
|
|
2535 |
self.UIManager.get_widget("/Popup/Full Screen").hide()
|
|
2536 |
self.UIManager.get_widget("/Popup/Exit Full Screen").show()
|
|
2537 |
self.statusbar.hide()
|
|
2538 |
self.statusbar2.hide()
|
|
2539 |
self.toolbar.hide()
|
|
2540 |
self.menubar.hide()
|
|
2541 |
self.thumbscroll.hide()
|
|
2542 |
self.thumbpane.hide()
|
|
2543 |
self.window.fullscreen()
|
|
2544 |
self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
|
|
2545 |
self.set_slideshow_sensitivities()
|
|
2546 |
if self.simple_bgcolor:
|
|
2547 |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
2548 |
else:
|
|
2549 |
if self.simple_bgcolor:
|
|
2550 |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
|
2551 |
self.leave_fullscreen(action)
|
|
2552 |
|
|
2553 |
def leave_fullscreen(self, action):
|
|
2554 |
if self.fullscreen_mode:
|
|
2555 |
self.slideshow_controls_visible = False
|
|
2556 |
self.slideshow_window.hide_all()
|
|
2557 |
self.slideshow_window2.hide_all()
|
|
2558 |
self.fullscreen_mode = False
|
|
2559 |
self.UIManager.get_widget("/Popup/Full Screen").show()
|
|
2560 |
self.UIManager.get_widget("/Popup/Exit Full Screen").hide()
|
|
2561 |
if self.toolbar_show:
|
|
2562 |
self.toolbar.show()
|
|
2563 |
self.menubar.show()
|
|
2564 |
if self.statusbar_show:
|
|
2565 |
self.statusbar.show()
|
|
2566 |
self.statusbar2.show()
|
|
2567 |
if self.thumbpane_show:
|
|
2568 |
self.thumbscroll.show()
|
|
2569 |
self.thumbpane.show()
|
|
2570 |
self.thumbpane_update_images(False, self.curr_img_in_list)
|
|
2571 |
self.window.unfullscreen()
|
|
2572 |
self.change_cursor(None)
|
|
2573 |
self.set_slideshow_sensitivities()
|
|
2574 |
if self.simple_bgcolor:
|
|
2575 |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
|
2576 |
|
|
2577 |
def toggle_status_bar(self, action):
|
|
2578 |
if self.statusbar.get_property("visible"):
|
|
2579 |
self.statusbar.hide()
|
|
2580 |
self.statusbar2.hide()
|
|
2581 |
self.statusbar_show = False
|
|
2582 |
else:
|
|
2583 |
self.statusbar.show()
|
|
2584 |
self.statusbar2.show()
|
|
2585 |
self.statusbar_show = True
|
|
2586 |
if self.image_loaded and self.last_image_action_was_fit:
|
|
2587 |
if self.last_image_action_was_smart_fit:
|
|
2588 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
2589 |
else:
|
|
2590 |
self.zoom_to_fit_window(None, False, False)
|
|
2591 |
|
|
2592 |
def toggle_thumbpane(self, action):
|
|
2593 |
if self.thumbscroll.get_property("visible"):
|
|
2594 |
self.thumbscroll.hide()
|
|
2595 |
self.thumbpane.hide()
|
|
2596 |
self.thumbpane_show = False
|
|
2597 |
else:
|
|
2598 |
self.thumbscroll.show()
|
|
2599 |
self.thumbpane.show()
|
|
2600 |
self.thumbpane_show = True
|
|
2601 |
self.stop_now = False
|
|
2602 |
gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
|
|
2603 |
if self.image_loaded and self.last_image_action_was_fit:
|
|
2604 |
if self.last_image_action_was_smart_fit:
|
|
2605 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
2606 |
else:
|
|
2607 |
self.zoom_to_fit_window(None, False, False)
|
|
2608 |
|
|
2609 |
def toggle_toolbar(self, action):
|
|
2610 |
if self.toolbar.get_property("visible"):
|
|
2611 |
self.toolbar.hide()
|
|
2612 |
self.toolbar_show = False
|
|
2613 |
else:
|
|
2614 |
self.toolbar.show()
|
|
2615 |
self.toolbar_show = True
|
|
2616 |
if self.image_loaded and self.last_image_action_was_fit:
|
|
2617 |
if self.last_image_action_was_smart_fit:
|
|
2618 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
2619 |
else:
|
|
2620 |
self.zoom_to_fit_window(None, False, False)
|
|
2621 |
|
|
2622 |
def update_statusbar(self):
|
|
2623 |
# Update status bar:
|
|
2624 |
try:
|
|
2625 |
st = os.stat(self.currimg_name)
|
|
2626 |
filesize = st[stat.ST_SIZE] // 1000
|
|
2627 |
ratio = int(100 * self.currimg_zoomratio)
|
|
2628 |
status_text = (
|
|
2629 |
os.path.basename(self.currimg_name)
|
|
2630 |
+ ": "
|
|
2631 |
+ str(self.currimg_pixbuf_original.get_width())
|
|
2632 |
+ "x"
|
|
2633 |
+ str(self.currimg_pixbuf_original.get_height())
|
|
2634 |
+ " "
|
|
2635 |
+ str(filesize)
|
|
2636 |
+ "KB "
|
|
2637 |
+ str(ratio)
|
|
2638 |
+ "% "
|
|
2639 |
)
|
|
2640 |
except:
|
|
2641 |
status_text = _("Cannot load image.")
|
|
2642 |
self.statusbar.push(self.statusbar.get_context_id(""), status_text)
|
|
2643 |
status_text = ""
|
|
2644 |
if self.running_custom_actions:
|
|
2645 |
status_text = _("Custom actions: %(current)i of %(total)i") % {
|
|
2646 |
"current": self.curr_custom_action,
|
|
2647 |
"total": self.num_custom_actions,
|
|
2648 |
}
|
|
2649 |
elif self.searching_for_images:
|
|
2650 |
status_text = _("Scanning...")
|
|
2651 |
self.statusbar2.push(self.statusbar2.get_context_id(""), status_text)
|
|
2652 |
|
|
2653 |
def show_custom_actions(self, action):
|
|
2654 |
self.actions_dialog = gtk.Dialog(
|
|
2655 |
title=_("Configure Custom Actions"), parent=self.window
|
|
2656 |
)
|
|
2657 |
self.actions_dialog.set_has_separator(False)
|
|
2658 |
self.actions_dialog.set_resizable(False)
|
|
2659 |
table_actions = gtk.Table(13, 2, False)
|
|
2660 |
table_actions.attach(
|
|
2661 |
gtk.Label(), 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
2662 |
)
|
|
2663 |
actionscrollwindow = gtk.ScrolledWindow()
|
|
2664 |
self.actionstore = gtk.ListStore(str, str, str)
|
|
2665 |
self.actionwidget = gtk.TreeView()
|
|
2666 |
self.actionwidget.set_enable_search(False)
|
|
2667 |
self.actionwidget.set_rules_hint(True)
|
|
2668 |
self.actionwidget.connect("row-activated", self.edit_custom_action2)
|
|
2669 |
actionscrollwindow.add(self.actionwidget)
|
|
2670 |
actionscrollwindow.set_shadow_type(gtk.SHADOW_IN)
|
|
2671 |
actionscrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
|
2672 |
actionscrollwindow.set_size_request(500, 200)
|
|
2673 |
self.actionwidget.set_model(self.actionstore)
|
|
2674 |
self.cell = gtk.CellRendererText()
|
|
2675 |
self.cellbool = gtk.CellRendererPixbuf()
|
|
2676 |
self.tvcolumn0 = gtk.TreeViewColumn(_("Batch"))
|
|
2677 |
self.tvcolumn1 = gtk.TreeViewColumn(_("Action"), self.cell, markup=0)
|
|
2678 |
self.tvcolumn2 = gtk.TreeViewColumn(_("Shortcut"))
|
|
2679 |
self.tvcolumn1.set_max_width(
|
|
2680 |
self.actionwidget.size_request()[0]
|
|
2681 |
- self.tvcolumn0.get_width()
|
|
2682 |
- self.tvcolumn2.get_width()
|
|
2683 |
)
|
|
2684 |
self.actionwidget.append_column(self.tvcolumn0)
|
|
2685 |
self.actionwidget.append_column(self.tvcolumn1)
|
|
2686 |
self.actionwidget.append_column(self.tvcolumn2)
|
|
2687 |
self.populate_treeview()
|
|
2688 |
if len(self.action_names) > 0:
|
|
2689 |
self.actionwidget.get_selection().select_path(0)
|
|
2690 |
vbox_actions = gtk.VBox()
|
|
2691 |
addbutton = gtk.Button("", gtk.STOCK_ADD)
|
|
2692 |
addbutton.get_child().get_child().get_children()[1].set_text("")
|
|
2693 |
addbutton.connect("clicked", self.add_custom_action, self.actionwidget)
|
|
2694 |
addbutton.set_tooltip_text(_("Add action"))
|
|
2695 |
editbutton = gtk.Button("", gtk.STOCK_EDIT)
|
|
2696 |
editbutton.get_child().get_child().get_children()[1].set_text("")
|
|
2697 |
editbutton.connect("clicked", self.edit_custom_action, self.actionwidget)
|
|
2698 |
editbutton.set_tooltip_text(_("Edit selected action."))
|
|
2699 |
removebutton = gtk.Button("", gtk.STOCK_REMOVE)
|
|
2700 |
removebutton.get_child().get_child().get_children()[1].set_text("")
|
|
2701 |
removebutton.connect("clicked", self.remove_custom_action)
|
|
2702 |
removebutton.set_tooltip_text(_("Remove selected action."))
|
|
2703 |
upbutton = gtk.Button("", gtk.STOCK_GO_UP)
|
|
2704 |
upbutton.get_child().get_child().get_children()[1].set_text("")
|
|
2705 |
upbutton.connect("clicked", self.custom_action_move_up, self.actionwidget)
|
|
2706 |
upbutton.set_tooltip_text(_("Move selected action up."))
|
|
2707 |
downbutton = gtk.Button("", gtk.STOCK_GO_DOWN)
|
|
2708 |
downbutton.get_child().get_child().get_children()[1].set_text("")
|
|
2709 |
downbutton.connect("clicked", self.custom_action_move_down, self.actionwidget)
|
|
2710 |
downbutton.set_tooltip_text(_("Move selected action down."))
|
|
2711 |
vbox_buttons = gtk.VBox()
|
|
2712 |
propertyinfo = gtk.Label()
|
|
2713 |
propertyinfo.set_markup(
|
|
2714 |
"<small>"
|
|
2715 |
+ _("Parameters")
|
|
2716 |
+ ':\n<span font_family="Monospace">%F</span> - '
|
|
2717 |
+ _("File path, name, and extension")
|
|
2718 |
+ '\n<span font_family="Monospace">%P</span> - '
|
|
2719 |
+ _("File path")
|
|
2720 |
+ '\n<span font_family="Monospace">%N</span> - '
|
|
2721 |
+ _("File name without file extension")
|
|
2722 |
+ '\n<span font_family="Monospace">%E</span> - '
|
|
2723 |
+ _('File extension (i.e. ".png")')
|
|
2724 |
+ '\n<span font_family="Monospace">%L</span> - '
|
|
2725 |
+ _("List of files, space-separated")
|
|
2726 |
+ "</small>"
|
|
2727 |
)
|
|
2728 |
propertyinfo.set_alignment(0, 0)
|
|
2729 |
actioninfo = gtk.Label()
|
|
2730 |
actioninfo.set_markup(
|
|
2731 |
"<small>"
|
|
2732 |
+ _("Operations")
|
|
2733 |
+ ':\n<span font_family="Monospace">[NEXT]</span> - '
|
|
2734 |
+ _("Go to next image")
|
|
2735 |
+ '\n<span font_family="Monospace">[PREV]</span> - '
|
|
2736 |
+ _("Go to previous image")
|
|
2737 |
+ "</small>"
|
|
2738 |
)
|
|
2739 |
actioninfo.set_alignment(0, 0)
|
|
2740 |
hbox_info = gtk.HBox()
|
|
2741 |
hbox_info.pack_start(propertyinfo, False, False, 15)
|
|
2742 |
hbox_info.pack_start(actioninfo, False, False, 15)
|
|
2743 |
vbox_buttons.pack_start(addbutton, False, False, 5)
|
|
2744 |
vbox_buttons.pack_start(editbutton, False, False, 5)
|
|
2745 |
vbox_buttons.pack_start(removebutton, False, False, 5)
|
|
2746 |
vbox_buttons.pack_start(upbutton, False, False, 5)
|
|
2747 |
vbox_buttons.pack_start(downbutton, False, False, 0)
|
|
2748 |
hbox_top = gtk.HBox()
|
|
2749 |
hbox_top.pack_start(actionscrollwindow, True, True, 5)
|
|
2750 |
hbox_top.pack_start(vbox_buttons, False, False, 5)
|
|
2751 |
vbox_actions.pack_start(hbox_top, True, True, 5)
|
|
2752 |
vbox_actions.pack_start(hbox_info, False, False, 5)
|
|
2753 |
hbox_instructions = gtk.HBox()
|
|
2754 |
info_image = gtk.Image()
|
|
2755 |
info_image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_BUTTON)
|
|
2756 |
hbox_instructions.pack_start(info_image, False, False, 5)
|
|
2757 |
instructions = gtk.Label(
|
|
2758 |
_(
|
|
2759 |
"Here you can define custom actions with shortcuts. Actions use the built-in parameters and operations listed below and can have multiple statements separated by a semicolon. Batch actions apply to all images in the list."
|
|
2760 |
)
|
|
2761 |
)
|
|
2762 |
instructions.set_line_wrap(True)
|
|
2763 |
instructions.set_alignment(0, 0.5)
|
|
2764 |
hbox_instructions.pack_start(instructions, False, False, 5)
|
|
2765 |
table_actions.attach(
|
|
2766 |
hbox_instructions,
|
|
2767 |
1,
|
|
2768 |
3,
|
|
2769 |
2,
|
|
2770 |
3,
|
|
2771 |
gtk.FILL | gtk.EXPAND,
|
|
2772 |
gtk.FILL | gtk.EXPAND,
|
|
2773 |
5,
|
|
2774 |
0,
|
|
2775 |
)
|
|
2776 |
table_actions.attach(
|
|
2777 |
gtk.Label(), 1, 3, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
2778 |
)
|
|
2779 |
table_actions.attach(
|
|
2780 |
vbox_actions,
|
|
2781 |
1,
|
|
2782 |
3,
|
|
2783 |
4,
|
|
2784 |
12,
|
|
2785 |
gtk.FILL | gtk.EXPAND,
|
|
2786 |
gtk.FILL | gtk.EXPAND,
|
|
2787 |
15,
|
|
2788 |
0,
|
|
2789 |
)
|
|
2790 |
table_actions.attach(
|
|
2791 |
gtk.Label(),
|
|
2792 |
1,
|
|
2793 |
3,
|
|
2794 |
12,
|
|
2795 |
13,
|
|
2796 |
gtk.FILL | gtk.EXPAND,
|
|
2797 |
gtk.FILL | gtk.EXPAND,
|
|
2798 |
15,
|
|
2799 |
0,
|
|
2800 |
)
|
|
2801 |
self.actions_dialog.vbox.pack_start(table_actions, False, False, 0)
|
|
2802 |
# Show dialog:
|
|
2803 |
self.actions_dialog.vbox.show_all()
|
|
2804 |
instructions.set_size_request(self.actions_dialog.size_request()[0] - 50, -1)
|
|
2805 |
close_button = self.actions_dialog.add_button(
|
|
2806 |
gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE
|
|
2807 |
)
|
|
2808 |
close_button.grab_focus()
|
|
2809 |
self.actions_dialog.run()
|
|
2810 |
self.refresh_custom_actions_menu()
|
|
2811 |
while gtk.events_pending():
|
|
2812 |
gtk.main_iteration()
|
|
2813 |
if len(self.image_list) == 0:
|
|
2814 |
self.set_image_sensitivities(False)
|
|
2815 |
self.actions_dialog.destroy()
|
|
2816 |
|
|
2817 |
def add_custom_action(self, button, treeview):
|
|
2818 |
self.open_custom_action_dialog(True, "", "", "None", False, treeview)
|
|
2819 |
|
|
2820 |
def edit_custom_action2(self, treeview, path, view_column):
|
|
2821 |
self.edit_custom_action(None, treeview)
|
|
2822 |
|
|
2823 |
def edit_custom_action(self, button, treeview):
|
|
2824 |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
|
2825 |
if iter != None:
|
|
2826 |
(row,) = self.actionstore.get_path(iter)
|
|
2827 |
self.open_custom_action_dialog(
|
|
2828 |
False,
|
|
2829 |
self.action_names[row],
|
|
2830 |
self.action_commands[row],
|
|
2831 |
self.action_shortcuts[row],
|
|
2832 |
self.action_batch[row],
|
|
2833 |
treeview,
|
|
2834 |
)
|
|
2835 |
|
|
2836 |
def open_custom_action_dialog(
|
|
2837 |
self, add_call, name, command, shortcut, batch, treeview
|
|
2838 |
):
|
|
2839 |
if add_call:
|
|
2840 |
self.dialog_name = gtk.Dialog(
|
|
2841 |
_("Add Custom Action"),
|
|
2842 |
self.actions_dialog,
|
|
2843 |
gtk.DIALOG_MODAL,
|
|
2844 |
(
|
|
2845 |
gtk.STOCK_CANCEL,
|
|
2846 |
gtk.RESPONSE_REJECT,
|
|
2847 |
gtk.STOCK_OK,
|
|
2848 |
gtk.RESPONSE_ACCEPT,
|
|
2849 |
),
|
|
2850 |
)
|
|
2851 |
else:
|
|
2852 |
self.dialog_name = gtk.Dialog(
|
|
2853 |
_("Edit Custom Action"),
|
|
2854 |
self.actions_dialog,
|
|
2855 |
gtk.DIALOG_MODAL,
|
|
2856 |
(
|
|
2857 |
gtk.STOCK_CANCEL,
|
|
2858 |
gtk.RESPONSE_REJECT,
|
|
2859 |
gtk.STOCK_OK,
|
|
2860 |
gtk.RESPONSE_ACCEPT,
|
|
2861 |
),
|
|
2862 |
)
|
|
2863 |
self.dialog_name.set_modal(True)
|
|
2864 |
table = gtk.Table(2, 4, False)
|
|
2865 |
action_name_label = gtk.Label(_("Action Name:"))
|
|
2866 |
action_name_label.set_alignment(0, 0.5)
|
|
2867 |
action_command_label = gtk.Label(_("Command:"))
|
|
2868 |
action_command_label.set_alignment(0, 0.5)
|
|
2869 |
shortcut_label = gtk.Label(_("Shortcut:"))
|
|
2870 |
shortcut_label.set_alignment(0, 0.5)
|
|
2871 |
table.attach(
|
|
2872 |
action_name_label,
|
|
2873 |
0,
|
|
2874 |
1,
|
|
2875 |
0,
|
|
2876 |
1,
|
|
2877 |
gtk.FILL | gtk.EXPAND,
|
|
2878 |
gtk.FILL | gtk.EXPAND,
|
|
2879 |
15,
|
|
2880 |
0,
|
|
2881 |
)
|
|
2882 |
table.attach(
|
|
2883 |
action_command_label,
|
|
2884 |
0,
|
|
2885 |
1,
|
|
2886 |
1,
|
|
2887 |
2,
|
|
2888 |
gtk.FILL | gtk.EXPAND,
|
|
2889 |
gtk.FILL | gtk.EXPAND,
|
|
2890 |
15,
|
|
2891 |
0,
|
|
2892 |
)
|
|
2893 |
table.attach(
|
|
2894 |
shortcut_label,
|
|
2895 |
0,
|
|
2896 |
1,
|
|
2897 |
2,
|
|
2898 |
3,
|
|
2899 |
gtk.FILL | gtk.EXPAND,
|
|
2900 |
gtk.FILL | gtk.EXPAND,
|
|
2901 |
15,
|
|
2902 |
0,
|
|
2903 |
)
|
|
2904 |
action_name = gtk.Entry()
|
|
2905 |
action_name.set_text(name)
|
|
2906 |
action_command = gtk.Entry()
|
|
2907 |
action_command.set_text(command)
|
|
2908 |
table.attach(
|
|
2909 |
action_name, 1, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
2910 |
)
|
|
2911 |
table.attach(
|
|
2912 |
action_command,
|
|
2913 |
1,
|
|
2914 |
2,
|
|
2915 |
1,
|
|
2916 |
2,
|
|
2917 |
gtk.FILL | gtk.EXPAND,
|
|
2918 |
gtk.FILL | gtk.EXPAND,
|
|
2919 |
15,
|
|
2920 |
0,
|
|
2921 |
)
|
|
2922 |
self.shortcut = gtk.Button(shortcut)
|
|
2923 |
self.shortcut.connect("clicked", self.shortcut_clicked)
|
|
2924 |
table.attach(
|
|
2925 |
self.shortcut,
|
|
2926 |
1,
|
|
2927 |
2,
|
|
2928 |
2,
|
|
2929 |
3,
|
|
2930 |
gtk.FILL | gtk.EXPAND,
|
|
2931 |
gtk.FILL | gtk.EXPAND,
|
|
2932 |
15,
|
|
2933 |
0,
|
|
2934 |
)
|
|
2935 |
batchmode = gtk.CheckButton(_("Perform action on all images (Batch)"))
|
|
2936 |
batchmode.set_active(batch)
|
|
2937 |
table.attach(
|
|
2938 |
batchmode, 0, 2, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
2939 |
)
|
|
2940 |
self.dialog_name.vbox.pack_start(table, False, False, 5)
|
|
2941 |
self.dialog_name.vbox.show_all()
|
|
2942 |
self.dialog_name.connect(
|
|
2943 |
"response",
|
|
2944 |
self.dialog_name_response,
|
|
2945 |
add_call,
|
|
2946 |
action_name,
|
|
2947 |
action_command,
|
|
2948 |
self.shortcut,
|
|
2949 |
batchmode,
|
|
2950 |
treeview,
|
|
2951 |
)
|
|
2952 |
self.dialog_name.run()
|
|
2953 |
|
|
2954 |
def dialog_name_response(
|
|
2955 |
self,
|
|
2956 |
dialog,
|
|
2957 |
response,
|
|
2958 |
add_call,
|
|
2959 |
action_name,
|
|
2960 |
action_command,
|
|
2961 |
shortcut,
|
|
2962 |
batchmode,
|
|
2963 |
treeview,
|
|
2964 |
):
|
|
2965 |
if response == gtk.RESPONSE_ACCEPT:
|
|
2966 |
if not (
|
|
2967 |
action_command.get_text() == ""
|
|
2968 |
or action_name.get_text() == ""
|
|
2969 |
or self.shortcut.get_label() == "None"
|
|
2970 |
):
|
|
2971 |
name = action_name.get_text()
|
|
2972 |
command = action_command.get_text()
|
|
2973 |
if (
|
|
2974 |
("[NEXT]" in command.strip()) and command.strip()[-6:] != "[NEXT]"
|
|
2975 |
) or (
|
|
2976 |
("[PREV]" in command.strip()) and command.strip()[-6:] != "[PREV]"
|
|
2977 |
):
|
|
2978 |
error_dialog = gtk.MessageDialog(
|
|
2979 |
self.actions_dialog,
|
|
2980 |
gtk.DIALOG_MODAL,
|
|
2981 |
gtk.MESSAGE_WARNING,
|
|
2982 |
gtk.BUTTONS_CLOSE,
|
|
2983 |
_(
|
|
2984 |
"[PREV] and [NEXT] are only valid alone or at the end of the command"
|
|
2985 |
),
|
|
2986 |
)
|
|
2987 |
error_dialog.set_title(_("Invalid Custom Action"))
|
|
2988 |
error_dialog.run()
|
|
2989 |
error_dialog.destroy()
|
|
2990 |
return
|
|
2991 |
shortcut = shortcut.get_label()
|
|
2992 |
batch = batchmode.get_active()
|
|
2993 |
dialog.destroy()
|
|
2994 |
if add_call:
|
|
2995 |
self.action_names.append(name)
|
|
2996 |
self.action_commands.append(command)
|
|
2997 |
self.action_shortcuts.append(shortcut)
|
|
2998 |
self.action_batch.append(batch)
|
|
2999 |
else:
|
|
3000 |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
|
3001 |
(rownum,) = self.actionstore.get_path(iter)
|
|
3002 |
self.action_names[rownum] = name
|
|
3003 |
self.action_commands[rownum] = command
|
|
3004 |
self.action_shortcuts[rownum] = shortcut
|
|
3005 |
self.action_batch[rownum] = batch
|
|
3006 |
self.populate_treeview()
|
|
3007 |
if add_call:
|
|
3008 |
rownum = len(self.action_names) - 1
|
|
3009 |
treeview.get_selection().select_path(rownum)
|
|
3010 |
while gtk.events_pending():
|
|
3011 |
gtk.main_iteration()
|
|
3012 |
# Keep item in visible rect:
|
|
3013 |
visible_rect = treeview.get_visible_rect()
|
|
3014 |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
|
3015 |
if row_rect.y + row_rect.height > visible_rect.height:
|
|
3016 |
top_coord = (
|
|
3017 |
row_rect.y + row_rect.height - visible_rect.height
|
|
3018 |
) + visible_rect.y
|
|
3019 |
treeview.scroll_to_point(-1, top_coord)
|
|
3020 |
elif row_rect.y < 0:
|
|
3021 |
treeview.scroll_to_cell(rownum)
|
|
3022 |
else:
|
|
3023 |
error_dialog = gtk.MessageDialog(
|
|
3024 |
self.actions_dialog,
|
|
3025 |
gtk.DIALOG_MODAL,
|
|
3026 |
gtk.MESSAGE_WARNING,
|
|
3027 |
gtk.BUTTONS_CLOSE,
|
|
3028 |
_("Incomplete custom action specified."),
|
|
3029 |
)
|
|
3030 |
error_dialog.set_title(_("Invalid Custom Action"))
|
|
3031 |
error_dialog.run()
|
|
3032 |
error_dialog.destroy()
|
|
3033 |
else:
|
|
3034 |
dialog.destroy()
|
|
3035 |
|
|
3036 |
def custom_action_move_down(self, button, treeview):
|
|
3037 |
iter = None
|
|
3038 |
selection = treeview.get_selection()
|
|
3039 |
model, iter = selection.get_selected()
|
|
3040 |
if iter:
|
|
3041 |
rownum = int(model.get_string_from_iter(iter))
|
|
3042 |
if rownum < len(self.action_names) - 1:
|
|
3043 |
# Move item down:
|
|
3044 |
temp_name = self.action_names[rownum]
|
|
3045 |
temp_shortcut = self.action_shortcuts[rownum]
|
|
3046 |
temp_command = self.action_commands[rownum]
|
|
3047 |
temp_batch = self.action_batch[rownum]
|
|
3048 |
self.action_names[rownum] = self.action_names[rownum + 1]
|
|
3049 |
self.action_shortcuts[rownum] = self.action_shortcuts[rownum + 1]
|
|
3050 |
self.action_commands[rownum] = self.action_commands[rownum + 1]
|
|
3051 |
self.action_batch[rownum] = self.action_batch[rownum + 1]
|
|
3052 |
self.action_names[rownum + 1] = temp_name
|
|
3053 |
self.action_shortcuts[rownum + 1] = temp_shortcut
|
|
3054 |
self.action_commands[rownum + 1] = temp_command
|
|
3055 |
self.action_batch[rownum + 1] = temp_batch
|
|
3056 |
# Repopulate treeview and keep item selected:
|
|
3057 |
self.populate_treeview()
|
|
3058 |
selection.select_path((rownum + 1,))
|
|
3059 |
while gtk.events_pending():
|
|
3060 |
gtk.main_iteration()
|
|
3061 |
# Keep item in visible rect:
|
|
3062 |
rownum = rownum + 1
|
|
3063 |
visible_rect = treeview.get_visible_rect()
|
|
3064 |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
|
3065 |
if row_rect.y + row_rect.height > visible_rect.height:
|
|
3066 |
top_coord = (
|
|
3067 |
row_rect.y + row_rect.height - visible_rect.height
|
|
3068 |
) + visible_rect.y
|
|
3069 |
treeview.scroll_to_point(-1, top_coord)
|
|
3070 |
elif row_rect.y < 0:
|
|
3071 |
treeview.scroll_to_cell(rownum)
|
|
3072 |
|
|
3073 |
def custom_action_move_up(self, button, treeview):
|
|
3074 |
iter = None
|
|
3075 |
selection = treeview.get_selection()
|
|
3076 |
model, iter = selection.get_selected()
|
|
3077 |
if iter:
|
|
3078 |
rownum = int(model.get_string_from_iter(iter))
|
|
3079 |
if rownum > 0:
|
|
3080 |
# Move item down:
|
|
3081 |
temp_name = self.action_names[rownum]
|
|
3082 |
temp_shortcut = self.action_shortcuts[rownum]
|
|
3083 |
temp_command = self.action_commands[rownum]
|
|
3084 |
temp_batch = self.action_batch[rownum]
|
|
3085 |
self.action_names[rownum] = self.action_names[rownum - 1]
|
|
3086 |
self.action_shortcuts[rownum] = self.action_shortcuts[rownum - 1]
|
|
3087 |
self.action_commands[rownum] = self.action_commands[rownum - 1]
|
|
3088 |
self.action_batch[rownum] = self.action_batch[rownum - 1]
|
|
3089 |
self.action_names[rownum - 1] = temp_name
|
|
3090 |
self.action_shortcuts[rownum - 1] = temp_shortcut
|
|
3091 |
self.action_commands[rownum - 1] = temp_command
|
|
3092 |
self.action_batch[rownum - 1] = temp_batch
|
|
3093 |
# Repopulate treeview and keep item selected:
|
|
3094 |
self.populate_treeview()
|
|
3095 |
selection.select_path((rownum - 1,))
|
|
3096 |
while gtk.events_pending():
|
|
3097 |
gtk.main_iteration()
|
|
3098 |
# Keep item in visible rect:
|
|
3099 |
rownum = rownum - 1
|
|
3100 |
visible_rect = treeview.get_visible_rect()
|
|
3101 |
row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
|
|
3102 |
if row_rect.y + row_rect.height > visible_rect.height:
|
|
3103 |
top_coord = (
|
|
3104 |
row_rect.y + row_rect.height - visible_rect.height
|
|
3105 |
) + visible_rect.y
|
|
3106 |
treeview.scroll_to_point(-1, top_coord)
|
|
3107 |
elif row_rect.y < 0:
|
|
3108 |
treeview.scroll_to_cell(rownum)
|
|
3109 |
|
|
3110 |
def shortcut_clicked(self, widget):
|
|
3111 |
self.dialog_shortcut = gtk.Dialog(
|
|
3112 |
_("Action Shortcut"),
|
|
3113 |
self.dialog_name,
|
|
3114 |
gtk.DIALOG_MODAL,
|
|
3115 |
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT),
|
|
3116 |
)
|
|
3117 |
self.shortcut_label = gtk.Label(_("Press the desired shortcut for the action."))
|
|
3118 |
hbox = gtk.HBox()
|
|
3119 |
hbox.pack_start(self.shortcut_label, False, False, 15)
|
|
3120 |
self.dialog_shortcut.vbox.pack_start(hbox, False, False, 5)
|
|
3121 |
self.dialog_shortcut.vbox.show_all()
|
|
3122 |
self.dialog_shortcut.connect("key-press-event", self.shortcut_keypress)
|
|
3123 |
self.dialog_shortcut.run()
|
|
3124 |
self.dialog_shortcut.destroy()
|
|
3125 |
|
|
3126 |
def shortcut_keypress(self, widget, event):
|
|
3127 |
shortcut = gtk.accelerator_name(event.keyval, event.state)
|
|
3128 |
if "<Mod2>" in shortcut:
|
|
3129 |
shortcut = shortcut.replace("<Mod2>", "")
|
|
3130 |
if (
|
|
3131 |
shortcut[(len(shortcut) - 2) : len(shortcut)] != "_L"
|
|
3132 |
and shortcut[(len(shortcut) - 2) : len(shortcut)] != "_R"
|
|
3133 |
):
|
|
3134 |
# Validate to make sure the shortcut hasn't already been used:
|
|
3135 |
for i in range(len(self.keys)):
|
|
3136 |
if shortcut == self.keys[i][1]:
|
|
3137 |
error_dialog = gtk.MessageDialog(
|
|
3138 |
self.dialog_shortcut,
|
|
3139 |
gtk.DIALOG_MODAL,
|
|
3140 |
gtk.MESSAGE_WARNING,
|
|
3141 |
gtk.BUTTONS_CLOSE,
|
|
3142 |
_("The shortcut '%(shortcut)s' is already used for '%(key)s'.")
|
|
3143 |
% {"shortcut": shortcut, "key": self.keys[i][0]},
|
|
3144 |
)
|
|
3145 |
error_dialog.set_title(_("Invalid Shortcut"))
|
|
3146 |
error_dialog.run()
|
|
3147 |
error_dialog.destroy()
|
|
3148 |
return
|
|
3149 |
for i in range(len(self.action_shortcuts)):
|
|
3150 |
if shortcut == self.action_shortcuts[i]:
|
|
3151 |
error_dialog = gtk.MessageDialog(
|
|
3152 |
self.dialog_shortcut,
|
|
3153 |
gtk.DIALOG_MODAL,
|
|
3154 |
gtk.MESSAGE_WARNING,
|
|
3155 |
gtk.BUTTONS_CLOSE,
|
|
3156 |
_("The shortcut '%(shortcut)s' is already used for '%(key)s'.")
|
|
3157 |
% {"shortcut": shortcut, "key": self.action_names[i]},
|
|
3158 |
)
|
|
3159 |
error_dialog.set_title(_("Invalid Shortcut"))
|
|
3160 |
error_dialog.run()
|
|
3161 |
error_dialog.destroy()
|
|
3162 |
return
|
|
3163 |
self.shortcut.set_label(shortcut)
|
|
3164 |
widget.destroy()
|
|
3165 |
|
|
3166 |
def remove_custom_action(self, button):
|
|
3167 |
(model, iter) = self.actionwidget.get_selection().get_selected()
|
|
3168 |
if iter != None:
|
|
3169 |
(row,) = self.actionstore.get_path(iter)
|
|
3170 |
self.action_names.pop(row)
|
|
3171 |
self.action_shortcuts.pop(row)
|
|
3172 |
self.action_commands.pop(row)
|
|
3173 |
self.action_batch.pop(row)
|
|
3174 |
self.populate_treeview()
|
|
3175 |
self.actionwidget.grab_focus()
|
|
3176 |
|
|
3177 |
def populate_treeview(self):
|
|
3178 |
self.actionstore.clear()
|
|
3179 |
for i in range(len(self.action_names)):
|
|
3180 |
if self.action_batch[i]:
|
|
3181 |
pb = gtk.STOCK_APPLY
|
|
3182 |
else:
|
|
3183 |
pb = None
|
|
3184 |
self.actionstore.append(
|
|
3185 |
[
|
|
3186 |
pb,
|
|
3187 |
"<big><b>"
|
|
3188 |
+ self.action_names[i].replace("&", "&")
|
|
3189 |
+ "</b></big>\n<small>"
|
|
3190 |
+ self.action_commands[i].replace("&", "&")
|
|
3191 |
+ "</small>",
|
|
3192 |
self.action_shortcuts[i],
|
|
3193 |
]
|
|
3194 |
)
|
|
3195 |
self.tvcolumn0.clear()
|
|
3196 |
self.tvcolumn1.clear()
|
|
3197 |
self.tvcolumn2.clear()
|
|
3198 |
self.tvcolumn0.pack_start(self.cellbool)
|
|
3199 |
self.tvcolumn1.pack_start(self.cell)
|
|
3200 |
self.tvcolumn2.pack_start(self.cell)
|
|
3201 |
self.tvcolumn0.add_attribute(self.cellbool, "stock-id", 0)
|
|
3202 |
self.tvcolumn1.set_attributes(self.cell, markup=1)
|
|
3203 |
self.tvcolumn2.set_attributes(self.cell, text=2)
|
|
3204 |
self.tvcolumn1.set_expand(True)
|
|
3205 |
|
|
3206 |
def screenshot(self, action):
|
|
3207 |
cancel = self.autosave_image()
|
|
3208 |
if cancel:
|
|
3209 |
return
|
|
3210 |
# Dialog:
|
|
3211 |
dialog = gtk.Dialog(
|
|
3212 |
_("Screenshot"),
|
|
3213 |
self.window,
|
|
3214 |
gtk.DIALOG_MODAL,
|
|
3215 |
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT),
|
|
3216 |
)
|
|
3217 |
snapbutton = dialog.add_button(_("_Snap"), gtk.RESPONSE_ACCEPT)
|
|
3218 |
snapimage = gtk.Image()
|
|
3219 |
snapimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
|
3220 |
snapbutton.set_image(snapimage)
|
|
3221 |
loc = gtk.Label()
|
|
3222 |
loc.set_markup("<b>" + _("Location") + "</b>")
|
|
3223 |
loc.set_alignment(0, 0)
|
|
3224 |
area = gtk.RadioButton()
|
|
3225 |
area1 = gtk.RadioButton(group=area, label=_("Entire screen"))
|
|
3226 |
area2 = gtk.RadioButton(group=area, label=_("Window under pointer"))
|
|
3227 |
if not HAS_XMOUSE:
|
|
3228 |
area2.set_sensitive(False)
|
|
3229 |
area1.set_active(True)
|
|
3230 |
de = gtk.Label()
|
|
3231 |
de.set_markup("<b>" + _("Delay") + "</b>")
|
|
3232 |
de.set_alignment(0, 0)
|
|
3233 |
delaybox = gtk.HBox()
|
|
3234 |
adj = gtk.Adjustment(self.screenshot_delay, 0, 30, 1, 10, 0)
|
|
3235 |
delay = gtk.SpinButton(adj, 0, 0)
|
|
3236 |
delay.set_numeric(True)
|
|
3237 |
delay.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
3238 |
delay.set_wrap(False)
|
|
3239 |
delaylabel = gtk.Label(_(" seconds"))
|
|
3240 |
delaybox.pack_start(delay, False)
|
|
3241 |
delaybox.pack_start(delaylabel, False)
|
|
3242 |
table = gtk.Table()
|
|
3243 |
table.attach(
|
|
3244 |
gtk.Label(), 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3245 |
)
|
|
3246 |
table.attach(
|
|
3247 |
loc, 1, 2, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3248 |
)
|
|
3249 |
table.attach(
|
|
3250 |
gtk.Label(), 1, 2, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3251 |
)
|
|
3252 |
table.attach(
|
|
3253 |
area1, 1, 2, 4, 5, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3254 |
)
|
|
3255 |
table.attach(
|
|
3256 |
area2, 1, 2, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3257 |
)
|
|
3258 |
table.attach(
|
|
3259 |
gtk.Label(), 1, 2, 6, 7, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3260 |
)
|
|
3261 |
table.attach(
|
|
3262 |
de, 1, 2, 7, 8, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3263 |
)
|
|
3264 |
table.attach(
|
|
3265 |
gtk.Label(), 1, 2, 8, 9, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3266 |
)
|
|
3267 |
table.attach(
|
|
3268 |
delaybox, 1, 2, 9, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3269 |
)
|
|
3270 |
table.attach(
|
|
3271 |
gtk.Label(),
|
|
3272 |
1,
|
|
3273 |
2,
|
|
3274 |
10,
|
|
3275 |
11,
|
|
3276 |
gtk.FILL | gtk.EXPAND,
|
|
3277 |
gtk.FILL | gtk.EXPAND,
|
|
3278 |
30,
|
|
3279 |
0,
|
|
3280 |
)
|
|
3281 |
dialog.vbox.pack_start(table)
|
|
3282 |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
|
3283 |
dialog.vbox.show_all()
|
|
3284 |
response = dialog.run()
|
|
3285 |
if response == gtk.RESPONSE_ACCEPT:
|
|
3286 |
dialog.destroy()
|
|
3287 |
while gtk.events_pending():
|
|
3288 |
gtk.main_iteration()
|
|
3289 |
self.screenshot_delay = delay.get_value_as_int()
|
|
3290 |
gobject.timeout_add(
|
|
3291 |
int(self.screenshot_delay * 1000),
|
|
3292 |
self._screenshot_grab,
|
|
3293 |
area1.get_active(),
|
|
3294 |
)
|
|
3295 |
else:
|
|
3296 |
dialog.destroy()
|
|
3297 |
|
|
3298 |
def _screenshot_grab(self, entire_screen):
|
|
3299 |
root_win = gtk.gdk.get_default_root_window()
|
|
3300 |
if entire_screen:
|
|
3301 |
x = 0
|
|
3302 |
y = 0
|
|
3303 |
width = gtk.gdk.screen_width()
|
|
3304 |
height = gtk.gdk.screen_height()
|
|
3305 |
else:
|
|
3306 |
(x, y, width, height) = xmouse.geometry()
|
|
3307 |
pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height)
|
|
3308 |
pix = pix.get_from_drawable(
|
|
3309 |
root_win, gtk.gdk.colormap_get_system(), x, y, 0, 0, width, height
|
|
3310 |
)
|
|
3311 |
# Save as /tmp/mirage-<random>/filename.ext
|
|
3312 |
tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
|
|
3313 |
tmpfile = tmpdir + "screenshot.png"
|
|
3314 |
pix.save(tmpfile, "png")
|
|
3315 |
# Load file:
|
|
3316 |
self.image_list = [tmpfile]
|
|
3317 |
self.curr_img_in_list = 0
|
|
3318 |
gobject.idle_add(self.load_new_image2, False, False, False, False, True)
|
|
3319 |
self.update_statusbar()
|
|
3320 |
self.set_go_navigation_sensitivities(False)
|
|
3321 |
self.set_slideshow_sensitivities()
|
|
3322 |
self.thumbpane_update_images(True, self.curr_img_in_list)
|
|
3323 |
del pix
|
|
3324 |
self.window.present()
|
|
3325 |
|
|
3326 |
def show_properties(self, action):
|
|
3327 |
show_props = gtk.Dialog(_("Properties"), self.window)
|
|
3328 |
show_props.set_has_separator(False)
|
|
3329 |
show_props.set_resizable(False)
|
|
3330 |
table = gtk.Table(3, 3, False)
|
|
3331 |
image = gtk.Image()
|
|
3332 |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
|
3333 |
image_is_anim = False
|
|
3334 |
if animtest.is_static_image():
|
|
3335 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
3336 |
self.currimg_pixbuf_original, 180, self.zoom_quality
|
|
3337 |
)
|
|
3338 |
else:
|
|
3339 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
3340 |
animtest.get_static_image(), 180, self.zoom_quality
|
|
3341 |
)
|
|
3342 |
image_is_anim = True
|
|
3343 |
image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
|
|
3344 |
vbox_left = gtk.VBox()
|
|
3345 |
filename = gtk.Label(_("File name:"))
|
|
3346 |
filename.set_alignment(1, 1)
|
|
3347 |
filedate = gtk.Label(_("File modified:"))
|
|
3348 |
filedate.set_alignment(1, 1)
|
|
3349 |
imagesize = gtk.Label(_("Dimensions:"))
|
|
3350 |
imagesize.set_alignment(1, 1)
|
|
3351 |
filesize = gtk.Label(_("File size:"))
|
|
3352 |
filesize.set_alignment(1, 1)
|
|
3353 |
filetype = gtk.Label(_("File type:"))
|
|
3354 |
filetype.set_alignment(1, 1)
|
|
3355 |
transparency = gtk.Label(_("Transparency:"))
|
|
3356 |
transparency.set_alignment(1, 1)
|
|
3357 |
animation = gtk.Label(_("Animation:"))
|
|
3358 |
animation.set_alignment(1, 1)
|
|
3359 |
bits = gtk.Label(_("Bits per sample:"))
|
|
3360 |
bits.set_alignment(1, 1)
|
|
3361 |
channels = gtk.Label(_("Channels:"))
|
|
3362 |
channels.set_alignment(1, 1)
|
|
3363 |
vbox_left.pack_start(filename, False, False, 2)
|
|
3364 |
vbox_left.pack_start(filedate, False, False, 2)
|
|
3365 |
vbox_left.pack_start(imagesize, False, False, 2)
|
|
3366 |
vbox_left.pack_start(filesize, False, False, 2)
|
|
3367 |
vbox_left.pack_start(filetype, False, False, 2)
|
|
3368 |
vbox_left.pack_start(transparency, False, False, 2)
|
|
3369 |
vbox_left.pack_start(animation, False, False, 2)
|
|
3370 |
vbox_left.pack_start(bits, False, False, 2)
|
|
3371 |
vbox_left.pack_start(channels, False, False, 2)
|
|
3372 |
vbox_right = gtk.VBox()
|
|
3373 |
filestat = os.stat(self.currimg_name)
|
|
3374 |
filename2 = gtk.Label(os.path.basename(self.currimg_name))
|
|
3375 |
filedate2 = gtk.Label(
|
|
3376 |
time.strftime("%c", time.localtime(filestat[stat.ST_MTIME]))
|
|
3377 |
)
|
|
3378 |
imagesize2 = gtk.Label(
|
|
3379 |
str(self.currimg_pixbuf_original.get_width())
|
|
3380 |
+ "x"
|
|
3381 |
+ str(self.currimg_pixbuf_original.get_height())
|
|
3382 |
)
|
|
3383 |
filetype2 = gtk.Label(
|
|
3384 |
gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]["mime_types"][0]
|
|
3385 |
)
|
|
3386 |
filesize2 = gtk.Label(str(filestat[stat.ST_SIZE] // 1000) + "KB")
|
|
3387 |
if not image_is_anim and pixbuf.get_has_alpha():
|
|
3388 |
transparency2 = gtk.Label(_("Yes"))
|
|
3389 |
else:
|
|
3390 |
transparency2 = gtk.Label(_("No"))
|
|
3391 |
if animtest.is_static_image():
|
|
3392 |
animation2 = gtk.Label(_("No"))
|
|
3393 |
else:
|
|
3394 |
animation2 = gtk.Label(_("Yes"))
|
|
3395 |
bits2 = gtk.Label(str(pixbuf.get_bits_per_sample()))
|
|
3396 |
channels2 = gtk.Label(str(pixbuf.get_n_channels()))
|
|
3397 |
filename2.set_alignment(0, 1)
|
|
3398 |
filedate2.set_alignment(0, 1)
|
|
3399 |
imagesize2.set_alignment(0, 1)
|
|
3400 |
filesize2.set_alignment(0, 1)
|
|
3401 |
filetype2.set_alignment(0, 1)
|
|
3402 |
transparency2.set_alignment(0, 1)
|
|
3403 |
animation2.set_alignment(0, 1)
|
|
3404 |
bits2.set_alignment(0, 1)
|
|
3405 |
channels2.set_alignment(0, 1)
|
|
3406 |
vbox_right.pack_start(filename2, False, False, 2)
|
|
3407 |
vbox_right.pack_start(filedate2, False, False, 2)
|
|
3408 |
vbox_right.pack_start(imagesize2, False, False, 2)
|
|
3409 |
vbox_right.pack_start(filesize2, False, False, 2)
|
|
3410 |
vbox_right.pack_start(filetype2, False, False, 2)
|
|
3411 |
vbox_right.pack_start(transparency2, False, False, 2)
|
|
3412 |
vbox_right.pack_start(animation2, False, False, 2)
|
|
3413 |
vbox_right.pack_start(bits2, False, False, 2)
|
|
3414 |
vbox_right.pack_start(channels2, False, False, 2)
|
|
3415 |
hbox = gtk.HBox()
|
|
3416 |
hbox.pack_start(vbox_left, False, False, 3)
|
|
3417 |
hbox.pack_start(vbox_right, False, False, 3)
|
|
3418 |
table.attach(
|
|
3419 |
image, 1, 2, 1, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3420 |
)
|
|
3421 |
table.attach(
|
|
3422 |
hbox, 2, 3, 1, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3423 |
)
|
|
3424 |
show_props.vbox.pack_start(table, False, False, 15)
|
|
3425 |
show_props.vbox.show_all()
|
|
3426 |
close_button = show_props.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
|
3427 |
close_button.grab_focus()
|
|
3428 |
show_props.run()
|
|
3429 |
show_props.destroy()
|
|
3430 |
|
|
3431 |
def show_prefs(self, action):
|
|
3432 |
prev_thumbnail_size = self.thumbnail_size
|
|
3433 |
self.prefs_dialog = gtk.Dialog(_("Mirage Preferences"), self.window)
|
|
3434 |
self.prefs_dialog.set_has_separator(False)
|
|
3435 |
self.prefs_dialog.set_resizable(False)
|
|
3436 |
# "Interface" prefs:
|
|
3437 |
table_settings = gtk.Table(14, 3, False)
|
|
3438 |
bglabel = gtk.Label()
|
|
3439 |
bglabel.set_markup("<b>" + _("Interface") + "</b>")
|
|
3440 |
bglabel.set_alignment(0, 1)
|
|
3441 |
color_hbox = gtk.HBox(False, 0)
|
|
3442 |
colortext = gtk.Label(_("Background color:"))
|
|
3443 |
self.colorbutton = gtk.ColorButton(self.bgcolor)
|
|
3444 |
self.colorbutton.connect("color-set", self.bgcolor_selected)
|
|
3445 |
self.colorbutton.set_size_request(150, -1)
|
|
3446 |
self.colorbutton.set_tooltip_text(
|
|
3447 |
_("Sets the background color for the application.")
|
|
3448 |
)
|
|
3449 |
color_hbox.pack_start(colortext, False, False, 0)
|
|
3450 |
color_hbox.pack_start(self.colorbutton, False, False, 0)
|
|
3451 |
color_hbox.pack_start(gtk.Label(), True, True, 0)
|
|
3452 |
|
|
3453 |
simplecolor_hbox = gtk.HBox(False, 0)
|
|
3454 |
simplecolortext = gtk.Label(_("Simple background color:"))
|
|
3455 |
simplecolorbutton = gtk.CheckButton()
|
|
3456 |
simplecolorbutton.connect("toggled", self.simple_bgcolor_selected)
|
|
3457 |
simplecolor_hbox.pack_start(simplecolortext, False, False, 0)
|
|
3458 |
simplecolor_hbox.pack_start(simplecolorbutton, False, False, 0)
|
|
3459 |
simplecolor_hbox.pack_start(gtk.Label(), True, True, 0)
|
|
3460 |
if self.simple_bgcolor:
|
|
3461 |
simplecolorbutton.set_active(True)
|
|
3462 |
|
|
3463 |
fullscreen = gtk.CheckButton(_("Open Mirage in fullscreen mode"))
|
|
3464 |
fullscreen.set_active(self.start_in_fullscreen)
|
|
3465 |
thumbbox = gtk.HBox()
|
|
3466 |
thumblabel = gtk.Label(_("Thumbnail size:"))
|
|
3467 |
thumbbox.pack_start(thumblabel, False, False, 0)
|
|
3468 |
thumbsize = gtk.combo_box_new_text()
|
|
3469 |
option = 0
|
|
3470 |
for size in self.thumbnail_sizes:
|
|
3471 |
thumbsize.append_text(size + " x " + size)
|
|
3472 |
if self.thumbnail_size == int(size):
|
|
3473 |
thumbsize.set_active(option)
|
|
3474 |
option += 1
|
|
3475 |
thumbbox.pack_start(thumbsize, False, False, 5)
|
|
3476 |
table_settings.attach(
|
|
3477 |
gtk.Label(), 1, 3, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3478 |
)
|
|
3479 |
table_settings.attach(
|
|
3480 |
bglabel, 1, 3, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3481 |
)
|
|
3482 |
table_settings.attach(
|
|
3483 |
gtk.Label(), 1, 3, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3484 |
)
|
|
3485 |
table_settings.attach(
|
|
3486 |
simplecolor_hbox,
|
|
3487 |
1,
|
|
3488 |
2,
|
|
3489 |
4,
|
|
3490 |
5,
|
|
3491 |
gtk.FILL | gtk.EXPAND,
|
|
3492 |
gtk.FILL | gtk.EXPAND,
|
|
3493 |
30,
|
|
3494 |
0,
|
|
3495 |
)
|
|
3496 |
table_settings.attach(
|
|
3497 |
color_hbox, 1, 2, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3498 |
)
|
|
3499 |
table_settings.attach(
|
|
3500 |
gtk.Label(), 1, 3, 6, 7, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3501 |
)
|
|
3502 |
table_settings.attach(
|
|
3503 |
thumbbox, 1, 3, 7, 8, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3504 |
)
|
|
3505 |
table_settings.attach(
|
|
3506 |
gtk.Label(), 1, 3, 8, 9, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3507 |
)
|
|
3508 |
table_settings.attach(
|
|
3509 |
fullscreen, 1, 3, 9, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3510 |
)
|
|
3511 |
table_settings.attach(
|
|
3512 |
gtk.Label(),
|
|
3513 |
1,
|
|
3514 |
3,
|
|
3515 |
10,
|
|
3516 |
11,
|
|
3517 |
gtk.FILL | gtk.EXPAND,
|
|
3518 |
gtk.FILL | gtk.EXPAND,
|
|
3519 |
30,
|
|
3520 |
0,
|
|
3521 |
)
|
|
3522 |
table_settings.attach(
|
|
3523 |
gtk.Label(),
|
|
3524 |
1,
|
|
3525 |
3,
|
|
3526 |
11,
|
|
3527 |
12,
|
|
3528 |
gtk.FILL | gtk.EXPAND,
|
|
3529 |
gtk.FILL | gtk.EXPAND,
|
|
3530 |
30,
|
|
3531 |
0,
|
|
3532 |
)
|
|
3533 |
table_settings.attach(
|
|
3534 |
gtk.Label(),
|
|
3535 |
1,
|
|
3536 |
3,
|
|
3537 |
12,
|
|
3538 |
13,
|
|
3539 |
gtk.FILL | gtk.EXPAND,
|
|
3540 |
gtk.FILL | gtk.EXPAND,
|
|
3541 |
30,
|
|
3542 |
0,
|
|
3543 |
)
|
|
3544 |
table_settings.attach(
|
|
3545 |
gtk.Label(),
|
|
3546 |
1,
|
|
3547 |
3,
|
|
3548 |
13,
|
|
3549 |
14,
|
|
3550 |
gtk.FILL | gtk.EXPAND,
|
|
3551 |
gtk.FILL | gtk.EXPAND,
|
|
3552 |
30,
|
|
3553 |
0,
|
|
3554 |
)
|
|
3555 |
table_settings.attach(
|
|
3556 |
gtk.Label(),
|
|
3557 |
1,
|
|
3558 |
3,
|
|
3559 |
14,
|
|
3560 |
15,
|
|
3561 |
gtk.FILL | gtk.EXPAND,
|
|
3562 |
gtk.FILL | gtk.EXPAND,
|
|
3563 |
30,
|
|
3564 |
0,
|
|
3565 |
)
|
|
3566 |
# "Behavior" tab:
|
|
3567 |
table_behavior = gtk.Table(14, 2, False)
|
|
3568 |
openlabel = gtk.Label()
|
|
3569 |
openlabel.set_markup("<b>" + _("Open Behavior") + "</b>")
|
|
3570 |
openlabel.set_alignment(0, 1)
|
|
3571 |
hbox_openmode = gtk.HBox()
|
|
3572 |
hbox_openmode.pack_start(gtk.Label(_("Open new image in:")), False, False, 0)
|
|
3573 |
combobox = gtk.combo_box_new_text()
|
|
3574 |
combobox.append_text(_("Smart Mode"))
|
|
3575 |
combobox.append_text(_("Zoom To Fit Mode"))
|
|
3576 |
combobox.append_text(_("1:1 Mode"))
|
|
3577 |
combobox.append_text(_("Last Active Mode"))
|
|
3578 |
combobox.set_active(self.open_mode)
|
|
3579 |
hbox_openmode.pack_start(combobox, False, False, 5)
|
|
3580 |
openallimages = gtk.CheckButton(_("Load all images in current directory"))
|
|
3581 |
openallimages.set_active(self.open_all_images)
|
|
3582 |
openallimages.set_tooltip_text(
|
|
3583 |
_(
|
|
3584 |
"If enabled, opening an image in Mirage will automatically load all images found in that image's directory."
|
|
3585 |
)
|
|
3586 |
)
|
|
3587 |
hiddenimages = gtk.CheckButton(_("Allow loading hidden files"))
|
|
3588 |
hiddenimages.set_active(self.open_hidden_files)
|
|
3589 |
hiddenimages.set_tooltip_text(
|
|
3590 |
_(
|
|
3591 |
"If checked, Mirage will open hidden files. Otherwise, hidden files will be ignored."
|
|
3592 |
)
|
|
3593 |
)
|
|
3594 |
openpref = gtk.RadioButton()
|
|
3595 |
openpref1 = gtk.RadioButton(
|
|
3596 |
group=openpref, label=_("Use last chosen directory")
|
|
3597 |
)
|
|
3598 |
openpref1.set_tooltip_text(
|
|
3599 |
_("The default 'Open' directory will be the last directory used.")
|
|
3600 |
)
|
|
3601 |
openpref2 = gtk.RadioButton(
|
|
3602 |
group=openpref, label=_("Use this fixed directory:")
|
|
3603 |
)
|
|
3604 |
openpref2.connect("toggled", self.prefs_use_fixed_dir_clicked)
|
|
3605 |
openpref2.set_tooltip_text(
|
|
3606 |
_("The default 'Open' directory will be this specified directory.")
|
|
3607 |
)
|
|
3608 |
hbox_defaultdir = gtk.HBox()
|
|
3609 |
self.defaultdir = gtk.Button()
|
|
3610 |
hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
|
|
3611 |
hbox_defaultdir.pack_start(self.defaultdir, False, False, 0)
|
|
3612 |
hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
|
|
3613 |
if len(self.fixed_dir) > 25:
|
|
3614 |
self.defaultdir.set_label("..." + self.fixed_dir[-22:])
|
|
3615 |
else:
|
|
3616 |
self.defaultdir.set_label(self.fixed_dir)
|
|
3617 |
self.defaultdir.connect("clicked", self.defaultdir_clicked)
|
|
3618 |
self.defaultdir.set_size_request(250, -1)
|
|
3619 |
if self.use_last_dir:
|
|
3620 |
openpref1.set_active(True)
|
|
3621 |
self.defaultdir.set_sensitive(False)
|
|
3622 |
else:
|
|
3623 |
openpref2.set_active(True)
|
|
3624 |
self.defaultdir.set_sensitive(True)
|
|
3625 |
table_behavior.attach(
|
|
3626 |
gtk.Label(), 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3627 |
)
|
|
3628 |
table_behavior.attach(
|
|
3629 |
openlabel, 1, 2, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3630 |
)
|
|
3631 |
table_behavior.attach(
|
|
3632 |
gtk.Label(), 1, 2, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3633 |
)
|
|
3634 |
table_behavior.attach(
|
|
3635 |
hbox_openmode,
|
|
3636 |
1,
|
|
3637 |
2,
|
|
3638 |
4,
|
|
3639 |
5,
|
|
3640 |
gtk.FILL | gtk.EXPAND,
|
|
3641 |
gtk.FILL | gtk.EXPAND,
|
|
3642 |
30,
|
|
3643 |
0,
|
|
3644 |
)
|
|
3645 |
table_behavior.attach(
|
|
3646 |
gtk.Label(), 1, 2, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3647 |
)
|
|
3648 |
table_behavior.attach(
|
|
3649 |
openallimages,
|
|
3650 |
1,
|
|
3651 |
2,
|
|
3652 |
6,
|
|
3653 |
7,
|
|
3654 |
gtk.FILL | gtk.EXPAND,
|
|
3655 |
gtk.FILL | gtk.EXPAND,
|
|
3656 |
30,
|
|
3657 |
0,
|
|
3658 |
)
|
|
3659 |
table_behavior.attach(
|
|
3660 |
hiddenimages,
|
|
3661 |
1,
|
|
3662 |
2,
|
|
3663 |
7,
|
|
3664 |
8,
|
|
3665 |
gtk.FILL | gtk.EXPAND,
|
|
3666 |
gtk.FILL | gtk.EXPAND,
|
|
3667 |
30,
|
|
3668 |
0,
|
|
3669 |
)
|
|
3670 |
table_behavior.attach(
|
|
3671 |
gtk.Label(), 1, 2, 8, 9, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3672 |
)
|
|
3673 |
table_behavior.attach(
|
|
3674 |
openpref1, 1, 2, 9, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3675 |
)
|
|
3676 |
table_behavior.attach(
|
|
3677 |
openpref2, 1, 2, 10, 11, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3678 |
)
|
|
3679 |
table_behavior.attach(
|
|
3680 |
hbox_defaultdir,
|
|
3681 |
1,
|
|
3682 |
2,
|
|
3683 |
11,
|
|
3684 |
12,
|
|
3685 |
gtk.FILL | gtk.EXPAND,
|
|
3686 |
gtk.FILL | gtk.EXPAND,
|
|
3687 |
45,
|
|
3688 |
0,
|
|
3689 |
)
|
|
3690 |
table_behavior.attach(
|
|
3691 |
gtk.Label(),
|
|
3692 |
1,
|
|
3693 |
2,
|
|
3694 |
12,
|
|
3695 |
13,
|
|
3696 |
gtk.FILL | gtk.EXPAND,
|
|
3697 |
gtk.FILL | gtk.EXPAND,
|
|
3698 |
45,
|
|
3699 |
0,
|
|
3700 |
)
|
|
3701 |
# "Navigation" tab:
|
|
3702 |
table_navigation = gtk.Table(14, 2, False)
|
|
3703 |
navlabel = gtk.Label()
|
|
3704 |
navlabel.set_markup("<b>" + _("Navigation") + "</b>")
|
|
3705 |
navlabel.set_alignment(0, 1)
|
|
3706 |
preloadnav = gtk.CheckButton(label=_("Preload images for faster navigation"))
|
|
3707 |
preloadnav.set_active(self.preloading_images)
|
|
3708 |
preloadnav.set_tooltip_text(
|
|
3709 |
_(
|
|
3710 |
"If enabled, the next and previous images in the list will be preloaded during idle time. Note that the speed increase comes at the expense of memory usage, so it is recommended to disable this option on machines with limited ram."
|
|
3711 |
)
|
|
3712 |
)
|
|
3713 |
hbox_listwrap = gtk.HBox()
|
|
3714 |
hbox_listwrap.pack_start(
|
|
3715 |
gtk.Label(_("Wrap around imagelist:")), False, False, 0
|
|
3716 |
)
|
|
3717 |
combobox2 = gtk.combo_box_new_text()
|
|
3718 |
combobox2.append_text(_("No"))
|
|
3719 |
combobox2.append_text(_("Yes"))
|
|
3720 |
combobox2.append_text(_("Prompt User"))
|
|
3721 |
combobox2.set_active(self.listwrap_mode)
|
|
3722 |
hbox_listwrap.pack_start(combobox2, False, False, 5)
|
|
3723 |
table_navigation.attach(
|
|
3724 |
gtk.Label(), 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3725 |
)
|
|
3726 |
table_navigation.attach(
|
|
3727 |
navlabel, 1, 2, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3728 |
)
|
|
3729 |
table_navigation.attach(
|
|
3730 |
gtk.Label(), 1, 2, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3731 |
)
|
|
3732 |
table_navigation.attach(
|
|
3733 |
hbox_listwrap,
|
|
3734 |
1,
|
|
3735 |
2,
|
|
3736 |
4,
|
|
3737 |
5,
|
|
3738 |
gtk.FILL | gtk.EXPAND,
|
|
3739 |
gtk.FILL | gtk.EXPAND,
|
|
3740 |
30,
|
|
3741 |
0,
|
|
3742 |
)
|
|
3743 |
table_navigation.attach(
|
|
3744 |
gtk.Label(), 1, 2, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3745 |
)
|
|
3746 |
table_navigation.attach(
|
|
3747 |
preloadnav, 1, 2, 6, 7, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3748 |
)
|
|
3749 |
table_navigation.attach(
|
|
3750 |
gtk.Label(), 1, 2, 7, 8, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3751 |
)
|
|
3752 |
table_navigation.attach(
|
|
3753 |
gtk.Label(), 1, 2, 8, 9, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3754 |
)
|
|
3755 |
table_navigation.attach(
|
|
3756 |
gtk.Label(),
|
|
3757 |
1,
|
|
3758 |
2,
|
|
3759 |
9,
|
|
3760 |
10,
|
|
3761 |
gtk.FILL | gtk.EXPAND,
|
|
3762 |
gtk.FILL | gtk.EXPAND,
|
|
3763 |
30,
|
|
3764 |
0,
|
|
3765 |
)
|
|
3766 |
table_navigation.attach(
|
|
3767 |
gtk.Label(),
|
|
3768 |
1,
|
|
3769 |
2,
|
|
3770 |
10,
|
|
3771 |
11,
|
|
3772 |
gtk.FILL | gtk.EXPAND,
|
|
3773 |
gtk.FILL | gtk.EXPAND,
|
|
3774 |
30,
|
|
3775 |
0,
|
|
3776 |
)
|
|
3777 |
table_navigation.attach(
|
|
3778 |
gtk.Label(),
|
|
3779 |
1,
|
|
3780 |
2,
|
|
3781 |
11,
|
|
3782 |
12,
|
|
3783 |
gtk.FILL | gtk.EXPAND,
|
|
3784 |
gtk.FILL | gtk.EXPAND,
|
|
3785 |
0,
|
|
3786 |
0,
|
|
3787 |
)
|
|
3788 |
table_navigation.attach(
|
|
3789 |
gtk.Label(),
|
|
3790 |
1,
|
|
3791 |
2,
|
|
3792 |
12,
|
|
3793 |
13,
|
|
3794 |
gtk.FILL | gtk.EXPAND,
|
|
3795 |
gtk.FILL | gtk.EXPAND,
|
|
3796 |
0,
|
|
3797 |
0,
|
|
3798 |
)
|
|
3799 |
table_navigation.attach(
|
|
3800 |
gtk.Label(),
|
|
3801 |
1,
|
|
3802 |
2,
|
|
3803 |
13,
|
|
3804 |
14,
|
|
3805 |
gtk.FILL | gtk.EXPAND,
|
|
3806 |
gtk.FILL | gtk.EXPAND,
|
|
3807 |
0,
|
|
3808 |
0,
|
|
3809 |
)
|
|
3810 |
# "Slideshow" tab:
|
|
3811 |
table_slideshow = gtk.Table(14, 2, False)
|
|
3812 |
slideshowlabel = gtk.Label()
|
|
3813 |
slideshowlabel.set_markup("<b>" + _("Slideshow Mode") + "</b>")
|
|
3814 |
slideshowlabel.set_alignment(0, 1)
|
|
3815 |
hbox_delay = gtk.HBox()
|
|
3816 |
hbox_delay.pack_start(
|
|
3817 |
gtk.Label(_("Delay between images in seconds:")), False, False, 0
|
|
3818 |
)
|
|
3819 |
spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1, 10, 0)
|
|
3820 |
delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
|
|
3821 |
delayspin.set_numeric(True)
|
|
3822 |
hbox_delay.pack_start(delayspin, False, False, 5)
|
|
3823 |
randomize = gtk.CheckButton(_("Randomize order of images"))
|
|
3824 |
randomize.set_active(self.slideshow_random)
|
|
3825 |
randomize.set_tooltip_text(
|
|
3826 |
_(
|
|
3827 |
"If enabled, a random image will be chosen during slideshow mode (without loading any image twice)."
|
|
3828 |
)
|
|
3829 |
)
|
|
3830 |
disable_screensaver = gtk.CheckButton(
|
|
3831 |
_("Disable screensaver in slideshow mode")
|
|
3832 |
)
|
|
3833 |
disable_screensaver.set_active(self.disable_screensaver)
|
|
3834 |
disable_screensaver.set_tooltip_text(
|
|
3835 |
_(
|
|
3836 |
"If enabled, xscreensaver will be temporarily disabled during slideshow mode."
|
|
3837 |
)
|
|
3838 |
)
|
|
3839 |
ss_in_fs = gtk.CheckButton(_("Always start in fullscreen mode"))
|
|
3840 |
ss_in_fs.set_tooltip_text(
|
|
3841 |
_(
|
|
3842 |
"If enabled, starting a slideshow will put the application in fullscreen mode."
|
|
3843 |
)
|
|
3844 |
)
|
|
3845 |
ss_in_fs.set_active(self.slideshow_in_fullscreen)
|
|
3846 |
table_slideshow.attach(
|
|
3847 |
gtk.Label(), 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3848 |
)
|
|
3849 |
table_slideshow.attach(
|
|
3850 |
slideshowlabel,
|
|
3851 |
1,
|
|
3852 |
2,
|
|
3853 |
2,
|
|
3854 |
3,
|
|
3855 |
gtk.FILL | gtk.EXPAND,
|
|
3856 |
gtk.FILL | gtk.EXPAND,
|
|
3857 |
15,
|
|
3858 |
0,
|
|
3859 |
)
|
|
3860 |
table_slideshow.attach(
|
|
3861 |
gtk.Label(), 1, 2, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3862 |
)
|
|
3863 |
table_slideshow.attach(
|
|
3864 |
hbox_delay, 1, 2, 4, 5, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3865 |
)
|
|
3866 |
table_slideshow.attach(
|
|
3867 |
gtk.Label(), 1, 2, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3868 |
)
|
|
3869 |
table_slideshow.attach(
|
|
3870 |
disable_screensaver,
|
|
3871 |
1,
|
|
3872 |
2,
|
|
3873 |
6,
|
|
3874 |
7,
|
|
3875 |
gtk.FILL | gtk.EXPAND,
|
|
3876 |
gtk.FILL | gtk.EXPAND,
|
|
3877 |
30,
|
|
3878 |
0,
|
|
3879 |
)
|
|
3880 |
table_slideshow.attach(
|
|
3881 |
ss_in_fs, 1, 2, 7, 8, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3882 |
)
|
|
3883 |
table_slideshow.attach(
|
|
3884 |
randomize, 1, 2, 8, 9, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3885 |
)
|
|
3886 |
table_slideshow.attach(
|
|
3887 |
gtk.Label(), 1, 2, 9, 10, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 0, 0
|
|
3888 |
)
|
|
3889 |
table_slideshow.attach(
|
|
3890 |
gtk.Label(),
|
|
3891 |
1,
|
|
3892 |
2,
|
|
3893 |
10,
|
|
3894 |
11,
|
|
3895 |
gtk.FILL | gtk.EXPAND,
|
|
3896 |
gtk.FILL | gtk.EXPAND,
|
|
3897 |
0,
|
|
3898 |
0,
|
|
3899 |
)
|
|
3900 |
table_slideshow.attach(
|
|
3901 |
gtk.Label(),
|
|
3902 |
1,
|
|
3903 |
2,
|
|
3904 |
11,
|
|
3905 |
12,
|
|
3906 |
gtk.FILL | gtk.EXPAND,
|
|
3907 |
gtk.FILL | gtk.EXPAND,
|
|
3908 |
0,
|
|
3909 |
0,
|
|
3910 |
)
|
|
3911 |
table_slideshow.attach(
|
|
3912 |
gtk.Label(),
|
|
3913 |
1,
|
|
3914 |
2,
|
|
3915 |
12,
|
|
3916 |
13,
|
|
3917 |
gtk.FILL | gtk.EXPAND,
|
|
3918 |
gtk.FILL | gtk.EXPAND,
|
|
3919 |
0,
|
|
3920 |
0,
|
|
3921 |
)
|
|
3922 |
table_slideshow.attach(
|
|
3923 |
gtk.Label(),
|
|
3924 |
1,
|
|
3925 |
2,
|
|
3926 |
13,
|
|
3927 |
14,
|
|
3928 |
gtk.FILL | gtk.EXPAND,
|
|
3929 |
gtk.FILL | gtk.EXPAND,
|
|
3930 |
0,
|
|
3931 |
0,
|
|
3932 |
)
|
|
3933 |
# "Image" tab:
|
|
3934 |
table_image = gtk.Table(14, 2, False)
|
|
3935 |
imagelabel = gtk.Label()
|
|
3936 |
imagelabel.set_markup("<b>" + _("Image Editing") + "</b>")
|
|
3937 |
imagelabel.set_alignment(0, 1)
|
|
3938 |
deletebutton = gtk.CheckButton(_("Confirm image delete"))
|
|
3939 |
deletebutton.set_active(self.confirm_delete)
|
|
3940 |
|
|
3941 |
zoom_hbox = gtk.HBox()
|
|
3942 |
zoom_hbox.pack_start(gtk.Label(_("Scaling quality:")), False, False, 0)
|
|
3943 |
zoomcombo = gtk.combo_box_new_text()
|
|
3944 |
zoomcombo.append_text(_("Nearest (Fastest)"))
|
|
3945 |
zoomcombo.append_text(_("Tiles"))
|
|
3946 |
zoomcombo.append_text(_("Bilinear"))
|
|
3947 |
zoomcombo.append_text(_("Hyper (Best)"))
|
|
3948 |
zoomcombo.set_active(self.zoomvalue)
|
|
3949 |
zoom_hbox.pack_start(zoomcombo, False, False, 0)
|
|
3950 |
zoom_hbox.pack_start(gtk.Label(), True, True, 0)
|
|
3951 |
|
|
3952 |
hbox_save = gtk.HBox()
|
|
3953 |
savelabel = gtk.Label(_("Modified images:"))
|
|
3954 |
savecombo = gtk.combo_box_new_text()
|
|
3955 |
savecombo.append_text(_("Ignore Changes"))
|
|
3956 |
savecombo.append_text(_("Auto-Save"))
|
|
3957 |
savecombo.append_text(_("Prompt For Action"))
|
|
3958 |
savecombo.set_active(self.savemode)
|
|
3959 |
hbox_save.pack_start(savelabel, False, False, 0)
|
|
3960 |
hbox_save.pack_start(savecombo, False, False, 5)
|
|
3961 |
|
|
3962 |
hbox_quality = gtk.HBox()
|
|
3963 |
qualitylabel = gtk.Label(_("Quality to save in:"))
|
|
3964 |
qspin_adj = gtk.Adjustment(self.quality_save, 0, 100, 1, 100, 0)
|
|
3965 |
qualityspin = gtk.SpinButton(qspin_adj, 1.0, 0)
|
|
3966 |
qualityspin.set_numeric(True)
|
|
3967 |
hbox_quality.pack_start(qualitylabel, False, False, 0)
|
|
3968 |
hbox_quality.pack_start(qualityspin, False, False, 5)
|
|
3969 |
table_image.attach(
|
|
3970 |
gtk.Label(), 1, 3, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3971 |
)
|
|
3972 |
table_image.attach(
|
|
3973 |
imagelabel, 1, 3, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 15, 0
|
|
3974 |
)
|
|
3975 |
table_image.attach(
|
|
3976 |
gtk.Label(), 1, 3, 3, 4, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3977 |
)
|
|
3978 |
table_image.attach(
|
|
3979 |
zoom_hbox, 1, 3, 4, 5, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3980 |
)
|
|
3981 |
table_image.attach(
|
|
3982 |
gtk.Label(), 1, 3, 5, 6, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3983 |
)
|
|
3984 |
table_image.attach(
|
|
3985 |
hbox_save, 1, 3, 6, 7, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3986 |
)
|
|
3987 |
table_image.attach(
|
|
3988 |
gtk.Label(), 1, 3, 7, 8, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 30, 0
|
|
3989 |
)
|
|
3990 |
table_image.attach(
|
|
3991 |
hbox_quality,
|
|
3992 |
1,
|
|
3993 |
3,
|
|
3994 |
8,
|
|
3995 |
9,
|
|
3996 |
gtk.FILL | gtk.EXPAND,
|
|
3997 |
gtk.FILL | gtk.EXPAND,
|
|
3998 |
30,
|
|
3999 |
0,
|
|
4000 |
)
|
|
4001 |
table_image.attach(
|
|
4002 |
gtk.Label(),
|
|
4003 |
1,
|
|
4004 |
3,
|
|
4005 |
9,
|
|
4006 |
10,
|
|
4007 |
gtk.FILL | gtk.EXPAND,
|
|
4008 |
gtk.FILL | gtk.EXPAND,
|
|
4009 |
30,
|
|
4010 |
0,
|
|
4011 |
)
|
|
4012 |
table_image.attach(
|
|
4013 |
deletebutton,
|
|
4014 |
1,
|
|
4015 |
3,
|
|
4016 |
10,
|
|
4017 |
11,
|
|
4018 |
gtk.FILL | gtk.EXPAND,
|
|
4019 |
gtk.FILL | gtk.EXPAND,
|
|
4020 |
30,
|
|
4021 |
0,
|
|
4022 |
)
|
|
4023 |
table_image.attach(
|
|
4024 |
gtk.Label(),
|
|
4025 |
1,
|
|
4026 |
3,
|
|
4027 |
11,
|
|
4028 |
12,
|
|
4029 |
gtk.FILL | gtk.EXPAND,
|
|
4030 |
gtk.FILL | gtk.EXPAND,
|
|
4031 |
30,
|
|
4032 |
0,
|
|
4033 |
)
|
|
4034 |
table_image.attach(
|
|
4035 |
gtk.Label(),
|
|
4036 |
1,
|
|
4037 |
3,
|
|
4038 |
12,
|
|
4039 |
13,
|
|
4040 |
gtk.FILL | gtk.EXPAND,
|
|
4041 |
gtk.FILL | gtk.EXPAND,
|
|
4042 |
30,
|
|
4043 |
0,
|
|
4044 |
)
|
|
4045 |
table_image.attach(
|
|
4046 |
gtk.Label(),
|
|
4047 |
1,
|
|
4048 |
3,
|
|
4049 |
13,
|
|
4050 |
14,
|
|
4051 |
gtk.FILL | gtk.EXPAND,
|
|
4052 |
gtk.FILL | gtk.EXPAND,
|
|
4053 |
30,
|
|
4054 |
0,
|
|
4055 |
)
|
|
4056 |
table_image.attach(
|
|
4057 |
gtk.Label(),
|
|
4058 |
1,
|
|
4059 |
3,
|
|
4060 |
14,
|
|
4061 |
15,
|
|
4062 |
gtk.FILL | gtk.EXPAND,
|
|
4063 |
gtk.FILL | gtk.EXPAND,
|
|
4064 |
30,
|
|
4065 |
0,
|
|
4066 |
)
|
|
4067 |
# Add tabs:
|
|
4068 |
notebook = gtk.Notebook()
|
|
4069 |
notebook.append_page(table_behavior, gtk.Label(_("Behavior")))
|
|
4070 |
notebook.append_page(table_navigation, gtk.Label(_("Navigation")))
|
|
4071 |
notebook.append_page(table_settings, gtk.Label(_("Interface")))
|
|
4072 |
notebook.append_page(table_slideshow, gtk.Label(_("Slideshow")))
|
|
4073 |
notebook.append_page(table_image, gtk.Label(_("Image")))
|
|
4074 |
notebook.set_current_page(0)
|
|
4075 |
hbox = gtk.HBox()
|
|
4076 |
self.prefs_dialog.vbox.pack_start(hbox, False, False, 7)
|
|
4077 |
hbox.pack_start(notebook, False, False, 7)
|
|
4078 |
notebook.connect("switch-page", self.prefs_tab_switched)
|
|
4079 |
# Show prefs:
|
|
4080 |
self.prefs_dialog.vbox.show_all()
|
|
4081 |
self.close_button = self.prefs_dialog.add_button(
|
|
4082 |
gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE
|
|
4083 |
)
|
|
4084 |
self.close_button.grab_focus()
|
|
4085 |
response = self.prefs_dialog.run()
|
|
4086 |
if response == gtk.RESPONSE_CLOSE or response == gtk.RESPONSE_DELETE_EVENT:
|
|
4087 |
self.zoomvalue = zoomcombo.get_active()
|
|
4088 |
if int(round(self.zoomvalue, 0)) == 0:
|
|
4089 |
self.zoom_quality = gtk.gdk.INTERP_NEAREST
|
|
4090 |
elif int(round(self.zoomvalue, 0)) == 1:
|
|
4091 |
self.zoom_quality = gtk.gdk.INTERP_TILES
|
|
4092 |
elif int(round(self.zoomvalue, 0)) == 2:
|
|
4093 |
self.zoom_quality = gtk.gdk.INTERP_BILINEAR
|
|
4094 |
elif int(round(self.zoomvalue, 0)) == 3:
|
|
4095 |
self.zoom_quality = gtk.gdk.INTERP_HYPER
|
|
4096 |
self.open_all_images = openallimages.get_active()
|
|
4097 |
self.open_hidden_files = hiddenimages.get_active()
|
|
4098 |
if openpref1.get_active():
|
|
4099 |
self.use_last_dir = True
|
|
4100 |
else:
|
|
4101 |
self.use_last_dir = False
|
|
4102 |
open_mode_prev = self.open_mode
|
|
4103 |
self.open_mode = combobox.get_active()
|
|
4104 |
preloading_images_prev = self.preloading_images
|
|
4105 |
self.preloading_images = preloadnav.get_active()
|
|
4106 |
self.listwrap_mode = combobox2.get_active()
|
|
4107 |
self.slideshow_delay = delayspin.get_value()
|
|
4108 |
self.curr_slideshow_delay = self.slideshow_delay
|
|
4109 |
self.slideshow_random = randomize.get_active()
|
|
4110 |
self.curr_slideshow_random = self.slideshow_random
|
|
4111 |
self.disable_screensaver = disable_screensaver.get_active()
|
|
4112 |
self.slideshow_in_fullscreen = ss_in_fs.get_active()
|
|
4113 |
self.savemode = savecombo.get_active()
|
|
4114 |
self.start_in_fullscreen = fullscreen.get_active()
|
|
4115 |
self.confirm_delete = deletebutton.get_active()
|
|
4116 |
self.quality_save = qualityspin.get_value()
|
|
4117 |
self.thumbnail_size = int(self.thumbnail_sizes[thumbsize.get_active()])
|
|
4118 |
if self.thumbnail_size != prev_thumbnail_size:
|
|
4119 |
gobject.idle_add(self.thumbpane_set_size)
|
|
4120 |
gobject.idle_add(
|
|
4121 |
self.thumbpane_update_images, True, self.curr_img_in_list
|
|
4122 |
)
|
|
4123 |
self.prefs_dialog.destroy()
|
|
4124 |
self.set_go_navigation_sensitivities(False)
|
|
4125 |
if (self.preloading_images and not preloading_images_prev) or (
|
|
4126 |
open_mode_prev != self.open_mode
|
|
4127 |
):
|
|
4128 |
# The user just turned on preloading, so do it:
|
|
4129 |
self.preloadimg_next_in_list = -1
|
|
4130 |
self.preloadimg_prev_in_list = -1
|
|
4131 |
self.preload_when_idle = gobject.idle_add(
|
|
4132 |
self.preload_next_image, False
|
|
4133 |
)
|
|
4134 |
self.preload_when_idle2 = gobject.idle_add(
|
|
4135 |
self.preload_prev_image, False
|
|
4136 |
)
|
|
4137 |
elif not self.preloading_images:
|
|
4138 |
self.preloadimg_next_in_list = -1
|
|
4139 |
self.preloadimg_prev_in_list = -1
|
|
4140 |
|
|
4141 |
def prefs_use_fixed_dir_clicked(self, button):
|
|
4142 |
if button.get_active():
|
|
4143 |
self.defaultdir.set_sensitive(True)
|
|
4144 |
else:
|
|
4145 |
self.defaultdir.set_sensitive(False)
|
|
4146 |
|
|
4147 |
def rename_image(self, action):
|
|
4148 |
if len(self.image_list) > 0:
|
|
4149 |
temp_slideshow_mode = self.slideshow_mode
|
|
4150 |
if self.slideshow_mode:
|
|
4151 |
self.toggle_slideshow(None)
|
|
4152 |
rename_dialog = gtk.Dialog(_("Rename Image"), self.window, gtk.DIALOG_MODAL)
|
|
4153 |
self.rename_txt = gtk.Entry()
|
|
4154 |
filename = os.path.basename(self.currimg_name)
|
|
4155 |
self.rename_txt.set_text(filename)
|
|
4156 |
self.rename_txt.set_activates_default(True)
|
|
4157 |
cancelbutton = rename_dialog.add_button(
|
|
4158 |
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL
|
|
4159 |
)
|
|
4160 |
renamebutton = rename_dialog.add_button(_("_Rename"), gtk.RESPONSE_ACCEPT)
|
|
4161 |
renameimage = gtk.Image()
|
|
4162 |
renameimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
|
4163 |
renamebutton.set_image(renameimage)
|
|
4164 |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
|
4165 |
if animtest.is_static_image():
|
|
4166 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
4167 |
self.currimg_pixbuf_original, 60, self.zoom_quality
|
|
4168 |
)
|
|
4169 |
else:
|
|
4170 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
4171 |
animtest.get_static_image(), 60, self.zoom_quality
|
|
4172 |
)
|
|
4173 |
image = gtk.Image()
|
|
4174 |
image.set_from_pixbuf(pixbuf)
|
|
4175 |
instructions = gtk.Label(_("Enter the new name:"))
|
|
4176 |
instructions.set_alignment(0, 1)
|
|
4177 |
hbox = gtk.HBox()
|
|
4178 |
hbox.pack_start(image, False, False, 10)
|
|
4179 |
vbox_stuff = gtk.VBox()
|
|
4180 |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
|
4181 |
vbox_stuff.pack_start(instructions, False, False, 0)
|
|
4182 |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
|
4183 |
vbox_stuff.pack_start(self.rename_txt, True, True, 0)
|
|
4184 |
vbox_stuff.pack_start(gtk.Label(), False, False, 0)
|
|
4185 |
hbox.pack_start(vbox_stuff, True, True, 10)
|
|
4186 |
rename_dialog.vbox.pack_start(hbox, False, False, 0)
|
|
4187 |
rename_dialog.set_has_separator(True)
|
|
4188 |
rename_dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
|
4189 |
rename_dialog.set_size_request(300, -1)
|
|
4190 |
rename_dialog.vbox.show_all()
|
|
4191 |
rename_dialog.connect("show", self.select_rename_text)
|
|
4192 |
response = rename_dialog.run()
|
|
4193 |
if response == gtk.RESPONSE_ACCEPT:
|
|
4194 |
try:
|
|
4195 |
new_filename = (
|
|
4196 |
os.path.dirname(self.currimg_name)
|
|
4197 |
+ "/"
|
|
4198 |
+ self.rename_txt.get_text()
|
|
4199 |
)
|
|
4200 |
shutil.move(self.currimg_name, new_filename)
|
|
4201 |
# Update thumbnail filename:
|
|
4202 |
try:
|
|
4203 |
shutil.move(
|
|
4204 |
self_get_name(self.currimg_name)[1],
|
|
4205 |
self.thumbnail_get_name(new_filename)[1],
|
|
4206 |
)
|
|
4207 |
except:
|
|
4208 |
pass
|
|
4209 |
self.recent_file_remove_and_refresh_name(self.currimg_name)
|
|
4210 |
self.currimg_name = new_filename
|
|
4211 |
self.register_file_with_recent_docs(self.currimg_name)
|
|
4212 |
self.update_title()
|
|
4213 |
except:
|
|
4214 |
error_dialog = gtk.MessageDialog(
|
|
4215 |
self.window,
|
|
4216 |
gtk.DIALOG_MODAL,
|
|
4217 |
gtk.MESSAGE_WARNING,
|
|
4218 |
gtk.BUTTONS_OK,
|
|
4219 |
_("Unable to rename %s") % self.currimg_name,
|
|
4220 |
)
|
|
4221 |
error_dialog.set_title(_("Unable to rename"))
|
|
4222 |
error_dialog.run()
|
|
4223 |
error_dialog.destroy()
|
|
4224 |
rename_dialog.destroy()
|
|
4225 |
if temp_slideshow_mode:
|
|
4226 |
self.toggle_slideshow(None)
|
|
4227 |
|
|
4228 |
def select_rename_text(self, widget):
|
|
4229 |
filename = os.path.basename(self.currimg_name)
|
|
4230 |
fileext = os.path.splitext(os.path.basename(self.currimg_name))[1]
|
|
4231 |
self.rename_txt.select_region(0, len(filename) - len(fileext))
|
|
4232 |
|
|
4233 |
def delete_image(self, action):
|
|
4234 |
if len(self.image_list) > 0:
|
|
4235 |
temp_slideshow_mode = self.slideshow_mode
|
|
4236 |
if self.slideshow_mode:
|
|
4237 |
self.toggle_slideshow(None)
|
|
4238 |
delete_dialog = gtk.Dialog(_("Delete Image"), self.window, gtk.DIALOG_MODAL)
|
|
4239 |
if self.confirm_delete:
|
|
4240 |
permlabel = gtk.Label(
|
|
4241 |
_("Are you sure you wish to permanently delete %s?")
|
|
4242 |
% os.path.split(self.currimg_name)[1]
|
|
4243 |
)
|
|
4244 |
permlabel.set_line_wrap(True)
|
|
4245 |
permlabel.set_alignment(0, 0.1)
|
|
4246 |
warningicon = gtk.Image()
|
|
4247 |
warningicon.set_from_stock(
|
|
4248 |
gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG
|
|
4249 |
)
|
|
4250 |
hbox = gtk.HBox()
|
|
4251 |
hbox.pack_start(warningicon, False, False, 10)
|
|
4252 |
hbox.pack_start(permlabel, False, False, 10)
|
|
4253 |
delete_dialog.vbox.pack_start(gtk.Label(), False, False, 0)
|
|
4254 |
delete_dialog.vbox.pack_start(hbox, False, False, 0)
|
|
4255 |
cancelbutton = delete_dialog.add_button(
|
|
4256 |
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL
|
|
4257 |
)
|
|
4258 |
deletebutton = delete_dialog.add_button(
|
|
4259 |
gtk.STOCK_DELETE, gtk.RESPONSE_YES
|
|
4260 |
)
|
|
4261 |
delete_dialog.set_has_separator(False)
|
|
4262 |
deletebutton.set_property("has-focus", True)
|
|
4263 |
delete_dialog.set_default_response(gtk.RESPONSE_YES)
|
|
4264 |
delete_dialog.vbox.show_all()
|
|
4265 |
response = delete_dialog.run()
|
|
4266 |
else:
|
|
4267 |
response = gtk.RESPONSE_YES
|
|
4268 |
if response == gtk.RESPONSE_YES:
|
|
4269 |
try:
|
|
4270 |
os.remove(self.currimg_name)
|
|
4271 |
self.image_modified = False
|
|
4272 |
try:
|
|
4273 |
os.remove(self.thumbnail_get_name(self.currimg_name)[1])
|
|
4274 |
except:
|
|
4275 |
pass
|
|
4276 |
self.recent_file_remove_and_refresh_name(self.currimg_name)
|
|
4277 |
iter = self.thumblist.get_iter((self.curr_img_in_list,))
|
|
4278 |
try:
|
|
4279 |
self.thumbnail_loaded.pop(self.curr_img_in_list)
|
|
4280 |
self.thumbpane_update_images()
|
|
4281 |
except:
|
|
4282 |
pass
|
|
4283 |
self.thumblist.remove(iter)
|
|
4284 |
templist = self.image_list
|
|
4285 |
self.image_list = []
|
|
4286 |
for item in templist:
|
|
4287 |
if item != self.currimg_name:
|
|
4288 |
self.image_list.append(item)
|
|
4289 |
if len(self.image_list) >= 1:
|
|
4290 |
if len(self.image_list) == 1:
|
|
4291 |
self.curr_img_in_list = 0
|
|
4292 |
elif self.curr_img_in_list == len(self.image_list):
|
|
4293 |
self.curr_img_in_list -= 1
|
|
4294 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
4295 |
self.preloadimg_prev_in_list = -1
|
|
4296 |
self.preloadimg_next_in_list = -1
|
|
4297 |
self.load_when_idle = gobject.idle_add(
|
|
4298 |
self.load_new_image, False, False, True, True, True, True
|
|
4299 |
)
|
|
4300 |
self.set_go_navigation_sensitivities(False)
|
|
4301 |
else:
|
|
4302 |
self.imageview.clear()
|
|
4303 |
self.update_title()
|
|
4304 |
self.statusbar.push(self.statusbar.get_context_id(""), "")
|
|
4305 |
self.image_loaded = False
|
|
4306 |
self.set_slideshow_sensitivities()
|
|
4307 |
self.set_image_sensitivities(False)
|
|
4308 |
self.set_go_navigation_sensitivities(False)
|
|
4309 |
# Select new item:
|
|
4310 |
self.thumbpane_select(self.curr_img_in_list)
|
|
4311 |
except:
|
|
4312 |
error_dialog = gtk.MessageDialog(
|
|
4313 |
self.window,
|
|
4314 |
gtk.DIALOG_MODAL,
|
|
4315 |
gtk.MESSAGE_WARNING,
|
|
4316 |
gtk.BUTTONS_OK,
|
|
4317 |
_("Unable to delete %s") % self.currimg_name,
|
|
4318 |
)
|
|
4319 |
error_dialog.set_title(_("Unable to delete"))
|
|
4320 |
error_dialog.run()
|
|
4321 |
error_dialog.destroy()
|
|
4322 |
delete_dialog.destroy()
|
|
4323 |
if temp_slideshow_mode:
|
|
4324 |
self.toggle_slideshow(None)
|
|
4325 |
|
|
4326 |
def defaultdir_clicked(self, button):
|
|
4327 |
getdir = gtk.FileChooserDialog(
|
|
4328 |
title=_("Choose directory"),
|
|
4329 |
action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
|
4330 |
buttons=(
|
|
4331 |
gtk.STOCK_CANCEL,
|
|
4332 |
gtk.RESPONSE_CANCEL,
|
|
4333 |
gtk.STOCK_OPEN,
|
|
4334 |
gtk.RESPONSE_OK,
|
|
4335 |
),
|
|
4336 |
)
|
|
4337 |
getdir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
|
4338 |
getdir.set_filename(self.fixed_dir)
|
|
4339 |
getdir.set_default_response(gtk.RESPONSE_OK)
|
|
4340 |
response = getdir.run()
|
|
4341 |
if response == gtk.RESPONSE_OK:
|
|
4342 |
self.fixed_dir = getdir.get_filenames()[0]
|
|
4343 |
if len(self.fixed_dir) > 25:
|
|
4344 |
button.set_label("..." + self.fixed_dir[-22:])
|
|
4345 |
else:
|
|
4346 |
button.set_label(self.fixed_dir)
|
|
4347 |
getdir.destroy()
|
|
4348 |
else:
|
|
4349 |
getdir.destroy()
|
|
4350 |
|
|
4351 |
def prefs_tab_switched(self, notebook, page, page_num):
|
|
4352 |
do_when_idle = gobject.idle_add(self.grab_close_button)
|
|
4353 |
|
|
4354 |
def grab_close_button(self):
|
|
4355 |
self.close_button.grab_focus()
|
|
4356 |
|
|
4357 |
def bgcolor_selected(self, widget):
|
|
4358 |
# When the user selects a color, store this color in self.bgcolor (which will
|
|
4359 |
# later be saved to .miragerc) and set this background color:
|
|
4360 |
self.bgcolor = widget.get_property("color")
|
|
4361 |
if not self.simple_bgcolor:
|
|
4362 |
self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
4363 |
self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
4364 |
self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
|
|
4365 |
|
|
4366 |
def simple_bgcolor_selected(self, widget):
|
|
4367 |
if widget.get_active():
|
|
4368 |
self.simple_bgcolor = True
|
|
4369 |
self.layout.modify_bg(gtk.STATE_NORMAL, None)
|
|
4370 |
else:
|
|
4371 |
self.simple_bgcolor = False
|
|
4372 |
self.bgcolor_selected(self.colorbutton)
|
|
4373 |
|
|
4374 |
def show_about(self, action):
|
|
4375 |
# Help > About
|
|
4376 |
self.about_dialog = gtk.AboutDialog()
|
|
4377 |
try:
|
|
4378 |
self.about_dialog.set_transient_for(self.window)
|
|
4379 |
self.about_dialog.set_modal(True)
|
|
4380 |
except:
|
|
4381 |
pass
|
|
4382 |
self.about_dialog.set_name("Mirage")
|
|
4383 |
self.about_dialog.set_version(__version__)
|
|
4384 |
self.about_dialog.set_comments(_("A fast GTK+ Image Viewer."))
|
|
4385 |
self.about_dialog.set_license(__license__)
|
|
4386 |
self.about_dialog.set_authors(
|
|
4387 |
[
|
|
4388 |
"Scott Horowitz <stonecrest@gmail.com>",
|
|
4389 |
"Fredric Johansson <fredric.miscmail@gmail.com>",
|
|
4390 |
]
|
|
4391 |
)
|
|
4392 |
self.about_dialog.set_artists(["William Rea <sillywilly@gmail.com>"])
|
|
4393 |
self.about_dialog.set_translator_credits(
|
|
4394 |
"cs - Petr Pisar <petr.pisar@atlas.cz>\nde - Bjoern Martensen <bjoern.martensen@gmail.com>\nes - Isidro Arribas <cdhotfire@gmail.com>\nfr - Mike Massonnet <mmassonnet@gmail.com>\nhu - Sandor Lisovszki <lisovszki@dunakanyar.net>\nnl - Pascal De Vuyst <pascal.devuyst@gmail.com>\npl - Tomasz Dominikowski <dominikowski@gmail.com>\npt_BR - Danilo Martins <mawkee@gmail.com>\nru - mavka <mavka@justos.org>\nit - Daniele Maggio <dado84@freemail.it>\nzh_CN - Jayden Suen <no.sun@163.com>"
|
|
4395 |
)
|
|
4396 |
gtk.about_dialog_set_url_hook(self.show_website, "http://mirageiv.berlios.de")
|
|
4397 |
self.about_dialog.set_website_label("http://mirageiv.berlios.de")
|
|
4398 |
icon_path = self.find_path("mirage.png")
|
|
4399 |
try:
|
|
4400 |
icon_pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
|
|
4401 |
self.about_dialog.set_logo(icon_pixbuf)
|
|
4402 |
except:
|
|
4403 |
pass
|
|
4404 |
self.about_dialog.connect("response", self.close_about)
|
|
4405 |
self.about_dialog.connect("delete_event", self.close_about)
|
|
4406 |
self.about_dialog.show_all()
|
|
4407 |
|
|
4408 |
def show_website(self, dialog, blah, link):
|
|
4409 |
self.browser_load(link)
|
|
4410 |
|
|
4411 |
def show_help(self, action):
|
|
4412 |
self.browser_load("http://mirageiv.berlios.de/docs.html")
|
|
4413 |
|
|
4414 |
def browser_load(self, docslink):
|
|
4415 |
try:
|
|
4416 |
pid = subprocess.Popen(["gnome-open", docslink]).pid
|
|
4417 |
except:
|
|
4418 |
try:
|
|
4419 |
pid = subprocess.Popen(["exo-open", docslink]).pid
|
|
4420 |
except:
|
|
4421 |
try:
|
|
4422 |
pid = subprocess.Popen(["kfmclient", "openURL", docslink]).pid
|
|
4423 |
except:
|
|
4424 |
try:
|
|
4425 |
pid = subprocess.Popen(["firefox", docslink]).pid
|
|
4426 |
except:
|
|
4427 |
try:
|
|
4428 |
pid = subprocess.Popen(["mozilla", docslink]).pid
|
|
4429 |
except:
|
|
4430 |
try:
|
|
4431 |
pid = subprocess.Popen(["opera", docslink]).pid
|
|
4432 |
except:
|
|
4433 |
error_dialog = gtk.MessageDialog(
|
|
4434 |
self.window,
|
|
4435 |
gtk.DIALOG_MODAL,
|
|
4436 |
gtk.MESSAGE_WARNING,
|
|
4437 |
gtk.BUTTONS_CLOSE,
|
|
4438 |
_("Unable to launch a suitable browser."),
|
|
4439 |
)
|
|
4440 |
error_dialog.run()
|
|
4441 |
error_dialog.destroy()
|
|
4442 |
|
|
4443 |
def close_about(self, event, data=None):
|
|
4444 |
self.about_dialog.hide()
|
|
4445 |
return True
|
|
4446 |
|
|
4447 |
def mousewheel_scrolled(self, widget, event):
|
|
4448 |
if event.type == gtk.gdk.SCROLL:
|
|
4449 |
# Zooming of the image by Ctrl-mousewheel
|
|
4450 |
if event.state & gtk.gdk.CONTROL_MASK:
|
|
4451 |
if event.direction == gtk.gdk.SCROLL_UP:
|
|
4452 |
self.zoom_in(None)
|
|
4453 |
elif event.direction == gtk.gdk.SCROLL_DOWN:
|
|
4454 |
self.zoom_out(None)
|
|
4455 |
return True
|
|
4456 |
# Navigation of images with mousewheel:
|
|
4457 |
else:
|
|
4458 |
if event.direction == gtk.gdk.SCROLL_UP:
|
|
4459 |
self.goto_prev_image(None)
|
|
4460 |
elif event.direction == gtk.gdk.SCROLL_DOWN:
|
|
4461 |
self.goto_next_image(None)
|
|
4462 |
return True
|
|
4463 |
|
|
4464 |
def mouse_moved(self, widget, event):
|
|
4465 |
# This handles the panning of the image
|
|
4466 |
if event.is_hint:
|
|
4467 |
x, y, state = event.window.get_pointer()
|
|
4468 |
else:
|
|
4469 |
state = event.state
|
|
4470 |
x, y = event.x_root, event.y_root
|
|
4471 |
if (state & gtk.gdk.BUTTON2_MASK) or (state & gtk.gdk.BUTTON1_MASK):
|
|
4472 |
# Prevent self.expose_event() from potentially further changing the
|
|
4473 |
# adjustments upon the adjustment value changes
|
|
4474 |
self.updating_adjustments = True
|
|
4475 |
xadjust = self.layout.get_hadjustment()
|
|
4476 |
newx = xadjust.value + (self.prevmousex - x)
|
|
4477 |
if newx >= xadjust.lower and newx <= xadjust.upper - xadjust.page_size:
|
|
4478 |
xadjust.set_value(newx)
|
|
4479 |
self.layout.set_hadjustment(xadjust)
|
|
4480 |
yadjust = self.layout.get_vadjustment()
|
|
4481 |
newy = yadjust.value + (self.prevmousey - y)
|
|
4482 |
if newy >= yadjust.lower and newy <= yadjust.upper - yadjust.page_size:
|
|
4483 |
yadjust.set_value(newy)
|
|
4484 |
self.layout.set_vadjustment(yadjust)
|
|
4485 |
self.updating_adjustments = False
|
|
4486 |
self.prevmousex = x
|
|
4487 |
self.prevmousey = y
|
|
4488 |
if self.fullscreen_mode:
|
|
4489 |
# Show cursor on movement, then hide after 2 seconds of no movement
|
|
4490 |
self.change_cursor(None)
|
|
4491 |
if not self.slideshow_controls_visible:
|
|
4492 |
gobject.source_remove(self.timer_id)
|
|
4493 |
if not self.closing_app:
|
|
4494 |
while gtk.events_pending():
|
|
4495 |
gtk.main_iteration()
|
|
4496 |
self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
|
|
4497 |
if y > 0.9 * self.available_image_height():
|
|
4498 |
self.slideshow_controls_show()
|
|
4499 |
else:
|
|
4500 |
self.slideshow_controls_hide()
|
|
4501 |
return True
|
|
4502 |
|
|
4503 |
def button_pressed(self, widget, event):
|
|
4504 |
if self.image_loaded:
|
|
4505 |
# Changes the cursor to the 'resize' cursor, like GIMP, on a middle click:
|
|
4506 |
if (event.button == 2 or event.button == 1) and (
|
|
4507 |
self.hscroll.get_property("visible") == True
|
|
4508 |
or self.vscroll.get_property("visible") == True
|
|
4509 |
):
|
|
4510 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
|
|
4511 |
self.prevmousex = event.x_root
|
|
4512 |
self.prevmousey = event.y_root
|
|
4513 |
# Right-click popup:
|
|
4514 |
elif self.image_loaded and event.button == 3:
|
|
4515 |
self.UIManager.get_widget("/Popup").popup(
|
|
4516 |
None, None, None, event.button, event.time
|
|
4517 |
)
|
|
4518 |
return True
|
|
4519 |
|
|
4520 |
def button_released(self, widget, event):
|
|
4521 |
# Resets the cursor when middle mouse button is released
|
|
4522 |
if event.button == 2 or event.button == 1:
|
|
4523 |
self.change_cursor(None)
|
|
4524 |
return True
|
|
4525 |
|
|
4526 |
def zoom_in(self, action):
|
|
4527 |
if self.currimg_name != "" and self.UIManager.get_widget(
|
|
4528 |
"/MainMenu/ViewMenu/In"
|
|
4529 |
).get_property("sensitive"):
|
|
4530 |
self.image_zoomed = True
|
|
4531 |
self.currimg_zoomratio = self.currimg_zoomratio * 1.25
|
|
4532 |
self.set_zoom_sensitivities()
|
|
4533 |
self.last_image_action_was_fit = False
|
|
4534 |
self.put_zoom_image_to_window(False)
|
|
4535 |
self.update_statusbar()
|
|
4536 |
|
|
4537 |
def zoom_out(self, action):
|
|
4538 |
if self.currimg_name != "" and self.UIManager.get_widget(
|
|
4539 |
"/MainMenu/ViewMenu/Out"
|
|
4540 |
).get_property("sensitive"):
|
|
4541 |
if self.currimg_zoomratio == self.min_zoomratio:
|
|
4542 |
# No point in proceeding..
|
|
4543 |
return
|
|
4544 |
self.image_zoomed = True
|
|
4545 |
self.currimg_zoomratio = self.currimg_zoomratio * 1 / 1.25
|
|
4546 |
if self.currimg_zoomratio < self.min_zoomratio:
|
|
4547 |
self.currimg_zoomratio = self.min_zoomratio
|
|
4548 |
self.set_zoom_sensitivities()
|
|
4549 |
self.last_image_action_was_fit = False
|
|
4550 |
self.put_zoom_image_to_window(False)
|
|
4551 |
self.update_statusbar()
|
|
4552 |
|
|
4553 |
def zoom_to_fit_window_action(self, action):
|
|
4554 |
self.zoom_to_fit_window(action, False, False)
|
|
4555 |
|
|
4556 |
def zoom_to_fit_window(self, action, is_preloadimg_next, is_preloadimg_prev):
|
|
4557 |
if is_preloadimg_next:
|
|
4558 |
if self.preloading_images and self.preloadimg_next_in_list != -1:
|
|
4559 |
win_width = self.available_image_width()
|
|
4560 |
win_height = self.available_image_height()
|
|
4561 |
preimg_width = self.preloadimg_next_pixbuf_original.get_width()
|
|
4562 |
preimg_height = self.preloadimg_next_pixbuf_original.get_height()
|
|
4563 |
prewidth_ratio = float(preimg_width) / win_width
|
|
4564 |
preheight_ratio = float(preimg_height) / win_height
|
|
4565 |
if prewidth_ratio < preheight_ratio:
|
|
4566 |
premax_ratio = preheight_ratio
|
|
4567 |
else:
|
|
4568 |
premax_ratio = prewidth_ratio
|
|
4569 |
self.preloadimg_next_zoomratio = 1 / float(max_ratio)
|
|
4570 |
elif is_preloadimg_prev:
|
|
4571 |
if self.preloading_images and self.preloadimg_prev_in_list != -1:
|
|
4572 |
win_width = self.available_image_width()
|
|
4573 |
win_height = self.available_image_height()
|
|
4574 |
preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
|
|
4575 |
preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
|
|
4576 |
prewidth_ratio = float(preimg_width) / win_width
|
|
4577 |
preheight_ratio = float(preimg_height) / win_height
|
|
4578 |
if prewidth_ratio < preheight_ratio:
|
|
4579 |
premax_ratio = preheight_ratio
|
|
4580 |
else:
|
|
4581 |
premax_ratio = prewidth_ratio
|
|
4582 |
self.preloadimg_prev_zoomratio = 1 / float(max_ratio)
|
|
4583 |
else:
|
|
4584 |
if self.currimg_name != "" and (
|
|
4585 |
self.slideshow_mode
|
|
4586 |
or self.UIManager.get_widget("/MainMenu/ViewMenu/Fit").get_property(
|
|
4587 |
"sensitive"
|
|
4588 |
)
|
|
4589 |
):
|
|
4590 |
self.image_zoomed = True
|
|
4591 |
self.last_mode = self.open_mode_fit
|
|
4592 |
self.last_image_action_was_fit = True
|
|
4593 |
self.last_image_action_was_smart_fit = False
|
|
4594 |
# Calculate zoomratio needed to fit to window:
|
|
4595 |
win_width = self.available_image_width()
|
|
4596 |
win_height = self.available_image_height()
|
|
4597 |
img_width = self.currimg_pixbuf_original.get_width()
|
|
4598 |
img_height = self.currimg_pixbuf_original.get_height()
|
|
4599 |
width_ratio = float(img_width) / win_width
|
|
4600 |
height_ratio = float(img_height) / win_height
|
|
4601 |
if width_ratio < height_ratio:
|
|
4602 |
max_ratio = height_ratio
|
|
4603 |
else:
|
|
4604 |
max_ratio = width_ratio
|
|
4605 |
self.currimg_zoomratio = 1 / float(max_ratio)
|
|
4606 |
self.set_zoom_sensitivities()
|
|
4607 |
self.put_zoom_image_to_window(False)
|
|
4608 |
self.update_statusbar()
|
|
4609 |
|
|
4610 |
def zoom_to_fit_or_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
|
|
4611 |
if is_preloadimg_next:
|
|
4612 |
if self.preloading_images and self.preloadimg_next_in_list != -1:
|
|
4613 |
win_width = self.available_image_width()
|
|
4614 |
win_height = self.available_image_height()
|
|
4615 |
preimg_width = self.preloadimg_next_pixbuf_original.get_width()
|
|
4616 |
preimg_height = self.preloadimg_next_pixbuf_original.get_height()
|
|
4617 |
prewidth_ratio = float(preimg_width) / win_width
|
|
4618 |
preheight_ratio = float(preimg_height) / win_height
|
|
4619 |
if prewidth_ratio < preheight_ratio:
|
|
4620 |
premax_ratio = preheight_ratio
|
|
4621 |
else:
|
|
4622 |
premax_ratio = prewidth_ratio
|
|
4623 |
self.preloadimg_next_zoomratio = 1 / float(premax_ratio)
|
|
4624 |
if self.preloadimg_next_zoomratio > 1:
|
|
4625 |
self.preloadimg_next_zoomratio = 1
|
|
4626 |
elif is_preloadimg_prev:
|
|
4627 |
if self.preloading_images and self.preloadimg_prev_in_list != -1:
|
|
4628 |
win_width = self.available_image_width()
|
|
4629 |
win_height = self.available_image_height()
|
|
4630 |
preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
|
|
4631 |
preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
|
|
4632 |
prewidth_ratio = float(preimg_width) / win_width
|
|
4633 |
preheight_ratio = float(preimg_height) / win_height
|
|
4634 |
if prewidth_ratio < preheight_ratio:
|
|
4635 |
premax_ratio = preheight_ratio
|
|
4636 |
else:
|
|
4637 |
premax_ratio = prewidth_ratio
|
|
4638 |
self.preloadimg_prev_zoomratio = 1 / float(premax_ratio)
|
|
4639 |
if self.preloadimg_prev_zoomratio > 1:
|
|
4640 |
self.preloadimg_prev_zoomratio = 1
|
|
4641 |
else:
|
|
4642 |
if self.currimg_name != "":
|
|
4643 |
self.image_zoomed = True
|
|
4644 |
# Calculate zoomratio needed to fit to window:
|
|
4645 |
win_width = self.available_image_width()
|
|
4646 |
win_height = self.available_image_height()
|
|
4647 |
img_width = self.currimg_pixbuf_original.get_width()
|
|
4648 |
img_height = self.currimg_pixbuf_original.get_height()
|
|
4649 |
width_ratio = float(img_width) / win_width
|
|
4650 |
height_ratio = float(img_height) / win_height
|
|
4651 |
if width_ratio < height_ratio:
|
|
4652 |
max_ratio = height_ratio
|
|
4653 |
else:
|
|
4654 |
max_ratio = width_ratio
|
|
4655 |
self.currimg_zoomratio = 1 / float(max_ratio)
|
|
4656 |
self.set_zoom_sensitivities()
|
|
4657 |
if self.currimg_zoomratio > 1:
|
|
4658 |
# Revert to 1:1 zoom
|
|
4659 |
self.zoom_1_to_1(action, False, False)
|
|
4660 |
else:
|
|
4661 |
self.put_zoom_image_to_window(False)
|
|
4662 |
self.update_statusbar()
|
|
4663 |
self.last_image_action_was_fit = True
|
|
4664 |
self.last_image_action_was_smart_fit = True
|
|
4665 |
|
|
4666 |
def zoom_1_to_1_action(self, action):
|
|
4667 |
self.zoom_1_to_1(action, False, False)
|
|
4668 |
|
|
4669 |
def zoom_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
|
|
4670 |
if is_preloadimg_next:
|
|
4671 |
if self.preloading_images:
|
|
4672 |
self.preloadimg_next_zoomratio = 1
|
|
4673 |
elif is_preloadimg_prev:
|
|
4674 |
if self.preloading_images:
|
|
4675 |
self.preloadimg_prev_zoomratio = 1
|
|
4676 |
else:
|
|
4677 |
if self.currimg_name != "" and (
|
|
4678 |
self.slideshow_mode
|
|
4679 |
or self.currimg_is_animation
|
|
4680 |
or (
|
|
4681 |
not self.currimg_is_animation
|
|
4682 |
and self.UIManager.get_widget(
|
|
4683 |
"/MainMenu/ViewMenu/1:1"
|
|
4684 |
).get_property("sensitive")
|
|
4685 |
)
|
|
4686 |
):
|
|
4687 |
self.image_zoomed = True
|
|
4688 |
self.last_mode = self.open_mode_1to1
|
|
4689 |
self.last_image_action_was_fit = False
|
|
4690 |
self.currimg_zoomratio = 1
|
|
4691 |
self.put_zoom_image_to_window(False)
|
|
4692 |
self.update_statusbar()
|
|
4693 |
|
|
4694 |
def rotate_left(self, action):
|
|
4695 |
self.rotate_left_or_right(
|
|
4696 |
self.UIManager.get_widget("/MainMenu/EditMenu/Rotate Left"), 90
|
|
4697 |
)
|
|
4698 |
|
|
4699 |
def rotate_right(self, action):
|
|
4700 |
self.rotate_left_or_right(
|
|
4701 |
self.UIManager.get_widget("/MainMenu/EditMenu/Rotate Right"), 270
|
|
4702 |
)
|
|
4703 |
|
|
4704 |
def rotate_left_or_right(self, widget, angle):
|
|
4705 |
if self.currimg_name != "" and widget.get_property("sensitive"):
|
|
4706 |
self.currimg_pixbuf_original = self.image_rotate(
|
|
4707 |
self.currimg_pixbuf_original, angle
|
|
4708 |
)
|
|
4709 |
if self.last_image_action_was_fit:
|
|
4710 |
if self.last_image_action_was_smart_fit:
|
|
4711 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
4712 |
else:
|
|
4713 |
self.zoom_to_fit_window(None, False, False)
|
|
4714 |
else:
|
|
4715 |
self.currimg_width, self.currimg_height = (
|
|
4716 |
self.currimg_height,
|
|
4717 |
self.currimg_width,
|
|
4718 |
)
|
|
4719 |
self.layout.set_size(self.currimg_width, self.currimg_height)
|
|
4720 |
self.currimg_pixbuf = self.image_rotate(self.currimg_pixbuf, angle)
|
|
4721 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
4722 |
self.show_scrollbars_if_needed()
|
|
4723 |
self.center_image()
|
|
4724 |
self.update_statusbar()
|
|
4725 |
self.image_modified = True
|
|
4726 |
|
|
4727 |
def flip_image_vert(self, action):
|
|
4728 |
self.flip_image_vert_or_horiz(
|
|
4729 |
self.UIManager.get_widget("/MainMenu/EditMenu/Flip Vertically"), True
|
|
4730 |
)
|
|
4731 |
|
|
4732 |
def flip_image_horiz(self, action):
|
|
4733 |
self.flip_image_vert_or_horiz(
|
|
4734 |
self.UIManager.get_widget("/MainMenu/EditMenu/Flip Horizontally"), False
|
|
4735 |
)
|
|
4736 |
|
|
4737 |
def flip_image_vert_or_horiz(self, widget, vertical):
|
|
4738 |
if self.currimg_name != "" and widget.get_property("sensitive"):
|
|
4739 |
self.currimg_pixbuf = self.image_flip(self.currimg_pixbuf, vertical)
|
|
4740 |
self.currimg_pixbuf_original = self.image_flip(
|
|
4741 |
self.currimg_pixbuf_original, vertical
|
|
4742 |
)
|
|
4743 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
4744 |
self.image_modified = True
|
|
4745 |
|
|
4746 |
def get_pixbuf_of_size(self, pixbuf, size, zoom_quality):
|
|
4747 |
# Creates a pixbuf that fits in the specified square of sizexsize
|
|
4748 |
# while preserving the aspect ratio
|
|
4749 |
# Returns tuple: (scaled_pixbuf, actual_width, actual_height)
|
|
4750 |
image_width = pixbuf.get_width()
|
|
4751 |
image_height = pixbuf.get_height()
|
|
4752 |
if image_width - size > image_height - size:
|
|
4753 |
if image_width > size:
|
|
4754 |
image_height = int(size / float(image_width) * image_height)
|
|
4755 |
image_width = size
|
|
4756 |
else:
|
|
4757 |
if image_height > size:
|
|
4758 |
image_width = int(size / float(image_height) * image_width)
|
|
4759 |
image_height = size
|
|
4760 |
if not pixbuf.get_has_alpha():
|
|
4761 |
crop_pixbuf = pixbuf.scale_simple(image_width, image_height, zoom_quality)
|
|
4762 |
else:
|
|
4763 |
colormap = self.imageview.get_colormap()
|
|
4764 |
light_grey = colormap.alloc_color("#666666", True, True)
|
|
4765 |
dark_grey = colormap.alloc_color("#999999", True, True)
|
|
4766 |
crop_pixbuf = pixbuf.composite_color_simple(
|
|
4767 |
image_width,
|
|
4768 |
image_height,
|
|
4769 |
zoom_quality,
|
|
4770 |
255,
|
|
4771 |
8,
|
|
4772 |
light_grey.pixel,
|
|
4773 |
dark_grey.pixel,
|
|
4774 |
)
|
|
4775 |
return (crop_pixbuf, image_width, image_height)
|
|
4776 |
|
|
4777 |
def pixbuf_add_border(self, pix):
|
|
4778 |
# Add a gray outline to pix. This will increase the pixbuf size by
|
|
4779 |
# 2 pixels lengthwise and heightwise, 1 on each side. Returns pixbuf.
|
|
4780 |
try:
|
|
4781 |
width = pix.get_width()
|
|
4782 |
height = pix.get_height()
|
|
4783 |
newpix = gtk.gdk.Pixbuf(
|
|
4784 |
gtk.gdk.COLORSPACE_RGB, True, 8, width + 2, height + 2
|
|
4785 |
)
|
|
4786 |
newpix.fill(0x858585FF)
|
|
4787 |
pix.copy_area(0, 0, width, height, newpix, 1, 1)
|
|
4788 |
return newpix
|
|
4789 |
except:
|
|
4790 |
return pix
|
|
4791 |
|
|
4792 |
def crop_image(self, action):
|
|
4793 |
dialog = gtk.Dialog(
|
|
4794 |
_("Crop Image"),
|
|
4795 |
self.window,
|
|
4796 |
gtk.DIALOG_MODAL,
|
|
4797 |
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT),
|
|
4798 |
)
|
|
4799 |
cropbutton = dialog.add_button(_("C_rop"), gtk.RESPONSE_ACCEPT)
|
|
4800 |
cropimage = gtk.Image()
|
|
4801 |
cropimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
|
4802 |
cropbutton.set_image(cropimage)
|
|
4803 |
image = gtk.DrawingArea()
|
|
4804 |
crop_pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
4805 |
self.currimg_pixbuf_original, 400, self.zoom_quality
|
|
4806 |
)
|
|
4807 |
image.set_size_request(image_width, image_height)
|
|
4808 |
hbox = gtk.HBox()
|
|
4809 |
hbox.pack_start(gtk.Label(), expand=True)
|
|
4810 |
hbox.pack_start(image, expand=False)
|
|
4811 |
hbox.pack_start(gtk.Label(), expand=True)
|
|
4812 |
vbox_left = gtk.VBox()
|
|
4813 |
x_adj = gtk.Adjustment(0, 0, self.currimg_pixbuf_original.get_width(), 1, 10, 0)
|
|
4814 |
x = gtk.SpinButton(x_adj, 0, 0)
|
|
4815 |
x.set_numeric(True)
|
|
4816 |
x.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
4817 |
x.set_wrap(False)
|
|
4818 |
x_label = gtk.Label("X:")
|
|
4819 |
x_label.set_alignment(0, 0.7)
|
|
4820 |
y_adj = gtk.Adjustment(
|
|
4821 |
0, 0, self.currimg_pixbuf_original.get_height(), 1, 10, 0
|
|
4822 |
)
|
|
4823 |
y = gtk.SpinButton(y_adj, 0, 0)
|
|
4824 |
y.set_numeric(True)
|
|
4825 |
y.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
4826 |
y.set_wrap(False)
|
|
4827 |
y_label = gtk.Label("Y:")
|
|
4828 |
x_label.set_size_request(y_label.size_request()[0], -1)
|
|
4829 |
hbox_x = gtk.HBox()
|
|
4830 |
hbox_y = gtk.HBox()
|
|
4831 |
hbox_x.pack_start(x_label, False, False, 10)
|
|
4832 |
hbox_x.pack_start(x, False, False, 0)
|
|
4833 |
hbox_x.pack_start(gtk.Label(), False, False, 3)
|
|
4834 |
hbox_y.pack_start(y_label, False, False, 10)
|
|
4835 |
hbox_y.pack_start(y, False, False, 0)
|
|
4836 |
hbox_y.pack_start(gtk.Label(), False, False, 3)
|
|
4837 |
vbox_left.pack_start(hbox_x, False, False, 0)
|
|
4838 |
vbox_left.pack_start(hbox_y, False, False, 0)
|
|
4839 |
vbox_right = gtk.VBox()
|
|
4840 |
width_adj = gtk.Adjustment(
|
|
4841 |
self.currimg_pixbuf_original.get_width(),
|
|
4842 |
1,
|
|
4843 |
self.currimg_pixbuf_original.get_width(),
|
|
4844 |
1,
|
|
4845 |
10,
|
|
4846 |
0,
|
|
4847 |
)
|
|
4848 |
width = gtk.SpinButton(width_adj, 0, 0)
|
|
4849 |
width.set_numeric(True)
|
|
4850 |
width.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
4851 |
width.set_wrap(False)
|
|
4852 |
width_label = gtk.Label(_("Width:"))
|
|
4853 |
width_label.set_alignment(0, 0.7)
|
|
4854 |
height_adj = gtk.Adjustment(
|
|
4855 |
self.currimg_pixbuf_original.get_height(),
|
|
4856 |
1,
|
|
4857 |
self.currimg_pixbuf_original.get_height(),
|
|
4858 |
1,
|
|
4859 |
10,
|
|
4860 |
0,
|
|
4861 |
)
|
|
4862 |
height = gtk.SpinButton(height_adj, 0, 0)
|
|
4863 |
height.set_numeric(True)
|
|
4864 |
height.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
4865 |
height.set_wrap(False)
|
|
4866 |
height_label = gtk.Label(_("Height:"))
|
|
4867 |
width_label.set_size_request(height_label.size_request()[0], -1)
|
|
4868 |
height_label.set_alignment(0, 0.7)
|
|
4869 |
hbox_width = gtk.HBox()
|
|
4870 |
hbox_height = gtk.HBox()
|
|
4871 |
hbox_width.pack_start(width_label, False, False, 10)
|
|
4872 |
hbox_width.pack_start(width, False, False, 0)
|
|
4873 |
hbox_height.pack_start(height_label, False, False, 10)
|
|
4874 |
hbox_height.pack_start(height, False, False, 0)
|
|
4875 |
vbox_right.pack_start(hbox_width, False, False, 0)
|
|
4876 |
vbox_right.pack_start(hbox_height, False, False, 0)
|
|
4877 |
hbox2 = gtk.HBox()
|
|
4878 |
hbox2.pack_start(gtk.Label(), expand=True)
|
|
4879 |
hbox2.pack_start(vbox_left, False, False, 0)
|
|
4880 |
hbox2.pack_start(vbox_right, False, False, 0)
|
|
4881 |
hbox2.pack_start(gtk.Label(), expand=True)
|
|
4882 |
dialog.vbox.pack_start(hbox, False, False, 0)
|
|
4883 |
dialog.vbox.pack_start(hbox2, False, False, 15)
|
|
4884 |
dialog.set_resizable(False)
|
|
4885 |
dialog.vbox.show_all()
|
|
4886 |
image.set_events(
|
|
4887 |
gtk.gdk.POINTER_MOTION_MASK
|
|
4888 |
| gtk.gdk.POINTER_MOTION_HINT_MASK
|
|
4889 |
| gtk.gdk.BUTTON_PRESS_MASK
|
|
4890 |
| gtk.gdk.BUTTON_MOTION_MASK
|
|
4891 |
| gtk.gdk.BUTTON_RELEASE_MASK
|
|
4892 |
)
|
|
4893 |
image.connect(
|
|
4894 |
"expose-event",
|
|
4895 |
self.crop_image_expose_cb,
|
|
4896 |
crop_pixbuf,
|
|
4897 |
image_width,
|
|
4898 |
image_height,
|
|
4899 |
)
|
|
4900 |
image.connect(
|
|
4901 |
"motion_notify_event",
|
|
4902 |
self.crop_image_mouse_moved,
|
|
4903 |
image,
|
|
4904 |
0,
|
|
4905 |
0,
|
|
4906 |
x,
|
|
4907 |
y,
|
|
4908 |
width,
|
|
4909 |
height,
|
|
4910 |
image_width,
|
|
4911 |
image_height,
|
|
4912 |
width_adj,
|
|
4913 |
height_adj,
|
|
4914 |
)
|
|
4915 |
image.connect("button_press_event", self.crop_image_button_press, image)
|
|
4916 |
image.connect("button_release_event", self.crop_image_button_release)
|
|
4917 |
self.x_changed = x.connect(
|
|
4918 |
"value-changed",
|
|
4919 |
self.crop_value_changed,
|
|
4920 |
x,
|
|
4921 |
y,
|
|
4922 |
width,
|
|
4923 |
height,
|
|
4924 |
width_adj,
|
|
4925 |
height_adj,
|
|
4926 |
image_width,
|
|
4927 |
image_height,
|
|
4928 |
image,
|
|
4929 |
0,
|
|
4930 |
)
|
|
4931 |
self.y_changed = y.connect(
|
|
4932 |
"value-changed",
|
|
4933 |
self.crop_value_changed,
|
|
4934 |
x,
|
|
4935 |
y,
|
|
4936 |
width,
|
|
4937 |
height,
|
|
4938 |
width_adj,
|
|
4939 |
height_adj,
|
|
4940 |
image_width,
|
|
4941 |
image_height,
|
|
4942 |
image,
|
|
4943 |
1,
|
|
4944 |
)
|
|
4945 |
self.width_changed = width.connect(
|
|
4946 |
"value-changed",
|
|
4947 |
self.crop_value_changed,
|
|
4948 |
x,
|
|
4949 |
y,
|
|
4950 |
width,
|
|
4951 |
height,
|
|
4952 |
width_adj,
|
|
4953 |
height_adj,
|
|
4954 |
image_width,
|
|
4955 |
image_height,
|
|
4956 |
image,
|
|
4957 |
2,
|
|
4958 |
)
|
|
4959 |
self.height_changed = height.connect(
|
|
4960 |
"value-changed",
|
|
4961 |
self.crop_value_changed,
|
|
4962 |
x,
|
|
4963 |
y,
|
|
4964 |
width,
|
|
4965 |
height,
|
|
4966 |
width_adj,
|
|
4967 |
height_adj,
|
|
4968 |
image_width,
|
|
4969 |
image_height,
|
|
4970 |
image,
|
|
4971 |
3,
|
|
4972 |
)
|
|
4973 |
image.realize()
|
|
4974 |
self.crop_rectangle = [0, 0]
|
|
4975 |
self.drawing_crop_rectangle = False
|
|
4976 |
self.update_rectangle = False
|
|
4977 |
self.rect = None
|
|
4978 |
response = dialog.run()
|
|
4979 |
if response == gtk.RESPONSE_ACCEPT:
|
|
4980 |
dialog.destroy()
|
|
4981 |
if self.rect != None:
|
|
4982 |
temp_pixbuf = gtk.gdk.Pixbuf(
|
|
4983 |
gtk.gdk.COLORSPACE_RGB,
|
|
4984 |
self.currimg_pixbuf_original.get_has_alpha(),
|
|
4985 |
8,
|
|
4986 |
self.coords[2],
|
|
4987 |
self.coords[3],
|
|
4988 |
)
|
|
4989 |
self.currimg_pixbuf_original.copy_area(
|
|
4990 |
self.coords[0],
|
|
4991 |
self.coords[1],
|
|
4992 |
self.coords[2],
|
|
4993 |
self.coords[3],
|
|
4994 |
temp_pixbuf,
|
|
4995 |
0,
|
|
4996 |
0,
|
|
4997 |
)
|
|
4998 |
self.currimg_pixbuf_original = temp_pixbuf
|
|
4999 |
del temp_pixbuf
|
|
5000 |
gc.collect()
|
|
5001 |
self.load_new_image2(False, True, False, False)
|
|
5002 |
self.image_modified = True
|
|
5003 |
else:
|
|
5004 |
dialog.destroy()
|
|
5005 |
|
|
5006 |
def crop_value_changed(
|
|
5007 |
self,
|
|
5008 |
currspinbox,
|
|
5009 |
x,
|
|
5010 |
y,
|
|
5011 |
width,
|
|
5012 |
height,
|
|
5013 |
width_adj,
|
|
5014 |
height_adj,
|
|
5015 |
image_width,
|
|
5016 |
image_height,
|
|
5017 |
image,
|
|
5018 |
type,
|
|
5019 |
):
|
|
5020 |
if type == 0: # X
|
|
5021 |
if (
|
|
5022 |
x.get_value() + width.get_value()
|
|
5023 |
> self.currimg_pixbuf_original.get_width()
|
|
5024 |
):
|
|
5025 |
width.handler_block(self.width_changed)
|
|
5026 |
width.set_value(
|
|
5027 |
self.currimg_pixbuf_original.get_width() - x.get_value()
|
|
5028 |
)
|
|
5029 |
width.handler_unblock(self.width_changed)
|
|
5030 |
elif type == 1: # Y
|
|
5031 |
if (
|
|
5032 |
y.get_value() + height.get_value()
|
|
5033 |
> self.currimg_pixbuf_original.get_height()
|
|
5034 |
):
|
|
5035 |
height.handler_block(self.height_changed)
|
|
5036 |
height.set_value(
|
|
5037 |
self.currimg_pixbuf_original.get_height() - y.get_value()
|
|
5038 |
)
|
|
5039 |
height.handler_unblock(self.height_changed)
|
|
5040 |
self.coords = [
|
|
5041 |
int(x.get_value()),
|
|
5042 |
int(y.get_value()),
|
|
5043 |
int(width.get_value()),
|
|
5044 |
int(height.get_value()),
|
|
5045 |
]
|
|
5046 |
self.crop_rectangle[0] = int(
|
|
5047 |
round(
|
|
5048 |
float(self.coords[0])
|
|
5049 |
/ self.currimg_pixbuf_original.get_width()
|
|
5050 |
* image_width,
|
|
5051 |
0,
|
|
5052 |
)
|
|
5053 |
)
|
|
5054 |
self.crop_rectangle[1] = int(
|
|
5055 |
round(
|
|
5056 |
float(self.coords[1])
|
|
5057 |
/ self.currimg_pixbuf_original.get_height()
|
|
5058 |
* image_height,
|
|
5059 |
0,
|
|
5060 |
)
|
|
5061 |
)
|
|
5062 |
x2 = (
|
|
5063 |
int(
|
|
5064 |
round(
|
|
5065 |
float(self.coords[2])
|
|
5066 |
/ self.currimg_pixbuf_original.get_width()
|
|
5067 |
* image_width,
|
|
5068 |
0,
|
|
5069 |
)
|
|
5070 |
)
|
|
5071 |
+ self.crop_rectangle[0]
|
|
5072 |
)
|
|
5073 |
y2 = (
|
|
5074 |
int(
|
|
5075 |
round(
|
|
5076 |
float(self.coords[3])
|
|
5077 |
/ self.currimg_pixbuf_original.get_height()
|
|
5078 |
* image_height,
|
|
5079 |
0,
|
|
5080 |
)
|
|
5081 |
)
|
|
5082 |
+ self.crop_rectangle[1]
|
|
5083 |
)
|
|
5084 |
self.drawing_crop_rectangle = True
|
|
5085 |
self.update_rectangle = True
|
|
5086 |
self.crop_image_mouse_moved(
|
|
5087 |
None,
|
|
5088 |
None,
|
|
5089 |
image,
|
|
5090 |
x2,
|
|
5091 |
y2,
|
|
5092 |
x,
|
|
5093 |
y,
|
|
5094 |
width,
|
|
5095 |
height,
|
|
5096 |
image_width,
|
|
5097 |
image_height,
|
|
5098 |
width_adj,
|
|
5099 |
height_adj,
|
|
5100 |
)
|
|
5101 |
self.update_rectangle = False
|
|
5102 |
self.drawing_crop_rectangle = False
|
|
5103 |
|
|
5104 |
def crop_image_expose_cb(self, image, event, pixbuf, width, height):
|
|
5105 |
image.window.draw_pixbuf(None, pixbuf, 0, 0, 0, 0, width, height)
|
|
5106 |
|
|
5107 |
def crop_image_mouse_moved(
|
|
5108 |
self,
|
|
5109 |
widget,
|
|
5110 |
event,
|
|
5111 |
image,
|
|
5112 |
x2,
|
|
5113 |
y2,
|
|
5114 |
x,
|
|
5115 |
y,
|
|
5116 |
width,
|
|
5117 |
height,
|
|
5118 |
image_width,
|
|
5119 |
image_height,
|
|
5120 |
width_adj,
|
|
5121 |
height_adj,
|
|
5122 |
):
|
|
5123 |
if event != None:
|
|
5124 |
x2, y2, state = event.window.get_pointer()
|
|
5125 |
if self.drawing_crop_rectangle:
|
|
5126 |
if self.crop_rectangle != None or self.update_rectangle:
|
|
5127 |
gc = image.window.new_gc(function=gtk.gdk.INVERT)
|
|
5128 |
if self.rect != None:
|
|
5129 |
# Get rid of the previous drawn rectangle:
|
|
5130 |
image.window.draw_rectangle(
|
|
5131 |
gc,
|
|
5132 |
False,
|
|
5133 |
self.rect[0],
|
|
5134 |
self.rect[1],
|
|
5135 |
self.rect[2],
|
|
5136 |
self.rect[3],
|
|
5137 |
)
|
|
5138 |
self.rect = [0, 0, 0, 0]
|
|
5139 |
if self.crop_rectangle[0] > x2:
|
|
5140 |
self.rect[0] = x2
|
|
5141 |
self.rect[2] = self.crop_rectangle[0] - x2
|
|
5142 |
else:
|
|
5143 |
self.rect[0] = self.crop_rectangle[0]
|
|
5144 |
self.rect[2] = x2 - self.crop_rectangle[0]
|
|
5145 |
if self.crop_rectangle[1] > y2:
|
|
5146 |
self.rect[1] = y2
|
|
5147 |
self.rect[3] = self.crop_rectangle[1] - y2
|
|
5148 |
else:
|
|
5149 |
self.rect[1] = self.crop_rectangle[1]
|
|
5150 |
self.rect[3] = y2 - self.crop_rectangle[1]
|
|
5151 |
image.window.draw_rectangle(
|
|
5152 |
gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3]
|
|
5153 |
)
|
|
5154 |
# Convert the rectangle coordinates of the current image
|
|
5155 |
# to coordinates of pixbuf_original
|
|
5156 |
if self.rect[0] < 0:
|
|
5157 |
self.rect[2] = self.rect[2] + self.rect[0]
|
|
5158 |
self.rect[0] = 0
|
|
5159 |
if self.rect[1] < 0:
|
|
5160 |
self.rect[3] = self.rect[3] + self.rect[1]
|
|
5161 |
self.rect[1] = 0
|
|
5162 |
if event != None:
|
|
5163 |
self.coords = [0, 0, 0, 0]
|
|
5164 |
self.coords[0] = int(
|
|
5165 |
round(
|
|
5166 |
float(self.rect[0])
|
|
5167 |
/ image_width
|
|
5168 |
* self.currimg_pixbuf_original.get_width(),
|
|
5169 |
0,
|
|
5170 |
)
|
|
5171 |
)
|
|
5172 |
self.coords[1] = int(
|
|
5173 |
round(
|
|
5174 |
float(self.rect[1])
|
|
5175 |
/ image_height
|
|
5176 |
* self.currimg_pixbuf_original.get_height(),
|
|
5177 |
0,
|
|
5178 |
)
|
|
5179 |
)
|
|
5180 |
self.coords[2] = int(
|
|
5181 |
round(
|
|
5182 |
float(self.rect[2])
|
|
5183 |
/ image_width
|
|
5184 |
* self.currimg_pixbuf_original.get_width(),
|
|
5185 |
0,
|
|
5186 |
)
|
|
5187 |
)
|
|
5188 |
self.coords[3] = int(
|
|
5189 |
round(
|
|
5190 |
float(self.rect[3])
|
|
5191 |
/ image_height
|
|
5192 |
* self.currimg_pixbuf_original.get_height(),
|
|
5193 |
0,
|
|
5194 |
)
|
|
5195 |
)
|
|
5196 |
if (
|
|
5197 |
self.coords[0] + self.coords[2]
|
|
5198 |
> self.currimg_pixbuf_original.get_width()
|
|
5199 |
):
|
|
5200 |
self.coords[2] = (
|
|
5201 |
self.currimg_pixbuf_original.get_width() - self.coords[0]
|
|
5202 |
)
|
|
5203 |
if (
|
|
5204 |
self.coords[1] + self.coords[3]
|
|
5205 |
> self.currimg_pixbuf_original.get_height()
|
|
5206 |
):
|
|
5207 |
self.coords[3] = (
|
|
5208 |
self.currimg_pixbuf_original.get_height() - self.coords[1]
|
|
5209 |
)
|
|
5210 |
x.handler_block(self.x_changed)
|
|
5211 |
y.handler_block(self.y_changed)
|
|
5212 |
width.handler_block(self.width_changed)
|
|
5213 |
height.handler_block(self.height_changed)
|
|
5214 |
x.set_value(self.coords[0])
|
|
5215 |
y.set_value(self.coords[1])
|
|
5216 |
width.set_value(self.coords[2])
|
|
5217 |
height.set_value(self.coords[3])
|
|
5218 |
x.handler_unblock(self.x_changed)
|
|
5219 |
y.handler_unblock(self.y_changed)
|
|
5220 |
width_adj.set_property(
|
|
5221 |
"upper", self.currimg_pixbuf_original.get_width() - self.coords[0]
|
|
5222 |
)
|
|
5223 |
height_adj.set_property(
|
|
5224 |
"upper", self.currimg_pixbuf_original.get_height() - self.coords[1]
|
|
5225 |
)
|
|
5226 |
width.handler_unblock(self.width_changed)
|
|
5227 |
height.handler_unblock(self.height_changed)
|
|
5228 |
|
|
5229 |
def crop_image_button_press(self, widget, event, image):
|
|
5230 |
x, y, state = event.window.get_pointer()
|
|
5231 |
if state & gtk.gdk.BUTTON1_MASK:
|
|
5232 |
self.drawing_crop_rectangle = True
|
|
5233 |
self.crop_rectangle = [x, y]
|
|
5234 |
gc = image.window.new_gc(function=gtk.gdk.INVERT)
|
|
5235 |
if self.rect != None:
|
|
5236 |
# Get rid of the previous drawn rectangle:
|
|
5237 |
image.window.draw_rectangle(
|
|
5238 |
gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3]
|
|
5239 |
)
|
|
5240 |
self.rect = None
|
|
5241 |
|
|
5242 |
def crop_image_button_release(self, widget, event):
|
|
5243 |
x, y, state = event.window.get_pointer()
|
|
5244 |
if not (state & gtk.gdk.BUTTON1_MASK):
|
|
5245 |
self.drawing_crop_rectangle = False
|
|
5246 |
|
|
5247 |
def saturation(self, action):
|
|
5248 |
dialog = gtk.Dialog(
|
|
5249 |
_("Saturation"),
|
|
5250 |
self.window,
|
|
5251 |
gtk.DIALOG_MODAL,
|
|
5252 |
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT),
|
|
5253 |
)
|
|
5254 |
resizebutton = dialog.add_button(_("_Saturate"), gtk.RESPONSE_ACCEPT)
|
|
5255 |
resizeimage = gtk.Image()
|
|
5256 |
resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
|
5257 |
resizebutton.set_image(resizeimage)
|
|
5258 |
scale = gtk.HScale()
|
|
5259 |
scale.set_draw_value(False)
|
|
5260 |
scale.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
|
|
5261 |
scale.set_range(0, 2)
|
|
5262 |
scale.set_increments(0.1, 0.5)
|
|
5263 |
scale.set_value(1)
|
|
5264 |
scale.connect("value-changed", self.saturation_preview)
|
|
5265 |
label = gtk.Label(_("Saturation level:"))
|
|
5266 |
label.set_alignment(0, 0.5)
|
|
5267 |
hbox1 = gtk.HBox()
|
|
5268 |
hbox1.pack_start(label, True, True, 10)
|
|
5269 |
hbox2 = gtk.HBox()
|
|
5270 |
hbox2.pack_start(scale, True, True, 20)
|
|
5271 |
dialog.vbox.pack_start(gtk.Label(" "))
|
|
5272 |
dialog.vbox.pack_start(hbox1, False)
|
|
5273 |
dialog.vbox.pack_start(hbox2, True, True, 10)
|
|
5274 |
dialog.vbox.pack_start(gtk.Label(" "))
|
|
5275 |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
|
5276 |
dialog.vbox.show_all()
|
|
5277 |
response = dialog.run()
|
|
5278 |
if response == gtk.RESPONSE_ACCEPT:
|
|
5279 |
self.currimg_pixbuf_original.saturate_and_pixelate(
|
|
5280 |
self.currimg_pixbuf_original, scale.get_value(), False
|
|
5281 |
)
|
|
5282 |
self.currimg_pixbuf.saturate_and_pixelate(
|
|
5283 |
self.currimg_pixbuf, scale.get_value(), False
|
|
5284 |
)
|
|
5285 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
5286 |
self.image_modified = True
|
|
5287 |
dialog.destroy()
|
|
5288 |
else:
|
|
5289 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
5290 |
dialog.destroy()
|
|
5291 |
|
|
5292 |
def saturation_preview(self, range):
|
|
5293 |
while gtk.events_pending():
|
|
5294 |
gtk.main_iteration()
|
|
5295 |
try:
|
|
5296 |
bak = self.currimg_pixbuf.copy()
|
|
5297 |
self.currimg_pixbuf.saturate_and_pixelate(
|
|
5298 |
self.currimg_pixbuf, range.get_value(), False
|
|
5299 |
)
|
|
5300 |
self.imageview.set_from_pixbuf(self.currimg_pixbuf)
|
|
5301 |
self.currimg_pixbuf = bak.copy()
|
|
5302 |
del bak
|
|
5303 |
except:
|
|
5304 |
pass
|
|
5305 |
gc.collect()
|
|
5306 |
|
|
5307 |
def resize_image(self, action):
|
|
5308 |
dialog = gtk.Dialog(
|
|
5309 |
_("Resize Image"),
|
|
5310 |
self.window,
|
|
5311 |
gtk.DIALOG_MODAL,
|
|
5312 |
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT),
|
|
5313 |
)
|
|
5314 |
resizebutton = dialog.add_button(_("_Resize"), gtk.RESPONSE_ACCEPT)
|
|
5315 |
resizeimage = gtk.Image()
|
|
5316 |
resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
|
|
5317 |
resizebutton.set_image(resizeimage)
|
|
5318 |
hbox_width = gtk.HBox()
|
|
5319 |
width_adj = gtk.Adjustment(
|
|
5320 |
self.currimg_pixbuf_original.get_width(), 1, 100000000000, 1, 10, 0
|
|
5321 |
)
|
|
5322 |
width = gtk.SpinButton(width_adj, 0, 0)
|
|
5323 |
width.set_numeric(True)
|
|
5324 |
width.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
5325 |
width.set_wrap(False)
|
|
5326 |
width_label = gtk.Label(_("Width:"))
|
|
5327 |
width_label.set_alignment(0, 0.7)
|
|
5328 |
hbox_width.pack_start(width_label, False, False, 10)
|
|
5329 |
hbox_width.pack_start(width, False, False, 0)
|
|
5330 |
hbox_width.pack_start(gtk.Label(_("pixels")), False, False, 10)
|
|
5331 |
hbox_height = gtk.HBox()
|
|
5332 |
height_adj = gtk.Adjustment(
|
|
5333 |
self.currimg_pixbuf_original.get_height(), 1, 100000000000, 1, 10, 0
|
|
5334 |
)
|
|
5335 |
height = gtk.SpinButton(height_adj, 0, 0)
|
|
5336 |
height.set_numeric(True)
|
|
5337 |
height.set_update_policy(gtk.UPDATE_IF_VALID)
|
|
5338 |
height.set_wrap(False)
|
|
5339 |
height_label = gtk.Label(_("Height:"))
|
|
5340 |
width_label.set_size_request(height_label.size_request()[0], -1)
|
|
5341 |
height_label.set_alignment(0, 0.7)
|
|
5342 |
hbox_height.pack_start(height_label, False, False, 10)
|
|
5343 |
hbox_height.pack_start(height, False, False, 0)
|
|
5344 |
hbox_height.pack_start(gtk.Label(_("pixels")), False, False, 10)
|
|
5345 |
hbox_aspect = gtk.HBox()
|
|
5346 |
aspect_checkbox = gtk.CheckButton(_("Preserve aspect ratio"))
|
|
5347 |
aspect_checkbox.set_active(self.preserve_aspect)
|
|
5348 |
hbox_aspect.pack_start(aspect_checkbox, False, False, 10)
|
|
5349 |
vbox = gtk.VBox()
|
|
5350 |
vbox.pack_start(gtk.Label(), False, False, 0)
|
|
5351 |
vbox.pack_start(hbox_width, False, False, 0)
|
|
5352 |
vbox.pack_start(hbox_height, False, False, 0)
|
|
5353 |
vbox.pack_start(gtk.Label(), False, False, 0)
|
|
5354 |
vbox.pack_start(hbox_aspect, False, False, 0)
|
|
5355 |
vbox.pack_start(gtk.Label(), False, False, 0)
|
|
5356 |
hbox_total = gtk.HBox()
|
|
5357 |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
|
5358 |
if animtest.is_static_image():
|
|
5359 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
5360 |
self.currimg_pixbuf_original, 96, self.zoom_quality
|
|
5361 |
)
|
|
5362 |
else:
|
|
5363 |
pixbuf, image_width, image_height = self.get_pixbuf_of_size(
|
|
5364 |
animtest.get_static_image(), 96, self.zoom_quality
|
|
5365 |
)
|
|
5366 |
image = gtk.Image()
|
|
5367 |
image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
|
|
5368 |
hbox_total.pack_start(image, False, False, 10)
|
|
5369 |
hbox_total.pack_start(vbox, False, False, 10)
|
|
5370 |
dialog.vbox.pack_start(hbox_total, False, False, 0)
|
|
5371 |
width.connect("value-changed", self.preserve_image_aspect, "width", height)
|
|
5372 |
height.connect("value-changed", self.preserve_image_aspect, "height", width)
|
|
5373 |
aspect_checkbox.connect("toggled", self.aspect_ratio_toggled, width, height)
|
|
5374 |
dialog.set_default_response(gtk.RESPONSE_ACCEPT)
|
|
5375 |
dialog.vbox.show_all()
|
|
5376 |
response = dialog.run()
|
|
5377 |
if response == gtk.RESPONSE_ACCEPT:
|
|
5378 |
pixelheight = height.get_value_as_int()
|
|
5379 |
pixelwidth = width.get_value_as_int()
|
|
5380 |
dialog.destroy()
|
|
5381 |
self.currimg_pixbuf_original = self.currimg_pixbuf_original.scale_simple(
|
|
5382 |
pixelwidth, pixelheight, self.zoom_quality
|
|
5383 |
)
|
|
5384 |
self.load_new_image2(False, True, False, False)
|
|
5385 |
self.image_modified = True
|
|
5386 |
else:
|
|
5387 |
dialog.destroy()
|
|
5388 |
|
|
5389 |
def aspect_ratio_toggled(self, togglebutton, width, height):
|
|
5390 |
self.preserve_aspect = togglebutton.get_active()
|
|
5391 |
if self.preserve_aspect:
|
|
5392 |
# Set height based on width and aspect ratio
|
|
5393 |
target_value = (
|
|
5394 |
float(width.get_value_as_int())
|
|
5395 |
/ self.currimg_pixbuf_original.get_width()
|
|
5396 |
)
|
|
5397 |
target_value = int(target_value * self.currimg_pixbuf_original.get_height())
|
|
5398 |
self.ignore_preserve_aspect_callback = True
|
|
5399 |
height.set_value(target_value)
|
|
5400 |
self.ignore_preserve_aspect_callback = False
|
|
5401 |
|
|
5402 |
def preserve_image_aspect(self, currspinbox, type, otherspinbox):
|
|
5403 |
if not self.preserve_aspect:
|
|
5404 |
return
|
|
5405 |
if self.ignore_preserve_aspect_callback:
|
|
5406 |
return
|
|
5407 |
if type == "width":
|
|
5408 |
target_value = (
|
|
5409 |
float(currspinbox.get_value_as_int())
|
|
5410 |
/ self.currimg_pixbuf_original.get_width()
|
|
5411 |
)
|
|
5412 |
target_value = int(target_value * self.currimg_pixbuf_original.get_height())
|
|
5413 |
else:
|
|
5414 |
target_value = (
|
|
5415 |
float(currspinbox.get_value_as_int())
|
|
5416 |
/ self.currimg_pixbuf_original.get_height()
|
|
5417 |
)
|
|
5418 |
target_value = int(target_value * self.currimg_pixbuf_original.get_width())
|
|
5419 |
self.ignore_preserve_aspect_callback = True
|
|
5420 |
otherspinbox.set_value(target_value)
|
|
5421 |
self.ignore_preserve_aspect_callback = False
|
|
5422 |
|
|
5423 |
def goto_prev_image(self, action):
|
|
5424 |
self.goto_image("PREV", action)
|
|
5425 |
|
|
5426 |
def goto_next_image(self, action):
|
|
5427 |
self.goto_image("NEXT", action)
|
|
5428 |
|
|
5429 |
def goto_random_image(self, action):
|
|
5430 |
self.goto_image("RANDOM", action)
|
|
5431 |
|
|
5432 |
def goto_first_image(self, action):
|
|
5433 |
self.goto_image("FIRST", action)
|
|
5434 |
|
|
5435 |
def goto_last_image(self, action):
|
|
5436 |
self.goto_image("LAST", action)
|
|
5437 |
|
|
5438 |
def goto_image(self, location, action):
|
|
5439 |
# location can be "LAST", "FIRST", "NEXT", "PREV", "RANDOM", or a number
|
|
5440 |
if self.slideshow_mode and action != "ss":
|
|
5441 |
gobject.source_remove(self.timer_delay)
|
|
5442 |
if (
|
|
5443 |
(
|
|
5444 |
(location == "PREV" or location == "NEXT" or location == "RANDOM")
|
|
5445 |
and len(self.image_list) > 1
|
|
5446 |
)
|
|
5447 |
or (
|
|
5448 |
location == "FIRST"
|
|
5449 |
and (len(self.image_list) > 1 and self.curr_img_in_list != 0)
|
|
5450 |
)
|
|
5451 |
or (
|
|
5452 |
location == "LAST"
|
|
5453 |
and (
|
|
5454 |
len(self.image_list) > 1
|
|
5455 |
and self.curr_img_in_list != len(self.image_list) - 1
|
|
5456 |
)
|
|
5457 |
)
|
|
5458 |
or valid_int(location)
|
|
5459 |
):
|
|
5460 |
self.load_new_image_stop_now()
|
|
5461 |
cancel = self.autosave_image()
|
|
5462 |
if cancel:
|
|
5463 |
return
|
|
5464 |
check_wrap = False
|
|
5465 |
if location != "RANDOM":
|
|
5466 |
self.randomlist = []
|
|
5467 |
if location == "FIRST":
|
|
5468 |
self.curr_img_in_list = 0
|
|
5469 |
elif location == "RANDOM":
|
|
5470 |
if self.randomlist == []:
|
|
5471 |
self.reinitialize_randomlist()
|
|
5472 |
else:
|
|
5473 |
# check if we have seen every image; if so, reinitialize array and repeat:
|
|
5474 |
all_items_are_true = True
|
|
5475 |
for item in self.randomlist:
|
|
5476 |
if not item:
|
|
5477 |
all_items_are_true = False
|
|
5478 |
if all_items_are_true:
|
|
5479 |
if not self.slideshow_mode or (
|
|
5480 |
self.slideshow_mode and self.listwrap_mode == 1
|
|
5481 |
):
|
|
5482 |
self.reinitialize_randomlist()
|
|
5483 |
else:
|
|
5484 |
check_wrap = True
|
|
5485 |
elif location == "LAST":
|
|
5486 |
self.curr_img_in_list = len(self.image_list) - 1
|
|
5487 |
elif location == "PREV":
|
|
5488 |
if self.curr_img_in_list > 0:
|
|
5489 |
self.curr_img_in_list -= 1
|
|
5490 |
else:
|
|
5491 |
check_wrap = True
|
|
5492 |
elif location == "NEXT":
|
|
5493 |
if self.curr_img_in_list < len(self.image_list) - 1:
|
|
5494 |
self.curr_img_in_list += 1
|
|
5495 |
else:
|
|
5496 |
check_wrap = True
|
|
5497 |
if check_wrap:
|
|
5498 |
if self.listwrap_mode == 0:
|
|
5499 |
if location == "NEXT":
|
|
5500 |
if self.slideshow_mode:
|
|
5501 |
self.toggle_slideshow(None)
|
|
5502 |
return
|
|
5503 |
elif (
|
|
5504 |
location == "PREV" or location == "NEXT"
|
|
5505 |
) and self.listwrap_mode == 1:
|
|
5506 |
if location == "PREV":
|
|
5507 |
self.curr_img_in_list = len(self.image_list) - 1
|
|
5508 |
elif location == "NEXT":
|
|
5509 |
self.curr_img_in_list = 0
|
|
5510 |
else:
|
|
5511 |
if self.curr_img_in_list != self.loaded_img_in_list:
|
|
5512 |
# Ensure that the user is looking at the correct "last" image before
|
|
5513 |
# they are asked the wrap question:
|
|
5514 |
if location == "PREV":
|
|
5515 |
self.load_new_image(True, False, True, True, True, True)
|
|
5516 |
else:
|
|
5517 |
self.load_new_image(False, False, True, True, True, True)
|
|
5518 |
self.set_go_navigation_sensitivities(False)
|
|
5519 |
self.thumbpane_select(self.curr_img_in_list)
|
|
5520 |
if self.fullscreen_mode:
|
|
5521 |
self.change_cursor(None)
|
|
5522 |
if location == "PREV":
|
|
5523 |
dialog = gtk.MessageDialog(
|
|
5524 |
self.window,
|
|
5525 |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
|
5526 |
gtk.MESSAGE_QUESTION,
|
|
5527 |
gtk.BUTTONS_YES_NO,
|
|
5528 |
_(
|
|
5529 |
"You are viewing the first image in the list. Wrap around to the last image?"
|
|
5530 |
),
|
|
5531 |
)
|
|
5532 |
elif location == "NEXT":
|
|
5533 |
dialog = gtk.MessageDialog(
|
|
5534 |
self.window,
|
|
5535 |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
|
5536 |
gtk.MESSAGE_QUESTION,
|
|
5537 |
gtk.BUTTONS_YES_NO,
|
|
5538 |
_(
|
|
5539 |
"You are viewing the last image in the list. Wrap around to the first image?"
|
|
5540 |
),
|
|
5541 |
)
|
|
5542 |
elif location == "RANDOM":
|
|
5543 |
dialog = gtk.MessageDialog(
|
|
5544 |
self.window,
|
|
5545 |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
|
5546 |
gtk.MESSAGE_QUESTION,
|
|
5547 |
gtk.BUTTONS_YES_NO,
|
|
5548 |
_(
|
|
5549 |
"All images have been viewed. Would you like to cycle through the images again?"
|
|
5550 |
),
|
|
5551 |
)
|
|
5552 |
dialog.set_title(_("Wrap?"))
|
|
5553 |
dialog.label.set_property("can-focus", False)
|
|
5554 |
dialog.set_default_response(gtk.RESPONSE_YES)
|
|
5555 |
self.user_prompt_visible = True
|
|
5556 |
response = dialog.run()
|
|
5557 |
if response == gtk.RESPONSE_YES:
|
|
5558 |
if location == "PREV":
|
|
5559 |
self.curr_img_in_list = len(self.image_list) - 1
|
|
5560 |
elif location == "NEXT":
|
|
5561 |
self.curr_img_in_list = 0
|
|
5562 |
elif location == "RANDOM":
|
|
5563 |
self.reinitialize_randomlist()
|
|
5564 |
dialog.destroy()
|
|
5565 |
self.user_prompt_visible = False
|
|
5566 |
if self.fullscreen_mode:
|
|
5567 |
self.hide_cursor
|
|
5568 |
else:
|
|
5569 |
dialog.destroy()
|
|
5570 |
self.user_prompt_visible = False
|
|
5571 |
if self.fullscreen_mode:
|
|
5572 |
self.hide_cursor
|
|
5573 |
else:
|
|
5574 |
self.change_cursor(None)
|
|
5575 |
if self.slideshow_mode:
|
|
5576 |
self.toggle_slideshow(None)
|
|
5577 |
return
|
|
5578 |
if location == "RANDOM":
|
|
5579 |
# Find random image that hasn't already been chosen:
|
|
5580 |
j = random.randint(0, len(self.image_list) - 1)
|
|
5581 |
while self.randomlist[j]:
|
|
5582 |
j = random.randint(0, len(self.image_list) - 1)
|
|
5583 |
self.curr_img_in_list = j
|
|
5584 |
self.randomlist[j] = True
|
|
5585 |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
|
5586 |
if valid_int(location):
|
|
5587 |
prev_img = self.curr_img_in_list
|
|
5588 |
self.curr_img_in_list = int(location)
|
|
5589 |
if not self.fullscreen_mode and (
|
|
5590 |
not self.slideshow_mode or (self.slideshow_mode and action != "ss")
|
|
5591 |
):
|
|
5592 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
5593 |
if location == "PREV" or (
|
|
5594 |
valid_int(location) and int(location) == prev_img - 1
|
|
5595 |
):
|
|
5596 |
self.load_when_idle = gobject.idle_add(
|
|
5597 |
self.load_new_image, True, False, True, True, True, True
|
|
5598 |
)
|
|
5599 |
else:
|
|
5600 |
self.load_when_idle = gobject.idle_add(
|
|
5601 |
self.load_new_image, False, False, True, True, True, True
|
|
5602 |
)
|
|
5603 |
self.set_go_navigation_sensitivities(False)
|
|
5604 |
if self.slideshow_mode:
|
|
5605 |
if self.curr_slideshow_random:
|
|
5606 |
self.timer_delay = gobject.timeout_add(
|
|
5607 |
int(self.curr_slideshow_delay * 1000),
|
|
5608 |
self.goto_random_image,
|
|
5609 |
"ss",
|
|
5610 |
)
|
|
5611 |
else:
|
|
5612 |
self.timer_delay = gobject.timeout_add(
|
|
5613 |
int(self.curr_slideshow_delay * 1000),
|
|
5614 |
self.goto_next_image,
|
|
5615 |
"ss",
|
|
5616 |
)
|
|
5617 |
gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
|
|
5618 |
|
|
5619 |
def set_go_navigation_sensitivities(self, skip_initial_check):
|
|
5620 |
# setting skip_image_list_check to True is useful when calling from
|
|
5621 |
# expand_filelist_and_load_image() for example, as self.image_list has not
|
|
5622 |
# yet fully populated
|
|
5623 |
if (
|
|
5624 |
not self.image_loaded or len(self.image_list) == 1
|
|
5625 |
) and not skip_initial_check:
|
|
5626 |
self.set_previous_image_sensitivities(False)
|
|
5627 |
self.set_first_image_sensitivities(False)
|
|
5628 |
self.set_next_image_sensitivities(False)
|
|
5629 |
self.set_last_image_sensitivities(False)
|
|
5630 |
self.set_random_image_sensitivities(False)
|
|
5631 |
elif self.curr_img_in_list == 0:
|
|
5632 |
if self.listwrap_mode == 0:
|
|
5633 |
self.set_previous_image_sensitivities(False)
|
|
5634 |
else:
|
|
5635 |
self.set_previous_image_sensitivities(True)
|
|
5636 |
self.set_first_image_sensitivities(False)
|
|
5637 |
self.set_next_image_sensitivities(True)
|
|
5638 |
self.set_last_image_sensitivities(True)
|
|
5639 |
self.set_random_image_sensitivities(True)
|
|
5640 |
elif self.curr_img_in_list == len(self.image_list) - 1:
|
|
5641 |
self.set_previous_image_sensitivities(True)
|
|
5642 |
self.set_first_image_sensitivities(True)
|
|
5643 |
if self.listwrap_mode == 0:
|
|
5644 |
self.set_next_image_sensitivities(False)
|
|
5645 |
else:
|
|
5646 |
self.set_next_image_sensitivities(True)
|
|
5647 |
self.set_last_image_sensitivities(False)
|
|
5648 |
self.set_random_image_sensitivities(True)
|
|
5649 |
else:
|
|
5650 |
self.set_previous_image_sensitivities(True)
|
|
5651 |
self.set_first_image_sensitivities(True)
|
|
5652 |
self.set_next_image_sensitivities(True)
|
|
5653 |
self.set_last_image_sensitivities(True)
|
|
5654 |
self.set_random_image_sensitivities(True)
|
|
5655 |
|
|
5656 |
def reinitialize_randomlist(self):
|
|
5657 |
self.randomlist = []
|
|
5658 |
for i in range(len(self.image_list)):
|
|
5659 |
self.randomlist.append(False)
|
|
5660 |
self.randomlist[self.curr_img_in_list] = True
|
|
5661 |
|
|
5662 |
def image_load_failed(self, reset_cursor, filename=""):
|
|
5663 |
# If a filename is provided, use it for display:
|
|
5664 |
if len(filename) == 0:
|
|
5665 |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
|
5666 |
else:
|
|
5667 |
self.currmg_name = filename
|
|
5668 |
if self.verbose and self.currimg_name != "":
|
|
5669 |
print(_("Loading: %s") % self.currimg_name)
|
|
5670 |
self.update_title()
|
|
5671 |
self.put_error_image_to_window()
|
|
5672 |
self.image_loaded = False
|
|
5673 |
self.currimg_pixbuf_original = None
|
|
5674 |
if reset_cursor:
|
|
5675 |
if not self.fullscreen_mode:
|
|
5676 |
self.change_cursor(None)
|
|
5677 |
|
|
5678 |
def load_new_image_stop_now(self):
|
|
5679 |
try:
|
|
5680 |
gobject.source_remove(self.load_when_idle)
|
|
5681 |
except:
|
|
5682 |
pass
|
|
5683 |
try:
|
|
5684 |
gobject.source_remove(self.preload_when_idle)
|
|
5685 |
except:
|
|
5686 |
pass
|
|
5687 |
try:
|
|
5688 |
gobject.source_remove(self.preload_when_idle2)
|
|
5689 |
except:
|
|
5690 |
pass
|
|
5691 |
|
|
5692 |
def load_new_image(
|
|
5693 |
self,
|
|
5694 |
check_prev_last,
|
|
5695 |
use_current_pixbuf_original,
|
|
5696 |
reset_cursor,
|
|
5697 |
perform_onload_action,
|
|
5698 |
preload_next_image_after,
|
|
5699 |
preload_prev_image_after,
|
|
5700 |
):
|
|
5701 |
try:
|
|
5702 |
self.load_new_image2(
|
|
5703 |
check_prev_last,
|
|
5704 |
use_current_pixbuf_original,
|
|
5705 |
reset_cursor,
|
|
5706 |
perform_onload_action,
|
|
5707 |
)
|
|
5708 |
except:
|
|
5709 |
self.image_load_failed(True)
|
|
5710 |
if preload_next_image_after:
|
|
5711 |
self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
|
|
5712 |
if preload_prev_image_after:
|
|
5713 |
self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, False)
|
|
5714 |
|
|
5715 |
def check_preloadimg_prev_for_existing(
|
|
5716 |
self, prev_index, reset_preloadimg_prev_in_list
|
|
5717 |
):
|
|
5718 |
# Determines if preloadimg_prev needs to be updated; if so,
|
|
5719 |
# checks if the image is already stored in self.currimg
|
|
5720 |
# or self.preloadimg_next and can be reused.
|
|
5721 |
reset_preloadimg_prev_in_list = False
|
|
5722 |
if prev_index != self.preloadimg_prev_in_list and prev_index != -1:
|
|
5723 |
# Need to update preloadimg_prev:
|
|
5724 |
if (
|
|
5725 |
prev_index == self.loaded_img_in_list
|
|
5726 |
and not self.image_modified
|
|
5727 |
and not self.image_zoomed
|
|
5728 |
):
|
|
5729 |
self.preloadimg_prev_in_list = self.loaded_img_in_list
|
|
5730 |
self.preloadimg_prev_name = self.currimg_name
|
|
5731 |
self.preloadimg_prev_width = self.currimg_width
|
|
5732 |
self.preloadimg_prev_height = self.currimg_height
|
|
5733 |
self.preloadimg_prev_pixbuf = self.currimg_pixbuf
|
|
5734 |
self.preloadimg_prev_pixbuf_original = self.currimg_pixbuf_original
|
|
5735 |
self.preloadimg_prev_zoomratio = self.currimg_zoomratio
|
|
5736 |
self.preloadimg_prev_is_animation = self.currimg_is_animation
|
|
5737 |
elif prev_index == self.preloadimg_next_in_list:
|
|
5738 |
self.preloadimg_prev_in_list = self.preloadimg_next_in_list
|
|
5739 |
self.preloadimg_prev_name = self.preloadimg_next_name
|
|
5740 |
self.preloadimg_prev_width = self.preloadimg_next_width
|
|
5741 |
self.preloadimg_prev_height = self.preloadimg_next_height
|
|
5742 |
self.preloadimg_prev_pixbuf = self.preloadimg_next_pixbuf
|
|
5743 |
self.preloadimg_prev_pixbuf_original = (
|
|
5744 |
self.preloadimg_next_pixbuf_original
|
|
5745 |
)
|
|
5746 |
self.preloadimg_prev_zoomratio = self.preloadimg_next_zoomratio
|
|
5747 |
self.preloadimg_prev_is_animation = self.preloadimg_next_is_animation
|
|
5748 |
else:
|
|
5749 |
reset_preloadimg_prev_in_list = True
|
|
5750 |
elif prev_index == -1:
|
|
5751 |
reset_preloadimg_prev_in_list = True
|
|
5752 |
|
|
5753 |
def check_preloadimg_next_for_existing(
|
|
5754 |
self, next_index, reset_preloadimg_next_in_list
|
|
5755 |
):
|
|
5756 |
# Determines if preloadimg_next needs to be updated; if so,
|
|
5757 |
# checks if the image is already stored in self.currimg
|
|
5758 |
# or self.preloadimg_prev and can be reused.
|
|
5759 |
reset_preloadimg_next_in_list = False
|
|
5760 |
if next_index != self.preloadimg_next_in_list and next_index != -1:
|
|
5761 |
# Need to update preloadimg_next:
|
|
5762 |
if (
|
|
5763 |
next_index == self.loaded_img_in_list
|
|
5764 |
and not self.image_modified
|
|
5765 |
and not self.image_zoomed
|
|
5766 |
):
|
|
5767 |
self.preloadimg_next_in_list = self.loaded_img_in_list
|
|
5768 |
self.preloadimg_next_name = self.currimg_name
|
|
5769 |
self.preloadimg_next_width = self.currimg_width
|
|
5770 |
self.preloadimg_next_height = self.currimg_height
|
|
5771 |
self.preloadimg_next_pixbuf = self.currimg_pixbuf
|
|
5772 |
self.preloadimg_next_pixbuf_original = self.currimg_pixbuf_original
|
|
5773 |
self.preloadimg_next_zoomratio = self.currimg_zoomratio
|
|
5774 |
self.preloadimg_next_is_animation = self.currimg_is_animation
|
|
5775 |
elif next_index == self.preloadimg_prev_in_list:
|
|
5776 |
self.preloadimg_next_in_list = self.preloadimg_prev_in_list
|
|
5777 |
self.preloadimg_next_name = self.preloadimg_prev_name
|
|
5778 |
self.preloadimg_next_width = self.preloadimg_prev_width
|
|
5779 |
self.preloadimg_next_height = self.preloadimg_prev_height
|
|
5780 |
self.preloadimg_next_pixbuf = self.preloadimg_prev_pixbuf
|
|
5781 |
self.preloadimg_next_pixbuf_original = (
|
|
5782 |
self.preloadimg_prev_pixbuf_original
|
|
5783 |
)
|
|
5784 |
self.preloadimg_next_zoomratio = self.preloadimg_prev_zoomratio
|
|
5785 |
self.preloadimg_next_is_animation = self.preloadimg_prev_is_animation
|
|
5786 |
else:
|
|
5787 |
reset_preloadimg_next_in_list = True
|
|
5788 |
elif next_index == -1:
|
|
5789 |
reset_preloadimg_next_in_list = True
|
|
5790 |
|
|
5791 |
def check_currimg_for_existing(self):
|
|
5792 |
# Determines if currimg needs to be updated; if so,
|
|
5793 |
# checks if the image is already stored in self.preloadimg_next
|
|
5794 |
# or self.preloadimg_prev and can be reused (the whole point of
|
|
5795 |
# preloading!)
|
|
5796 |
used_prev = False
|
|
5797 |
used_next = False
|
|
5798 |
if self.curr_img_in_list != self.loaded_img_in_list:
|
|
5799 |
# Need to update currimg:
|
|
5800 |
if self.curr_img_in_list == self.preloadimg_prev_in_list:
|
|
5801 |
# Set preload_prev_image as current image
|
|
5802 |
self.currimg_name = self.preloadimg_prev_name
|
|
5803 |
self.currimg_width = self.preloadimg_prev_width
|
|
5804 |
self.currimg_height = self.preloadimg_prev_height
|
|
5805 |
self.currimg_pixbuf = self.preloadimg_prev_pixbuf
|
|
5806 |
self.currimg_pixbuf_original = self.preloadimg_prev_pixbuf_original
|
|
5807 |
self.currimg_zoomratio = self.preloadimg_prev_zoomratio
|
|
5808 |
self.currimg_is_animation = self.preloadimg_prev_is_animation
|
|
5809 |
used_prev = True
|
|
5810 |
if self.verbose and self.currimg_name != "":
|
|
5811 |
print(_("Loading: %s") % self.currimg_name)
|
|
5812 |
self.put_zoom_image_to_window(True)
|
|
5813 |
if not self.currimg_is_animation:
|
|
5814 |
self.set_image_sensitivities(True)
|
|
5815 |
else:
|
|
5816 |
self.set_image_sensitivities(False)
|
|
5817 |
elif self.curr_img_in_list == self.preloadimg_next_in_list:
|
|
5818 |
# Use preload_next_image as current image
|
|
5819 |
self.currimg_name = self.preloadimg_next_name
|
|
5820 |
self.currimg_width = self.preloadimg_next_width
|
|
5821 |
self.currimg_height = self.preloadimg_next_height
|
|
5822 |
self.currimg_pixbuf = self.preloadimg_next_pixbuf
|
|
5823 |
self.currimg_pixbuf_original = self.preloadimg_next_pixbuf_original
|
|
5824 |
self.currimg_zoomratio = self.preloadimg_next_zoomratio
|
|
5825 |
self.currimg_is_animation = self.preloadimg_next_is_animation
|
|
5826 |
used_next = True
|
|
5827 |
if self.verbose and self.currimg_name != "":
|
|
5828 |
print(_("Loading: %s") % self.currimg_name)
|
|
5829 |
self.put_zoom_image_to_window(True)
|
|
5830 |
if not self.currimg_is_animation:
|
|
5831 |
self.set_image_sensitivities(True)
|
|
5832 |
else:
|
|
5833 |
self.set_image_sensitivities(False)
|
|
5834 |
return used_prev, used_next
|
|
5835 |
|
|
5836 |
def load_new_image2(
|
|
5837 |
self,
|
|
5838 |
check_prev_last,
|
|
5839 |
use_current_pixbuf_original,
|
|
5840 |
reset_cursor,
|
|
5841 |
perform_onload_action,
|
|
5842 |
skip_recentfiles=False,
|
|
5843 |
):
|
|
5844 |
# check_prev_last is used to determine if we should check whether
|
|
5845 |
# preloadimg_prev can be reused last. This should really only
|
|
5846 |
# be done if the user just clicked the previous image button in
|
|
5847 |
# order to reduce the number of image loads.
|
|
5848 |
# If use_current_pixbuf_original == True, do not reload the
|
|
5849 |
# self.currimg_pixbuf_original from the file; instead, use the existing
|
|
5850 |
# one. This is only currently useful for resizing images.
|
|
5851 |
# Determine the indices in the self.image_list array for the
|
|
5852 |
# previous and next preload images.
|
|
5853 |
next_index = self.curr_img_in_list + 1
|
|
5854 |
if next_index > len(self.image_list) - 1:
|
|
5855 |
if self.listwrap_mode == 0:
|
|
5856 |
next_index = -1
|
|
5857 |
else:
|
|
5858 |
next_index = 0
|
|
5859 |
prev_index = self.curr_img_in_list - 1
|
|
5860 |
if prev_index < 0:
|
|
5861 |
if self.listwrap_mode == 0:
|
|
5862 |
prev_index = -1
|
|
5863 |
else:
|
|
5864 |
prev_index = len(self.image_list) - 1
|
|
5865 |
if self.preloading_images:
|
|
5866 |
reset_preloadimg_next_in_list = False
|
|
5867 |
reset_preloadimg_prev_in_list = False
|
|
5868 |
if check_prev_last:
|
|
5869 |
self.check_preloadimg_next_for_existing(
|
|
5870 |
next_index, reset_preloadimg_next_in_list
|
|
5871 |
)
|
|
5872 |
else:
|
|
5873 |
self.check_preloadimg_prev_for_existing(
|
|
5874 |
prev_index, reset_preloadimg_prev_in_list
|
|
5875 |
)
|
|
5876 |
used_prev, used_next = self.check_currimg_for_existing()
|
|
5877 |
if self.preloading_images:
|
|
5878 |
if check_prev_last:
|
|
5879 |
self.check_preloadimg_prev_for_existing(
|
|
5880 |
prev_index, reset_preloadimg_prev_in_list
|
|
5881 |
)
|
|
5882 |
else:
|
|
5883 |
self.check_preloadimg_next_for_existing(
|
|
5884 |
next_index, reset_preloadimg_next_in_list
|
|
5885 |
)
|
|
5886 |
if reset_preloadimg_prev_in_list:
|
|
5887 |
self.preloadimg_prev_in_list = -1
|
|
5888 |
if reset_preloadimg_next_in_list:
|
|
5889 |
self.preloadimg_next_in_list = -1
|
|
5890 |
if used_prev or used_next:
|
|
5891 |
# If we used a preload image, set the correct boolean variables
|
|
5892 |
if self.open_mode == self.open_mode_smart or (
|
|
5893 |
self.open_mode == self.open_mode_last
|
|
5894 |
and self.last_mode == self.open_mode_smart
|
|
5895 |
):
|
|
5896 |
self.last_image_action_was_fit = True
|
|
5897 |
self.last_image_action_was_smart_fit = True
|
|
5898 |
elif self.open_mode == self.open_mode_fit or (
|
|
5899 |
self.open_mode == self.open_mode_last
|
|
5900 |
and self.last_mode == self.open_mode_fit
|
|
5901 |
):
|
|
5902 |
self.last_image_action_was_fit = True
|
|
5903 |
self.last_image_action_was_smart_fit = False
|
|
5904 |
elif self.open_mode == self.open_mode_1to1 or (
|
|
5905 |
self.open_mode == self.open_mode_last
|
|
5906 |
and self.last_mode == self.open_mode_1to1
|
|
5907 |
):
|
|
5908 |
self.last_image_action_was_fit = False
|
|
5909 |
else:
|
|
5910 |
# Need to load the current image
|
|
5911 |
self.currimg_pixbuf = None
|
|
5912 |
self.currimg_zoomratio = 1
|
|
5913 |
self.currimg_name = str(self.image_list[self.curr_img_in_list])
|
|
5914 |
if self.verbose and self.currimg_name != "":
|
|
5915 |
print(_("Loading: %s") % self.currimg_name)
|
|
5916 |
animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
|
|
5917 |
if animtest.is_static_image() or (
|
|
5918 |
use_current_pixbuf_original and not self.currimg_is_animation
|
|
5919 |
):
|
|
5920 |
self.currimg_is_animation = False
|
|
5921 |
if not use_current_pixbuf_original:
|
|
5922 |
self.currimg_pixbuf_original = animtest.get_static_image()
|
|
5923 |
self.set_image_sensitivities(True)
|
|
5924 |
if self.open_mode == self.open_mode_smart or (
|
|
5925 |
self.open_mode == self.open_mode_last
|
|
5926 |
and self.last_mode == self.open_mode_smart
|
|
5927 |
):
|
|
5928 |
self.zoom_to_fit_or_1_to_1(None, False, False)
|
|
5929 |
elif self.open_mode == self.open_mode_fit or (
|
|
5930 |
self.open_mode == self.open_mode_last
|
|
5931 |
and self.last_mode == self.open_mode_fit
|
|
5932 |
):
|
|
5933 |
self.zoom_to_fit_window(None, False, False)
|
|
5934 |
elif self.open_mode == self.open_mode_1to1 or (
|
|
5935 |
self.open_mode == self.open_mode_last
|
|
5936 |
and self.last_mode == self.open_mode_1to1
|
|
5937 |
):
|
|
5938 |
self.zoom_1_to_1(None, False, False)
|
|
5939 |
else:
|
|
5940 |
self.currimg_is_animation = True
|
|
5941 |
if not use_current_pixbuf_original:
|
|
5942 |
self.currimg_pixbuf_original = animtest
|
|
5943 |
self.zoom_1_to_1(None, False, False)
|
|
5944 |
self.set_image_sensitivities(False)
|
|
5945 |
if self.onload_cmd != None and perform_onload_action:
|
|
5946 |
self.parse_action_command(self.onload_cmd, False)
|
|
5947 |
self.update_statusbar()
|
|
5948 |
self.update_title()
|
|
5949 |
self.image_loaded = True
|
|
5950 |
self.image_modified = False
|
|
5951 |
self.image_zoomed = False
|
|
5952 |
self.set_slideshow_sensitivities()
|
|
5953 |
if not skip_recentfiles:
|
|
5954 |
self.register_file_with_recent_docs(self.currimg_name)
|
|
5955 |
if reset_cursor:
|
|
5956 |
if not self.fullscreen_mode:
|
|
5957 |
self.change_cursor(None)
|
|
5958 |
|
|
5959 |
def preload_next_image(self, use_existing_image):
|
|
5960 |
try:
|
|
5961 |
if self.preloading_images and len(self.image_list) > 1:
|
|
5962 |
if not use_existing_image:
|
|
5963 |
next_index = self.curr_img_in_list + 1
|
|
5964 |
if next_index > len(self.image_list) - 1:
|
|
5965 |
if self.listwrap_mode == 0:
|
|
5966 |
self.preloadimg_next_in_list == -1
|
|
5967 |
return
|
|
5968 |
else:
|
|
5969 |
next_index = 0
|
|
5970 |
if next_index == self.preloadimg_next_in_list:
|
|
5971 |
return
|
|
5972 |
self.preloadimg_next_in_list = next_index
|
|
5973 |
self.preloadimg_next_name = str(self.image_list[next_index])
|
|
5974 |
pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
|
|
5975 |
if pre_animtest.is_static_image():
|
|
5976 |
self.preloadimg_next_is_animation = False
|
|
5977 |
self.preloadimg_next_pixbuf_original = (
|
|
5978 |
pre_animtest.get_static_image()
|
|
5979 |
)
|
|
5980 |
else:
|
|
5981 |
self.preloadimg_next_is_animation = True
|
|
5982 |
self.preloadimg_next_pixbuf_original = pre_animtest
|
|
5983 |
if self.preloadimg_next_in_list == -1:
|
|
5984 |
return
|
|
5985 |
# Determine self.preloadimg_next_zoomratio
|
|
5986 |
if self.open_mode == self.open_mode_smart or (
|
|
5987 |
self.open_mode == self.open_mode_last
|
|
5988 |
and self.last_mode == self.open_mode_smart
|
|
5989 |
):
|
|
5990 |
self.zoom_to_fit_or_1_to_1(None, True, False)
|
|
5991 |
elif self.open_mode == self.open_mode_fit or (
|
|
5992 |
self.open_mode == self.open_mode_last
|
|
5993 |
and self.last_mode == self.open_mode_fit
|
|
5994 |
):
|
|
5995 |
self.zoom_to_fit_window(None, True, False)
|
|
5996 |
elif self.open_mode == self.open_mode_1to1 or (
|
|
5997 |
self.open_mode == self.open_mode_last
|
|
5998 |
and self.last_mode == self.open_mode_1to1
|
|
5999 |
):
|
|
6000 |
self.zoom_1_to_1(None, True, False)
|
|
6001 |
# Always start with the original image to preserve quality!
|
|
6002 |
# Calculate image size:
|
|
6003 |
self.preloadimg_next_width = int(
|
|
6004 |
self.preloadimg_next_pixbuf_original.get_width()
|
|
6005 |
* self.preloadimg_next_zoomratio
|
|
6006 |
)
|
|
6007 |
self.preloadimg_next_height = int(
|
|
6008 |
self.preloadimg_next_pixbuf_original.get_height()
|
|
6009 |
* self.preloadimg_next_zoomratio
|
|
6010 |
)
|
|
6011 |
if not self.preloadimg_next_is_animation:
|
|
6012 |
# Scale image:
|
|
6013 |
if not self.preloadimg_next_pixbuf_original.get_has_alpha():
|
|
6014 |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.scale_simple(
|
|
6015 |
self.preloadimg_next_width,
|
|
6016 |
self.preloadimg_next_height,
|
|
6017 |
self.zoom_quality,
|
|
6018 |
)
|
|
6019 |
else:
|
|
6020 |
colormap = self.imageview.get_colormap()
|
|
6021 |
light_grey = colormap.alloc_color("#666666", True, True)
|
|
6022 |
dark_grey = colormap.alloc_color("#999999", True, True)
|
|
6023 |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.composite_color_simple(
|
|
6024 |
self.preloadimg_next_width,
|
|
6025 |
self.preloadimg_next_height,
|
|
6026 |
self.zoom_quality,
|
|
6027 |
255,
|
|
6028 |
8,
|
|
6029 |
light_grey.pixel,
|
|
6030 |
dark_grey.pixel,
|
|
6031 |
)
|
|
6032 |
else:
|
|
6033 |
self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original
|
|
6034 |
gc.collect()
|
|
6035 |
if self.verbose:
|
|
6036 |
print(_("Preloading: %s") % self.preloadimg_next_name)
|
|
6037 |
except:
|
|
6038 |
self.preloadimg_next_in_list = -1
|
|
6039 |
|
|
6040 |
def preload_prev_image(self, use_existing_image):
|
|
6041 |
try:
|
|
6042 |
if self.preloading_images and len(self.image_list) > 1:
|
|
6043 |
if not use_existing_image:
|
|
6044 |
prev_index = self.curr_img_in_list - 1
|
|
6045 |
if prev_index < 0:
|
|
6046 |
if self.listwrap_mode == 0:
|
|
6047 |
self.preloadimg_prev_in_list == -1
|
|
6048 |
return
|
|
6049 |
else:
|
|
6050 |
prev_index = len(self.image_list) - 1
|
|
6051 |
if prev_index == self.preloadimg_prev_in_list:
|
|
6052 |
return
|
|
6053 |
self.preloadimg_prev_in_list = prev_index
|
|
6054 |
self.preloadimg_prev_name = str(self.image_list[prev_index])
|
|
6055 |
pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
|
|
6056 |
if pre_animtest.is_static_image():
|
|
6057 |
self.preloadimg_prev_is_animation = False
|
|
6058 |
self.preloadimg_prev_pixbuf_original = (
|
|
6059 |
pre_animtest.get_static_image()
|
|
6060 |
)
|
|
6061 |
else:
|
|
6062 |
self.preloadimg_prev_is_animation = True
|
|
6063 |
self.preloadimg_prev_pixbuf_original = pre_animtest
|
|
6064 |
if self.preloadimg_prev_in_list == -1:
|
|
6065 |
return
|
|
6066 |
# Determine self.preloadimg_prev_zoomratio
|
|
6067 |
if self.open_mode == self.open_mode_smart or (
|
|
6068 |
self.open_mode == self.open_mode_last
|
|
6069 |
and self.last_mode == self.open_mode_smart
|
|
6070 |
):
|
|
6071 |
self.zoom_to_fit_or_1_to_1(None, False, True)
|
|
6072 |
elif self.open_mode == self.open_mode_fit or (
|
|
6073 |
self.open_mode == self.open_mode_last
|
|
6074 |
and self.last_mode == self.open_mode_fit
|
|
6075 |
):
|
|
6076 |
self.zoom_to_fit_window(None, False, True)
|
|
6077 |
elif self.open_mode == self.open_mode_1to1 or (
|
|
6078 |
self.open_mode == self.open_mode_last
|
|
6079 |
and self.last_mode == self.open_mode_1to1
|
|
6080 |
):
|
|
6081 |
self.zoom_1_to_1(None, False, True)
|
|
6082 |
# Always start with the original image to preserve quality!
|
|
6083 |
# Calculate image size:
|
|
6084 |
self.preloadimg_prev_width = int(
|
|
6085 |
self.preloadimg_prev_pixbuf_original.get_width()
|
|
6086 |
* self.preloadimg_prev_zoomratio
|
|
6087 |
)
|
|
6088 |
self.preloadimg_prev_height = int(
|
|
6089 |
self.preloadimg_prev_pixbuf_original.get_height()
|
|
6090 |
* self.preloadimg_prev_zoomratio
|
|
6091 |
)
|
|
6092 |
if not self.preloadimg_prev_is_animation:
|
|
6093 |
# Scale image:
|
|
6094 |
if not self.preloadimg_prev_pixbuf_original.get_has_alpha():
|
|
6095 |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.scale_simple(
|
|
6096 |
self.preloadimg_prev_width,
|
|
6097 |
self.preloadimg_prev_height,
|
|
6098 |
self.zoom_quality,
|
|
6099 |
)
|
|
6100 |
else:
|
|
6101 |
colormap = self.imageview.get_colormap()
|
|
6102 |
light_grey = colormap.alloc_color("#666666", True, True)
|
|
6103 |
dark_grey = colormap.alloc_color("#999999", True, True)
|
|
6104 |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.composite_color_simple(
|
|
6105 |
self.preloadimg_prev_width,
|
|
6106 |
self.preloadimg_prev_height,
|
|
6107 |
self.zoom_quality,
|
|
6108 |
255,
|
|
6109 |
8,
|
|
6110 |
light_grey.pixel,
|
|
6111 |
dark_grey.pixel,
|
|
6112 |
)
|
|
6113 |
else:
|
|
6114 |
self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original
|
|
6115 |
gc.collect()
|
|
6116 |
if self.verbose:
|
|
6117 |
print(_("Preloading: %s") % self.preloadimg_prev_name)
|
|
6118 |
except:
|
|
6119 |
self.preloadimg_prev_in_list = -1
|
|
6120 |
|
|
6121 |
def change_cursor(self, type):
|
|
6122 |
for i in gtk.gdk.window_get_toplevels():
|
|
6123 |
if (
|
|
6124 |
i.get_window_type() != gtk.gdk.WINDOW_TEMP
|
|
6125 |
and i.get_window_type() != gtk.gdk.WINDOW_CHILD
|
|
6126 |
):
|
|
6127 |
i.set_cursor(type)
|
|
6128 |
self.layout.window.set_cursor(type)
|
|
6129 |
|
|
6130 |
def expand_filelist_and_load_image(self, inputlist):
|
|
6131 |
# Takes the current list (i.e. ["pic.jpg", "pic2.gif", "../images"]) and
|
|
6132 |
# expands it into a list of all pictures found
|
|
6133 |
self.thumblist.clear()
|
|
6134 |
first_image_loaded_successfully = False
|
|
6135 |
self.images_found = 0
|
|
6136 |
self.stop_now = True # Make sure that any previous search process is stopped
|
|
6137 |
self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
|
6138 |
# Reset preload images:
|
|
6139 |
self.preloadimg_next_in_list = -1
|
|
6140 |
self.preloadimg_prev_in_list = -1
|
|
6141 |
# If any directories were passed, display "Searching..." in statusbar:
|
|
6142 |
self.searching_for_images = False
|
|
6143 |
for item in inputlist:
|
|
6144 |
if os.path.isdir(item):
|
|
6145 |
self.searching_for_images = True
|
|
6146 |
self.update_statusbar()
|
|
6147 |
if not self.closing_app:
|
|
6148 |
while gtk.events_pending():
|
|
6149 |
gtk.main_iteration()
|
|
6150 |
first_image = ""
|
|
6151 |
first_image_found = False
|
|
6152 |
first_image_loaded = False
|
|
6153 |
second_image = ""
|
|
6154 |
second_image_found = False
|
|
6155 |
second_image_preloaded = False
|
|
6156 |
self.randomlist = []
|
|
6157 |
folderlist = []
|
|
6158 |
self.image_list = []
|
|
6159 |
self.curr_img_in_list = 0
|
|
6160 |
go_buttons_enabled = False
|
|
6161 |
self.set_go_sensitivities(False)
|
|
6162 |
# Clean up list (remove preceding "file://" or "file:" and trailing "/")
|
|
6163 |
for itemnum in range(len(inputlist)):
|
|
6164 |
# Strip off preceding file..
|
|
6165 |
if inputlist[itemnum].startswith("file://"):
|
|
6166 |
inputlist[itemnum] = inputlist[itemnum][7:]
|
|
6167 |
elif inputlist[itemnum].startswith("file:"):
|
|
6168 |
inputlist[itemnum] = inputlist[itemnum][5:]
|
|
6169 |
# Strip off trailing "/" if it exists:
|
|
6170 |
if inputlist[itemnum][len(inputlist[itemnum]) - 1] == "/":
|
|
6171 |
inputlist[itemnum] = inputlist[itemnum][: (len(inputlist[itemnum]) - 1)]
|
|
6172 |
if not (
|
|
6173 |
inputlist[itemnum].startswith("http://")
|
|
6174 |
or inputlist[itemnum].startswith("ftp://")
|
|
6175 |
):
|
|
6176 |
inputlist[itemnum] = os.path.abspath(inputlist[itemnum])
|
|
6177 |
else:
|
|
6178 |
try:
|
|
6179 |
# Remote file. Save as /tmp/mirage-<random>/filename.ext
|
|
6180 |
tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
|
|
6181 |
tmpfile = tmpdir + os.path.basename(inputlist[itemnum])
|
|
6182 |
socket.setdefaulttimeout(5)
|
|
6183 |
urllib.request.urlretrieve(inputlist[itemnum], tmpfile)
|
|
6184 |
inputlist[itemnum] = tmpfile
|
|
6185 |
except:
|
|
6186 |
pass
|
|
6187 |
# Remove hidden files from list:
|
|
6188 |
if not self.open_hidden_files:
|
|
6189 |
tmplist = []
|
|
6190 |
for item in inputlist:
|
|
6191 |
if os.path.basename(item)[0] != ".":
|
|
6192 |
tmplist.append(item)
|
|
6193 |
elif self.verbose:
|
|
6194 |
print(_("Skipping: %s") % item)
|
|
6195 |
inputlist = tmplist
|
|
6196 |
if len(inputlist) == 0:
|
|
6197 |
# All files/dirs were hidden, exit..
|
|
6198 |
self.currimg_name = ""
|
|
6199 |
self.searching_for_images = False
|
|
6200 |
self.set_go_navigation_sensitivities(False)
|
|
6201 |
self.set_slideshow_sensitivities()
|
|
6202 |
if not self.closing_app:
|
|
6203 |
self.change_cursor(None)
|
|
6204 |
self.recursive = False
|
|
6205 |
self.put_error_image_to_window()
|
|
6206 |
self.update_title()
|
|
6207 |
return
|
|
6208 |
init_image = os.path.abspath(inputlist[0])
|
|
6209 |
self.stop_now = False
|
|
6210 |
# If open all images in dir...
|
|
6211 |
if self.open_all_images:
|
|
6212 |
temp = inputlist
|
|
6213 |
inputlist = []
|
|
6214 |
for item in temp:
|
|
6215 |
if os.path.isfile(item):
|
|
6216 |
itempath = os.path.dirname(os.path.abspath(item))
|
|
6217 |
temp = self.recursive
|
|
6218 |
self.recursive = False
|
|
6219 |
self.stop_now = False
|
|
6220 |
self.expand_directory(
|
|
6221 |
itempath, False, go_buttons_enabled, False, False
|
|
6222 |
)
|
|
6223 |
self.recursive = temp
|
|
6224 |
else:
|
|
6225 |
inputlist.append(item)
|
|
6226 |
for item in self.image_list:
|
|
6227 |
inputlist.append(item)
|
|
6228 |
if first_image_found and not second_image_found:
|
|
6229 |
second_image_found = True
|
|
6230 |
second_image = item
|
|
6231 |
second_image_came_from_dir = False
|
|
6232 |
if item == init_image:
|
|
6233 |
first_image_found = True
|
|
6234 |
first_image = item
|
|
6235 |
first_image_came_from_dir = False
|
|
6236 |
self.curr_img_in_list = len(inputlist) - 1
|
|
6237 |
self.image_list = []
|
|
6238 |
for item in inputlist:
|
|
6239 |
if not self.closing_app:
|
|
6240 |
if os.path.isfile(item):
|
|
6241 |
if self.valid_image(item):
|
|
6242 |
if not second_image_found and first_image_found:
|
|
6243 |
second_image_found = True
|
|
6244 |
second_image = item
|
|
6245 |
second_image_came_from_dir = False
|
|
6246 |
if not first_image_found:
|
|
6247 |
first_image_found = True
|
|
6248 |
first_image = item
|
|
6249 |
first_image_came_from_dir = False
|
|
6250 |
self.image_list.append(item)
|
|
6251 |
if self.verbose:
|
|
6252 |
self.images_found += 1
|
|
6253 |
print(
|
|
6254 |
_("Found: %(item)s [%(number)i]")
|
|
6255 |
% {"item": item, "number": self.images_found}
|
|
6256 |
)
|
|
6257 |
else:
|
|
6258 |
# If it's a directory that was explicitly selected or passed to
|
|
6259 |
# the program, get all the files in the dir.
|
|
6260 |
# Retrieve only images in the top directory specified by the user
|
|
6261 |
# unless explicitly told to recurse (via -R or in Settings>Preferences)
|
|
6262 |
folderlist.append(item)
|
|
6263 |
if not second_image_found:
|
|
6264 |
# See if we can find an image in this directory:
|
|
6265 |
self.stop_now = False
|
|
6266 |
self.expand_directory(
|
|
6267 |
item, True, go_buttons_enabled, False, False
|
|
6268 |
)
|
|
6269 |
itemnum = 0
|
|
6270 |
while itemnum < len(self.image_list) and not second_image_found:
|
|
6271 |
if os.path.isfile(self.image_list[itemnum]):
|
|
6272 |
if not second_image_found and first_image_found:
|
|
6273 |
second_image_found = True
|
|
6274 |
second_image_came_from_dir = True
|
|
6275 |
second_image = self.image_list[itemnum]
|
|
6276 |
self.set_go_navigation_sensitivities(True)
|
|
6277 |
go_buttons_enabled = True
|
|
6278 |
while gtk.events_pending():
|
|
6279 |
gtk.main_iteration(True)
|
|
6280 |
if not first_image_found:
|
|
6281 |
first_image_found = True
|
|
6282 |
first_image = self.image_list[itemnum]
|
|
6283 |
first_image_came_from_dir = True
|
|
6284 |
itemnum += 1
|
|
6285 |
# Load first image and display:
|
|
6286 |
if (
|
|
6287 |
first_image_found
|
|
6288 |
and not first_image_loaded
|
|
6289 |
and self.curr_img_in_list <= len(self.image_list) - 1
|
|
6290 |
):
|
|
6291 |
first_image_loaded = True
|
|
6292 |
if self.slideshow_mode:
|
|
6293 |
self.toggle_slideshow(None)
|
|
6294 |
if self.verbose and self.currimg_name != "":
|
|
6295 |
print(_("Loading: %s") % self.currimg_name)
|
|
6296 |
try:
|
|
6297 |
self.load_new_image2(False, False, True, True)
|
|
6298 |
# Calling load_new_image2 will reset the following two vars
|
|
6299 |
# to 0, so ensure they are -1 again (no images preloaded)
|
|
6300 |
self.preloadimg_prev_in_list = -1
|
|
6301 |
self.preloadimg_next_in_list = -1
|
|
6302 |
if not self.currimg_is_animation:
|
|
6303 |
self.previmg_width = self.currimg_pixbuf.get_width()
|
|
6304 |
else:
|
|
6305 |
self.previmg_width = (
|
|
6306 |
self.currimg_pixbuf.get_static_image().get_width()
|
|
6307 |
)
|
|
6308 |
self.image_loaded = True
|
|
6309 |
first_image_loaded_successfully = True
|
|
6310 |
if not self.closing_app:
|
|
6311 |
while gtk.events_pending():
|
|
6312 |
gtk.main_iteration(True)
|
|
6313 |
except:
|
|
6314 |
pass
|
|
6315 |
if first_image_came_from_dir:
|
|
6316 |
self.image_list = []
|
|
6317 |
# Pre-load second image:
|
|
6318 |
if (
|
|
6319 |
second_image_found
|
|
6320 |
and not second_image_preloaded
|
|
6321 |
and (
|
|
6322 |
(
|
|
6323 |
not second_image_came_from_dir
|
|
6324 |
and self.curr_img_in_list + 1 <= len(self.image_list) - 1
|
|
6325 |
)
|
|
6326 |
or second_image_came_from_dir
|
|
6327 |
)
|
|
6328 |
):
|
|
6329 |
second_image_preloaded = True
|
|
6330 |
temp = self.image_list
|
|
6331 |
self.image_list = []
|
|
6332 |
while len(self.image_list) < self.curr_img_in_list + 1:
|
|
6333 |
self.image_list.append(first_image)
|
|
6334 |
self.image_list.append(second_image)
|
|
6335 |
self.preload_next_image(False)
|
|
6336 |
self.image_list = temp
|
|
6337 |
if first_image_found:
|
|
6338 |
# Sort the filelist and folderlist alphabetically, and recurse into folderlist:
|
|
6339 |
if first_image_came_from_dir:
|
|
6340 |
self.add_folderlist_images(folderlist, go_buttons_enabled)
|
|
6341 |
self.do_image_list_stuff(first_image, second_image)
|
|
6342 |
else:
|
|
6343 |
self.do_image_list_stuff(first_image, second_image)
|
|
6344 |
self.add_folderlist_images(folderlist, go_buttons_enabled)
|
|
6345 |
self.update_title()
|
|
6346 |
if not self.closing_app:
|
|
6347 |
while gtk.events_pending():
|
|
6348 |
gtk.main_iteration(True)
|
|
6349 |
if not first_image_loaded_successfully:
|
|
6350 |
self.image_load_failed(False, init_image)
|
|
6351 |
self.searching_for_images = False
|
|
6352 |
self.update_statusbar()
|
|
6353 |
self.set_go_navigation_sensitivities(False)
|
|
6354 |
self.set_slideshow_sensitivities()
|
|
6355 |
self.thumbpane_update_images(True, self.curr_img_in_list)
|
|
6356 |
if not self.closing_app:
|
|
6357 |
self.change_cursor(None)
|
|
6358 |
self.recursive = False
|
|
6359 |
|
|
6360 |
def add_folderlist_images(self, folderlist, go_buttons_enabled):
|
|
6361 |
if len(folderlist) > 0:
|
|
6362 |
folderlist.sort(locale.strcoll)
|
|
6363 |
folderlist = list(set(folderlist))
|
|
6364 |
for item in folderlist:
|
|
6365 |
if not self.closing_app:
|
|
6366 |
if (
|
|
6367 |
not self.open_hidden_files and os.path.basename(item)[0] != "."
|
|
6368 |
) or self.open_hidden_files:
|
|
6369 |
self.stop_now = False
|
|
6370 |
self.expand_directory(
|
|
6371 |
item, False, go_buttons_enabled, True, True
|
|
6372 |
)
|
|
6373 |
|
|
6374 |
def do_image_list_stuff(self, first_image, second_image):
|
|
6375 |
if len(self.image_list) > 0:
|
|
6376 |
self.set_go_navigation_sensitivities(True)
|
|
6377 |
self.image_list = list(set(self.image_list))
|
|
6378 |
self.image_list.sort(locale.strcoll)
|
|
6379 |
|
|
6380 |
def expand_directory(
|
|
6381 |
self,
|
|
6382 |
item,
|
|
6383 |
stop_when_second_image_found,
|
|
6384 |
go_buttons_enabled,
|
|
6385 |
update_window_title,
|
|
6386 |
print_found_msg,
|
|
6387 |
):
|
|
6388 |
if not self.stop_now and not self.closing_app:
|
|
6389 |
folderlist = []
|
|
6390 |
filelist = []
|
|
6391 |
if not os.access(item, os.R_OK):
|
|
6392 |
return False
|
|
6393 |
for item2 in os.listdir(item):
|
|
6394 |
if not self.closing_app and not self.stop_now:
|
|
6395 |
while gtk.events_pending():
|
|
6396 |
gtk.main_iteration(True)
|
|
6397 |
item2 = item + os.sep + item2
|
|
6398 |
item_fullpath2 = os.path.abspath(item2)
|
|
6399 |
if (
|
|
6400 |
not self.open_hidden_files
|
|
6401 |
and os.path.basename(item_fullpath2)[0] != "."
|
|
6402 |
) or self.open_hidden_files:
|
|
6403 |
if os.path.isfile(item_fullpath2) and self.valid_image(
|
|
6404 |
item_fullpath2
|
|
6405 |
):
|
|
6406 |
filelist.append(item2)
|
|
6407 |
if self.verbose and print_found_msg:
|
|
6408 |
self.images_found += 1
|
|
6409 |
print(
|
|
6410 |
_("Found: %(fullpath)s [%(number)i]")
|
|
6411 |
% {
|
|
6412 |
"fullpath": item_fullpath2,
|
|
6413 |
"number": self.images_found,
|
|
6414 |
}
|
|
6415 |
)
|
|
6416 |
elif os.path.isdir(item_fullpath2) and self.recursive:
|
|
6417 |
folderlist.append(item_fullpath2)
|
|
6418 |
elif self.verbose:
|
|
6419 |
print(_("Skipping: %s") % item_fullpath2)
|
|
6420 |
if len(self.image_list) > 0 and update_window_title:
|
|
6421 |
self.update_title()
|
|
6422 |
# Sort the filelist and folderlist alphabetically:
|
|
6423 |
if len(filelist) > 0:
|
|
6424 |
filelist.sort(locale.strcoll)
|
|
6425 |
for item2 in filelist:
|
|
6426 |
if not item2 in self.image_list:
|
|
6427 |
self.image_list.append(item2)
|
|
6428 |
if stop_when_second_image_found and len(self.image_list) == 2:
|
|
6429 |
return
|
|
6430 |
if not go_buttons_enabled and len(self.image_list) > 1:
|
|
6431 |
self.set_go_navigation_sensitivities(True)
|
|
6432 |
go_buttons_enabled = True
|
|
6433 |
# Recurse into the folderlist:
|
|
6434 |
if len(folderlist) > 0:
|
|
6435 |
folderlist.sort(locale.strcoll)
|
|
6436 |
for item2 in folderlist:
|
|
6437 |
if not self.stop_now:
|
|
6438 |
self.expand_directory(
|
|
6439 |
item2,
|
|
6440 |
stop_when_second_image_found,
|
|
6441 |
go_buttons_enabled,
|
|
6442 |
update_window_title,
|
|
6443 |
print_found_msg,
|
|
6444 |
)
|
|
6445 |
|
|
6446 |
def register_file_with_recent_docs(self, imgfile):
|
|
6447 |
self.recent_file_add_and_refresh(imgfile)
|
|
6448 |
if os.path.isfile(imgfile) and gtk.check_version(2, 10, 0) == None:
|
|
6449 |
try:
|
|
6450 |
gtk_recent_manager = gtk.recent_manager_get_default()
|
|
6451 |
uri = ""
|
|
6452 |
if imgfile[:7] != "file://":
|
|
6453 |
uri = "file://"
|
|
6454 |
uri = uri + urllib.request.pathname2url(os.path.abspath(imgfile))
|
|
6455 |
gtk_recent_manager.add_item(uri)
|
|
6456 |
except:
|
|
6457 |
# Isnt currently functional on win32
|
|
6458 |
if sys.platform == "win32":
|
|
6459 |
pass
|
|
6460 |
else:
|
|
6461 |
raise
|
|
6462 |
|
|
6463 |
def valid_image(self, file):
|
|
6464 |
test = gtk.gdk.pixbuf_get_file_info(file)
|
|
6465 |
if test == None:
|
|
6466 |
return False
|
|
6467 |
elif test[0]["name"] == "wbmp":
|
|
6468 |
# some regular files are thought to be wbmp for whatever reason,
|
|
6469 |
# so let's check further.. :(
|
|
6470 |
try:
|
|
6471 |
test2 = gtk.gdk.pixbuf_new_from_file(file)
|
|
6472 |
return True
|
|
6473 |
except:
|
|
6474 |
return False
|
|
6475 |
else:
|
|
6476 |
return True
|
|
6477 |
|
|
6478 |
def image_flip(self, old_pix, vertical):
|
|
6479 |
width = old_pix.get_width()
|
|
6480 |
height = old_pix.get_height()
|
|
6481 |
d = None
|
|
6482 |
if vertical:
|
|
6483 |
d, w, h, rws = imgfuncs.vert(
|
|
6484 |
old_pix.get_pixels(),
|
|
6485 |
width,
|
|
6486 |
height,
|
|
6487 |
old_pix.get_rowstride(),
|
|
6488 |
old_pix.get_n_channels(),
|
|
6489 |
)
|
|
6490 |
else:
|
|
6491 |
d, w, h, rws = imgfuncs.horiz(
|
|
6492 |
old_pix.get_pixels(),
|
|
6493 |
width,
|
|
6494 |
height,
|
|
6495 |
old_pix.get_rowstride(),
|
|
6496 |
old_pix.get_n_channels(),
|
|
6497 |
)
|
|
6498 |
if d:
|
|
6499 |
new_pix = gtk.gdk.pixbuf_new_from_data(
|
|
6500 |
d,
|
|
6501 |
old_pix.get_colorspace(),
|
|
6502 |
old_pix.get_has_alpha(),
|
|
6503 |
old_pix.get_bits_per_sample(),
|
|
6504 |
w,
|
|
6505 |
h,
|
|
6506 |
rws,
|
|
6507 |
)
|
|
6508 |
return new_pix
|
|
6509 |
return old_pix
|
|
6510 |
|
|
6511 |
def image_rotate(self, old_pix, full_angle):
|
|
6512 |
width = old_pix.get_width()
|
|
6513 |
height = old_pix.get_height()
|
|
6514 |
angle = full_angle - (int(full_angle) // 360) * 360
|
|
6515 |
if angle:
|
|
6516 |
d = None
|
|
6517 |
if angle % 270 == 0:
|
|
6518 |
d, w, h, rws = imgfuncs.right(
|
|
6519 |
old_pix.get_pixels(),
|
|
6520 |
width,
|
|
6521 |
height,
|
|
6522 |
old_pix.get_rowstride(),
|
|
6523 |
old_pix.get_n_channels(),
|
|
6524 |
)
|
|
6525 |
elif angle % 180 == 0:
|
|
6526 |
d, w, h, rws = imgfuncs.mirror(
|
|
6527 |
old_pix.get_pixels(),
|
|
6528 |
width,
|
|
6529 |
height,
|
|
6530 |
old_pix.get_rowstride(),
|
|
6531 |
old_pix.get_n_channels(),
|
|
6532 |
)
|
|
6533 |
elif angle % 90 == 0:
|
|
6534 |
d, w, h, rws = imgfuncs.left(
|
|
6535 |
old_pix.get_pixels(),
|
|
6536 |
width,
|
|
6537 |
height,
|
|
6538 |
old_pix.get_rowstride(),
|
|
6539 |
old_pix.get_n_channels(),
|
|
6540 |
)
|
|
6541 |
if d:
|
|
6542 |
new_pix = gtk.gdk.pixbuf_new_from_data(
|
|
6543 |
d,
|
|
6544 |
old_pix.get_colorspace(),
|
|
6545 |
old_pix.get_has_alpha(),
|
|
6546 |
old_pix.get_bits_per_sample(),
|
|
6547 |
w,
|
|
6548 |
h,
|
|
6549 |
rws,
|
|
6550 |
)
|
|
6551 |
return new_pix
|
|
6552 |
return old_pix
|
|
6553 |
|
|
6554 |
def toggle_slideshow(self, action):
|
|
6555 |
if len(self.image_list) > 1:
|
|
6556 |
if not self.slideshow_mode:
|
|
6557 |
if self.slideshow_in_fullscreen and not self.fullscreen_mode:
|
|
6558 |
self.enter_fullscreen(None)
|
|
6559 |
self.slideshow_mode = True
|
|
6560 |
self.update_title()
|
|
6561 |
self.set_slideshow_sensitivities()
|
|
6562 |
if not self.curr_slideshow_random:
|
|
6563 |
self.timer_delay = gobject.timeout_add(
|
|
6564 |
int(self.curr_slideshow_delay * 1000),
|
|
6565 |
self.goto_next_image,
|
|
6566 |
"ss",
|
|
6567 |
)
|
|
6568 |
else:
|
|
6569 |
self.reinitialize_randomlist()
|
|
6570 |
self.timer_delay = gobject.timeout_add(
|
|
6571 |
int(self.curr_slideshow_delay * 1000),
|
|
6572 |
self.goto_random_image,
|
|
6573 |
"ss",
|
|
6574 |
)
|
|
6575 |
self.ss_start.hide()
|
|
6576 |
self.ss_stop.show()
|
|
6577 |
timer_screensaver = gobject.timeout_add(
|
|
6578 |
1000, self.disable_screensaver_in_slideshow_mode
|
|
6579 |
)
|
|
6580 |
else:
|
|
6581 |
self.slideshow_mode = False
|
|
6582 |
gobject.source_remove(self.timer_delay)
|
|
6583 |
self.update_title()
|
|
6584 |
self.set_slideshow_sensitivities()
|
|
6585 |
self.set_zoom_sensitivities()
|
|
6586 |
self.ss_stop.hide()
|
|
6587 |
self.ss_start.show()
|
|
6588 |
|
|
6589 |
def update_title(self):
|
|
6590 |
if len(self.image_list) == 0:
|
|
6591 |
title = "Mirage"
|
|
6592 |
else:
|
|
6593 |
title = (
|
|
6594 |
"Mirage - "
|
|
6595 |
+ _("[%(current)i of %(total)i]")
|
|
6596 |
% {"current": self.curr_img_in_list + 1, "total": len(self.image_list)}
|
|
6597 |
+ " "
|
|
6598 |
+ os.path.basename(self.currimg_name)
|
|
6599 |
)
|
|
6600 |
if self.slideshow_mode:
|
|
6601 |
title = title + " - " + _("Slideshow Mode")
|
|
6602 |
self.window.set_title(title)
|
|
6603 |
|
|
6604 |
def slideshow_controls_show(self):
|
|
6605 |
if not self.slideshow_controls_visible and not self.controls_moving:
|
|
6606 |
self.slideshow_controls_visible = True
|
|
6607 |
|
|
6608 |
self.ss_delayspin.set_value(self.curr_slideshow_delay)
|
|
6609 |
self.ss_randomize.set_active(self.curr_slideshow_random)
|
|
6610 |
|
|
6611 |
if self.slideshow_mode:
|
|
6612 |
self.ss_start.set_no_show_all(True)
|
|
6613 |
self.ss_stop.set_no_show_all(False)
|
|
6614 |
else:
|
|
6615 |
self.ss_start.set_no_show_all(False)
|
|
6616 |
self.ss_stop.set_no_show_all(True)
|
|
6617 |
|
|
6618 |
(xpos, ypos) = self.window.get_position()
|
|
6619 |
screen = self.window.get_screen()
|
|
6620 |
self.slideshow_window.set_screen(screen)
|
|
6621 |
self.slideshow_window2.set_screen(screen)
|
|
6622 |
|
|
6623 |
self.slideshow_window.show_all()
|
|
6624 |
self.slideshow_window2.show_all()
|
|
6625 |
if not self.closing_app:
|
|
6626 |
while gtk.events_pending():
|
|
6627 |
gtk.main_iteration()
|
|
6628 |
|
|
6629 |
ss_winheight = self.slideshow_window.allocation.height
|
|
6630 |
ss_win2width = self.slideshow_window2.allocation.width
|
|
6631 |
winheight = self.window.allocation.height
|
|
6632 |
winwidth = self.window.allocation.width
|
|
6633 |
y = -3.0
|
|
6634 |
self.controls_moving = True
|
|
6635 |
while y < ss_winheight:
|
|
6636 |
self.slideshow_window.move(2 + xpos, int(winheight - y - 2))
|
|
6637 |
self.slideshow_window2.move(
|
|
6638 |
winwidth - ss_win2width - 2 + xpos, int(winheight - y - 2)
|
|
6639 |
)
|
|
6640 |
y += 0.05
|
|
6641 |
if not self.closing_app:
|
|
6642 |
while gtk.events_pending():
|
|
6643 |
gtk.main_iteration()
|
|
6644 |
self.controls_moving = False
|
|
6645 |
|
|
6646 |
def slideshow_controls_hide(self):
|
|
6647 |
if self.slideshow_controls_visible and not self.controls_moving:
|
|
6648 |
self.slideshow_controls_visible = False
|
|
6649 |
|
|
6650 |
(xpos, ypos) = self.window.get_position()
|
|
6651 |
|
|
6652 |
ss_winheight = self.slideshow_window.allocation.height
|
|
6653 |
ss_win2width = self.slideshow_window2.allocation.width
|
|
6654 |
winheight = self.window.allocation.height
|
|
6655 |
winwidth = self.window.allocation.width
|
|
6656 |
y = float(self.slideshow_window.allocation.height * 1.0)
|
|
6657 |
self.controls_moving = True
|
|
6658 |
while y > -3:
|
|
6659 |
self.slideshow_window.move(2 + xpos, int(winheight - y - 2))
|
|
6660 |
self.slideshow_window2.move(
|
|
6661 |
winwidth - ss_win2width - 2 + xpos, int(winheight - y - 2)
|
|
6662 |
)
|
|
6663 |
y -= 0.05
|
|
6664 |
if not self.closing_app:
|
|
6665 |
while gtk.events_pending():
|
|
6666 |
gtk.main_iteration()
|
|
6667 |
self.controls_moving = False
|
|
6668 |
|
|
6669 |
def disable_screensaver_in_slideshow_mode(self):
|
|
6670 |
if self.slideshow_mode and self.disable_screensaver:
|
|
6671 |
test = os.spawnlp(
|
|
6672 |
os.P_WAIT,
|
|
6673 |
"/usr/bin/xscreensaver-command",
|
|
6674 |
"xscreensaver-command",
|
|
6675 |
"-deactivate",
|
|
6676 |
)
|
|
6677 |
if test != 127:
|
|
6678 |
timer_screensaver = gobject.timeout_add(
|
|
6679 |
1000, self.disable_screensaver_in_slideshow_mode
|
|
6680 |
)
|
|
6681 |
|
|
6682 |
def main(self):
|
|
6683 |
gtk.main()
|
|
6684 |
|
4575 | 6685 |
|
4576 | 6686 |
if __name__ == "__main__":
|
4577 | |
base = Base()
|
4578 | |
gtk.gdk.threads_enter()
|
4579 | |
base.main()
|
4580 | |
gtk.gdk.threads_leave()
|
|
6687 |
base = Base()
|
|
6688 |
gtk.gdk.threads_enter()
|
|
6689 |
base.main()
|
|
6690 |
gtk.gdk.threads_leave()
|