bzr branch
http://bzr.ed.am/gtk/eog-manage-raws
4
by edam
- added unkeep command |
1 |
# raw-tools.py |
2 |
# |
|
3 |
# Copyright (C) 2011 Tim Marston <edam@waxworlds.org> |
|
4 |
# |
|
5 |
# This file is part of Raw Tools (hereafter referred to as "this program"). |
|
6 |
# See http://www.waxworlds.org/edam/software/gtk/eog-raw-tools for more |
|
7 |
# information. |
|
8 |
# |
|
9 |
# This program is free software: you can redistribute it and/or modify |
|
10 |
# it under the terms of the GNU General Public License as published by |
|
11 |
# the Free Software Foundation, either version 3 of the License, or |
|
12 |
# (at your option) any later version. |
|
13 |
# |
|
14 |
# This program is distributed in the hope that it will be useful, |
|
15 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
# GNU General Public License for more details. |
|
18 |
# |
|
19 |
# You should have received a copy of the GNU General Public License |
|
20 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
21 |
||
22 |
||
23 |
# version 0.1 |
|
24 |
||
7
by edam
switch to gir Gio |
25 |
from gi.repository import GObject, Gtk, Eog, Gio |
26 |
import os, re |
|
5.1.1
by edam
updated for GTK 3.0 |
27 |
|
28 |
class RawToolsPlugin( GObject.Object, Eog.WindowActivatable ): |
|
29 |
||
30 |
# Override EogWindowActivatable's window property |
|
31 |
window = GObject.property( type = Eog.Window ) |
|
32 |
||
33 |
# list of file extension to recognise as RAW files |
|
1
by edam
initial comit |
34 |
raw_file_extensions = [ 'cr2', '3fr', 'ari', 'arw', 'srf', 'sr2', 'bay', |
35 |
'crw', 'cr2', 'cap', 'iiq', 'eip', 'dcs', 'dcr', 'drf', 'k25', 'kdc', |
|
36 |
'dng', 'erf', 'fff', 'mef', 'mos', 'mrw', 'nef', 'nrw', 'orf', 'ptx', |
|
37 |
'pef', 'pxn', 'r3d', 'raf', 'raw', 'rw2', 'rwl', 'rwz', 'x3f' ] |
|
38 |
||
39 |
def __init__( self ): |
|
5.1.1
by edam
updated for GTK 3.0 |
40 |
GObject.Object.__init__( self ) |
1
by edam
initial comit |
41 |
|
5.1.1
by edam
updated for GTK 3.0 |
42 |
def do_activate( self ): |
1
by edam
initial comit |
43 |
|
44 |
# insert menu item |
|
5.1.1
by edam
updated for GTK 3.0 |
45 |
ui_manager = self.window.get_ui_manager() |
46 |
self.action_group = Gtk.ActionGroup( 'EogRawToolsPluginActions' ) |
|
47 |
self.action_group.add_actions( [ ( 'EogPluginRunKeepRaw', None, |
|
2
by edam
- added status bar information |
48 |
_( 'Keep Raw Image' ), 'K', |
49 |
_( "Move the accompanying raw file to a 'raw' subdirectory" ), |
|
5.1.1
by edam
updated for GTK 3.0 |
50 |
self.do_keep_raw_image ) ], self.window ) |
51 |
self.action_group.add_actions( [ ( 'EogPluginRunUnkeepRaw', None, |
|
4
by edam
- added unkeep command |
52 |
_( 'Unkeep Raw Image' ), 'U', |
53 |
_( "Move the accompanying raw file back to the image's directory" ), |
|
5.1.1
by edam
updated for GTK 3.0 |
54 |
self.do_unkeep_raw_image ) ], self.window ) |
55 |
self.action_group.add_actions( [ ( 'EogPluginRunDeleteRaw', None, |
|
2
by edam
- added status bar information |
56 |
_( 'Delete Unkept Raw Images' ), None, |
57 |
_( "Delete all raw files in the current image's directory (the unkept ones)" ), |
|
5.1.1
by edam
updated for GTK 3.0 |
58 |
self.do_delete_raw_images ) ], self.window ) |
59 |
ui_manager.insert_action_group( self.action_group, -1 ) |
|
60 |
self.ui_id = ui_manager.add_ui_from_string( """ |
|
1
by edam
initial comit |
61 |
<ui> |
62 |
<menubar name="MainMenu"> |
|
63 |
<menu name="ToolsMenu" action="Tools"> |
|
64 |
<separator /> |
|
2
by edam
- added status bar information |
65 |
<menuitem name="EogPluginRunKeepRaw" |
1
by edam
initial comit |
66 |
action="EogPluginRunKeepRaw" /> |
4
by edam
- added unkeep command |
67 |
<menuitem name="EogPluginRunUnkeepRaw" |
68 |
action="EogPluginRunUnkeepRaw" /> |
|
2
by edam
- added status bar information |
69 |
<menuitem name="EogPluginRunDeleteRaw" |
70 |
action="EogPluginRunDeleteRaw" /> |
|
1
by edam
initial comit |
71 |
<separator /> |
72 |
</menu> |
|
73 |
</menubar> |
|
74 |
<popup name="ViewPopup"> |
|
75 |
<separator /> |
|
76 |
<menuitem action="EogPluginRunKeepRaw" /> |
|
77 |
<separator /> |
|
78 |
</popup> |
|
79 |
</ui> |
|
80 |
""" ) |
|
81 |
||
2
by edam
- added status bar information |
82 |
# insert status bar |
5.1.1
by edam
updated for GTK 3.0 |
83 |
self.statusbar = Gtk.Statusbar() |
84 |
#self.statusbar.set_size_request( 100, 10 ) |
|
85 |
statusbar = self.window.get_statusbar() |
|
86 |
statusbar.pack_end( self.statusbar, False, False, 0 ); |
|
87 |
self.statusbar.show() |
|
2
by edam
- added status bar information |
88 |
|
1
by edam
initial comit |
89 |
# connect to selection change |
5.1.1
by edam
updated for GTK 3.0 |
90 |
thumb_view = self.window.get_thumb_view() |
91 |
self.on_selection_change_id = thumb_view.connect_after( \ |
|
92 |
'selection_changed', self.on_selection_change, self.window ) |
|
1
by edam
initial comit |
93 |
|
94 |
# init ui state |
|
5.1.1
by edam
updated for GTK 3.0 |
95 |
self.update_status( self.window ) |
96 |
||
97 |
def do_deactivate( self ): |
|
98 |
||
99 |
# remove menu items |
|
100 |
ui_manager = self.window.get_ui_manager() |
|
101 |
ui_manager.remove_ui( self.ui_id ) |
|
102 |
self.ui_id = 0 |
|
103 |
ui_manager.remove_action_group( self.action_group ) |
|
104 |
self.action_group = None |
|
105 |
ui_manager.ensure_update() |
|
1
by edam
initial comit |
106 |
|
2
by edam
- added status bar information |
107 |
# disconnect handlers |
5.1.1
by edam
updated for GTK 3.0 |
108 |
thumb_view = self.window.get_thumb_view() |
109 |
thumb_view.disconnect( self.on_selection_change_id ) |
|
1
by edam
initial comit |
110 |
|
2
by edam
- added status bar information |
111 |
# remove status bar entry |
5.1.1
by edam
updated for GTK 3.0 |
112 |
statusbar = self.window.get_statusbar() |
113 |
Gtk.Container.remove( statusbar, self.statusbar ) |
|
1
by edam
initial comit |
114 |
|
115 |
def on_selection_change( self, view, data ): |
|
2
by edam
- added status bar information |
116 |
self.update_status( data ) |
117 |
||
118 |
def get_raw_filename_from_image( self, image ): |
|
1
by edam
initial comit |
119 |
fname = image.get_file().get_path() |
120 |
||
2
by edam
- added status bar information |
121 |
# get the base fileanme (with no extension), read for searching |
1
by edam
initial comit |
122 |
base_fname = image.get_file().get_path() |
123 |
pos = base_fname.rfind( '.' ) |
|
124 |
if( pos != -1 ): |
|
2
by edam
- added status bar information |
125 |
|
126 |
# check if the extension of the current image makes it a raw file |
|
127 |
for ext in self.raw_file_extensions + \ |
|
128 |
map( lambda x: x.upper(), self.raw_file_extensions ): |
|
129 |
if( base_fname[ pos : ] == ext ): |
|
130 |
return False; |
|
131 |
||
132 |
# remove extension from base filename |
|
1
by edam
initial comit |
133 |
base_fname = base_fname[ 0 : pos ] |
134 |
||
135 |
# check for stupidity |
|
136 |
if( base_fname[ -1 : None ] == '/' ): |
|
2
by edam
- added status bar information |
137 |
return False |
138 |
||
139 |
# loop through valid raw file extensions, uppercase and lowercase |
|
140 |
for ext in self.raw_file_extensions + \ |
|
141 |
map( lambda x: x.upper(), self.raw_file_extensions ): |
|
142 |
||
143 |
# if the raw file exists, we found it |
|
144 |
if( os.path.isfile( base_fname + '.' + ext ) ): |
|
145 |
return os.path.basename( base_fname + '.' + ext ); |
|
1
by edam
initial comit |
146 |
|
147 |
# path the raw images will be moved to |
|
148 |
raw_path = os.path.dirname( fname ) + '/raw'; |
|
149 |
||
2
by edam
- added status bar information |
150 |
# loop through valid raw file extensions, uppercase and lowercase |
1
by edam
initial comit |
151 |
for ext in self.raw_file_extensions + \ |
2
by edam
- added status bar information |
152 |
map( lambda x: x.upper(), self.raw_file_extensions ): |
153 |
||
154 |
# if the raw file exists, we found it |
|
155 |
if( os.path.isfile( os.path.dirname( fname ) + '/raw/' + \ |
|
156 |
os.path.basename( base_fname + '.' + ext ) ) ): |
|
157 |
return os.path.basename( base_fname + '.' + ext ); |
|
158 |
||
159 |
# not found |
|
160 |
return False; |
|
161 |
||
162 |
def update_status( self, window ): |
|
163 |
thumb_view = window.get_thumb_view() |
|
164 |
||
165 |
# do we have just the one selected image? we can't handle multiple |
|
166 |
# images because EogThumbView.get_selected_images() doesn't work. |
|
5.1.1
by edam
updated for GTK 3.0 |
167 |
self.action_group.set_sensitive( \ |
2
by edam
- added status bar information |
168 |
thumb_view.get_n_selected() == 1 ) |
169 |
||
170 |
# update the status bar |
|
171 |
if( thumb_view.get_n_selected() > 0 ): |
|
172 |
image = thumb_view.get_first_selected_image() |
|
173 |
raw_fname = self.get_raw_filename_from_image( image ) |
|
174 |
path = os.path.dirname( image.get_file().get_path() ) |
|
5.1.1
by edam
updated for GTK 3.0 |
175 |
self.statusbar.pop( 0 ) |
2
by edam
- added status bar information |
176 |
if( raw_fname is False ): |
5.1.1
by edam
updated for GTK 3.0 |
177 |
self.statusbar.push( 0, " " + _( 'raw: -' ) ) |
2
by edam
- added status bar information |
178 |
elif( os.path.isfile( path + '/' + raw_fname ) ): |
5.1.1
by edam
updated for GTK 3.0 |
179 |
self.statusbar.push( 0, " " + _( 'raw: unkept' ) ) |
2
by edam
- added status bar information |
180 |
else: |
5.1.1
by edam
updated for GTK 3.0 |
181 |
self.statusbar.push( 0, " " + _( 'raw: keep' ) ) |
2
by edam
- added status bar information |
182 |
|
5.1.1
by edam
updated for GTK 3.0 |
183 |
def do_keep_raw_image( self, action, window ): |
2
by edam
- added status bar information |
184 |
|
185 |
# do we have just the one selected image? we can't handle multiple |
|
186 |
# images because EogThumbView.get_selected_images() doesn't work. |
|
5.1.1
by edam
updated for GTK 3.0 |
187 |
thumb_view = window.get_thumb_view() |
2
by edam
- added status bar information |
188 |
if( thumb_view.get_n_selected() == 1 ): |
189 |
||
190 |
# get the image |
|
191 |
image = thumb_view.get_first_selected_image() |
|
192 |
if( image != None ): |
|
193 |
self.keep_raw_image( image ) |
|
194 |
||
195 |
# update ui |
|
5.1.1
by edam
updated for GTK 3.0 |
196 |
self.update_status( window ) |
2
by edam
- added status bar information |
197 |
|
5.1.1
by edam
updated for GTK 3.0 |
198 |
def do_unkeep_raw_image( self, action, window ): |
4
by edam
- added unkeep command |
199 |
|
200 |
# do we have just the one selected image? we can't handle multiple |
|
201 |
# images because EogThumbView.get_selected_images() doesn't work. |
|
5.1.1
by edam
updated for GTK 3.0 |
202 |
thumb_view = window.get_thumb_view() |
4
by edam
- added unkeep command |
203 |
if( thumb_view.get_n_selected() == 1 ): |
204 |
||
205 |
# get the image |
|
206 |
image = thumb_view.get_first_selected_image() |
|
207 |
if( image != None ): |
|
208 |
self.unkeep_raw_image( image ) |
|
209 |
||
210 |
# update ui |
|
5.1.1
by edam
updated for GTK 3.0 |
211 |
self.update_status( window ) |
4
by edam
- added unkeep command |
212 |
|
2
by edam
- added status bar information |
213 |
def keep_raw_image( self, image ): |
214 |
||
215 |
raw_fname = self.get_raw_filename_from_image( image ) |
|
216 |
if( raw_fname is False ): |
|
5.1.1
by edam
updated for GTK 3.0 |
217 |
dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.MODAL, |
218 |
Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, |
|
2
by edam
- added status bar information |
219 |
_( 'Raw file not found!' ) ) |
220 |
dialog.format_secondary_text( _( "This image doesn't appear to " + |
|
221 |
"have an accompanying raw file." ) ) |
|
1
by edam
initial comit |
222 |
dialog.run() |
223 |
dialog.destroy() |
|
224 |
return |
|
2
by edam
- added status bar information |
225 |
|
226 |
# does raw file exist? |
|
227 |
path = os.path.dirname( image.get_file().get_path() ) |
|
228 |
if( os.path.isfile( path + '/' + raw_fname ) ): |
|
229 |
||
230 |
# create the raw directory, if it doesn't exist |
|
231 |
if( not os.path.isdir( path + '/raw' ) ): |
|
232 |
os.mkdir( path + '/raw' ); |
|
233 |
||
234 |
# move the raw file in to the raw directory |
|
235 |
os.rename( path + '/' + raw_fname, path + '/raw/' + raw_fname ) |
|
236 |
||
4
by edam
- added unkeep command |
237 |
def unkeep_raw_image( self, image ): |
238 |
||
239 |
raw_fname = self.get_raw_filename_from_image( image ) |
|
240 |
if( raw_fname is False ): |
|
5.1.1
by edam
updated for GTK 3.0 |
241 |
dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.MODAL, |
242 |
Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, |
|
4
by edam
- added unkeep command |
243 |
_( 'Raw file not found!' ) ) |
244 |
dialog.format_secondary_text( _( "This image doesn't appear to " + |
|
245 |
"have an accompanying raw file." ) ) |
|
246 |
dialog.run() |
|
247 |
dialog.destroy() |
|
248 |
return |
|
249 |
||
250 |
# does raw file exist? |
|
251 |
path = os.path.dirname( image.get_file().get_path() ) |
|
252 |
if( os.path.isfile( path + '/raw/' + raw_fname ) ): |
|
253 |
||
254 |
# move the raw file back to the parent directory |
|
255 |
os.rename( path + '/raw/' + raw_fname, path + '/' + raw_fname ) |
|
256 |
||
257 |
# if the raw directory is empty, remove it |
|
258 |
if( len( os.listdir( path + '/raw' ) ) == 0 ): |
|
259 |
os.rmdir( path + '/raw' ) |
|
260 |
||
5.1.1
by edam
updated for GTK 3.0 |
261 |
def do_delete_raw_images( self, action, window ): |
2
by edam
- added status bar information |
262 |
|
263 |
# get path to first selected image, if there is one |
|
5.1.1
by edam
updated for GTK 3.0 |
264 |
thumb_view = window.get_thumb_view() |
2
by edam
- added status bar information |
265 |
if( thumb_view.get_n_selected() == 1 ): |
266 |
image = thumb_view.get_first_selected_image() |
|
267 |
path = os.path.dirname( image.get_file().get_path() ) |
|
268 |
||
269 |
# build a regex that will match raw filenames |
|
270 |
regex = re.compile( |
|
271 |
'.*\.(' + '|'.join( self.raw_file_extensions ) + ')', re.I ) |
|
272 |
||
273 |
# itterate through files in the dir |
|
274 |
files = set() |
|
275 |
for file in os.listdir( path ): |
|
276 |
if( regex.match( file ) ): |
|
277 |
files.add( file ) |
|
278 |
||
279 |
# do we have any files to delete? |
|
280 |
if( len( files ) > 0 ): |
|
281 |
||
282 |
# ask the user if they are sure |
|
5.1.1
by edam
updated for GTK 3.0 |
283 |
dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.MODAL, |
284 |
Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, |
|
2
by edam
- added status bar information |
285 |
_( 'Delete Raw Files?' ) ) |
286 |
if( len( files ) == 1 ): |
|
287 |
subject = _( ' remaining raw file' ) |
|
288 |
else: |
|
289 |
subject = _( ' remaining raw files' ) |
|
290 |
dialog.format_secondary_text( |
|
291 |
_( 'You are about to delete the ' ) + |
|
292 |
str( len( files ) ) + subject + |
|
293 |
_( " that you haven't specifically asked to keep from " + |
|
294 |
"the directory that the current image is in.\n\n" + |
|
295 |
"Do you want to continue?" ) ) |
|
296 |
result = dialog.run() |
|
297 |
dialog.destroy() |
|
5.1.1
by edam
updated for GTK 3.0 |
298 |
if( result != Gtk.ResponseType.YES ): |
2
by edam
- added status bar information |
299 |
return |
300 |
||
301 |
# delete the files |
|
302 |
for file in files: |
|
7
by edam
switch to gir Gio |
303 |
Gio.file_parse_name( path + '/' + file ).trash( None ) |
4
by edam
- added unkeep command |
304 |
#os.unlink( path + '/' + file ) |
2
by edam
- added status bar information |
305 |
|
5.1.1
by edam
updated for GTK 3.0 |
306 |
self.update_status( window ) |
2
by edam
- added status bar information |
307 |
|
308 |
# else, tell the user there aren't any raw files! |
|
309 |
else: |
|
5.1.1
by edam
updated for GTK 3.0 |
310 |
dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.MODAL, |
311 |
Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, |
|
2
by edam
- added status bar information |
312 |
_( 'No raw files to delete!' ) ) |
313 |
dialog.format_secondary_text( |
|
314 |
_( 'There are no raw files to delete!' ) ) |
|
315 |
dialog.run() |
|
316 |
dialog.destroy() |