Reorganized source code hierarchy:
[joel/kofoto.git] / src / packages / kofoto / gkofoto / thumbnailview.py
1 import gtk
2 from kofoto.gkofoto.objectcollectionview import *
3 from kofoto.gkofoto.objectcollection import *
4 from environment import env
5
6 class ThumbnailView(ObjectCollectionView):
7
8 ###############################################################################
9 ### Public
10
11     def __init__(self):
12         env.debug("Init ThumbnailView")
13 ##        ObjectCollectionView.__init__(self,
14 ##                                      env.widgets["thumbnailList"])
15         ObjectCollectionView.__init__(self,
16                                       env.widgets["thumbnailView"])
17         self.__currentMaxWidth = env.thumbnailSize[0]
18         self.__selectionLocked = False
19         return
20         self._viewWidget.connect("select_icon", self._widgetIconSelected)
21         self._viewWidget.connect("unselect_icon", self._widgetIconUnselected)
22
23     def importSelection(self, objectSelection):
24         if not self.__selectionLocked:
25             env.debug("ThumbnailView is importing selection.")
26             self.__selectionLocked = True
27             self._viewWidget.unselect_all()
28             for rowNr in objectSelection:
29                 self._viewWidget.select_icon(rowNr)
30             self.__selectionLocked = False
31         self._updateContextMenu()
32
33     def _showHelper(self):
34         env.enter("ThumbnailView.showHelper()")
35         env.widgets["thumbnailView"].show()
36         self._viewWidget.grab_focus()
37         self.__scrollToFirstSelectedObject()
38         env.exit("ThumbnailView.showHelper()")
39
40     def _hideHelper(self):
41         env.enter("ThumbnailView.hideHelper()")
42         env.widgets["thumbnailView"].hide()
43         env.exit("ThumbnailView.hideHelper()")
44
45     def _connectObjectCollectionHelper(self):
46         env.enter("Connecting ThumbnailView to object collection")
47         # The model is loaded in thawHelper instead.
48         env.exit("Connecting ThumbnailView to object collection")
49
50     def _disconnectObjectCollectionHelper(self):
51         env.enter("Disconnecting ThumbnailView from object collection")
52         # The model is unloaded in freezeHelper instead.
53         env.exit("Disconnecting ThumbnailView from object collection")
54
55     def _freezeHelper(self):
56         env.enter("ThumbnailView.freezeHelper()")
57         self._clearAllConnections()
58         self._viewWidget.clear()
59         env.exit("ThumbnailView.freezeHelper()")
60
61     def _thawHelper(self):
62         env.enter("ThumbnailView.thawHelper()")
63         model = self._objectCollection.getModel()
64         for row in model:
65             self.__loadRow(row)
66         self._connect(model, "row_inserted",   self._rowInserted)
67         self._connect(model, "row_deleted",    self._rowDeleted)
68         self._connect(model, "rows_reordered", self._rowsReordered)
69         self._connect(model, "row_changed",    self._rowChanged)
70         env.exit("ThumbnailView.thawHelper()")
71
72 ###############################################################################
73 ### Callback functions registered by this class but invoked from other classes.
74
75     def _rowChanged(self, model, path, iterator):
76         env.debug("ThumbnailView row changed.")
77         self.__selectionLocked = True
78         self._viewWidget.remove(path[0])
79         # For some reason that I don't understand model[path].path != path
80         # Hence we pass by path as the location where the icon shall be
81         # inserted.
82         self.__loadRow(model[path[0]], path[0])
83         if path[0] in self._objectCollection.getObjectSelection():
84             self._viewWidget.select_icon(path[0])
85         self.__selectionLocked = False
86
87     def _rowInserted(self, model, path, iterator):
88         env.debug("ThumbnailView row inserted.")
89         self.__loadRow(model[path])
90
91     def _rowsReordered(self, model, b, c, d):
92         env.debug("ThumbnailView rows reordered.")
93         # TODO I Don't know how to parse which rows that has
94         #      been reordered. Hence I must reload all rows.
95         self._viewWidget.clear()
96         for row in self._objectCollection.getModel():
97             self.__loadRow(row)
98         self.importSelection(self._objectCollection.getObjectSelection())
99
100     def _rowDeleted(self, model, path):
101         env.debug("ThumbnailView row deleted.")
102         self._viewWidget.remove(path[0])
103
104     def _widgetIconSelected(self, widget, index, event):
105         if not self.__selectionLocked:
106             env.enter("ThumbnailView selection changed")
107             self.__selectionLocked = True
108             self._objectCollection.getObjectSelection().addSelection(index)
109             self.__selectionLocked = False
110
111     def _widgetIconUnselected(self, widget, index, event):
112         if not self.__selectionLocked:
113             env.enter("ThumbnailView selection changed")
114             self.__selectionLocked = True
115             self._objectCollection.getObjectSelection().removeSelection(index)
116             self.__selectionLocked = False
117
118 ###############################################################################
119 ### Private
120
121     def __loadRow(self, row, location=None):
122         if location is None:
123             location = row.path[0]
124         if row[ObjectCollection.COLUMN_IS_ALBUM]:
125             text = row[ObjectCollection.COLUMN_ALBUM_TAG]
126         else:
127             # TODO Let configuration decide what to show...
128             text = row[ObjectCollection.COLUMN_OBJECT_ID]
129         pixbuf = row[ObjectCollection.COLUMN_THUMBNAIL]
130         if pixbuf == None:
131             # It is possible that we get the row inserted event before
132             # the thumbnail is loaded. The temporary icon will be removed
133             # when we receive the row changed event.
134             pixbuf = env.loadingPixbuf
135         self._viewWidget.insert_pixbuf(location, pixbuf, "", str(text))
136         self.__currentMaxWidth = max(self.__currentMaxWidth, pixbuf.get_width())
137         self._viewWidget.set_icon_width(self.__currentMaxWidth)
138
139     def __scrollToFirstSelectedObject(self):
140         numberOfIcons = self._viewWidget.get_num_icons()
141         if numberOfIcons > 1:
142             # First check that the widget contains icons because I don't know
143             # how icon_is_visible() is handled if the view is empty.
144             if (self._viewWidget.icon_is_visible(0) == gtk.VISIBILITY_FULL
145                 and self._viewWidget.icon_is_visible(numberOfIcons - 1) == gtk.VISIBILITY_FULL):
146                 # All icons already visible. No need to scroll widget.
147                 pass
148             else:
149                 # Scroll widget to first selected icon
150                 rowNr = self._objectCollection.getObjectSelection().getLowestSelectedRowNr()
151                 if rowNr is not None:
152                     self._viewWidget.moveto(rowNr, 0.4)