Use list.sort's keyword parameters
[joel/kofoto.git] / src / packages / kofoto / gkofoto / singleobjectview.py
1 import gtk
2 from kofoto.gkofoto.environment import env
3 from kofoto.gkofoto.imageview import ImageView
4 from kofoto.gkofoto.objectcollectionview import ObjectCollectionView
5 from kofoto.gkofoto.imageversionslist import ImageVersionsList
6
7 def _make_callback_wrapper(fn):
8     def f(*unused):
9         fn()
10     return f
11
12 class SingleObjectView(ObjectCollectionView, gtk.HPaned):
13
14 ###############################################################################
15 ### Public
16
17     def __init__(self):
18         env.debug("Init SingleObjectView")
19         ObjectCollectionView.__init__(self, env.widgets["objectView"])
20         gtk.HPaned.__init__(self)
21         self._viewWidget.add(self)
22         self.__imageView = ImageView()
23         self.__imageView.set_error_pixbuf(
24             gtk.gdk.pixbuf_new_from_file(env.unknownImageIconFileName))
25         self.__imageView.get_image_widget().connect(
26             "button_press_event", self._mouse_button_pressed)
27         self.pack1(self.__imageView, resize=True)
28         self.__imageVersionsFrame = gtk.Frame("Image versions")
29         self.__imageVersionsFrame.set_size_request(162, -1)
30         self.__imageVersionsWindow = gtk.ScrolledWindow()
31         self.__imageVersionsList = ImageVersionsList(self)
32         self.__imageVersionsFrame.add(self.__imageVersionsList)
33         self.pack2(self.__imageVersionsFrame, resize=False)
34         self.show_all()
35         env.widgets["nextButton"].connect("clicked", self._goto, 1)
36         env.widgets["menubarNextImage"].connect("activate", self._goto, 1)
37         env.widgets["previousButton"].connect("clicked", self._goto, -1)
38         env.widgets["menubarPreviousImage"].connect("activate", self._goto, -1)
39         env.widgets["zoomToFit"].connect(
40             "clicked", _make_callback_wrapper(self.__imageView.zoom_to_fit))
41         env.widgets["menubarZoomToFit"].connect(
42             "activate", _make_callback_wrapper(self.__imageView.zoom_to_fit))
43         env.widgets["zoom100"].connect(
44             "clicked", _make_callback_wrapper(self.__imageView.zoom_to_actual))
45         env.widgets["menubarActualSize"].connect(
46             "activate", _make_callback_wrapper(self.__imageView.zoom_to_actual))
47         env.widgets["zoomIn"].connect(
48             "clicked", _make_callback_wrapper(self.__imageView.zoom_in))
49         env.widgets["menubarZoomIn"].connect(
50             "activate", _make_callback_wrapper(self.__imageView.zoom_in))
51         env.widgets["zoomOut"].connect(
52             "clicked", _make_callback_wrapper(self.__imageView.zoom_out))
53         env.widgets["menubarZoomOut"].connect(
54             "activate", _make_callback_wrapper(self.__imageView.zoom_out))
55         env.widgets["menubarViewDetailsPane"].set_sensitive(True)
56         self.__loadedObject = False
57         self.__selectionLocked = False
58         self.__selectedRowNr = None
59         self.__currentImageLocation = None
60         self.__latestLoadPixbufHandle = None
61         self.__latestSize = (0, 0)
62
63     def showDetailsPane(self):
64         self.__imageVersionsFrame.show()
65
66     def hideDetailsPane(self):
67         self.__imageVersionsFrame.hide()
68
69     def importSelection(self, objectSelection):
70         if not self.__selectionLocked:
71             env.debug("SingleImageView is importing selection")
72             self.__selectionLocked = True
73             model = self._objectCollection.getModel()
74             self.__loadedObject = None
75             if len(model) == 0:
76                 # Model is empty. No rows can be selected.
77                 self.__selectedRowNr = -1
78                 self.__imageView.clear()
79             else:
80                 if len(objectSelection) == 0:
81                     # No objects is selected -> select first object
82                     self.__selectedRowNr = 0
83                     objectSelection.setSelection([self.__selectedRowNr])
84                 elif len(objectSelection) > 1:
85                     # More than one object selected -> select first object
86                     self.__selectedRowNr = objectSelection.getLowestSelectedRowNr()
87                     objectSelection.setSelection([self.__selectedRowNr])
88                 else:
89                     # Exactly one object selected
90                     self.__selectedRowNr = objectSelection.getLowestSelectedRowNr()
91                 self.__loadedObject = objectSelection[self.__selectedRowNr]
92             self.__loadObject(self.__loadedObject)
93             enablePreviousButton = (self.__selectedRowNr > 0)
94             env.widgets["previousButton"].set_sensitive(enablePreviousButton)
95             env.widgets["menubarPreviousImage"].set_sensitive(enablePreviousButton)
96             enableNextButton = (self.__selectedRowNr != -1 and
97                                 self.__selectedRowNr < len(model) - 1)
98             env.widgets["nextButton"].set_sensitive(enableNextButton)
99             env.widgets["menubarNextImage"].set_sensitive(enableNextButton)
100             self.__selectionLocked = False
101         self._updateContextMenu()
102
103         # Override sensitiveness set in _updateContextMenu.
104         for widgetName in [
105                 "menubarCut",
106                 "menubarCopy",
107                 "menubarDelete",
108                 "menubarDestroy",
109                 "menubarProperties",
110                 "menubarCreateAlbumChild",
111                 "menubarRegisterAndAddImages",
112                 "menubarGenerateHtml",
113                 ]:
114             env.widgets[widgetName].set_sensitive(False)
115
116     def __loadObject(self, obj):
117         self.__imageVersionsList.clear()
118         if obj == None:
119             location = env.unknownImageIconFileName
120         elif obj.isAlbum():
121             location = env.albumIconFileName
122         elif obj.getPrimaryVersion():
123             location = obj.getPrimaryVersion().getLocation()
124             self.__imageVersionsList.loadImage(obj)
125         else:
126             location = env.unknownImageIconFileName
127         self._loadImageAtLocation(location)
128
129     def _loadImageAtLocation(self, location):
130         if location == self.__currentImageLocation:
131             return
132         self.__currentImageLocation = location
133         self.__imageView.set_image(self.__loadPixbuf_cb)
134
135     def __loadPixbuf_cb(self, size_limit):
136         if self.__latestLoadPixbufHandle is not None:
137             env.pixbufLoader.cancel_load(self.__latestLoadPixbufHandle)
138         self.__latestLoadPixbufHandle = env.pixbufLoader.load(
139             self.__currentImageLocation,
140             size_limit,
141             self.__imageView.set_from_pixbuf,
142             self.__imageView.set_error)
143         if size_limit != self.__latestSize:
144             self._unloadImages(self.__latestSize)
145         self._preloadImages(size_limit)
146         self.__latestSize = size_limit
147
148     def _reloadSingleObjectView(self):
149         self.reload()
150
151     def reload(self):
152         self.__loadObject(self.__loadedObject)
153         self.__imageVersionsList.reload()
154         self._objectCollection.reloadSelectedRows()
155
156     def _showHelper(self):
157         env.enter("SingleObjectView.showHelper()")
158         env.widgets["objectView"].show()
159         env.widgets["objectView"].grab_focus()
160         self._connectMenubarImageItems() # Grossest hack of the month. Sigh.
161         for widgetName in [
162                 "zoom100",
163                 "zoomToFit",
164                 "zoomIn",
165                 "zoomOut",
166                 "menubarZoom",
167                 ]:
168             env.widgets[widgetName].set_sensitive(True)
169         env.exit("SingleObjectView.showHelper()")
170
171     def _hideHelper(self):
172         env.enter("SingleObjectView.hideHelper()")
173         env.widgets["objectView"].hide()
174         for widgetName in [
175                 "previousButton",
176                 "nextButton",
177                 "menubarPreviousImage",
178                 "menubarNextImage",
179                 "zoom100",
180                 "zoomToFit",
181                 "zoomIn",
182                 "zoomOut",
183                 "menubarZoom",
184                 ]:
185             env.widgets[widgetName].set_sensitive(False)
186         env.exit("SingleObjectView.hideHelper()")
187
188     def _connectObjectCollectionHelper(self):
189         env.enter("Connecting SingleObjectView to object collection")
190         env.exit("Connecting SingleObjectView to object collection")
191
192     def _disconnectObjectCollectionHelper(self):
193         env.enter("Disconnecting SingleObjectView from object collection")
194         env.exit("Disconnecting SingleObjectView from object collection")
195
196     def _freezeHelper(self):
197         env.enter("SingleObjectView.freezeHelper()")
198         self._clearAllConnections()
199         self._objectCollection.removeInsertedRowCallback(self._modelUpdated)
200         env.exit("SingleObjectView.freezeHelper()")
201
202     def _thawHelper(self):
203         env.enter("SingleObjectView.thawHelper()")
204         model = self._objectCollection.getModel()
205         # The following events are needed to update the previous and
206         # next navigation buttons.
207         self._connect(model, "rows_reordered", self._modelUpdated)
208         self._connect(model, "row_deleted", self._modelUpdated)
209         self._objectCollection.addInsertedRowCallback(self._modelUpdated)
210         env.exit("SingleObjectView.thawHelper()")
211
212     def _modelUpdated(self, *unused):
213         env.debug("SingleObjectView is handling model update")
214         self.importSelection(self._objectCollection.getObjectSelection())
215
216     def _goto(self, unused, direction):
217         objectSelection = self._objectCollection.getObjectSelection()
218         objectSelection.setSelection([self.__selectedRowNr + direction])
219
220     def _preloadImages(self, size):
221         self._preloadOrUnloadImages(size, True)
222
223     def _preloadOrUnloadImages(self, size, preload):
224         objectSelection = self._objectCollection.getObjectSelection()
225         for location in objectSelection.getImageFilenamesToPreload():
226             if preload:
227                 env.pixbufLoader.preload(location, size)
228             else:
229                 env.pixbufLoader.unload(location, size)
230
231     def _unloadImages(self, size):
232         self._preloadOrUnloadImages(size, False)
233
234     def _hasFocus(self):
235         return True
236
237     def _mouse_button_pressed(self, widget, event):
238         if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
239             env.mainwindow._fullScreen()
240         else:
241             ObjectCollectionView._mouse_button_pressed(self, widget, event)