20
20
from gi.repository import Gtk, GObject
26
23
from gettext import gettext as _
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,
31
from softwarecenter.ui.gtk3.widgets.buttons import (SectionSelector,
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
40
38
LOG = logging.getLogger(__name__)
43
42
class ViewSwitcher(Gtk.Box):
70
69
Gtk.Box.__init__(self)
71
70
self.set_orientation(Gtk.Orientation.HORIZONTAL)
72
self.set_spacing(StockEms.SMALL)
75
73
self.view_buttons = {}
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
79
80
# order is important here!
80
81
# first, the availablepane items
81
82
icon = SymbolicIcon("available")
82
available = self.append_section(ViewPages.AVAILABLE,
86
available.set_build_func(self.on_get_available_channels)
83
self.append_section_with_channel_sel(
87
self.on_get_available_channels)
88
89
# the installedpane items
89
90
icon = SymbolicIcon("installed")
90
installed = self.append_section(ViewPages.INSTALLED,
94
installed.set_build_func(self.on_get_installed_channels)
91
self.append_section_with_channel_sel(
95
self.on_get_installed_channels)
96
97
# the historypane item
97
98
icon = SymbolicIcon("history")
111
112
self.notify_icon_of_pending_count(pending)
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)
115
119
self.stop_icon_animation()
120
pending_btn = self.view_buttons[ViewPages.PENDING]
121
pending_btn.set_visible(False)
118
124
def start_icon_animation(self):
129
135
image = self.view_buttons[ViewPages.PENDING].image
130
136
image.set_transaction_count(count)
138
def introduce_button(self):
132
144
def on_transaction_finished(self, backend, result):
133
145
if result.success: self.on_channels_changed()
136
def append_section(self, view_id, label, icon, has_channel_sel=False):
137
btn = SectionSelector(label, icon, self.ICON_SIZE,
139
self.view_buttons[view_id] = btn
140
self.pack_start(btn, False, False, 0)
142
btn.connect('clicked', self.on_view_switch, view_id)
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:
152
vm = self.view_manager
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()
162
state.channel = AllAvailableChannel()
163
# decide which page we want to display
164
if hasattr(pane, "Pages"):
165
page = pane.Pages.HOME
168
# request page change
169
vm.display_page(pane, page, state)
172
self._prev_view = view_id
173
GObject.idle_add(config_view)
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)
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
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)
195
if _last_button is not None:
196
btn.join_group(_last_button)
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
204
btn.connect("clicked", self.on_section_sel_clicked, view_id)
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)
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)
165
220
def build_channel_list(self, popup, view_id):
166
221
# clean up old signal handlers
167
222
for sig in self._handlers:
207
262
def on_channel_selected(self, item, event, channel, view_id):
263
vm = self.view_manager
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
276
page = pane.Pages.LIST
279
# request page change
280
vm.display_page(pane, page, state)
209
283
if self._prev_item is item:
210
284
parent = item.get_parent()
214
288
if self._prev_item is not None:
215
289
self._prev_item.set_property("active", False)
217
290
self._prev_item = item
220
vm = self.view_manager
221
pane = vm.set_active_view(view_id)
223
# configure DisplayState
224
state = pane.state.copy()
225
state.channel = channel
227
# request page change
228
if channel.origin == "all":
229
page = pane.Pages.HOME
231
page = pane.Pages.LIST
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():
297
GObject.idle_add(config_view)
237
if __name__ == "__main__":
238
from softwarecenter.db.pkginfo import get_pkg_info
239
cache = get_pkg_info()
243
xapian_base_path = XAPIAN_BASE_PATH
244
pathname = os.path.join(xapian_base_path, "xapian")
246
db = StoreDatabase(pathname, cache)
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)
259
except xapian.DatabaseCorruptError, e:
260
logging.exception("xapian open failed")
262
_("Sorry, can not open the software database"),
263
_("Please re-install the 'software-center' "
265
# FIXME: force rebuild by providing a dbus service for this
269
logging.basicConfig(level=logging.DEBUG)
272
if len(sys.argv) > 1:
273
datadir = sys.argv[1]
274
elif os.path.exists("./data"):
277
datadir = "/usr/share/software-center"
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,
304
get_test_gtk3_viewmanager,
306
get_test_gtk3_icon_cache,
308
cache = get_test_pkg_info()
310
icons = get_test_gtk3_icon_cache()
311
datadir = get_test_datadir()
312
manager = get_test_gtk3_viewmanager()
314
view = ViewSwitcher(manager, datadir, db, cache, icons)
282
316
scroll = Gtk.ScrolledWindow()
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)
290
318
box.pack_start(scroll, True, True, 0)
293
321
scroll.add_with_viewport(view)
296
win.set_size_request(400,400)
324
win.set_size_request(400,200)
325
win.connect("destroy", Gtk.main_quit)
298
win.connect("destroy", Gtk.main_quit)
329
if __name__ == "__main__":
330
import softwarecenter.paths
331
logging.basicConfig(level=logging.DEBUG)
333
softwarecenter.paths.datadir = "./data"
334
win = get_test_window_viewswitcher()