/gtk/eog-manage-raws

To get this branch, use:
bzr branch http://bzr.ed.am/gtk/eog-manage-raws
2 by edam
- added status bar information
1
import eog, gtk, os, re
1 by edam
initial comit
2
3
class HelloWorldPlugin(eog.Plugin):
4
5
    raw_file_extensions = [ 'cr2', '3fr', 'ari', 'arw', 'srf', 'sr2', 'bay',
6
        'crw', 'cr2', 'cap', 'iiq', 'eip', 'dcs', 'dcr', 'drf', 'k25', 'kdc',
7
        'dng', 'erf', 'fff', 'mef', 'mos', 'mrw', 'nef', 'nrw', 'orf', 'ptx',
8
        'pef', 'pxn', 'r3d', 'raf', 'raw', 'rw2', 'rwl', 'rwz', 'x3f' ]
9
10
    def __init__( self ):
11
        eog.Plugin.__init__( self )
12
13
    def activate( self, window ):
14
        self._window = window
15
16
        # insert menu item
17
        manager = window.get_ui_manager()
2 by edam
- added status bar information
18
        self._action_group = gtk.ActionGroup( 'EogRawToolsPluginActions' )
19
        self._action_group.add_actions( [ ( 'EogPluginRunKeepRaw', None,
20
            _( 'Keep Raw Image' ), 'K',
21
            _( "Move the accompanying raw file to a 'raw' subdirectory" ),
1 by edam
initial comit
22
            self.on_keep_raw_image ) ] )
2 by edam
- added status bar information
23
        self._action_group.add_actions( [ ( 'EogPluginRunDeleteRaw', None,
24
            _( 'Delete Unkept Raw Images' ), None,
25
            _( "Delete all raw files in the current image's directory (the unkept ones)" ),
26
            self.on_delete_raw_images ) ] )
1 by edam
initial comit
27
        manager.insert_action_group( self._action_group, -1 )
28
        self._ui_id = manager.add_ui_from_string( """
29
            <ui>
30
                <menubar name="MainMenu">
31
                    <menu name="ToolsMenu" action="Tools">
32
                        <separator />
2 by edam
- added status bar information
33
                        <menuitem name="EogPluginRunKeepRaw"
1 by edam
initial comit
34
                            action="EogPluginRunKeepRaw" />
2 by edam
- added status bar information
35
                        <menuitem name="EogPluginRunDeleteRaw"
36
                            action="EogPluginRunDeleteRaw" />
1 by edam
initial comit
37
                        <separator />
38
                    </menu>
39
                </menubar>
40
                <popup name="ViewPopup">
41
                    <separator />
42
                    <menuitem action="EogPluginRunKeepRaw" />
43
                    <separator />
44
                </popup>
45
            </ui>
46
        """ )
47
2 by edam
- added status bar information
48
        # insert status bar
49
        self._statusbar = gtk.Statusbar()
50
        self._statusbar.set_has_resize_grip( False )
51
        self._statusbar.set_size_request( 85, 10 )
52
        statusbar = window.get_statusbar()
53
        statusbar.pack_end( self._statusbar, False, False, 0 );
54
        self._statusbar.show()
55
1 by edam
initial comit
56
        # connect to selection change
57
        thumb_view = window.get_thumb_view()
58
        self._on_selection_change_id = thumb_view.connect_after( \
2 by edam
- added status bar information
59
            'selection_changed', self.on_selection_change, window )
1 by edam
initial comit
60
61
        # init ui state
2 by edam
- added status bar information
62
        self.update_status( window )
1 by edam
initial comit
63
64
    def deactivate( self, window ):
65
2 by edam
- added status bar information
66
        # disconnect handlers
67
        thumb_view = window.get_thumb_view()
68
        thumb_view.disconnect( self._on_selection_change_id )
69
1 by edam
initial comit
70
        # remove menu items
71
        manager = window.get_ui_manager()
72
        manager.remove_ui( self._ui_id )
73
        manager.remove_action_group( self._action_group )
74
        manager.ensure_update()
75
2 by edam
- added status bar information
76
        # remove status bar entry
77
        statusbar = window.get_statusbar()
78
        statusbar.remove( self._statusbar )
1 by edam
initial comit
79
80
    def on_selection_change( self, view, data ):
2 by edam
- added status bar information
81
        self.update_status( data )
82
83
    def get_raw_filename_from_image( self, image ):
1 by edam
initial comit
84
        fname = image.get_file().get_path()
85
2 by edam
- added status bar information
86
        # get the base fileanme (with no extension), read for searching
1 by edam
initial comit
87
        base_fname = image.get_file().get_path()
88
        pos = base_fname.rfind( '.' )
89
        if( pos != -1 ):
2 by edam
- added status bar information
90
91
            # check if the extension of the current image makes it a raw file
92
            for ext in self.raw_file_extensions + \
93
                map( lambda x: x.upper(), self.raw_file_extensions ):
94
                if( base_fname[ pos : ] == ext ):
95
                    return False;
96
97
            # remove extension from base filename
1 by edam
initial comit
98
            base_fname = base_fname[ 0 : pos ]
99
        
100
        # check for stupidity
101
        if( base_fname[ -1 : None ] == '/' ):
2 by edam
- added status bar information
102
            return False
103
104
        # loop through valid raw file extensions, uppercase and lowercase
105
        for ext in self.raw_file_extensions + \
