92
101
import softwarecenter.ui.gtk3.dialogs as dialogs
94
103
from softwarecenter.ui.gtk3.SimpleGtkbuilderApp import SimpleGtkbuilderApp
95
from softwarecenter.ui.gtk3.panes.installedpane import InstalledPane
96
from softwarecenter.ui.gtk3.panes.availablepane import AvailablePane
104
with ExecutionTime("import InstalledPane"):
105
from softwarecenter.ui.gtk3.panes.installedpane import InstalledPane
106
with ExecutionTime("import AvailablePane"):
107
from softwarecenter.ui.gtk3.panes.availablepane import AvailablePane
97
108
from softwarecenter.ui.gtk3.panes.historypane import HistoryPane
98
109
from softwarecenter.ui.gtk3.panes.globalpane import GlobalPane
99
110
from softwarecenter.ui.gtk3.panes.pendingpane import PendingPane
247
258
START_DBUS = True
249
def __init__(self, datadir, xapian_base_path, options, args=None):
260
def __init__(self, options, args=None):
250
261
self.dbusControler = None
251
262
if self.START_DBUS:
252
263
# setup dbus and exit if there is another instance already running
253
264
self.setup_dbus_or_bring_other_instance_to_front(args)
255
self.datadir = datadir
266
self.datadir = softwarecenter.paths.datadir
256
267
super(SoftwareCenterAppGtk3, self).__init__(
257
datadir + "/ui/gtk3/SoftwareCenter.ui",
268
os.path.join(self.datadir, "ui", "gtk3", "SoftwareCenter.ui"),
259
270
gettext.bindtextdomain("software-center", "/usr/share/locale")
260
271
gettext.textdomain("software-center")
341
353
# initial css loading
342
354
init_sc_css_provider(self.window_main,
344
Gdk.Screen.get_default(),
356
Gdk.Screen.get_default())
347
358
# wire up the css provider to reconfigure on theme-changes
348
359
self.window_main.connect("style-updated",
349
360
self._on_style_updated,
350
361
init_sc_css_provider,
352
Gdk.Screen.get_default(),
363
Gdk.Screen.get_default())
364
# workaround broken engines (LP: #1021308)
365
self.window_main.emit("style-updated")
355
367
# register view manager and create view panes/widgets
356
368
self.view_manager = ViewManager(self.notebook_view, options)
358
370
with ExecutionTime("building panes"):
359
self.global_pane = GlobalPane(self.view_manager, self.datadir,
360
self.db, self.cache, self.icons)
371
self.global_pane = GlobalPane(self.view_manager, self.db,
372
self.cache, self.icons)
361
373
self.vbox1.pack_start(self.global_pane, False, False, 0)
362
374
self.vbox1.reorder_child(self.global_pane, 1)
413
422
with ExecutionTime("create review loader"):
414
423
self.review_loader = get_review_loader(self.cache, self.db)
415
# FIXME: add some kind of throttle, I-M-S here
416
self.review_loader.refresh_review_stats(
417
self.on_review_stats_loaded)
424
self.review_loader.connect(
425
"refresh-review-stats-finished", self.on_review_stats_loaded)
426
self.review_loader.refresh_review_stats()
418
427
#load usefulness votes from server when app starts
419
428
self.useful_cache = UsefulnessCache(True)
420
429
self.setup_database_rebuilding_listener()
499
506
def _run_software_center_agent(self):
500
507
""" helper that triggers the update-software-center-agent helper """
501
sc_agent_update = os.path.join(
502
self.datadir, "update-software-center-agent")
503
(pid, stdin, stdout, stderr) = GObject.spawn_async(
504
[sc_agent_update, "--datadir", self.datadir],
505
flags=GObject.SPAWN_DO_NOT_REAP_CHILD)
506
GObject.child_watch_add(
507
pid, self._on_update_software_center_agent_finished)
508
run_software_center_agent(self.db)
509
510
def _run_expunge_cache_helper(self):
510
511
""" helper that expires the piston-mini-client cache """
597
598
self._recommender_agent = RecommenderAgent()
598
599
return self._recommender_agent
600
def _on_update_software_center_agent_finished(self, pid, condition):
601
LOG.info("software-center-agent finished with status %i" %
602
os.WEXITSTATUS(condition))
603
if os.WEXITSTATUS(condition) == 0:
606
def on_review_stats_loaded(self, reviews):
601
def on_review_stats_loaded(self, loader, reviews):
607
602
LOG.debug("on_review_stats_loaded: '%s'" % len(reviews))
609
604
def destroy(self):
740
732
if self.menuitem_go_forward.get_sensitive():
741
733
self.menuitem_go_forward.activate()
743
def _on_lp_login(self, lp, token):
744
self._lp_login_successful = True
745
private_archives = self.glaunchpad.get_subscribed_archives()
746
channel_manager = self.view_switcher.get_model().channel_manager
747
channel_manager.feed_in_private_sources_list_entries(
750
def _on_sso_login(self, sso, oauth_result):
751
self._sso_login_successful = True
752
# appmanager needs to know about the oauth token for the reinstall
753
# previous purchases add_license_key call
754
self.app_manager.oauth_token = oauth_result
755
self.scagent.query_available_for_me()
757
735
def _on_style_updated(self, widget, init_css_callback, *args):
758
736
init_css_callback(widget, *args)
760
def _available_for_me_result(self, scagent, result_list):
761
#print "available_for_me_result", result_list
762
from softwarecenter.db.update import (
763
add_from_purchased_but_needs_reinstall_data)
764
available = add_from_purchased_but_needs_reinstall_data(result_list,
766
self.available_for_me_query = available
767
self.available_pane.on_previous_purchases_activated(available)
769
738
def get_icon_filename(self, iconname, iconsize):
770
739
iconinfo = self.icons.lookup_icon(iconname, iconsize, 0)
838
807
# return False to ensure that a possible GObject.timeout_add ends
841
def on_menuitem_launchpad_private_ppas_activate(self, menuitem):
842
from backend.launchpad import GLaunchpad
843
self.glaunchpad = GLaunchpad()
844
self.glaunchpad.connect("login-successful", self._on_lp_login)
845
from view.logindialog import LoginDialog
846
d = LoginDialog(self.glaunchpad, self.datadir, parent=self.window_main)
849
def _create_dbus_sso(self):
850
# see bug #773214 for the rationale, do not translate the appname
851
#appname = _("Ubuntu Software Center")
852
appname = SOFTWARE_CENTER_NAME_KEYRING
853
help_text = _("To reinstall previous purchases, sign in to the "
854
"Ubuntu Single Sign-On account you used to pay for them.")
855
#window = self.window_main.get_window()
856
#xid = self.get_window().xid
858
self.sso = get_sso_backend(xid,
861
self.sso.connect("login-successful", self._on_sso_login)
863
def _login_via_dbus_sso(self):
864
self._create_dbus_sso()
867
def _create_scagent_if_needed(self):
869
from softwarecenter.backend.scagent import SoftwareCenterAgent
870
self.scagent = SoftwareCenterAgent()
871
self.scagent.connect("available-for-me",
872
self._available_for_me_result)
810
def _on_reinstall_purchased_login(self, sso, oauth_result):
811
self._sso_login_successful = True
812
# appmanager needs to know about the oauth token for the reinstall
813
# previous purchases add_license_key call
814
self.app_manager.oauth_token = oauth_result
816
# the software-center-agent will ensure the previous-purchases
818
self._run_software_center_agent()
820
# show spinner as this may take some time, the spinner will
821
# automatically go away when a DB refreshes
822
self.available_pane.show_appview_spinner()
824
# show previous purchased
825
self.available_pane.on_previous_purchases_activated(
826
self.available_for_me_query)
828
def on_menuitem_reinstall_purchases_activate(self, menuitem):
829
self.view_manager.set_active_view(ViewPages.AVAILABLE)
830
self.view_manager.search_entry.clear_with_no_signal()
831
# its ok to use the sync version here to get the token, this is
834
token = helper.find_oauth_token_sync()
836
# trigger a software-center-agent run to ensure the merged in
837
# purchases are fresh
838
self._run_software_center_agent()
839
# we already have the list of available items, so just show it
840
# (no need for spinner here)
841
self.available_pane.on_previous_purchases_activated(
842
self.available_for_me_query)
844
# see bug #773214 for the rationale, do not translate the appname
845
#appname = _("Ubuntu Software Center")
846
appname = SOFTWARE_CENTER_NAME_KEYRING
848
"To reinstall previous purchases, sign in to the "
849
"Ubuntu Single Sign-On account you used to pay for them.")
850
#window = self.window_main.get_window()
851
#xid = self.get_window().xid
853
self.sso = get_login_backend(xid, appname, help_text)
855
"login-successful", self._on_reinstall_purchased_login)
874
858
def on_menuitem_recommendations_activate(self, menu_item):
875
859
rec_panel = self.available_pane.cat_view.recommended_for_you_panel
883
867
if res == Gtk.ResponseType.YES:
884
868
rec_panel.opt_in_to_recommendations_service()
886
def on_menuitem_reinstall_purchases_activate(self, menuitem):
887
self.view_manager.set_active_view(ViewPages.AVAILABLE)
888
self.view_manager.search_entry.clear_with_no_signal()
889
self.available_pane.show_appview_spinner()
890
if self.available_for_me_query:
891
# we already have the list of available items, so just show it
892
self.available_pane.on_previous_purchases_activated(
893
self.available_for_me_query)
895
# fetch the list of available items and show it
896
self._create_scagent_if_needed()
897
self._login_via_dbus_sso()
899
870
def on_menuitem_deauthorize_computer_activate(self, menuitem):
901
872
# FIXME: need Ubuntu SSO username here
1354
1325
self.view_manager.set_active_view(ViewPages.AVAILABLE)
1356
1327
def restore_state(self):
1357
if self.config.has_option("general", "size"):
1358
(x, y) = self.config.get("general", "size").split(",")
1359
self.window_main.set_default_size(int(x), int(y))
1328
(x, y) = self.config.app_window_size
1330
self.window_main.set_default_size(x, y)
1361
1332
# on first launch, specify the default window size to take
1362
1333
# advantage of the available screen real estate (but set a
1366
1337
self.window_main.set_default_size(
1367
1338
min(int(.85 * screen_width), 1200),
1368
1339
min(int(.85 * screen_height), 800))
1369
if (self.config.has_option("general", "maximized") and
1370
self.config.getboolean("general", "maximized")):
1340
if self.config.app_window_maximized:
1371
1341
self.window_main.maximize()
1372
if self.config.has_option("general", "add_to_launcher"):
1373
self.available_pane.add_to_launcher_enabled = (
1374
self.config.getboolean(
1378
# initial default state is to add to launcher, per spec
1379
self.available_pane.add_to_launcher_enabled = True
1381
1343
def save_state(self):
1382
1344
LOG.debug("save_state")
1385
1347
if window is None:
1387
1349
maximized = window.get_state() & Gdk.WindowState.MAXIMIZED
1389
self.config.set("general", "maximized", "True")
1391
self.config.set("general", "maximized", "False")
1350
self.config.app_window_maximized = maximized
1392
1352
# size only matters when non-maximized
1393
1353
size = self.window_main.get_size()
1394
self.config.set("general", "size", "%s, %s" % (size[0], size[1]))
1395
if self.available_pane.add_to_launcher_enabled:
1396
self.config.set("general", "add_to_launcher", "True")
1398
self.config.set("general", "add_to_launcher", "False")
1399
# store the recommender values
1400
self.config.set("general",
1402
self._get_recommender_agent().recommender_uuid)
1403
self.config.set("general",
1404
"recommender_profile_id",
1405
self._get_recommender_agent().recommender_profile_id)
1354
self.config.app_window_size = [size[0], size[1]]
1406
1355
self.config.write()
1408
1357
def write_memory_dump(self, fname=None):