~gary-lasker/software-center/installedview-search-fixes

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/panes/viewswitcher.py

mergedĀ fromĀ lp:~alexeftimie/software-center/backend-refactor

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
from gi.repository import Gtk, GObject
21
21
import logging
22
 
import os
23
 
import sys
24
 
import xapian
25
22
 
26
23
from gettext import gettext as _
27
24
 
28
25
from softwarecenter.backend import get_install_backend
29
26
from softwarecenter.db.database import StoreDatabase
30
27
from softwarecenter.enums import ViewPages
31
 
from softwarecenter.paths import XAPIAN_BASE_PATH
32
 
from softwarecenter.backend.channel import get_channels_manager
33
 
from softwarecenter.ui.gtk3.widgets.buttons import SectionSelector
 
28
from softwarecenter.backend.channel import (get_channels_manager,
 
29
                                            AllInstalledChannel,
 
30
                                            AllAvailableChannel)
 
31
from softwarecenter.ui.gtk3.widgets.buttons import (SectionSelector,
 
32
                                                    ChannelSelector)
34
33
from softwarecenter.ui.gtk3.em import StockEms
35
34
from softwarecenter.ui.gtk3.widgets.symbolic_icons import (
36
35
                                    SymbolicIcon, PendingSymbolicIcon)
37
 
import softwarecenter.ui.gtk3.dialogs as dialogs
38
36
 
39
37
 
40
38
LOG = logging.getLogger(__name__)
41
39
 
42
40
 
 
41
_last_button = None
43
42
class ViewSwitcher(Gtk.Box):
44
43
 