106
            map( lambda x: x.upper(), self.raw_file_extensions ):
107
108
            # if the raw file exists, we found it
109
            if( os.path.isfile( base_fname + '.' + ext ) ):
110
                return os.path.basename( base_fname + '.' + ext );
1 by edam
initial comit
111
112
        # path the raw images will be moved to
113
        raw_path = os.path.dirname( fname ) + '/raw';
114
2 by edam
- added status bar information
115
        # loop through valid raw file extensions, uppercase and lowercase
1 by edam
initial comit
116
        for ext in self.raw_file_extensions + \
2 by edam
- added status bar information
117
            map( lambda x: x.upper(), self.raw_file_extensions ):
118
119
            # if the raw file exists, we found it
120
            if( os.path.isfile( os.path.dirname( fname ) + '/raw/' + \
121
                os.path.basename( base_fname + '.' + ext ) ) ):
122
                return os.path.basename( base_fname + '.' + ext );
123
124
        # not found
125
        return False;
126
127
    def update_status( self, window ):
128
        thumb_view = window.get_thumb_view()
129
130
        # do we have just the one selected image? we can't handle multiple
131
        # images because EogThumbView.get_selected_images() doesn't work.
132
        self._action_group.set_sensitive( \
133
            thumb_view.get_n_selected() == 1 )
134
135
        # update the status bar
136
        if( thumb_view.get_n_selected() > 0 ):
137
            image = thumb_view.get_first_selected_image()
138
            raw_fname = self.get_raw_filename_from_image( image )
139
            path = os.path.dirname( image.get_file().get_path() )
140
            self._statusbar.pop( 0 )
141
            if( raw_fname is False ):
142
                self._statusbar.push( 0, _( 'raw: -' ) )
143
            elif( os.path.isfile( path + '/' + raw_fname ) ):
144
                self._statusbar.push( 0, _( 'raw: delete' ) )
145
            else:
146
                self._statusbar.push( 0, _( 'raw: keep' ) )
147
148
    def on_keep_raw_image( self, action ):
149
150
        # do we have just the one selected image? we can't handle multiple
151
        # images because EogThumbView.get_selected_images() doesn't work.
152
        thumb_view = self._window.get_thumb_view()
153
        if( thumb_view.get_n_selected() == 1 ):
154
155
            # get the image
156
            image = thumb_view.get_first_selected_image()
157
            if( image != None ):
158
                self.keep_raw_image( image )
159
160
            # update ui
161
            self.update_status( self._window )
162
163
    def keep_raw_image( self, image ):
164
165
        raw_fname = self.get_raw_filename_from_image( image )
166
        if( raw_fname is False ):
167
            dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL,
168
                gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
169
                _( 'Raw file not found!' ) )
170
            dialog.format_secondary_text( _( "This image doesn't appear to " +
171
                "have an accompanying raw file." ) )
1 by edam
initial comit
172
            dialog.run()
173
            dialog.destroy()
174
            return
2 by edam
- added status bar information
175
176
        # does raw file exist?
177
        path = os.path.dirname( image.get_file().get_path() )
178
        if( os.path.isfile( path + '/' + raw_fname ) ):
179
180
            # create the raw directory, if it doesn't exist
181
            if( not os.path.isdir( path + '/raw' ) ):
182
                os.mkdir( path + '/raw' );
183
184
            # move the raw file in to the raw directory
185
            os.rename( path + '/' + raw_fname, path + '/raw/' + raw_fname )
186
187
    def on_delete_raw_images( self, action ):
188
189
        # get path to first selected image, if there is one
190
        thumb_view = self._window.get_thumb_view()
191
        if( thumb_view.get_n_selected() == 1 ):
192
            image = thumb_view.get_first_selected_image()
193
            path = os.path.dirname( image.get_file().get_path() )
194
195
            # build a regex that will match raw filenames
196
            regex = re.compile(
197
                '.*\.(' + '|'.join( self.raw_file_extensions ) + ')', re.I )
198
199
            # itterate through files in the dir
200
            files = set()
201
            for file in os.listdir( path ):
202
                if( regex.match( file ) ):
203
                    files.add( file )
204
205
            # do we have any files to delete?
206
            if( len( files ) > 0 ):
207
208
                # ask the user if they are sure
209
                dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL,
210
                    gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
211
                    _( 'Delete Raw Files?' ) )
212
                if( len( files ) == 1 ):
213
                    subject = _( ' remaining raw file' )
214
                else:
215
                    subject = _( ' remaining raw files' )
216
                dialog.format_secondary_text(
217
                    _( 'You are about to delete the ' ) +
218
                    str( len( files ) ) + subject +
219
                    _( " that you haven't specifically asked to keep from " +
220
                        "the directory that the current image is in.\n\n" +
221
                        "Do you want to continue?" ) )
222
                result = dialog.run()
223
                dialog.destroy()
224
                if( result != gtk.RESPONSE_YES ):
225
                    return
226
227
                # delete the files
228
                for file in files:
229
                    os.unlink( path + '/' + file )
230
231
                self.update_status( self._window )
232
        
233
            # else, tell the user there aren't any raw files!
234
            else:
235
                dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL,
236
                    gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
237
                    _( 'No raw files to delete!' ) )
238
                dialog.format_secondary_text(
239
                    _( 'There are no raw files to delete!' ) )
240
                dialog.run()
241
                dialog.destroy()