def set_modified_sourceslist(self): """The sources list was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_sourceslist(self) self.show_distro() self.show_isv_sources() self.show_cdrom_sources() self.button_revert.set_sensitive(True)
def set_update_automation_level(self, widget, state): '''Call the backend to set the update automation level to the given value''' if widget.get_active() == True: self.vbox_auto_updates.foreach(lambda b: b.set_inconsistent(False)) SoftwareProperties.set_update_automation_level(self, state) self.set_modified_config()
def on_button_revert_clicked(self, button): """Restore the source list from the startup of the dialog""" SoftwareProperties.revert(self) self.set_modified_sourceslist() self.show_auto_update_level() self.button_revert.set_sensitive(False) self.modified_sourceslist = False
def on_button_revert_clicked(self): """Restore the source list from the startup of the dialog""" SoftwareProperties.revert(self) self.set_modified_sourceslist() self.show_auto_update_level() self.userinterface.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) self.modified_sourceslist = False
def set_modified_sourceslist(self): """The sources list was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_sourceslist(self) self.show_distro() self.show_isv_sources() self.show_cdrom_sources() self.userinterface.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
class SoftwarePropertiesTestCase(unittest.TestCase): @classmethod def setUpClass(cls): for k in apt_pkg.config.keys(): apt_pkg.config.clear(k) apt_pkg.init() def setUp(self): self.temp_dir = tempfile.mkdtemp() self.sp = SoftwareProperties() self.mock_key = os.path.join(self.temp_dir, u"määäp.asc") with open(self.mock_key, "wb") as fp: fp.write(u"bäää".encode("utf-8")) def tearDown(self): shutil.rmtree(self.temp_dir) def test_add_key_str(self): with patch.object(self.sp, "apt_key") as mock_apt_key: self.sp.add_key(self.mock_key) self.assertTrue(mock_apt_key.add.called) def test_add_key_bytes(self): with patch.object(self.sp, "apt_key") as mock_apt_key: mock_name_as_bytes = self.mock_key.encode("utf-8") self.sp.add_key(mock_name_as_bytes) self.assertTrue(mock_apt_key.add.called)
def __init__(self, conn=None, object_path=None, bus_name=None): dbus.service.Object.__init__(self, conn, object_path, bus_name) # The following variables are used bu _check_polkit_privilege self.dbus_info = None self.polkit = None self.enforce_polkit = True self.sp = SoftwareProperties()
def testCheckAndAddKey(self): sp = SoftwareProperties() line = "deb http://xxx/cial jaunty main" self.assert_(sp._is_line_in_whitelisted_channel(line) is None) line = "deb http://archive.canonical.com/ubuntu jaunty partner" self.assert_(sp._is_line_in_whitelisted_channel(line) is not None) line = "deb http://archive.canonical.com/ubuntu jaunty partner" sp.check_and_add_key_for_whitelisted_channels(line)
def list_all(self): sp = SoftwareProperties() isv_sources = sp.get_isv_sources() source_list = [] for source in isv_sources: if not str(source).startswith("#"): source_list.append(str(source)) return source_list
def on_button_revert_clicked(self): """Restore the source list from the startup of the dialog""" SoftwareProperties.revert(self) self.set_modified_sourceslist() self.show_auto_update_level() self.userinterface.buttonBox.button( QDialogButtonBox.Reset).setEnabled(False) self.modified_sourceslist = False
def set_modified_sourceslist(self): """The sources list was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_sourceslist(self) self.show_distro() self.show_isv_sources() self.show_cdrom_sources() self.userinterface.buttonBox.button( QDialogButtonBox.Reset).setEnabled(True)
def __init__(self, datadir=None, options=None, file=None, parent=None): """ Provide a GTK based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) gtk.window_set_default_icon_name("software-properties") SimpleGladeApp.__init__(self, datadir + "glade/main.glade", None, domain="software-properties") if parent: self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.window_main.show() self.window_main.set_transient_for(parent) # If externally called, reparent to external application. self.options = options if options and options.toplevel != None: self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.window_main.show() toplevel = gtk.gdk.window_foreign_new(int(options.toplevel)) if (toplevel): self.window_main.window.set_transient_for(toplevel) # Show what we have early self.window_main.show() # used to store the handlers of callbacks self.handlers = [] # Put some life into the user interface: self.init_popcon() self.init_auto_update() self.show_auto_update_level() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() # Setup and show the distro elements self.init_distro() self.show_distro() # Show the import/replace sources.list dialog if a file different # to the default sources.list was specified # NOTE: If the file path points to the default sources.list the user # perhaps assumed that s-p would act like a normal editor. # We have got some bug reports from users calling # "sudo software-properties-gtk /etc/apt/sources.list" from the # command line. if file != None and \ os.path.abspath(file) != "%s%s" % (apt_pkg.Config.FindDir("Dir::Etc"), apt_pkg.Config.Find("Dir::Etc::sourcelist")): self.open_file(file)
def __init__(self, bus, options=None, datadir=None, rootdir="/"): # init software properties SoftwareProperties.__init__(self, options=options, datadir=datadir, rootdir=rootdir) # used in _check_policykit_priviledge self.dbus_info = None self.polkit = None # init dbus service bus_name = dbus.service.BusName(DBUS_INTERFACE_NAME, bus=bus) dbus.service.Object.__init__(self, bus_name, DBUS_PATH) # useful for testing self.enforce_polkit = True logging.debug("waiting for connections")
def __init__(self, conn=None, object_path=None, bus_name=None): dbus.service.Object.__init__(self, conn, object_path, bus_name) # These are used by PolKit to check privileges self.dbus_info = None self.polkit = None self.enforce_polkit = True try: self.system_repo = repolib.SystemSource() except: self.system_repo = None self.sp = SoftwareProperties() self.cache = apt.Cache()
def on_auto_update_toggled(self, widget): """Enable or disable automatic updates and modify the user interface accordingly""" if self.checkbutton_auto_update.get_active(): self.combobox_update_interval.set_sensitive(True) self.vbox_auto_updates.set_sensitive(True) # if no frequency was specified use daily i = self.combobox_update_interval.get_active() if i == -1: i = 0 self.combobox_update_interval.set_active(i) value = self.combobox_interval_mapping[i] # A little hack to re-set the former selected update automation level self.vbox_auto_updates.foreach(lambda b: b.toggled()) else: self.combobox_update_interval.set_sensitive(False) self.vbox_auto_updates.set_sensitive(False) SoftwareProperties.set_update_automation_level(self, None) value = 0 self.set_update_interval(str(value))
def upgrade_and_install(): global args, log if args.skip_update or args.local: log.info('Skipping upgrade/install') return else: import apt cache = apt.Cache() try: # repos from softwareproperties.SoftwareProperties import SoftwareProperties sp = SoftwareProperties() for repo in repositories: if sp.add_source_from_line(repo): log.info('Adding repository: %s' % repo) else: log.error('Error adding repository: %s' % repo) sp.sourceslist.save() # packages log.info('Updating package info...') cache.update() cache.open(None) cache.upgrade() log.info('Marking packages for install: %s' % ' '.join(install_packages)) for pkg in install_packages: try: cache[pkg].mark_install() except KeyError: log.error('Could not mark package for install: %s' % pkg) log.info('Committing package changes') cache.commit() except apt.cache.LockFailedException: if not args.vmesh_trying_for_sudo: log.info("Need super-user rights to upgrade and install, restarting (with sudo)") restart(with_sudo=True, add_args=['--vmesh-trying-for-sudo']) else: log.error('Could not acquire apt cache lock (someone else is installing stuff, or this user is not a sudoer)') raise log.info("Upgrade/install complete, restarting (no sudo)") restart(with_sudo=False, add_args=['--skip-update'], remove_args=['--vmesh-trying-for-sudo'])
def on_auto_update_toggled(self): """Enable or disable automatic updates and modify the user interface accordingly""" if self.userinterface.checkbutton_auto_update.checkState() == Qt.Checked: self.userinterface.combobox_update_interval.setEnabled(True) self.userinterface.radiobutton_updates_inst_sec.setEnabled(True) self.userinterface.radiobutton_updates_download.setEnabled(True) self.userinterface.radiobutton_updates_notify.setEnabled(True) # if no frequency was specified use daily i = self.userinterface.combobox_update_interval.currentIndex() if i == -1: i = 0 self.userinterface.combobox_update_interval.setCurrentIndex(i) value = self.combobox_interval_mapping[i] else: self.userinterface.combobox_update_interval.setEnabled(False) self.userinterface.radiobutton_updates_inst_sec.setEnabled(False) self.userinterface.radiobutton_updates_download.setEnabled(False) self.userinterface.radiobutton_updates_notify.setEnabled(False) SoftwareProperties.set_update_automation_level(self, None) value = 0 self.set_update_interval(str(value))
def on_auto_update_toggled(self): """Enable or disable automatic updates and modify the user interface accordingly""" if self.userinterface.checkbutton_auto_update.checkState( ) == Qt.Checked: self.userinterface.combobox_update_interval.setEnabled(True) self.userinterface.radiobutton_updates_inst_sec.setEnabled(True) self.userinterface.radiobutton_updates_download.setEnabled(True) self.userinterface.radiobutton_updates_notify.setEnabled(True) # if no frequency was specified use daily i = self.userinterface.combobox_update_interval.currentIndex() if i == -1: i = 0 self.userinterface.combobox_update_interval.setCurrentIndex(i) value = self.combobox_interval_mapping[i] else: self.userinterface.combobox_update_interval.setEnabled(False) self.userinterface.radiobutton_updates_inst_sec.setEnabled(False) self.userinterface.radiobutton_updates_download.setEnabled(False) self.userinterface.radiobutton_updates_notify.setEnabled(False) SoftwareProperties.set_update_automation_level(self, None) value = 0 self.set_update_interval(str(value))
def set_update_automation_level(self, selected): """Call the backend to set the update automation level to the given value""" if self.userinterface.radiobutton_updates_download.isChecked(): SoftwareProperties.set_update_automation_level(self, softwareproperties.UPDATE_DOWNLOAD) elif self.userinterface.radiobutton_updates_inst_sec.isChecked(): SoftwareProperties.set_update_automation_level(self, softwareproperties.UPDATE_INST_SEC) elif self.userinterface.radiobutton_updates_notify.isChecked(): SoftwareProperties.set_update_automation_level(self, softwareproperties.UPDATE_NOTIFY) self.set_modified_config()
def set_update_automation_level(self, selected): """Call the backend to set the update automation level to the given value""" if self.userinterface.radiobutton_updates_download.isChecked(): SoftwareProperties.set_update_automation_level( self, softwareproperties.UPDATE_DOWNLOAD) elif self.userinterface.radiobutton_updates_inst_sec.isChecked(): SoftwareProperties.set_update_automation_level( self, softwareproperties.UPDATE_INST_SEC) elif self.userinterface.radiobutton_updates_notify.isChecked(): SoftwareProperties.set_update_automation_level( self, softwareproperties.UPDATE_NOTIFY) self.set_modified_config()
class Repos(plugin.Plugin): permissions = {'script': False, 'root': True, 'remove-pkg': False, 'system-config': True } sp = SoftwareProperties() ppas_list = [] def get_ppas(self): try: ppas_member = self.kettle_ark.getmember('data/repos/ppas.repos') except KeyError: raise BadKettle(_("The kettle is missing data for plugin: repos")) ppas_exfile = self.kettle_ark.extractfile(ppas_member) ppas_bytes = ppas_exfile.readlines() ppas_exfile.close() for i in ppas_bytes: line = i.decode('UTF-8')[:-1] self.ppas_list.append(line) return self.ppas_list def install_repos(self, repo_list): for i in repo_list: try: self.sp.add_source_from_line(i) self.sp.sourceslist.save() self.sp.reload_sourceslist() except: raise BadRepo(_("Couldn't add the repository %s" % i)) def get_to_root(self): subprocess.call(["/usr/bin/sudo", "/usr/bin/python3", self.plugin_path + "/repos-data/as_root.py", self.kettle.path]) def run_install(self): self.get_to_root()
def set_modified_config(self): """The config was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_config(self) self.userinterface.buttonBox.button( QDialogButtonBox.Reset).setEnabled(True)
def __init__(self, datadir=None, options=None, parent=None, file=None, attachWinID=None): """ Provide a KDE based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) self.options = options self.datadir = datadir global kapp kapp = QApplication.instance() kapp.setWindowIcon(QIcon.fromTheme("applications-other")) self.userinterface = SoftwarePropertiesKDEUI(datadir) self.userinterface.setWindowIcon(QIcon.fromTheme("applications-other")) self.userinterface.button_auth_restore.setIcon( QIcon.fromTheme("edit-undo")) self.userinterface.button_add_auth.setIcon(QIcon.fromTheme("list-add")) self.userinterface.button_auth_remove.setIcon( QIcon.fromTheme("list-remove")) self.userinterface.button_remove.setIcon( QIcon.fromTheme("list-remove")) self.userinterface.button_edit.setIcon( QIcon.fromTheme("document-edit")) self.userinterface.button_add.setIcon(QIcon.fromTheme("list-add")) self.userinterface.button_add_cdrom.setIcon( QIcon.fromTheme("media-optical")) translate_widget(self.userinterface) self.userinterface.show() # FIXME: winid not handled #if attachWinID is not None: #KWindowSystem.setMainWindow(self.userinterface, int(attachWinID)) # rejected() signal from Close button self.userinterface.buttonBox.rejected.connect(self.on_close_button) self.userinterface.buttonBox.button( QDialogButtonBox.Reset).setEnabled(False) # Put some life into the user interface: self.init_server_chooser() self.init_popcon() self.init_auto_update() self.init_release_upgrades() self.show_auto_update_level() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() self.userinterface.checkbutton_source_code.clicked.connect( self.on_checkbutton_source_code_toggled) self.userinterface.button_auth_restore.clicked.connect( self.on_restore_clicked) self.userinterface.button_add_auth.clicked.connect( self.add_key_clicked) self.userinterface.button_auth_remove.clicked.connect( self.remove_key_clicked) self.userinterface.checkbutton_popcon.toggled.connect( self.on_checkbutton_popcon_toggled) self.userinterface.checkbutton_auto_update.toggled.connect( self.on_auto_update_toggled) self.userinterface.combobox_update_interval.currentIndexChanged.connect( self.on_combobox_update_interval_changed) self.userinterface.button_remove.clicked.connect( self.on_remove_clicked) self.userinterface.button_edit.clicked.connect(self.on_edit_clicked) self.userinterface.button_add_cdrom.clicked.connect( self.on_button_add_cdrom_clicked) self.userinterface.button_add.clicked.connect(self.on_add_clicked) self.userinterface.treeview_sources.itemChanged.connect( self.on_isv_source_toggled) self.userinterface.treeview_sources.itemClicked.connect( self.on_treeview_sources_cursor_changed) self.userinterface.treeview_cdroms.itemChanged.connect( self.on_cdrom_source_toggled) self.userinterface.treeview2.itemClicked.connect( self.on_treeview_keys_cursor_changed) button_close = self.userinterface.buttonBox.button( QDialogButtonBox.Close) button_close.setIcon(QIcon.fromTheme("dialog-close")) button_revert = self.userinterface.buttonBox.button( QDialogButtonBox.Reset) button_revert.setIcon(QIcon.fromTheme("edit-undo")) button_revert.clicked.connect(self.on_button_revert_clicked) self.init_distro() self.show_distro()
class PPA(dbus.service.Object): def __init__(self, conn=None, object_path=None, bus_name=None): dbus.service.Object.__init__(self, conn, object_path, bus_name) # These are used by PolKit to check privileges self.dbus_info = None self.polkit = None self.enforce_polkit = True try: self.system_repo = repolib.SystemSource() except: self.system_repo = None self.sp = SoftwareProperties() self.cache = apt.Cache() @dbus.service.method( "org.pop_os.repoman.Interface", in_signature='', out_signature='', sender_keyword='sender', connection_keyword='conn' ) def exit(self, sender=None, conn=None): mainloop.quit() @dbus.service.method( "org.pop_os.repoman.Interface", in_signature='b', out_signature='b', sender_keyword='sender', connection_keyword='conn' ) def set_system_source_code_enabled(self, enabled, sender=None, conn=None): """ Enable or disable source code in the system source. Arguments: enabled (bool): The new state to set, True = Enabled. """ self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if self.system_repo: self.system_repo.load_from_file() new_types = [repolib.util.AptSourceType.BINARY] if enabled: new_types.append(repolib.util.AptSourceType.SOURCE) self.system_repo.types = new_types self.system_repo.save_to_disk() return enabled return False @dbus.service.method( "org.pop_os.repoman.Interface", in_signature='sb', out_signature='b', sender_keyword='sender', connection_keyword='conn' ) def set_system_comp_enabled(self, comp, enable, sender=None, conn=None): """ Enable or disable a component in the system source. Arguments: comp (str): the component to set enable (bool): The new state to set, True = Enabled. """ self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if self.system_repo: self.system_repo.load_from_file() self.system_repo.set_component_enabled(component=comp, enabled=enable) self.system_repo.save_to_disk() return True return False @dbus.service.method( "org.pop_os.repoman.Interface", in_signature='sb', out_signature='b', sender_keyword='sender', connection_keyword='conn' ) def set_system_suite_enabled(self, suite, enable, sender=None, conn=None): """ Enable or disable a suite in the system source. Arguments: suite (str): the suite to set enable (bool): The new state to set, True = Enabled. """ self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if self.system_repo: self.system_repo.load_from_file() self.system_repo.set_suite_enabled(suite=suite, enabled=enable) self.system_repo.save_to_disk() return True return False ## TODO: These are old SoftwareProperties Methods, and need to be replaced. @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='s', out_signature='bs', sender_keyword='sender', connection_keyword='conn' ) def add_repo(self, line, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) try: self.sp.add_source_from_line(line) self.sp.sourceslist.save() self.cache.open() self.cache.update() self.cache.open(None) self.sp.reload_sourceslist() return [True, ''] except Exception as e: print(str(e)) return [False, str(e)] @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='s', out_signature='bs', sender_keyword='sender', connection_keyword='conn' ) def delete_repo(self, repo, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) try: self.sp.remove_source(repo, remove_source_code=True) self.sp.sourceslist.save() self.cache.open() self.cache.update() self.cache.open(None) self.sp.reload_sourceslist() return [True, ''] except Exception as e: print(str(e)) return [False, str(e)] @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='ss', out_signature='bs', sender_keyword='sender', connection_keyword='conn' ) def modify_repo(self, old_repo, new_repo, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) try: old_source = self._find_source_from_string(old_repo) index = self.sp.sourceslist.list.index(old_source) file = self.sp.sourceslist.list[index].file new_source_entry = SourceEntry(new_repo, file) self.sp.sourceslist.list[index] = new_source_entry self.sp.sourceslist.save() self.cache.open() self.cache.update() self.cache.open(None) self.sp.reload_sourceslist() return [True, ''] except Exception as e: print(str(e)) return [False, str(e)] @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='b', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def set_source_code_enabled(self, enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if enabled: self.sp.enable_source_code_sources() else: self.sp.disable_source_code_sources() return 0 @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='sb', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def set_child_enabled(self, child, enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if enabled: self.sp.enable_child_source(child) else: self.sp.disable_child_source(child) return 0 @dbus.service.method( 'org.pop_os.repoman.Interface', in_signature='sb', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def set_comp_enabled(self, comp, enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'org.pop_os.repoman.modifysources' ) if enabled: self.sp.enable_component(comp) else: self.sp.disable_component(comp) return 0 def _find_source_from_string(self, line): # ensure that we have a current list, it might have been changed underneath # us self.sp.reload_sourceslist() for source in self.sp.sourceslist.list: if str(source) == line: return source return None @classmethod def _log_in_file(klass, filename, string): date = time.asctime(time.localtime()) ff = open(filename, "a") ff.write("%s : %s\n" %(date,str(string))) ff.close() @classmethod def _strip_source_line(self, source): source = source.replace("#", "# ") source = source.replace("[", "") source = source.replace("]", "") source = source.replace("'", "") source = source.replace(" ", " ") return source def _check_polkit_privilege(self, sender, conn, privilege): # from jockey '''Verify that sender has a given PolicyKit privilege. sender is the sender's (private) D-BUS name, such as ":1:42" (sender_keyword in @dbus.service.methods). conn is the dbus.Connection object (connection_keyword in @dbus.service.methods). privilege is the PolicyKit privilege string. This method returns if the caller is privileged, and otherwise throws a PermissionDeniedByPolicy exception. ''' if sender is None and conn is None: # called locally, not through D-BUS return if not self.enforce_polkit: # that happens for testing purposes when running on the session # bus, and it does not make sense to restrict operations here return # get peer PID if self.dbus_info is None: self.dbus_info = dbus.Interface(conn.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus') pid = self.dbus_info.GetConnectionUnixProcessID(sender) # query PolicyKit if self.polkit is None: self.polkit = dbus.Interface(dbus.SystemBus().get_object( 'org.freedesktop.PolicyKit1', '/org/freedesktop/PolicyKit1/Authority', False), 'org.freedesktop.PolicyKit1.Authority') try: # we don't need is_challenge return here, since we call with AllowUserInteraction (is_auth, _, details) = self.polkit.CheckAuthorization( ('unix-process', {'pid': dbus.UInt32(pid, variant_level=1), 'start-time': dbus.UInt64(0, variant_level=1)}), privilege, {'': ''}, dbus.UInt32(1), '', timeout=600) except dbus.DBusException as e: if e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown': # polkitd timed out, connect again self.polkit = None return self._check_polkit_privilege(sender, conn, privilege) else: raise if not is_auth: PPA._log_in_file('/tmp/repoman.log','_check_polkit_privilege: sender %s on connection %s pid %i is not authorized for %s: %s' % (sender, conn, pid, privilege, str(details))) raise PermissionDeniedByPolicy(privilege)
def __init__(self, parent): self.sp = SoftwareProperties() Gtk.Box.__init__(self, False, 0) self.parent = parent self.ppa = ppa.PPA(self) self.content_grid = Gtk.Grid() self.content_grid.set_margin_top(24) self.content_grid.set_margin_left(12) self.content_grid.set_margin_right(12) self.content_grid.set_margin_bottom(12) self.content_grid.set_row_spacing(6) self.content_grid.set_hexpand(True) self.content_grid.set_vexpand(True) self.add(self.content_grid) sources_title = Gtk.Label("Extra Sources") Gtk.StyleContext.add_class(sources_title.get_style_context(), "h2") sources_title.set_halign(Gtk.Align.START) self.content_grid.attach(sources_title, 0, 0, 1, 1) sources_label = Gtk.Label( "These sources are for software provided by " + "a third party. They may present a security " + "risk or can cause system instability. " + "\nOnly add sources that you trust.") sources_label.set_line_wrap(True) sources_label.set_halign(Gtk.Align.START) sources_label.set_justify(Gtk.Justification.FILL) sources_label.set_hexpand(True) self.content_grid.attach(sources_label, 0, 1, 1, 1) list_grid = Gtk.Grid() self.content_grid.attach(list_grid, 0, 2, 1, 1) list_window = Gtk.ScrolledWindow() list_grid.attach(list_window, 0, 0, 1, 1) self.ppa_liststore = Gtk.ListStore(str, str) self.view = Gtk.TreeView(self.ppa_liststore) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Source', renderer, markup=0) self.view.append_column(column) self.view.set_hexpand(True) self.view.set_vexpand(True) tree_selection = self.view.get_selection() tree_selection.connect('changed', self.on_row_change) list_window.add(self.view) # add button add_button = Gtk.Button.new_from_icon_name("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(add_button.get_style_context(), "image-button") add_button.set_tooltip_text("Add New Source") add_button.connect("clicked", self.on_add_button_clicked) # edit button edit_button = Gtk.Button.new_from_icon_name("edit-symbolic", Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(edit_button.get_style_context(), "image-button") edit_button.set_tooltip_text("Modify Selected Source") edit_button.connect("clicked", self.on_edit_button_clicked) action_bar = Gtk.ActionBar() Gtk.StyleContext.add_class(action_bar.get_style_context(), "inline-toolbar") action_bar.add(edit_button) action_bar.add(add_button) list_grid.attach(action_bar, 0, 1, 1, 1) self.generate_entries(self.ppa.get_isv())
class PPAObject(dbus.service.Object): cache = apt.Cache() def __init__(self, conn=None, object_path=None, bus_name=None): dbus.service.Object.__init__(self, conn, object_path, bus_name) # The following variables are used bu _check_polkit_privilege self.dbus_info = None self.polkit = None self.enforce_polkit = True self.sp = SoftwareProperties() @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='s', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def DelPPA(self, ppa, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.delppa' ) # PPA Remove code here try: self.sp.reload_sourceslist() self.sp.remove_source(ppa, remove_source_code=True) self.sp.sourceslist.save() self.sp.reload_sourceslist() return 0 except: raise AptException("Could not remove the APT Source") @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='s', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def AddPPA(self, ppa, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.addppa' ) # PPA Add code here try: self.sp.reload_sourceslist() self.sp.add_source_from_line(ppa) self.sp.sourceslist.save() self.sp.reload_sourceslist() return 0 except: raise AptException("Could not remove the APT Source") @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='ss', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def ModifyPPA(self, old_source, new_source, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.modppa' ) # PPA Modify code here try: self.sp.reload_sourceslist() old_source = self._strip_source_line(old_source) isvs = self.sp.get_isv_sources() for i in isvs: if str(i) == old_source: source = i index = self.sp.sourceslist.list.index(source) file = self.sp.sourceslist.list[index].file new_source_entry = SourceEntry(new_source,file) self.sp.sourceslist.list[index] = new_source_entry self.sp.sourceslist.save() self.cache.open() self.cache.update() self.cache.open(None) self.cache.close() self.sp.reload_sourceslist() return 0 except: raise AptException("Could not modify the APT Source") @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='sb', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def SetCompEnabled(self, comp_name, is_enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.modppa' ) # PPA Modify code here if is_enabled: self.sp.enable_component(comp_name) else: self.sp.disable_component(comp_name) return 0 @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='sb', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def SetChildEnabled(self, child_name, is_enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.modppa' ) # PPA Modify code here repos = self.sp.distro.source_template.children for repo in repos: if repo.name == child_name: child = repo if is_enabled: self.sp.enable_child_source(child) else: self.sp.disable_child_source(child) return 0 @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='b', out_signature='i', sender_keyword='sender', connection_keyword='conn' ) def SetSourceCodeEnabled(self, is_enabled, sender=None, conn=None): self._check_polkit_privilege( sender, conn, 'ro.santopiet.repoman.modppa' ) # PPA Modify code here if is_enabled: self.sp.enable_source_code_sources() else: self.sp.disable_source_code_sources() return 0 @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='', out_signature='', sender_keyword='sender', connection_keyword='conn' ) def RaiseException(self, sender=None, conn=None): raise RepomanException('Error managing software sources!') @dbus.service.method( "ro.santopiet.repoman.Interface", in_signature='', out_signature='', sender_keyword='sender', connection_keyword='conn' ) def Exit(self, sender=None, conn=None): mainloop.quit() @classmethod def _log_in_file(klass, filename, string): date = time.asctime(time.localtime()) ff = open(filename, "a") ff.write("%s : %s\n" %(date,str(string))) ff.close() @classmethod def _strip_source_line(self, source): source = source.replace("#", "# ") source = source.replace("[", "") source = source.replace("]", "") source = source.replace("'", "") source = source.replace(" ", " ") return source def _check_polkit_privilege(self, sender, conn, privilege): # from jockey '''Verify that sender has a given PolicyKit privilege. sender is the sender's (private) D-BUS name, such as ":1:42" (sender_keyword in @dbus.service.methods). conn is the dbus.Connection object (connection_keyword in @dbus.service.methods). privilege is the PolicyKit privilege string. This method returns if the caller is privileged, and otherwise throws a PermissionDeniedByPolicy exception. ''' if sender is None and conn is None: # called locally, not through D-BUS return if not self.enforce_polkit: # that happens for testing purposes when running on the session # bus, and it does not make sense to restrict operations here return # get peer PID if self.dbus_info is None: self.dbus_info = dbus.Interface(conn.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus') pid = self.dbus_info.GetConnectionUnixProcessID(sender) # query PolicyKit if self.polkit is None: self.polkit = dbus.Interface(dbus.SystemBus().get_object( 'org.freedesktop.PolicyKit1', '/org/freedesktop/PolicyKit1/Authority', False), 'org.freedesktop.PolicyKit1.Authority') try: # we don't need is_challenge return here, since we call with AllowUserInteraction (is_auth, _, details) = self.polkit.CheckAuthorization( ('unix-process', {'pid': dbus.UInt32(pid, variant_level=1), 'start-time': dbus.UInt64(0, variant_level=1)}), privilege, {'': ''}, dbus.UInt32(1), '', timeout=600) except dbus.DBusException as e: if e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown': # polkitd timed out, connect again self.polkit = None return self._check_polkit_privilege(sender, conn, privilege) else: raise if not is_auth: PPAObject._log_in_file('/tmp/repoman.log','_check_polkit_privilege: sender %s on connection %s pid %i is not authorized for %s: %s' % (sender, conn, pid, privilege, str(details))) raise PermissionDeniedByPolicy(privilege)
def setUp(self): self.temp_dir = tempfile.mkdtemp() self.sp = SoftwareProperties() self.mock_key = os.path.join(self.temp_dir, u"määäp.asc") with open(self.mock_key, "wb") as fp: fp.write(u"bäää".encode("utf-8"))
def on_install_button_active(button, model, itemSelectCount): global pulseTimer global installStatus global cache global view global p1 # set busy flag installStatus = 'busy' # Remove CANCEL button Gtk.Container.remove(grid, cancelButton) # Count items itemCount = len(model) # Add PPA's # Set progress progressBar.set_fraction(0.1) label.set_text("Installing new software sources...") appendToLog("Installing new software sources...") # Use APT module and SoftwareProperties to add-apt sp = SoftwareProperties() for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if ppaList[listItem] != '' : progressBar.set_text("Adding PPA for "+model[listItem][1]) # add-apt the python way ! taken from add-apt code try: sp.add_source_from_line(ppaList[listItem]) debugPrint("Added PPA - %s" % ppaList[listItem]) appendToLog("Added PPA - %s" % ppaList[listItem]) except: debugPrint("[Error] Could not add PPA - %s" % ppaList[listItem]) appendToLog("[Error] Could not add PPA - %s" % ppaList[listItem]) # Save new apt list sp.sourceslist.save() progressBar.set_fraction(0.2) # Add Keys for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if getAptKeyList[listItem] != '' : debugPrint("Name : %s" % model[listItem][1]) debugPrint("Keys : %s" % getAptKeyList[listItem]) progressBar.set_text("Adding software key for "+model[listItem][1]) # Add key the bash way TODO do this differently to handle errors/timeout # First check type of key wget or apt-key adv if "recv-keys" in getAptKeyList[listItem] : keyType='apt-key' else: keyType='wget' try: if keyType == 'wget': # Just read Key URL and do the rest p1 = subprocess.Popen(['wget', '-O', '-', getAptKeyList[listItem]], stdout=subprocess.PIPE) p2 = subprocess.Popen(['apt-key', 'add', '--yes', '--quiet', '-'], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. if keyType == 'apt-key': # Run command as is p6 = subprocess.Popen([getAptKeyList[listItem]], shell=True, stdout=subprocess.PIPE) debugPrint("Key added for : %s" % model[listItem][1]) appendToLog("Key added for : %s" % model[listItem][1]) debugPrint("Key status: %s" % output) appendToLog("Key status: %s" % output) except: debugPrint("[Error] Could not add key from - %s" % getAptKeyList[listItem]) appendToLog("[Error] Could not add key from - %s" % getAptKeyList[listItem]) progressBar.set_fraction(0.3) # Manually write to file to add APT for DEB repos for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if aptListEntryList[listItem] != '' : debugPrint("Name : %s" % model[listItem][1]) debugPrint("APT : %s" % aptListEntryList[listItem]) installTitles = installTitleList[listItem].split(' ') progressBar.set_text("Adding APT Repository for "+model[listItem][1]) # write sources to file try: writeToFile(os.path.join(aptListPath, installTitles[0]+'.list'), 'deb '+aptListEntryList[listItem]+'\n', 'w') #writeToFile(os.path.join(aptListPath, installTitles[0]+'.list'), 'deb-src '+aptListEntryList[listItem]+'\n', 'a') writeToFile(os.path.join(aptListPath, installTitles[0]+'.list.save'), 'deb '+aptListEntryList[listItem]+'\w', 'w') #writeToFile(os.path.join(aptListPath, installTitles[0]+'.list.save'), 'deb-src '+aptListEntryList[listItem]+'\n', 'a') debugPrint("Added APT - %s" % aptListEntryList[listItem]) appendToLog("Added APT - %s" % aptListEntryList[listItem]) except: debugPrint("[Error] Could not add APT - %s" % aptListEntryList[listItem]) appendToLog("[Error] Could not add APT - %s" % aptListEntryList[listItem]) onInstallError() # Save new apt list sp.sourceslist.save() # We need to open the cache again before updating progressBar.set_fraction(0.4) progressBar.set_text('Reading Software List...') debugPrint("[Progress] Open Cache...") appendToLog("[Progress] Open Cache...") cache.open() # Now, lets update the package list progressBar.set_fraction(0.5) progressBar.set_text('Updating Software Center...') debugPrint("[Progress] Cache update...") appendToLog("[Progress] Cache update...") pulseTimer = GLib.timeout_add(100, pulse) try: cache.update() except: appendToLog("[Warning] Cache update warnings. Not fatal - continue...") debugPrint("[Warning] Cache update warnings. Not fatal - continue...") GLib.source_remove(pulseTimer) # Now we can do the same as 'apt-get upgrade' does progressBar.set_fraction(0.7) #progressBar.set_text('Updating Software ...') #print "[progress] Updating Software ..." #cache.upgrade() # or we can play 'apt-get dist-upgrade' #cache.upgrade(True) # Q: Why does nothing happen? # A: You forgot to call commit()! debugPrint("[Progress] Commit Cache...") appendToLog("[Progress] Commit Cache...") progressBar.set_fraction(0.8) progressBar.set_text('Updating Software Center...') try: #cache.commit() cache.commit(aptAcquireProgress, aptInstallProgress) except: debugPrint("[Error] apt-get update failed") # Software sources added Done progressBar.set_fraction(1) progressBar.set_text('') label.set_text('Software sources added successfully') appendToLog('Software sources added successfully') # START installing apps one by one # using itemSelectCount to do progress increments progInc = float(100 / itemSelectCount) / 100 itemIncCount = 0 progressBar.set_fraction(0.02) for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: # With selected items ... label.set_text('Installing Software '+str(itemIncCount+1)+' of '+str(itemSelectCount)+' ...') appendToLog('[Notice] Installing Software '+str(itemIncCount+1)+' of '+str(itemSelectCount)+' ...') # Un Install first if RE-install is selected if installStateList[listItem] == 'installed': progressBar.set_text("Removing "+model[listItem][1]) # Set focus view.set_cursor(listItem) # open cache again for each install to update new packages list cache.open() # Get package list into array installTitles = installTitleList[listItem].split(' ') # mark packages for Remove for itemToRemove in installTitles: try: cache[itemToRemove].mark_delete() debugPrint("[Remove] Marked for Removal %s" % itemToRemove ) appendToLog("[Remove] Marked for Removal %s" % itemToRemove ) except: debugPrint("[Error] Packages not found for %s" % model[listItem][1] ) appendToLog("[Error] Packages not found for %s" % model[listItem][1] ) # TODO show install failed not done installError = "[Error] Packages not found for " + model[listItem][1] # Commit new cache and remove each set of packages try: aptAcquireProgress.start() progressTimer = GLib.timeout_add(200, renderCellProgress, model, listItem, 'remove') cache.commit(aptAcquireProgress, aptInstallProgress) aptAcquireProgress.stop() GLib.source_remove(progressTimer) # Update icon after removal model[listItem][4] = GdkPixbuf.Pixbuf.new_from_file(iconPathBlank) debugPrint("Un-Install complete for %s" % model[listItem][1] ) appendToLog("Un-Install complete for %s" % model[listItem][1] ) except: debugPrint("[Error] Un-Install failed for %s" % model[listItem][1] ) appendToLog("[Error] Un-Install failed for %s" % model[listItem][1] ) installError = "[Error] Un-Install failed for " + model[listItem][1] # Run Pre-install commands # if item has pre-install run that now if preInstallList[listItem] != '' : progressBar.set_text("Running pre-install for "+model[listItem][1]) # Run pre install commands the bash way TODO do this differently to handle errors/timeout try: p1 = subprocess.Popen([preInstallList[listItem]], shell=True, stdout=subprocess.PIPE) output = p1.communicate()[0] debugPrint("Running Pre install script for : %s" % model[listItem][1]) debugPrint("Pre install script output: %s" % output) appendToLog("Running Pre install script for : %s" % model[listItem][1]) appendToLog("Pre install script output: %s" % output) except: debugPrint("[Error] Pre install script error : %s" % model[listItem][1]) appendToLog("[Error] Pre install script error : %s" % model[listItem][1]) # Install software item FINALLY installError = '' # Initial cell progressbar value model[listItem][3] = 0 progressBar.set_text("Installing "+model[listItem][1]) debugPrint("Installing %s" % model[listItem][1]) appendToLog("Installing %s" % model[listItem][1]) # Set focus view.set_cursor(listItem) # open cache again for each install to update new packages list cache.open() # Get package list into array installTitles = installTitleList[listItem].split(' ') # mark packages for install for itemToInstall in installTitles: try: cache[itemToInstall].mark_install() debugPrint("[Install] Marked for install %s" % itemToInstall ) appendToLog("[Install] Marked for install %s" % itemToInstall ) except: debugPrint("[Error] Packages not found for %s" % model[listItem][1] ) appendToLog("[Error] Packages not found for %s" % model[listItem][1] ) # TODO show install failed not done installError = "[Error] Packages not found for " + model[listItem][1] # Commit new cache and install each set of packages try: #cache.upgrade() aptAcquireProgress.start() progressTimer = GLib.timeout_add(200, renderCellProgress, model, listItem, 'install') cache.commit(aptAcquireProgress, aptInstallProgress) #cache.commit() debugPrint("Install complete for %s" % model[listItem][1] ) appendToLog("Install complete for %s" % model[listItem][1] ) except: debugPrint("[Error] Installation failed for %s" % model[listItem][1] ) # TODO show install failed not done installError = "[Error] Installation failed for " + model[listItem][1] # END of Install # Run POST-install commands # if item has post-install run that now if postInstallList[listItem] != '' : progressBar.set_text("Running post-install for "+model[listItem][1]) # Run post install commands the bash way TODO do this differently to handle errors/timeout try: p1 = subprocess.Popen([postInstallList[listItem]], shell=True, stdout=subprocess.PIPE) output = p1.communicate()[0] debugPrint("Running Post install script for : %s" % model[listItem][1]) debugPrint("Post install script output: %s" % output) appendToLog("Running Post install script for : %s" % model[listItem][1]) appendToLog("Post install script output: %s" % output) except: debugPrint("[Error] Post install script error : %s" % model[listItem][1]) appendToLog("[Error] Post install script error : %s" % model[listItem][1]) # Set Cell Progress bar and deselect when done model[listItem][3] = 100 model[listItem][0] = False GLib.source_remove(progressTimer) aptAcquireProgress.stop() time.sleep(0.1) refreshGui() time.sleep(0.1) # Check if install ok and set icon if installError == '': iconPathMod = iconPathOk installStateList[listItem]='installed' else: iconPathMod = iconPathError installStateList[listItem]='error' # Set icon model[listItem][4] = GdkPixbuf.Pixbuf.new_from_file(iconPathMod) # If selected Inc for each item as we know not how many here # Move progress incrementally depending on number of install items itemIncCount = itemIncCount + 1 displayInc = progInc * itemIncCount # Update main progress bar at the end of each item install progressBar.set_fraction(displayInc) # All Done - The End - # Remove Timers GLib.source_remove(progressTimer) progressBar.set_fraction(1) progressBar.set_text('') # Stop Spinner spinner.stop() os.system("python notify.py") label.set_text('Installation Complete') debugPrint('[END] Installation Complete') appendToLog('[END] Installation Complete') # Set focus view.set_cursor(0) # Reset installstatus installStatus = 'complete' # Remove Cancel Button and spinner #Gtk.Container.remove(grid, cancelButton) Gtk.Container.remove(grid, spinner) # Activate Install Now/Done button button.set_sensitive(True)
def __init__(self, datadir=None, options=None, file=None, parent=None): """ Provide a GTK based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) gtk.window_set_default_icon_name("software-properties") SimpleGtkbuilderApp.__init__(self, os.path.join(datadir, "gtkbuilder", "main.ui"), domain="software-properties") if parent: self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.window_main.show() try: self.window_main.set_transient_for(parent) except: pass # If externally called, reparent to external application. self.options = options if options and options.toplevel != None: self.window_main.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.window_main.show() toplevel = gtk.gdk.window_foreign_new(int(options.toplevel)) if (toplevel): try: self.window_main.window.set_transient_for(toplevel) except: pass if options and options.open_tab: self.notebook_main.set_current_page(int(options.open_tab)) # Show what we have early self.window_main.show() # used to store the handlers of callbacks self.handlers = [] # Put some life into the user interface: #self.init_popcon() #self.init_auto_update() #self.init_release_upgrades() #self.show_auto_update_level() self.vbox_popcon.hide() self.vbox8.hide() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() # Setup and show the distro elements self.init_distro() self.show_distro() # Show the import/replace sources.list dialog if a file different # to the default sources.list was specified # NOTE: If the file path points to the default sources.list the user # perhaps assumed that s-p would act like a normal editor. # We have got some bug reports from users calling # "sudo software-properties-gtk /etc/apt/sources.list" from the # command line. if file != None and \ os.path.abspath(file) != "%s%s" % (apt_pkg.config.find_dir("Dir::Etc"), apt_pkg.config.find("Dir::Etc::sourcelist")): self.open_file(file)
class PPA: waiting = "Waiting for PPA" invalid = "Not a valid PPA" valid = "Valid PPA found" sources_path = "/etc/apt/sources.list.d/" cache = apt.Cache() sp = SoftwareProperties() def __init__(self, parent): self.parent = parent self.get_configuration() # Returns a list of all 3rd-party software sources. def get_isv(self): self.sp.reload_sourceslist() list = self.sp.get_isv_sources() print(list) return list # Returns the current distro Components. def get_distro_sources(self): components = self.sp.distro.source_template.components return components # Returns the current child repos (updates) def get_distro_child_repos(self): repos = self.sp.distro.source_template.children return repos # Get whether a component is enabled or not def get_comp_download_state(self, comp): (active, inconsistent) = self.sp.get_comp_download_state(comp) return (active, inconsistent) # Get whether a child repo is enabled or not def get_child_download_state(self, child): (active, inconsistent) = self.sp.get_comp_child_state(child) print(child.name + " (" + str(active) + ", " + str(inconsistent) + ")") return (active, inconsistent) # Get Source Code State def get_source_code_enabled(self): enabled = self.sp.get_source_code_state() if enabled == None: return (False, True) else: return (enabled, False) # Enable/Disable a component def set_comp_enabled(self, comp, enabled): if enabled == True: self.sp.enable_component(comp) else: self.sp.disable_component(comp) return 0 # Enable/Disable a child repo def set_child_enabled(self, child, enabled): if enabled == True: self.sp.enable_child_source(child) else: self.sp.disable_child_source(child) return 0 # Enable/Disable source code def set_source_code_enabled(self, enabled): if enabled == True: self.sp.enable_source_code_sources() elif enabled == False: self.sp.disable_source_code_sources() return 0 # Get the current sources configuration def get_configuration(self): self.enabledDict = {} self.update_automation_level = self.sp.get_update_automation_level( ) #FIXME Doesn't change self.release_upgrades_policy = self.sp.get_release_upgrades_policy( ) #0 on, 2 off self.source_code_state = self.sp.get_source_code_state() # Bool for comp in self.sp.distro.source_template.components: self.enabledDict[comp.name] = self.sp.get_comp_download_state( comp)[0] self.main_enabled = self.enabledDict['main'] self.univ_enabled = self.enabledDict['universe'] self.rest_enabled = self.enabledDict['restricted'] self.mult_enabled = self.enabledDict['multiverse'] for child in self.sp.distro.source_template.children: if child.type != 'deb-src': self.enabledDict[child.name] = self.sp.get_comp_child_state( child)[0] self.secu_enabled = self.enabledDict['artful-security'] self.recc_enabled = self.enabledDict['artful-updates'] self.back_enabled = self.enabledDict['artful-backports'] self.prop_enabled = self.enabledDict['artful-proposed'] return 0 def get_line(self, enabled, rtype, archs, uri, version, component): """Collect all values from the entries and create an apt line""" if enabled == True: line = "" else: line = "#" line = "%s %s %s %s %s %s" % (line, rtype, archs, uri, version, component) return line # Turn an added deb line into an apt source def deb_line_to_source(self, line): print(line) source = self.sp._find_source_from_string(line) return source # Modify an existing PPA def modify_ppa(self, old_source, rtype, archs, uri, version, component): print("Old source: %s\n" % old_source) print("New source: %s %s %s %s %s" % (rtype, archs, uri, version, component)) line = self.get_line(True, rtype, archs, uri, version, component) self.parent.parent.parent.hbar.spinner.start() self.parent.parent.parent.stack.list_all.view.set_sensitive(False) ModifyThread(self.parent, old_source, line, self.sp).start() # Starts a new thread to add a repository def add(self, url): self.parent.parent.parent.hbar.spinner.start() self.parent.parent.parent.stack.list_all.view.set_sensitive(False) AddThread(self.parent, url, self.sp).start() # Starts a new thread to remove a repository def remove(self, ppa): self.parent.parent.hbar.spinner.start() self.parent.parent.stack.list_all.view.set_sensitive(False) RemoveThread(self.parent, self.sources_path, ppa, self.sp).start() def list_all(self): sp = SoftwareProperties() isv_sources = sp.get_isv_sources() source_list = [] for source in isv_sources: if not str(source).startswith("#"): source_list.append(str(source)) return source_list
def __init__(self, parent): self.sp = SoftwareProperties() Gtk.Box.__init__(self, False, 0) self.parent = parent self.ppa = PPA(self) self.settings = Gtk.Settings() self.log = logging.getLogger("repoman.List") handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') handler.setFormatter(formatter) self.log.addHandler(handler) self.log.setLevel(logging.WARNING) self.content_grid = Gtk.Grid() self.content_grid.set_margin_top(24) self.content_grid.set_margin_left(12) self.content_grid.set_margin_right(12) self.content_grid.set_margin_bottom(12) self.content_grid.set_row_spacing(6) self.content_grid.set_hexpand(True) self.content_grid.set_vexpand(True) self.add(self.content_grid) sources_title = Gtk.Label(_("Extra Sources")) Gtk.StyleContext.add_class(sources_title.get_style_context(), "h2") sources_title.set_halign(Gtk.Align.START) self.content_grid.attach(sources_title, 0, 0, 1, 1) sources_label = Gtk.Label(_("These sources are for software provided by a third party. They may present a security risk or can cause system instability. Only add sources that you trust.")) sources_label.set_line_wrap(True) sources_label.set_halign(Gtk.Align.START) sources_label.set_justify(Gtk.Justification.FILL) sources_label.set_hexpand(True) self.content_grid.attach(sources_label, 0, 1, 1, 1) list_grid = Gtk.Grid() self.content_grid.attach(list_grid, 0, 2, 1, 1) list_window = Gtk.ScrolledWindow() list_grid.attach(list_window, 0, 0, 1, 1) self.ppa_liststore = Gtk.ListStore(str, str) self.view = Gtk.TreeView(self.ppa_liststore) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Source"), renderer, markup=0) self.view.append_column(column) self.view.set_hexpand(True) self.view.set_vexpand(True) self.view.connect("row-activated", self.on_row_activated) tree_selection = self.view.get_selection() tree_selection.connect('changed', self.on_row_change) list_window.add(self.view) # add button add_button = Gtk.ToolButton() add_button.set_icon_name("list-add-symbolic") Gtk.StyleContext.add_class(add_button.get_style_context(), "image-button") add_button.set_tooltip_text(_("Add New Source")) add_button.connect("clicked", self.on_add_button_clicked) # edit button edit_button = Gtk.ToolButton() edit_button.set_icon_name("edit-symbolic") Gtk.StyleContext.add_class(edit_button.get_style_context(), "image-button") edit_button.set_tooltip_text(_("Modify Selected Source")) edit_button.connect("clicked", self.on_edit_button_clicked) action_bar = Gtk.Toolbar() action_bar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(action_bar.get_style_context(), "inline-toolbar") action_bar.insert(edit_button, 0) action_bar.insert(add_button, 0) list_grid.attach(action_bar, 0, 1, 1, 1) self.generate_entries(self.ppa.get_isv())
def set_modified_config(self): """The config was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_config(self) self.button_revert.set_sensitive(True)
def set_modified_config(self): """The config was changed and now needs to be saved and reloaded""" SoftwareProperties.set_modified_config(self) self.userinterface.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
def __init__(self, datadir=None, options=None, file=None, parent=None): """ Provide a GTK based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) Gtk.Window.set_default_icon_name("software-properties") SimpleGtkbuilderApp.__init__(self, os.path.join(datadir, "gtkbuilder", "main.ui"), domain="software-properties") if parent: self.window_main.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.window_main.show() try: self.window_main.set_transient_for(parent) except: pass # If externally called, reparent to external application. self.options = options if options and options.toplevel != None: self.window_main.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.window_main.show() try: toplevel = Gdk.window_foreign_new(int(options.toplevel)) except AttributeError: toplevel = None if (toplevel): try: self.window_main.set_transient_for(toplevel) except: pass if options and options.open_tab: self.notebook_main.set_current_page(int(options.open_tab)) # gsettings all_schemas = Gio.Settings.list_schemas() if "com.ubuntu.update-notifier" in all_schemas: self.settings = Gio.Settings("com.ubuntu.update-notifier") # we need this for reverting self.initial_auto_launch = self.settings.get_int("regular-auto-launch-interval") else: self.settings = None self.initial_auto_launch = 0 self.combobox_other_updates.set_sensitive(False) # get the dbus backend bus = dbus.SystemBus() proxy = bus.get_object("com.ubuntu.SoftwareProperties", "/") self.backend = dbus.Interface(proxy, "com.ubuntu.SoftwareProperties") self.backend.connect_to_signal( "SourcesListModified", self.on_sources_list_modified) self.backend.connect_to_signal( "ConfigModified", self.on_config_modified) self.backend.connect_to_signal( "KeysModified", self.on_keys_modified) self.backend.connect_to_signal( "AuthFailed", self.on_auth_failed) self.backend.connect_to_signal( "CdromScanFailed", self.on_cdrom_scan_failed) # Show what we have early self.window_main.show() # used to store the handlers of callbacks self.handlers = [] # Put some life into the user interface: self.init_popcon() self.init_auto_update() self.init_release_upgrades() self.show_auto_update_level() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() # Setup and show the distro elements self.init_distro() self.show_distro() # Show the import/replace sources.list dialog if a file different # to the default sources.list was specified # NOTE: If the file path points to the default sources.list the user # perhaps assumed that s-p would act like a normal editor. # We have got some bug reports from users calling # "sudo software-properties-gtk /etc/apt/sources.list" from the # command line. if (file != None and os.path.abspath(file) != "%s%s" % (apt_pkg.config.find_dir("Dir::Etc"), apt_pkg.config.find("Dir::Etc::sourcelist"))): self.open_file(file)
class PPA: waiting = "Waiting for PPA" invalid = "Not a valid PPA" valid = "Valid PPA found" sources_path = "/etc/apt/sources.list.d/" cache = apt.Cache() sp = SoftwareProperties() def __init__(self, parent=None): self.parent = parent self.log = logging.getLogger("repoman.Updates") handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s %(name)-12s %(levelname)-8s %(message)s') handler.setFormatter(formatter) self.log.addHandler(handler) self.log.setLevel(logging.WARNING) # Returns a list of all 3rd-party software sources. def get_isv(self): self.sp.reload_sourceslist() list = self.sp.get_isv_sources() return list # Returns the current distro Components. def get_distro_sources(self): components = self.sp.distro.source_template.components return components # Returns the current child repos (updates) def get_distro_child_repos(self): repos = self.sp.distro.source_template.children return repos # Get whether a component is enabled or not def get_comp_download_state(self, comp): (active, inconsistent) = self.sp.get_comp_download_state(comp) return (active, inconsistent) # Get whether a child repo is enabled or not def get_child_download_state(self, child): (active, inconsistent) = self.sp.get_comp_child_state(child) self.log.debug(child.name + " (" + str(active) + ", " + str(inconsistent) + ")") return (active, inconsistent) # Get Source Code State def get_source_code_enabled(self): enabled = self.sp.get_source_code_state() if enabled == None: return (False, True) else: return (enabled, False) # Enable/Disable a component def set_comp_enabled(self, comp, enabled): self.log.info('Component: %s\nEnabled: %s' % (comp, enabled)) try: remote_object.SetCompEnabled(comp, enabled) except: self.exc = sys.exc_info() self.throw_error(self.exc[1]) return 0 # Enable/Disable a child repo def set_child_enabled(self, child, enabled): self.log.info('Child: %s\nEnabled: %s' % (child, enabled)) try: remote_object.SetChildEnabled(child.name, enabled) except: self.exc = sys.exc_info() self.throw_error(self.exc[1]) return 0 # Enable/Disable source code def set_source_code_enabled(self, enabled): self.log.info('Source enabled: %s' % enabled) try: remote_object.SetSourceCodeEnabled(enabled) except: self.exc = sys.exc_info() self.throw_error(self.exc[1]) return 0 def get_line(self, isdisabled, rtype, archs, uri, version, component): """Collect all values from the entries and create an apt line""" if isdisabled == True: disstr = "#" else: disstr = "" if archs == "[arch]": archs = "" line = "%s%s %s %s %s %s" % (disstr, rtype, archs, uri, version, component) return line # Turn an added deb line into an apt source def deb_line_to_source(self, line): self.log.info(line) source = self.sp._find_source_from_string(line) return source # Modify an existing PPA def modify_ppa(self, old_source, disabled, rtype, archs, uri, version, component): self.log.info("Old source: %s" % old_source) line = self.get_line(disabled, rtype, archs, uri, version, component) self.log.info("New source: %s" % line) self.parent.parent.parent.hbar.spinner.start() self.parent.parent.parent.stack.list_all.view.set_sensitive(False) ModifyThread(self.parent, old_source, line, self.sp).start() # Starts a new thread to add a repository def add(self, url): self.log.info("Adding source: %s" % url) print(type(url)) self.parent.parent.parent.hbar.spinner.start() self.parent.parent.parent.stack.list_all.view.set_sensitive(False) t = AddThread(self.parent, url, self.sp) t.start() # Starts a new thread to remove a repository def remove(self, ppa): self.log.info("Removing source: %s" % ppa) self.parent.parent.hbar.spinner.start() self.parent.parent.stack.list_all.view.set_sensitive(False) RemoveThread(self.parent, self.sources_path, ppa, self.sp).start() # Validate if a line appears to be a valid apt line or ppa. def validate(self, line): if line.startswith("deb"): if "http" in line: return True elif line.startswith("ppa:"): if "/" in line: return True elif line.startswith("http"): if "://" in line: return True else: return False # Get the current OS name, or fallback if not available def get_os_name(self): try: with open("/etc/os-release") as os_release_file: os_release = os_release_file.readlines() for line in os_release: parse = line.split('=') if parse[0] == "NAME": if parse[1].startswith('"'): return parse[1][1:-2] else: return parse[1][:-1] else: continue except FileNotFoundError: return "your OS" return "your OS" def throw_error(self, message): GObject.idle_add( self.parent.parent.parent.stack.list_all.throw_error_dialog, message, "error")
## ADD PPA TO SOURCE LIST ## ################################ PPA_LIST = open(PSTACK[0]+"ppa.lst").read().rstrip("\n") if len( PPA_LIST ) == 0: print "###################################################" print "# NO REPOSITORIES ARE MISSING #" print "###################################################" print "" else: PPA_LIST = PPA_LIST.split("\n") print "###################################################" print "# ADDING %i MISSING REPOSITORIES #" % (len(PPA_LIST)) print "###################################################" for PPA in PPA_LIST: if PPA != None and PPA != "": sp = SoftwareProperties() sp.add_source_from_line( PPA ) sp.sourceslist.save() print "" print "" ################################ ## INSTALL MISSING PROGRAMS ## ################################ APT_LIST = open("apt.lst").read().rstrip("\n") if len(APT_LIST) == 0: print "###################################################" print "# NO SOFTWARE TO INSTALLING #" print "###################################################" print
# Import softwareproperties try: from softwareproperties.SoftwareProperties import SoftwareProperties except ImportError: pkg = apt_cache['python-software-properties'] if pkg.is_installed: logger.error('Package: python-software-propertiesis already installed but python cannot import library.') else: pkg.mark_install() try: apt_cache.commit() from softwareproperties.SoftwareProperties import SoftwareProperties except Exception, err: logger.error('Package installation has failed: %s', str(err)) sys.exit(1) # Add ppa logger.debug('Add Openvswitch PPA') sp = SoftwareProperties() sp.add_source_from_line('ppa:sgran/openvswitch-precise') sp.sourceslist.save() logger.debug(subprocess.check_output('apt-get update',shell=True)) new_apt_cache = apt.cache.Cache() apt_cache = new_apt_cache main(args) logger.info('Finished!') sys.exit(0)
def on_install_button_active(button, model, itemSelectCount): global pulseTimer global installStatus global cache global view global p1 # set busy flag installStatus = 'busy' # Remove CANCEL button Gtk.Container.remove(grid, cancelButton) # Count items itemCount = len(model) # Add PPA's # Set progress progressBar.set_fraction(0.1) label.set_text("Installing new software sources...") appendToLog("Installing new software sources...") # Use APT module and SoftwareProperties to add-apt sp = SoftwareProperties() for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if ppaList[listItem] != '': progressBar.set_text("Adding PPA for " + model[listItem][1]) # add-apt the python way ! taken from add-apt code try: sp.add_source_from_line(ppaList[listItem]) debugPrint("Added PPA - %s" % ppaList[listItem]) appendToLog("Added PPA - %s" % ppaList[listItem]) except: debugPrint("[Error] Could not add PPA - %s" % ppaList[listItem]) appendToLog("[Error] Could not add PPA - %s" % ppaList[listItem]) # Save new apt list sp.sourceslist.save() progressBar.set_fraction(0.2) # Add Keys for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if getAptKeyList[listItem] != '': debugPrint("Name : %s" % model[listItem][1]) debugPrint("Keys : %s" % getAptKeyList[listItem]) progressBar.set_text("Adding software key for " + model[listItem][1]) # Add key the bash way TODO do this differently to handle errors/timeout # First check type of key wget or apt-key adv if "recv-keys" in getAptKeyList[listItem]: keyType = 'apt-key' else: keyType = 'wget' try: if keyType == 'wget': # Just read Key URL and do the rest p1 = subprocess.Popen( ['wget', '-O', '-', getAptKeyList[listItem]], stdout=subprocess.PIPE) p2 = subprocess.Popen( ['apt-key', 'add', '--yes', '--quiet', '-'], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close( ) # Allow p1 to receive a SIGPIPE if p2 exits. if keyType == 'apt-key': # Run command as is p6 = subprocess.Popen([getAptKeyList[listItem]], shell=True, stdout=subprocess.PIPE) debugPrint("Key added for : %s" % model[listItem][1]) appendToLog("Key added for : %s" % model[listItem][1]) debugPrint("Key status: %s" % output) appendToLog("Key status: %s" % output) except: debugPrint("[Error] Could not add key from - %s" % getAptKeyList[listItem]) appendToLog("[Error] Could not add key from - %s" % getAptKeyList[listItem]) progressBar.set_fraction(0.3) # Manually write to file to add APT for DEB repos for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: if aptListEntryList[listItem] != '': debugPrint("Name : %s" % model[listItem][1]) debugPrint("APT : %s" % aptListEntryList[listItem]) installTitles = installTitleList[listItem].split(' ') progressBar.set_text("Adding APT Repository for " + model[listItem][1]) # write sources to file try: writeToFile( os.path.join(aptListPath, installTitles[0] + '.list'), 'deb ' + aptListEntryList[listItem] + '\n', 'w') #writeToFile(os.path.join(aptListPath, installTitles[0]+'.list'), 'deb-src '+aptListEntryList[listItem]+'\n', 'a') writeToFile( os.path.join(aptListPath, installTitles[0] + '.list.save'), 'deb ' + aptListEntryList[listItem] + '\w', 'w') #writeToFile(os.path.join(aptListPath, installTitles[0]+'.list.save'), 'deb-src '+aptListEntryList[listItem]+'\n', 'a') debugPrint("Added APT - %s" % aptListEntryList[listItem]) appendToLog("Added APT - %s" % aptListEntryList[listItem]) except: debugPrint("[Error] Could not add APT - %s" % aptListEntryList[listItem]) appendToLog("[Error] Could not add APT - %s" % aptListEntryList[listItem]) onInstallError() # Save new apt list sp.sourceslist.save() # We need to open the cache again before updating progressBar.set_fraction(0.4) progressBar.set_text('Reading Software List...') debugPrint("[Progress] Open Cache...") appendToLog("[Progress] Open Cache...") cache.open() # Now, lets update the package list progressBar.set_fraction(0.5) progressBar.set_text('Updating Software Center...') debugPrint("[Progress] Cache update...") appendToLog("[Progress] Cache update...") pulseTimer = GLib.timeout_add(100, pulse) try: cache.update() except: appendToLog("[Warning] Cache update warnings. Not fatal - continue...") debugPrint("[Warning] Cache update warnings. Not fatal - continue...") GLib.source_remove(pulseTimer) # Now we can do the same as 'apt-get upgrade' does progressBar.set_fraction(0.7) #progressBar.set_text('Updating Software ...') #print "[progress] Updating Software ..." #cache.upgrade() # or we can play 'apt-get dist-upgrade' #cache.upgrade(True) # Q: Why does nothing happen? # A: You forgot to call commit()! debugPrint("[Progress] Commit Cache...") appendToLog("[Progress] Commit Cache...") progressBar.set_fraction(0.8) progressBar.set_text('Updating Software Center...') try: #cache.commit() cache.commit(aptAcquireProgress, aptInstallProgress) except: debugPrint("[Error] apt-get update failed") # Software sources added Done progressBar.set_fraction(1) progressBar.set_text('') label.set_text('Software sources added successfully') appendToLog('Software sources added successfully') # START installing apps one by one # using itemSelectCount to do progress increments progInc = float(100 / itemSelectCount) / 100 itemIncCount = 0 progressBar.set_fraction(0.02) for listItem in range(itemCount): # Check which items are selected True in list column 0 itemSelected = model[listItem][0] if itemSelected: # With selected items ... label.set_text('Installing Software ' + str(itemIncCount + 1) + ' of ' + str(itemSelectCount) + ' ...') appendToLog('[Notice] Installing Software ' + str(itemIncCount + 1) + ' of ' + str(itemSelectCount) + ' ...') # Un Install first if RE-install is selected if installStateList[listItem] == 'installed': progressBar.set_text("Removing " + model[listItem][1]) # Set focus view.set_cursor(listItem) # open cache again for each install to update new packages list cache.open() # Get package list into array installTitles = installTitleList[listItem].split(' ') # mark packages for Remove for itemToRemove in installTitles: try: cache[itemToRemove].mark_delete() debugPrint("[Remove] Marked for Removal %s" % itemToRemove) appendToLog("[Remove] Marked for Removal %s" % itemToRemove) except: debugPrint("[Error] Packages not found for %s" % model[listItem][1]) appendToLog("[Error] Packages not found for %s" % model[listItem][1]) # TODO show install failed not done installError = "[Error] Packages not found for " + model[ listItem][1] # Commit new cache and remove each set of packages try: aptAcquireProgress.start() progressTimer = GLib.timeout_add(200, renderCellProgress, model, listItem, 'remove') cache.commit(aptAcquireProgress, aptInstallProgress) aptAcquireProgress.stop() GLib.source_remove(progressTimer) # Update icon after removal model[listItem][4] = GdkPixbuf.Pixbuf.new_from_file( iconPathBlank) debugPrint("Un-Install complete for %s" % model[listItem][1]) appendToLog("Un-Install complete for %s" % model[listItem][1]) except: debugPrint("[Error] Un-Install failed for %s" % model[listItem][1]) appendToLog("[Error] Un-Install failed for %s" % model[listItem][1]) installError = "[Error] Un-Install failed for " + model[ listItem][1] # Run Pre-install commands # if item has pre-install run that now if preInstallList[listItem] != '': progressBar.set_text("Running pre-install for " + model[listItem][1]) # Run pre install commands the bash way TODO do this differently to handle errors/timeout try: p1 = subprocess.Popen([preInstallList[listItem]], shell=True, stdout=subprocess.PIPE) output = p1.communicate()[0] debugPrint("Running Pre install script for : %s" % model[listItem][1]) debugPrint("Pre install script output: %s" % output) appendToLog("Running Pre install script for : %s" % model[listItem][1]) appendToLog("Pre install script output: %s" % output) except: debugPrint("[Error] Pre install script error : %s" % model[listItem][1]) appendToLog("[Error] Pre install script error : %s" % model[listItem][1]) # Install software item FINALLY installError = '' # Initial cell progressbar value model[listItem][3] = 0 progressBar.set_text("Installing " + model[listItem][1]) debugPrint("Installing %s" % model[listItem][1]) appendToLog("Installing %s" % model[listItem][1]) # Set focus view.set_cursor(listItem) # open cache again for each install to update new packages list cache.open() # Get package list into array installTitles = installTitleList[listItem].split(' ') # mark packages for install for itemToInstall in installTitles: try: cache[itemToInstall].mark_install() debugPrint("[Install] Marked for install %s" % itemToInstall) appendToLog("[Install] Marked for install %s" % itemToInstall) except: debugPrint("[Error] Packages not found for %s" % model[listItem][1]) appendToLog("[Error] Packages not found for %s" % model[listItem][1]) # TODO show install failed not done installError = "[Error] Packages not found for " + model[ listItem][1] # Commit new cache and install each set of packages try: #cache.upgrade() aptAcquireProgress.start() progressTimer = GLib.timeout_add(200, renderCellProgress, model, listItem, 'install') cache.commit(aptAcquireProgress, aptInstallProgress) #cache.commit() debugPrint("Install complete for %s" % model[listItem][1]) appendToLog("Install complete for %s" % model[listItem][1]) except: debugPrint("[Error] Installation failed for %s" % model[listItem][1]) # TODO show install failed not done installError = "[Error] Installation failed for " + model[ listItem][1] # END of Install # Run POST-install commands # if item has post-install run that now if postInstallList[listItem] != '': progressBar.set_text("Running post-install for " + model[listItem][1]) # Run post install commands the bash way TODO do this differently to handle errors/timeout try: p1 = subprocess.Popen([postInstallList[listItem]], shell=True, stdout=subprocess.PIPE) output = p1.communicate()[0] debugPrint("Running Post install script for : %s" % model[listItem][1]) debugPrint("Post install script output: %s" % output) appendToLog("Running Post install script for : %s" % model[listItem][1]) appendToLog("Post install script output: %s" % output) except: debugPrint("[Error] Post install script error : %s" % model[listItem][1]) appendToLog("[Error] Post install script error : %s" % model[listItem][1]) # Set Cell Progress bar and deselect when done model[listItem][3] = 100 model[listItem][0] = False GLib.source_remove(progressTimer) aptAcquireProgress.stop() time.sleep(0.1) refreshGui() time.sleep(0.1) # Check if install ok and set icon if installError == '': iconPathMod = iconPathOk installStateList[listItem] = 'installed' else: iconPathMod = iconPathError installStateList[listItem] = 'error' # Set icon model[listItem][4] = GdkPixbuf.Pixbuf.new_from_file(iconPathMod) # If selected Inc for each item as we know not how many here # Move progress incrementally depending on number of install items itemIncCount = itemIncCount + 1 displayInc = progInc * itemIncCount # Update main progress bar at the end of each item install progressBar.set_fraction(displayInc) # All Done - The End - # Remove Timers GLib.source_remove(progressTimer) progressBar.set_fraction(1) progressBar.set_text('') # Stop Spinner spinner.stop() os.system("python notify.py") label.set_text('Installation Complete') debugPrint('[END] Installation Complete') appendToLog('[END] Installation Complete') # Set focus view.set_cursor(0) # Reset installstatus installStatus = 'complete' # Remove Cancel Button and spinner #Gtk.Container.remove(grid, cancelButton) Gtk.Container.remove(grid, spinner) # Activate Install Now/Done button button.set_sensitive(True)
def __init__(self, datadir=None, options=None, parent=None, file=None): """ Provide a KDE (actually Qt 4) based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) self.options = options self.datadir = datadir self.app = QApplication([]) self.userinterface = SoftwarePropertiesKDEUI(datadir) self.userinterface.setWindowIcon( QIcon("/usr/share/icons/hicolor/128x128/apps/adept_manager.png")) self.translate_widgets() self.userinterface.show() sys.excepthook = self.excepthook # rejected() signal from Close button self.app.connect(self.userinterface.buttonBox, SIGNAL("rejected()"), self.on_close_button) self.userinterface.buttonBox.button( QDialogButtonBox.Reset).setEnabled(False) # Put some life into the user interface: self.init_server_chooser() self.init_popcon() self.init_auto_update() self.show_auto_update_level() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() self.app.connect(self.userinterface.checkbutton_source_code, SIGNAL("clicked()"), self.on_checkbutton_source_code_toggled) self.app.connect(self.userinterface.button_auth_restore, SIGNAL("clicked()"), self.on_restore_clicked) self.app.connect(self.userinterface.button_add_auth, SIGNAL("clicked()"), self.add_key_clicked) self.app.connect(self.userinterface.button_auth_remove, SIGNAL("clicked()"), self.remove_key_clicked) self.app.connect(self.userinterface.checkbutton_popcon, SIGNAL("toggled(bool)"), self.on_checkbutton_popcon_toggled) self.app.connect(self.userinterface.checkbutton_auto_update, SIGNAL("toggled(bool)"), self.on_auto_update_toggled) self.app.connect(self.userinterface.combobox_update_interval, SIGNAL("currentIndexChanged(int)"), self.on_combobox_update_interval_changed) self.app.connect(self.userinterface.button_remove, SIGNAL("clicked()"), self.on_remove_clicked) self.app.connect(self.userinterface.button_edit, SIGNAL("clicked()"), self.on_edit_clicked) self.app.connect(self.userinterface.button_add_cdrom, SIGNAL("clicked()"), self.on_button_add_cdrom_clicked) self.app.connect(self.userinterface.button_add, SIGNAL("clicked()"), self.on_add_clicked) self.app.connect(self.userinterface.treeview_sources, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.on_isv_source_toggled) self.app.connect(self.userinterface.treeview_cdroms, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.on_cdrom_source_toggled) self.app.connect(self.userinterface.treeview_sources, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), self.on_treeview_sources_cursor_changed) button_revert = self.userinterface.buttonBox.button( QDialogButtonBox.Reset) self.app.connect(button_revert, SIGNAL("clicked()"), self.on_button_revert_clicked) self.init_distro() self.show_distro()
def __init__(self, datadir=None, options=None, parent=None, file=None, attachWinID=None): """ Provide a KDE based graphical user interface to configure the used software repositories, corresponding authentication keys and update automation """ SoftwareProperties.__init__(self, options=options, datadir=datadir) self.options = options self.datadir = datadir global kapp kapp = KApplication() self.userinterface = SoftwarePropertiesKDEUI(datadir) self.userinterface.setWindowIcon(KIcon("applications-other")) self.userinterface.button_auth_restore.setIcon(KIcon("edit-undo")) self.userinterface.button_add_auth.setIcon(KIcon("list-add")) self.userinterface.button_auth_remove.setIcon(KIcon("list-remove")) self.userinterface.button_remove.setIcon(KIcon("list-remove")) self.userinterface.button_edit.setIcon(KIcon("document-edit")) self.userinterface.button_add.setIcon(KIcon("list-add")) self.userinterface.button_add_cdrom.setIcon(KIcon("media-optical")) translate_widget(self.userinterface) self.userinterface.show() if attachWinID is not None: KWindowSystem.setMainWindow(self.userinterface, int(attachWinID)) # rejected() signal from Close button kapp.connect(self.userinterface.buttonBox, SIGNAL("rejected()"), self.on_close_button) self.userinterface.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) # Put some life into the user interface: self.init_server_chooser() self.init_popcon() self.init_auto_update() self.init_release_upgrades() self.show_auto_update_level() # Setup the key list self.init_keys() self.show_keys() # Setup the ISV sources list self.init_isv_sources() self.show_isv_sources() self.show_cdrom_sources() kapp.connect(self.userinterface.checkbutton_source_code, SIGNAL("clicked()"), self.on_checkbutton_source_code_toggled) kapp.connect(self.userinterface.button_auth_restore, SIGNAL("clicked()"), self.on_restore_clicked) kapp.connect(self.userinterface.button_add_auth, SIGNAL("clicked()"), self.add_key_clicked) kapp.connect(self.userinterface.button_auth_remove, SIGNAL("clicked()"), self.remove_key_clicked) kapp.connect(self.userinterface.checkbutton_popcon, SIGNAL("toggled(bool)"), self.on_checkbutton_popcon_toggled) kapp.connect(self.userinterface.checkbutton_auto_update, SIGNAL("toggled(bool)"), self.on_auto_update_toggled) kapp.connect(self.userinterface.combobox_update_interval, SIGNAL("currentIndexChanged(int)"), self.on_combobox_update_interval_changed) kapp.connect(self.userinterface.button_remove, SIGNAL("clicked()"), self.on_remove_clicked) kapp.connect(self.userinterface.button_edit, SIGNAL("clicked()"), self.on_edit_clicked) kapp.connect(self.userinterface.button_add_cdrom, SIGNAL("clicked()"), self.on_button_add_cdrom_clicked) kapp.connect(self.userinterface.button_add, SIGNAL("clicked()"), self.on_add_clicked) kapp.connect(self.userinterface.treeview_sources, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.on_isv_source_toggled) kapp.connect(self.userinterface.treeview_sources, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), self.on_treeview_sources_cursor_changed) kapp.connect(self.userinterface.treeview_cdroms, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.on_cdrom_source_toggled) kapp.connect(self.userinterface.treeview2, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), self.on_treeview_keys_cursor_changed) button_close = self.userinterface.buttonBox.button(QDialogButtonBox.Close) button_close.setIcon(KIcon("dialog-close")) button_revert = self.userinterface.buttonBox.button(QDialogButtonBox.Reset) button_revert.setIcon(KIcon("edit-undo")) kapp.connect(button_revert, SIGNAL("clicked()"), self.on_button_revert_clicked) self.init_distro() self.show_distro()
class List(Gtk.Box): listiter_count = 0 ppa_name = False def __init__(self, parent): self.sp = SoftwareProperties() Gtk.Box.__init__(self, False, 0) self.parent = parent self.ppa = ppa.PPA(self) self.content_grid = Gtk.Grid() self.content_grid.set_margin_top(24) self.content_grid.set_margin_left(12) self.content_grid.set_margin_right(12) self.content_grid.set_margin_bottom(12) self.content_grid.set_row_spacing(6) self.content_grid.set_hexpand(True) self.content_grid.set_vexpand(True) self.add(self.content_grid) sources_title = Gtk.Label("Extra Sources") Gtk.StyleContext.add_class(sources_title.get_style_context(), "h2") sources_title.set_halign(Gtk.Align.START) self.content_grid.attach(sources_title, 0, 0, 1, 1) sources_label = Gtk.Label( "These sources are for software provided by " + "a third party. They may present a security " + "risk or can cause system instability. " + "\nOnly add sources that you trust.") sources_label.set_line_wrap(True) sources_label.set_halign(Gtk.Align.START) sources_label.set_justify(Gtk.Justification.FILL) sources_label.set_hexpand(True) self.content_grid.attach(sources_label, 0, 1, 1, 1) list_grid = Gtk.Grid() self.content_grid.attach(list_grid, 0, 2, 1, 1) list_window = Gtk.ScrolledWindow() list_grid.attach(list_window, 0, 0, 1, 1) self.ppa_liststore = Gtk.ListStore(str, str) self.view = Gtk.TreeView(self.ppa_liststore) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Source', renderer, markup=0) self.view.append_column(column) self.view.set_hexpand(True) self.view.set_vexpand(True) tree_selection = self.view.get_selection() tree_selection.connect('changed', self.on_row_change) list_window.add(self.view) # add button add_button = Gtk.Button.new_from_icon_name("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(add_button.get_style_context(), "image-button") add_button.set_tooltip_text("Add New Source") add_button.connect("clicked", self.on_add_button_clicked) # edit button edit_button = Gtk.Button.new_from_icon_name("edit-symbolic", Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(edit_button.get_style_context(), "image-button") edit_button.set_tooltip_text("Modify Selected Source") edit_button.connect("clicked", self.on_edit_button_clicked) action_bar = Gtk.ActionBar() Gtk.StyleContext.add_class(action_bar.get_style_context(), "inline-toolbar") action_bar.add(edit_button) action_bar.add(add_button) list_grid.attach(action_bar, 0, 1, 1, 1) self.generate_entries(self.ppa.get_isv()) def on_edit_button_clicked(self, widget): source = self.ppa.deb_line_to_source(self.ppa_name) dialog = window.EditDialog(self.parent.parent, source.type, source.uri, source.dist, source.comps, source.architectures) response = dialog.run() if response == Gtk.ResponseType.OK: if dialog.type_box.get_active() == 0: new_rtype = "deb" elif dialog.type_box.get_active() == 1: new_rtype = "deb-src" new_uri = dialog.uri_entry.get_text() new_version = dialog.version_entry.get_text() new_component = dialog.component_entry.get_text() new_archs = "[arch=" for arch in source.architectures: new_archs = "%s%s," % (new_archs, arch) new_archs = new_archs[:-1] + "]" self.ppa.modify_ppa(source, new_rtype, new_archs, new_uri, new_version, new_component) else: print("The modify was canceled.") dialog.destroy() def on_add_button_clicked(self, widget): #self.ppa.remove(self.ppa_name) dialog = window.AddDialog(self.parent.parent) response = dialog.run() if response == Gtk.ResponseType.OK: url = dialog.ppa_entry.get_text() self.ppa.add(url) dialog.destroy() def generate_entries(self, isv_list): self.ppa_liststore.clear() print(str(self.listiter_count)) self.listiter_count = self.listiter_count + 1 for source in isv_list: if not str(source).startswith("#"): source_pretty = self.sp.render_source(source) self.ppa_liststore.insert_with_valuesv( -1, [0, 1], [source_pretty, str(source)]) def on_row_change(self, widget): (model, pathlist) = widget.get_selected_rows() for path in pathlist: tree_iter = model.get_iter(path) value = model.get_value(tree_iter, 1) self.ppa_name = value
class List(Gtk.Box): listiter_count = 0 ppa_name = False def __init__(self, parent): self.sp = SoftwareProperties() Gtk.Box.__init__(self, False, 0) self.parent = parent self.ppa = PPA(self) self.settings = Gtk.Settings() self.log = logging.getLogger("repoman.List") handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') handler.setFormatter(formatter) self.log.addHandler(handler) self.log.setLevel(logging.WARNING) self.content_grid = Gtk.Grid() self.content_grid.set_margin_top(24) self.content_grid.set_margin_left(12) self.content_grid.set_margin_right(12) self.content_grid.set_margin_bottom(12) self.content_grid.set_row_spacing(6) self.content_grid.set_hexpand(True) self.content_grid.set_vexpand(True) self.add(self.content_grid) sources_title = Gtk.Label(_("Extra Sources")) Gtk.StyleContext.add_class(sources_title.get_style_context(), "h2") sources_title.set_halign(Gtk.Align.START) self.content_grid.attach(sources_title, 0, 0, 1, 1) sources_label = Gtk.Label(_("These sources are for software provided by a third party. They may present a security risk or can cause system instability. Only add sources that you trust.")) sources_label.set_line_wrap(True) sources_label.set_halign(Gtk.Align.START) sources_label.set_justify(Gtk.Justification.FILL) sources_label.set_hexpand(True) self.content_grid.attach(sources_label, 0, 1, 1, 1) list_grid = Gtk.Grid() self.content_grid.attach(list_grid, 0, 2, 1, 1) list_window = Gtk.ScrolledWindow() list_grid.attach(list_window, 0, 0, 1, 1) self.ppa_liststore = Gtk.ListStore(str, str) self.view = Gtk.TreeView(self.ppa_liststore) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Source"), renderer, markup=0) self.view.append_column(column) self.view.set_hexpand(True) self.view.set_vexpand(True) self.view.connect("row-activated", self.on_row_activated) tree_selection = self.view.get_selection() tree_selection.connect('changed', self.on_row_change) list_window.add(self.view) # add button add_button = Gtk.ToolButton() add_button.set_icon_name("list-add-symbolic") Gtk.StyleContext.add_class(add_button.get_style_context(), "image-button") add_button.set_tooltip_text(_("Add New Source")) add_button.connect("clicked", self.on_add_button_clicked) # edit button edit_button = Gtk.ToolButton() edit_button.set_icon_name("edit-symbolic") Gtk.StyleContext.add_class(edit_button.get_style_context(), "image-button") edit_button.set_tooltip_text(_("Modify Selected Source")) edit_button.connect("clicked", self.on_edit_button_clicked) action_bar = Gtk.Toolbar() action_bar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR) Gtk.StyleContext.add_class(action_bar.get_style_context(), "inline-toolbar") action_bar.insert(edit_button, 0) action_bar.insert(add_button, 0) list_grid.attach(action_bar, 0, 1, 1, 1) self.generate_entries(self.ppa.get_isv()) def on_edit_button_clicked(self, widget): selec = self.view.get_selection() (model, pathlist) = selec.get_selected_rows() tree_iter = model.get_iter(pathlist[0]) value = model.get_value(tree_iter, 1) self.log.info("PPA to edit: %s" % value) self.do_edit(value) def on_row_activated(self, widget, data1, data2): tree_iter = self.ppa_liststore.get_iter(data1) value = self.ppa_liststore.get_value(tree_iter, 1) self.log.info("PPA to edit: %s" % value) self.do_edit(value) def do_edit(self, repo): source = self.ppa.deb_line_to_source(repo) dialog = EditDialog(self.parent.parent, source.disabled, source.type, source.uri, source.dist, source.comps, source.architectures, repo) response = dialog.run() if response == Gtk.ResponseType.OK: if dialog.type_box.get_active() == 0: new_rtype = "deb" elif dialog.type_box.get_active() == 1: new_rtype = "deb-src" new_disabled = not dialog.enabled_switch.get_active() new_uri = dialog.uri_entry.get_text() self.log.info(new_disabled) new_version = dialog.version_entry.get_text() new_component = dialog.component_entry.get_text() dialog.destroy() new_archs = "[arch=" for arch in source.architectures: new_archs = "%s%s," % (new_archs, arch) new_archs = new_archs[:-1] + "]" old_source = self.ppa.get_line( source.disabled, source.type, source.architectures, source.uri, source.dist, source.comps ) self.ppa.modify_ppa(old_source, new_disabled, new_rtype, new_archs, new_uri, new_version, new_component) self.generate_entries(self.ppa.get_isv()) else: dialog.destroy() self.generate_entries(self.ppa.get_isv()) def on_add_button_clicked(self, widget): #self.ppa.remove(self.ppa_name) dialog = AddDialog(self.parent.parent) response = dialog.run() if response == Gtk.ResponseType.OK: url = dialog.ppa_entry.get_text() dialog.destroy() self.ppa.add(url) else: dialog.destroy() def generate_entries(self, isv_list): self.ppa_liststore.clear() self.listiter_count = self.listiter_count + 1 for source in isv_list: if not "cdrom" in str(source): if not str(source).startswith("#"): source_pretty = self.sp.render_source(source) if "Partners" in source_pretty: continue self.ppa_liststore.insert_with_valuesv(-1, [0, 1], [source_pretty, str(source)]) for source in isv_list: if not "cdrom" in str(source): if str(source).startswith("#"): source_str_list = self.sp.render_source(source).split("b>") source_pretty = "%s%s <i>Disabled</i>" % (source_str_list[1][:-2], source_str_list[2]) if "Partners" in source_pretty: continue self.ppa_liststore.insert_with_valuesv(-1, [0, 1], [source_pretty, str(source)]) def on_row_change(self, widget): (model, pathlist) = widget.get_selected_rows() for path in pathlist : tree_iter = model.get_iter(path) value = model.get_value(tree_iter,1) self.ppa_name = value def throw_error_dialog(self, message, msg_type): if msg_type == "error": msg_type = Gtk.MessageType.ERROR dialog = Gtk.MessageDialog(self.parent.parent, 0, msg_type, Gtk.ButtonsType.CLOSE, message) dialog.run() dialog.destroy()