Use GNOME-style layout of OK and Cancel buttons.
[joel/kofoto.git] / src / gkofoto / gkofoto / handleimagesdialog.py
1 import gtk
2 import gobject
3 import os
4 from environment import env
5 from kofoto.shelf import \
6      ImageDoesNotExistError, ImageExistsError, \
7      MultipleImagesAtOneLocationError, NotAnImageError, \
8      makeValidTag
9 from kofoto.clientutils import walk_files
10
11 class HandleImagesDialog(gtk.FileChooserDialog):
12     def __init__(self):
13         gtk.FileChooserDialog.__init__(
14             self,
15             title="Handle images",
16             action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
17             buttons=(
18                 gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
19                 gtk.STOCK_OK, gtk.RESPONSE_OK))
20         self.connect("response", self._response)
21
22     def _response(self, widget, responseId):
23         if responseId == gtk.RESPONSE_CANCEL:
24             return
25         widgets = gtk.glade.XML(env.gladeFile, "handleImagesProgressDialog")
26         handleImagesProgressDialog = widgets.get_widget(
27             "handleImagesProgressDialog")
28         knownUnchangedImagesCount = widgets.get_widget(
29             "knownUnchangedImagesCount")
30         knownMovedImagesCount = widgets.get_widget(
31             "knownMovedImagesCount")
32         unknownModifiedImagesCount = widgets.get_widget(
33             "unknownModifiedImagesCount")
34         unknownFilesCount = widgets.get_widget(
35             "unknownFilesCount")
36         investigatedFilesCount = widgets.get_widget(
37             "investigatedFilesCount")
38         okButton = widgets.get_widget("okButton")
39         okButton.set_sensitive(False)
40
41         handleImagesProgressDialog.show()
42
43         knownUnchangedImages = 0
44         knownMovedImages = 0
45         unknownModifiedImages = 0
46         unknownFiles = 0
47         investigatedFiles = 0
48         modifiedImages = []
49         movedImages = []
50         for filepath in walk_files([self.get_filename()]):
51             try:
52                 filepath = filepath.decode("utf-8")
53             except UnicodeDecodeError:
54                 filepath = filepath.decode("latin1")
55             try:
56                 image = env.shelf.getImage(filepath)
57                 if image.getLocation() == os.path.realpath(filepath):
58                     # Registered.
59                     knownUnchangedImages += 1
60                     knownUnchangedImagesCount.set_text(
61                         str(knownUnchangedImages))
62                 else:
63                     # Moved.
64                     knownMovedImages += 1
65                     knownMovedImagesCount.set_text(str(knownMovedImages))
66                     movedImages.append(filepath)
67             except ImageDoesNotExistError:
68                 try:
69                     image = env.shelf.getImage(
70                         filepath, identifyByLocation=True)
71                     # Modified.
72                     unknownModifiedImages += 1
73                     unknownModifiedImagesCount.set_text(
74                         str(unknownModifiedImages))
75                     modifiedImages.append(filepath)
76                 except MultipleImagesAtOneLocationError:
77                     # Multiple images at one location.
78                     # TODO: Handle this error.
79                     pass
80                 except ImageDoesNotExistError:
81                     # Unregistered.
82                     unknownFiles += 1
83                     unknownFilesCount.set_text(str(unknownFiles))
84             investigatedFiles += 1
85             investigatedFilesCount.set_text(str(investigatedFiles))
86             while gtk.events_pending():
87                 gtk.main_iteration()
88
89         okButton.set_sensitive(True)
90         handleImagesProgressDialog.run()
91         handleImagesProgressDialog.destroy()
92
93         if modifiedImages or movedImages:
94             if modifiedImages:
95                 self._dialogHelper(
96                     "Update modified images",
97                     "The above image files have been modified. Press OK to"
98                     " make Kofoto recognize the new contents.",
99                     modifiedImages,
100                     self._updateModifiedImages)
101             if movedImages:
102                 self._dialogHelper(
103                     "Update moved or renamed images",
104                     "The above image files have been moved or renamed. Press OK to"
105                     " make Kofoto recognize the new locations.",
106                     movedImages,
107                     self._updateMovedImages)
108         else:
109             dialog = gtk.MessageDialog(
110                 type=gtk.MESSAGE_INFO,
111                 buttons=gtk.BUTTONS_OK,
112                 message_format="No modified, renamed or moved images found.")
113             dialog.run()
114             dialog.destroy()
115
116     def _dialogHelper(self, title, text, filepaths, handlerFunction):
117         widgets = gtk.glade.XML(env.gladeFile, "updateImagesDialog")
118         dialog = widgets.get_widget("updateImagesDialog")
119         dialog.set_title(title)
120         filenameList = widgets.get_widget("filenameList")
121         renderer = gtk.CellRendererText()
122         column = gtk.TreeViewColumn("Image filename", renderer, text=0)
123         filenameList.append_column(column)
124         dialogText = widgets.get_widget("dialogText")
125         dialogText.set_text(text)
126         model = gtk.ListStore(gobject.TYPE_STRING)
127         for filepath in filepaths:
128             model.append([filepath])
129         filenameList.set_model(model)
130         if dialog.run() == gtk.RESPONSE_OK:
131             handlerFunction(filepaths)
132         dialog.destroy()
133
134     def _error(self, errorText):
135         dialog = gtk.MessageDialog(
136             type=gtk.MESSAGE_ERROR,
137             buttons=gtk.BUTTONS_OK,
138             message_format=errorText)
139         dialog.run()
140         dialog.destroy()
141
142     def _updateModifiedImages(self, filepaths):
143         for filepath in filepaths:
144             try:
145                 image = env.shelf.getImage(
146                     filepath, identifyByLocation=True)
147                 image.contentChanged()
148             except ImageDoesNotExistError:
149                 self._error("Image does not exist: %s" % filepath)
150             except MultipleImagesAtOneLocationError:
151                 # TODO: Handle this.
152                 pass
153             except IOError, x:
154                 self._error("Error while reading %s: %s" % (
155                     filepath, x))
156
157     def _updateMovedImages(self, filepaths):
158         for filepath in filepaths:
159             try:
160                 image = env.shelf.getImage(filepath)
161                 image.locationChanged(filepath)
162             except ImageDoesNotExistError:
163                 self._error("Image does not exist: %s" % filepath)
164             except MultipleImagesAtOneLocationError:
165                 # TODO: Handle this.
166                 pass
167             except IOError, x:
168                 self._error("Error while reading %s: %s" % (
169                     filepath, x))