45
44
    __gsignals__ = {
69
68
        # widgetry
70
69
        Gtk.Box.__init__(self)
71
70
        self.set_orientation(Gtk.Orientation.HORIZONTAL)
72
 
        self.set_spacing(StockEms.SMALL)
73
71
 
74
72
        # Gui stuff
75
73
        self.view_buttons = {}
 
74
        self.selectors = {}
 
75
        self._prev_view = None  # track the previous active section
 
76
        self._prev_item = None  # track the previous active menu-item
76
77
        self._handlers = []
77
 
        self._prev_item = None
 
78
 
78
79
 
79
80
        # order is important here!
80
81
        # first, the availablepane items
81
82
        icon = SymbolicIcon("available")
82
 
        available = self.append_section(ViewPages.AVAILABLE,
83
 
                                        _("All Software"),
84
 
                                        icon,
85
 
                                        True)
86
 
        available.set_build_func(self.on_get_available_channels)
 
83
        self.append_section_with_channel_sel(
 
84
                                ViewPages.AVAILABLE,
 
85
                                _("All Software"),
 
86
                                icon,
 
87
                                self.on_get_available_channels)
87
88
 
88
89
        # the installedpane items
89
90
        icon = SymbolicIcon("installed")
90
 
        installed = self.append_section(ViewPages.INSTALLED,
91
 
                                        _("Installed"),
92
 
                                        icon,
93
 
                                        True)
94
 
        installed.set_build_func(self.on_get_installed_channels)
 
91
        self.append_section_with_channel_sel(
 
92
                                ViewPages.INSTALLED,
 
93
                                _("Installed"),
 
94
                                icon,
 
95
                                self.on_get_installed_channels)
95
96
 
96
97
        # the historypane item
97
98
        icon = SymbolicIcon("history")
111
112
        self.notify_icon_of_pending_count(pending)
112
113
        if pending > 0:
113
114
            self.start_icon_animation()
 
115
            pending_btn = self.view_buttons[ViewPages.PENDING]
 
116
            if not pending_btn.get_visible():
 
117
                pending_btn.set_visible(True)
114
118
        else:
115
119
            self.stop_icon_animation()
 
120
            pending_btn = self.view_buttons[ViewPages.PENDING]
 
121
            pending_btn.set_visible(False)
116
122
        return
117
123
 
118
124
    def start_icon_animation(self):
129
135
        image = self.view_buttons[ViewPages.PENDING].image
130
136
        image.set_transaction_count(count)
131
137
 
 
138
    def introduce_button(self):
 
139
 
 
140
        
 
141
 
 
142
        return
 
143
 
132
144
    def on_transaction_finished(self, backend, result):
133
145
        if result.success: self.on_channels_changed()
134
146
        return
135
147
 
136
 
    def append_section(self, view_id, label, icon, has_channel_sel=False):
137
 
        btn = SectionSelector(label, icon, self.ICON_SIZE,
138
 
                              has_channel_sel)
139
 
        self.view_buttons[view_id] = btn
140
 
        self.pack_start(btn, False, False, 0)
141
 
        btn.show()
142
 
        btn.connect('clicked', self.on_view_switch, view_id)
143
 
        return btn
144
 
 
145
 
    def on_view_switch(self, button, view_id):
146
 
        #~ pane = self.view_manager.get_view_widget(view_id)
147
 
        #~ pane.state.reset()
148
 
        self.view_manager.set_active_view(view_id)
 
148
    def on_section_sel_clicked(self, button, view_id):
 
149
        if self._prev_view is view_id:
 
150
            return True
 
151
 
 
152
        vm = self.view_manager
 
153
 
 
154
        def config_view():
 
155
            # set active pane
 
156
            pane = vm.set_active_view(view_id)
 
157
            # configure DisplayState
 
158
            state = pane.state.copy()
 
159
            if view_id == ViewPages.INSTALLED:
 
160
                state.channel = AllInstalledChannel()
 
161
            else:
 
162
                state.channel = AllAvailableChannel()
 
163
            # decide which page we want to display
 
164
            if hasattr(pane, "Pages"):
 
165
                page = pane.Pages.HOME
 
166
            else:
 
167
                page = None
 
168
            # request page change
 
169
            vm.display_page(pane, page, state)
 
170
            return False
 
171
 
 
172
        self._prev_view = view_id
 
173
        GObject.idle_add(config_view)
149
174
        return
150
175
 
151
176
    def on_get_available_channels(self, popup):
154
179
    def on_get_installed_channels(self, popup):
155
180
        return self.build_channel_list(popup, ViewPages.INSTALLED)
156
181
 
157
 
    def on_channels_changed(self):
158
 
        for view_id, btn in self.view_buttons.iteritems():
159
 
            if not btn.has_channel_sel: continue
 
182
    def on_channels_changed(self, backend, res):
 
183
        for view_id, sel in self.selectors.items():
160
184
            # setting popup to None will cause a rebuild of the popup
161
185
            # menu the next time the selector is clicked
162
 
            btn.popup = None
 
186
            sel.popup = None
163
187
        return
164
188
 
 
189
    def append_section(self, view_id, label, icon):
 
190
        btn = SectionSelector(label, icon, self.ICON_SIZE)
 
191
        self.view_buttons[view_id] = btn
 
192
        self.pack_start(btn, False, False, 0)
 
193
 
 
194
        global _last_button
 
195
        if _last_button is not None:
 
196
            btn.join_group(_last_button)
 
197
 
 
198
        _last_button = btn
 
199
 
 
200
        # this must go last otherwise as the buttons are added
 
201
        # to the group, toggled & clicked gets emitted... causing
 
202
        # all panes to fully initialise on USC startup, which is
 
203
        # undesirable!
 
204
        btn.connect("clicked", self.on_section_sel_clicked, view_id)
 
205
        return btn
 
206
 
 
207
    def append_channel_selector(self, section_btn, view_id, build_func):
 
208
        sel = ChannelSelector(section_btn)
 
209
        self.selectors[view_id] = sel
 
210
        sel.set_build_func(build_func)
 
211
        self.pack_start(sel, False, False, 0)
 
212
        return sel
 
213
 
 
214
    def append_section_with_channel_sel(self, view_id, label, icon, build_func):
 
215
        btn = self.append_section(view_id, label, icon)
 
216
        btn.draw_hint_has_channel_selector = True
 
217
        sel = self.append_channel_selector(btn, view_id, build_func)
 
218
        return btn, sel
 
219
 
165
220
    def build_channel_list(self, popup, view_id):
166
221
        # clean up old signal handlers
167
222
        for sig in self._handlers:
205
260
        return
206
261
 
207
262
    def on_channel_selected(self, item, event, channel, view_id):
 
263
        vm = self.view_manager
 
264
 
 
265
        def config_view():
 
266
            # set active pane
 
267
            pane = vm.set_active_view(view_id)
 
268
            # configure DisplayState
 
269
            state = pane.state.copy()
 
270
            state.channel = channel
 
271
            # decide which page we want to display
 
272
            if hasattr(pane, "Pages"):
 
273
                if channel.origin == "all":
 
274
                    page = pane.Pages.HOME
 
275
                else:
 
276
                    page = pane.Pages.LIST
 
277
            else:
 
278
                page = None
 
279
            # request page change
 
280
            vm.display_page(pane, page, state)
 
281
            return False
208
282
 
209
283
        if self._prev_item is item:
210
284
            parent = item.get_parent()
213
287
 
214
288
        if self._prev_item is not None:
215
289
            self._prev_item.set_property("active", False)
216
 
 
217
290
        self._prev_item = item
218
291
 
219
 
        # set active pane
220
 
        vm = self.view_manager
221
 
        pane = vm.set_active_view(view_id)
222
 
 
223
 
        # configure DisplayState
224
 
        state = pane.state.copy()
225
 
        state.channel = channel
226
 
 
227
 
        # request page change
228
 
        if channel.origin == "all":
229
 
            page = pane.Pages.HOME
230
 
        else:
231
 
            page = pane.Pages.LIST
232
 
 
233
 
        GObject.idle_add(vm.display_page, pane, page, state)
 
292
        # activate the section if need be
 
293
        btn = self.view_buttons[view_id]
 
294
        if not btn.get_active():
 
295
            btn.set_active(True)
 
296
 
 
297
        GObject.idle_add(config_view)
234
298
        return
235
299
 
236
300
 
237
 
if __name__ == "__main__":
238
 
    from softwarecenter.db.pkginfo import get_pkg_info
239
 
    cache = get_pkg_info()
240
 
    cache.open()
241
 
 
242
 
    # xapian
243
 
    xapian_base_path = XAPIAN_BASE_PATH
244
 
    pathname = os.path.join(xapian_base_path, "xapian")
245
 
    try:
246
 
        db = StoreDatabase(pathname, cache)
247
 
        db.open()
248
 
    except xapian.DatabaseOpeningError:
249
 
        # Couldn't use that folder as a database
250
 
        # This may be because we are in a bzr checkout and that
251
 
        #   folder is empty. If the folder is empty, and we can find the
252
 
        # script that does population, populate a database in it.
253
 
        if os.path.isdir(pathname) and not os.listdir(pathname):
254
 
            from softwarecenter.db.update import rebuild_database
255
 
            logging.info("building local database")
256
 
            rebuild_database(pathname)
257
 
            db = StoreDatabase(pathname, cache)
258
 
            db.open()
259
 
    except xapian.DatabaseCorruptError, e:
260
 
        logging.exception("xapian open failed")
261
 
        dialogs.error(None, 
262
 
                      _("Sorry, can not open the software database"),
263
 
                      _("Please re-install the 'software-center' "
264
 
                        "package."))
265
 
        # FIXME: force rebuild by providing a dbus service for this
266
 
        sys.exit(1)
267
 
 
268
 
 
269
 
    logging.basicConfig(level=logging.DEBUG)
270
 
    import sys
271
 
 
272
 
    if len(sys.argv) > 1:
273
 
        datadir = sys.argv[1]
274
 
    elif os.path.exists("./data"):
275
 
        datadir = "./data"
276
 
    else:
277
 
        datadir = "/usr/share/software-center"
278
 
 
279
 
    from softwarecenter.ui.gtk3.utils import get_sc_icon_theme
280
 
    icons = get_sc_icon_theme(datadir)
 
301
def get_test_window_viewswitcher():
 
302
    from softwarecenter.testutils import (get_test_db,
 
303
                                          get_test_datadir,
 
304
                                          get_test_gtk3_viewmanager,
 
305
                                          get_test_pkg_info,
 
306
                                          get_test_gtk3_icon_cache,
 
307
                                          )
 
308
    cache = get_test_pkg_info()
 
309
    db = get_test_db()
 
310
    icons = get_test_gtk3_icon_cache()
 
311
    datadir = get_test_datadir()
 
312
    manager = get_test_gtk3_viewmanager()
 
313
 
 
314
    view = ViewSwitcher(manager, datadir, db, cache, icons)
281
315
 
282
316
    scroll = Gtk.ScrolledWindow()
283
 
 
284
 
    from softwarecenter.ui.gtk3.session.viewmanager import ViewManager
285
 
    notebook = Gtk.Notebook()
286
 
    manager = ViewManager(notebook)
287
 
    view = ViewSwitcher(manager, datadir, db, cache, icons)
288
 
 
289
317
    box = Gtk.VBox()
290
318
    box.pack_start(scroll, True, True, 0)
291
319
 
293
321
    scroll.add_with_viewport(view)
294
322
 
295
323
    win.add(box)
296
 
    win.set_size_request(400,400)
 
324
    win.set_size_request(400,200)
 
325
    win.connect("destroy", Gtk.main_quit)
297
326
    win.show_all()
298
 
    win.connect("destroy", Gtk.main_quit)
 
327
    return win
 
328
 
 
329
if __name__ == "__main__":
 
330
    import softwarecenter.paths
 
331
    logging.basicConfig(level=logging.DEBUG)
 
332
 
 
333
    softwarecenter.paths.datadir = "./data"
 
334
    win = get_test_window_viewswitcher()
 
335
 
299
336
 
300
337
    Gtk.main()