Exemplo n.º 1
0
    def __init__(self):
        TweakModule.__init__(self, 'sourceeditor.ui')

        self.auto_backup_setting = GSetting(
            'com.ubuntu-tweak.tweak.auto-backup')

        self.textview = SourceView(SOURCES_LIST)
        self.textview.set_sensitive(False)
        self.sw1.add(self.textview)
        self.textview.get_buffer().connect('changed', self.on_buffer_changed)

        self.list_selection = self.list_view.get_selection()
        self.list_selection.connect("changed", self.on_selection_changed)

        self.infobar = Gtk.InfoBar()
        self.info_label = Gtk.Label(label='Current view the list')
        self.info_label.set_alignment(0, 0.5)
        self.infobar.get_content_area().add(self.info_label)
        self.infobar.connect("response", self.on_infobar_response)
        self.infobar.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
        self.infobar.hide()
        self.text_vbox.pack_start(self.infobar, False, False, 0)

        self.connect('realize', self.on_ui_realize)
        self.add_start(self.hpaned1)
Exemplo n.º 2
0
    def __init__(self, feature_name):
        GObject.GObject.__init__(self,
                                 hscrollbar_policy=Gtk.PolicyType.NEVER,
                                 vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
        self.set_property('shadow-type', Gtk.ShadowType.NONE)
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting('com.ubuntu-tweak.tweak.%s' % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport()
        viewport.set_property('shadow-type', Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        self.connect('size-allocate', self.rebuild_boxes)

        self._setting.connect_notify(self.load_modules)

        self.show_all()
Exemplo n.º 3
0
    def __init__(self, parent):
        GuiBuilder.__init__(self, file_name='preferences.ui')

        self.preferences_dialog.set_transient_for(parent)
        self.clips_setting = GSetting('com.ubuntu-tweak.tweak.clips')
        self.tweaks_setting = GSetting('com.ubuntu-tweak.tweak.tweaks')
        self.admins_setting = GSetting('com.ubuntu-tweak.tweak.admins')
        self.janitor_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.clips_location_setting = GSetting('com.ubuntu-tweak.tweak.last-clip-location')
Exemplo n.º 4
0
    def _initialize_ui_states(self, widget, splash_window):
        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 900 and height >= 506:
            self.mainwindow.set_default_size(width, height)

        for feature_button in ('overview_button', 'apps_button', 'admins_button', \
                               'tweaks_button', 'janitor_button'):
            button = getattr(self, feature_button)

            label = button.get_child().get_label()
            button.get_child().set_markup('<b>%s</b>' % label)
            button.get_child().set_use_underline(True)
        splash_window.destroy()
Exemplo n.º 5
0
    def __init__(self):
        TweakModule.__init__(self, 'sourceeditor.ui')

        self.auto_backup_setting = GSetting('com.ubuntu-tweak.tweak.auto-backup')

        self.textview = SourceView(SOURCES_LIST)
        self.textview.set_sensitive(False)
        self.sw1.add(self.textview)
        self.textview.get_buffer().connect('changed', self.on_buffer_changed)

        un_lock = PolkitButton(PK_ACTION_SOURCE)
        un_lock.connect('authenticated', self.on_polkit_action)
        self._authenticated = False
        self.hbuttonbox2.pack_end(un_lock, False, False, 0)

        self.list_selection = self.list_view.get_selection()
        self.list_selection.connect("changed", self.on_selection_changed)

        self.infobar = Gtk.InfoBar()
        self.info_label = Gtk.Label('Current view the list')
        self.info_label.set_alignment(0, 0.5)
        self.infobar.get_content_area().add(self.info_label)
        self.infobar.connect("response", self.on_infobar_response)
        self.infobar.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
        self.infobar.hide()
        self.text_vbox.pack_start(self.infobar, False, False, 0)

        self.connect('realize', self.on_ui_realize)
        self.add_start(self.hbox1)
Exemplo n.º 6
0
    def __init__(self, feature_name):
        GObject.GObject.__init__(
            self,
            shadow_type=Gtk.ShadowType.NONE,
            hscrollbar_policy=Gtk.PolicyType.NEVER,
            vscrollbar_policy=Gtk.PolicyType.AUTOMATIC,
        )
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting("com.ubuntu-tweak.tweak.%s" % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport(shadow_type=Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        self.connect("draw", self.rebuild_boxes)

        self._setting.connect_notify(self.load_modules, True)

        self.show_all()
Exemplo n.º 7
0
    def _initialize_ui_states(self, widget):
        # TODO implement the search feature
        self.window_size_setting = GSetting("com.ubuntu-tweak.tweak.window-size")
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        self.search_entry.hide()
Exemplo n.º 8
0
    def __init__(self, feature='', module='', splash_window=None):
        GuiBuilder.__init__(self, file_name='mainwindow.ui')

        tweaks_page = FeaturePage('tweaks')
        admins_page = FeaturePage('admins')
        self.no_result_box.label = self.result_text
        self.search_page = SearchPage(self.no_result_box)
        clip_page = ClipPage()
        self.apps_page = AppsPage(self.back_button, self.next_button)
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.recently_used_settings = GSetting(
            'com.ubuntu-tweak.tweak.recently-used')

        self.feature_dict['overview'] = self.notebook.append_page(
            clip_page, Gtk.Label('overview'))
        self.feature_dict['apps'] = self.notebook.append_page(
            self.apps_page, Gtk.Label())
        self.feature_dict['tweaks'] = self.notebook.append_page(
            tweaks_page, Gtk.Label('tweaks'))
        self.feature_dict['admins'] = self.notebook.append_page(
            admins_page, Gtk.Label('admins'))
        self.feature_dict['janitor'] = self.notebook.append_page(
            janitor_page, Gtk.Label('janitor'))
        self.feature_dict['wait'] = self.notebook.append_page(
            self._crete_wait_page(), Gtk.Label('wait'))
        self.feature_dict['search'] = self.notebook.append_page(
            self.search_page, Gtk.Label('search'))

        # Always show welcome page at first
        self.mainwindow.connect('realize', self._initialize_ui_states,
                                splash_window)
        self.back_button.connect('clicked', self.on_back_button_clicked)
        self.next_button.connect('clicked', self.on_next_button_clicked)
        tweaks_page.connect('module_selected', self.on_module_selected)
        self.search_page.connect('module_selected', self.on_module_selected)
        admins_page.connect('module_selected', self.on_module_selected)
        self.apps_page.connect('loaded', self.show_apps_page)
        clip_page.connect('load_module',
                          lambda widget, name: self.do_load_module(name))
        clip_page.connect(
            'load_feature',
            lambda widget, name: self.select_target_feature(name))

        self.mainwindow.show()

        if module:
            self.do_load_module(module)
        elif feature:
            self.select_target_feature(feature)

        accel_group = Gtk.AccelGroup()
        self.search_entry.add_accelerator('activate', accel_group, Gdk.KEY_f,
                                          Gdk.ModifierType.CONTROL_MASK,
                                          Gtk.AccelFlags.VISIBLE)
        self.mainwindow.add_accel_group(accel_group)
        thread.start_new_thread(self.preload_proxy_cache, ())
Exemplo n.º 9
0
    def __init__(self, parent):
        GuiBuilder.__init__(self, file_name='preferences.ui')

        self.preferences_dialog.set_transient_for(parent)
        self.clips_setting = GSetting('com.ubuntu-tweak.tweak.clips')
        self.tweaks_setting = GSetting('com.ubuntu-tweak.tweak.tweaks')
        self.admins_setting = GSetting('com.ubuntu-tweak.tweak.admins')
        self.janitor_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.clips_location_setting = GSetting('com.ubuntu-tweak.tweak.last-clip-location')
        
        auto_scan_label, auto_scan_switch = WidgetFactory.create("Switch",
                                                label=_("Auto scan:"),
                                                key='com.ubuntu-tweak.janitor.auto-scan',
                                                backend="gsettings")
        pack = GridPack((auto_scan_label, auto_scan_switch))
        self.generic_alignment.add(pack)

        self.generic_alignment.show_all()
Exemplo n.º 10
0
    def __init__(self):
        GObject.GObject.__init__(self)

        self.scan_tasks = []
        self.clean_tasks = []

        self.set_border_width(6)
        GuiBuilder.__init__(self, 'janitorpage.ui')

        self.autoscan_setting = GSetting('com.ubuntu-tweak.tweak.auto-scan')
        self.janitor_setting = GSetting('com.ubuntu-tweak.tweak.janitor')

        self.pack_start(self.vbox1, True, True, 0)

        self.connect('realize', self.setup_ui_tasks)
        self.janitor_view.get_selection().connect('changed', self.on_janitor_selection_changed)
        self.janitor_setting.connect_notify(self.update_model, True)
        self.show()
Exemplo n.º 11
0
    def _initialize_ui_states(self, widget, splash_window):
        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        for feature_button in ('overview_button', 'admins_button', \
                               'tweaks_button', 'janitor_button'):
            button = getattr(self, feature_button)
            label = button.get_child().get_label()
            button.get_child().set_markup('<b>%s</b>' % label)
            button.get_child().set_use_underline(True)
        splash_window.destroy()
Exemplo n.º 12
0
    def __init__(self, feature_name):
        GObject.GObject.__init__(self,
                                 hscrollbar_policy=Gtk.PolicyType.NEVER,
                                 vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
        self.set_property('shadow-type', Gtk.ShadowType.NONE)
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting('com.ubuntu-tweak.tweak.%s' % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport()
        viewport.set_property('shadow-type', Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        # TODO this will cause Bug #880663 randomly, as current there's no user extension for features, just disable it
        #        self._setting.connect_notify(self.load_modules)

        self.show_all()
Exemplo n.º 13
0
    def __init__(self, feature='', module=''):
        GuiBuilder.__init__(self, file_name='mainwindow.ui')

        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        Gtk.rc_parse(os.path.join(DATA_DIR, 'theme/ubuntu-tweak.rc'))

        tweaks_page = FeaturePage('tweaks')
        admins_page = FeaturePage('admins')
        clip_page = ClipPage()
#        apps_page = AppsPage()
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.rencently_used_settings = GSetting('com.ubuntu-tweak.tweak.rencently-used')

        self.feature_dict['overview'] = self.notebook.append_page(clip_page, Gtk.Label())
#        self.feature_dict['apps'] = self.notebook.append_page(apps_page, Gtk.Label())
        self.feature_dict['tweaks'] = self.notebook.append_page(tweaks_page, Gtk.Label())
        self.feature_dict['admins'] = self.notebook.append_page(admins_page, Gtk.Label())
        self.feature_dict['janitor'] = self.notebook.append_page(janitor_page, Gtk.Label())
        self.feature_dict['wait'] = self.notebook.append_page(self._crete_wait_page(),
                                                           Gtk.Label())

        # Always show welcome page at first
        self.mainwindow.connect('realize', self._initialize_ui_states)
        tweaks_page.connect('module_selected', self.on_module_selected)
        admins_page.connect('module_selected', self.on_module_selected)
        clip_page.connect('load_module', lambda widget, name: self.load_module(name))
        clip_page.connect('load_feature', lambda widget, name: self.select_target_feature(name))
        self.mainwindow.show()
        self.link_button.hide()

        if module:
            self.load_module(module)
        elif feature:
            self.select_target_feature(feature)
Exemplo n.º 14
0
    def __init__(self, parent):
        GuiBuilder.__init__(self, file_name='preferences.ui')

        self.preferences_dialog.set_transient_for(parent)
        self.clips_setting = GSetting('com.ubuntu-tweak.tweak.clips')
        self.tweaks_setting = GSetting('com.ubuntu-tweak.tweak.tweaks')
        self.admins_setting = GSetting('com.ubuntu-tweak.tweak.admins')
        self.janitor_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.clips_location_setting = GSetting(
            'com.ubuntu-tweak.tweak.last-clip-location')

        auto_scan_label, auto_scan_switch = WidgetFactory.create(
            "Switch",
            label=_("Auto scan:"),
            key='com.ubuntu-tweak.janitor.auto-scan',
            backend="gsettings")
        pack = GridPack((auto_scan_label, auto_scan_switch))
        self.generic_alignment.add(pack)

        self.generic_alignment.show_all()
Exemplo n.º 15
0
    def __init__(self, feature_name):
        GObject.GObject.__init__(self,
                                 hscrollbar_policy=Gtk.PolicyType.NEVER,
                                 vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
        self.set_property('shadow-type', Gtk.ShadowType.NONE)
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting('com.ubuntu-tweak.tweak.%s' % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport()
        viewport.set_property('shadow-type', Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        # TODO this will cause Bug #880663 randomly, as current there's no user extension for features, just disable it
#        self._setting.connect_notify(self.load_modules)

        self.show_all()
Exemplo n.º 16
0
    def __init__(self):
        GObject.GObject.__init__(self)

        self.scan_tasks = []
        self.clean_tasks = []
        self._total_count = 0

        self.set_border_width(6)
        GuiBuilder.__init__(self, 'janitorpage.ui')

        self.autoscan_setting = GSetting('com.ubuntu-tweak.janitor.auto-scan')
        self.autoscan_setting.connect_notify(self.on_autoscan_button_toggled)
        self.plugins_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.view_width_setting = GSetting(
            'com.ubuntu-tweak.janitor.janitor-view-width')

        self.pack_start(self.vbox1, True, True, 0)

        self.connect('realize', self.setup_ui_tasks)
        self.janitor_view.get_selection().connect(
            'changed', self.on_janitor_selection_changed)
        self.plugins_setting.connect_notify(self.update_model, True)

        self.show()
Exemplo n.º 17
0
class UbuntuTweakWindow(GuiBuilder):
    current_feature = 'overview'
    feature_dict = {}
    navigation_dict = {'tweaks': [None, None]}
    # the module name and page index: 'Compiz': 2
    loaded_modules = {}
    # reversed dict: 2: 'CompizClass'
    modules_index = {}

    def __init__(self, feature='', module='', splash_window=None):
        GuiBuilder.__init__(self, file_name='mainwindow.ui')

        tweaks_page = FeaturePage('tweaks')
        admins_page = FeaturePage('admins')
        self.no_result_box.label = self.result_text
        self.search_page = SearchPage(self.no_result_box)
        clip_page = ClipPage()
        self.apps_page = AppsPage(self.back_button, self.next_button)
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.recently_used_settings = GSetting('com.ubuntu-tweak.tweak.recently-used')

        self.feature_dict['overview'] = self.notebook.append_page(clip_page, Gtk.Label('overview'))
        self.feature_dict['apps'] = self.notebook.append_page(self.apps_page, Gtk.Label())
        self.feature_dict['tweaks'] = self.notebook.append_page(tweaks_page, Gtk.Label('tweaks'))
        self.feature_dict['admins'] = self.notebook.append_page(admins_page, Gtk.Label('admins'))
        self.feature_dict['janitor'] = self.notebook.append_page(janitor_page, Gtk.Label('janitor'))
        self.feature_dict['wait'] = self.notebook.append_page(self._crete_wait_page(),
                                                           Gtk.Label('wait'))
        self.feature_dict['search'] = self.notebook.append_page(self.search_page,
                                                           Gtk.Label('search'))

        # Always show welcome page at first
        self.mainwindow.connect('realize', self._initialize_ui_states, splash_window)
        self.back_button.connect('clicked', self.on_back_button_clicked)
        self.next_button.connect('clicked', self.on_next_button_clicked)
        tweaks_page.connect('module_selected', self.on_module_selected)
        self.search_page.connect('module_selected', self.on_module_selected)
        admins_page.connect('module_selected', self.on_module_selected)
        clip_page.connect('load_module', lambda widget, name: self.do_load_module(name))
        clip_page.connect('load_feature', lambda widget, name: self.select_target_feature(name))

        self.mainwindow.show()

        if module:
            self.do_load_module(module)
        elif feature:
            self.select_target_feature(feature)

        accel_group = Gtk.AccelGroup()
        self.search_entry.add_accelerator('activate',
                                          accel_group,
                                          Gdk.KEY_f,
                                          Gdk.ModifierType.CONTROL_MASK,
                                          Gtk.AccelFlags.VISIBLE)
        self.mainwindow.add_accel_group(accel_group)
        thread.start_new_thread(self.preload_proxy_cache, ())

    @log_func(log)
    def preload_proxy_cache(self):
        #This function just called to make sure the cache is loaded as soon as possible
        proxy.is_package_installed('ubuntu-tweak')

    @log_func(log)
    def on_search_entry_activate(self, widget):
        widget.grab_focus()
        self.on_search_entry_changed(widget)

    @log_func(log)
    def on_search_entry_changed(self, widget):
        text = widget.get_text()
        self.set_current_module(None, None)

        if text:
            self.notebook.set_current_page(self.feature_dict['search'])
            self.search_page.search(text)
            self.search_entry.set_property('secondary-icon-name', 'edit-clear')
        else:
            self.on_feature_button_clicked(getattr(self, '%s_button' % self.current_feature), self.current_feature)
            self.search_page.clean()
            self.search_entry.set_property('secondary-icon-name', 'edit-find')

    def on_search_entry_icon_press(self, widget, icon_pos, event):
        widget.set_text('')

    def get_module_and_index(self, name):
        index = self.loaded_modules[name]

        return self.modules_index[index], index

    def select_target_feature(self, text):
        toggle_button = getattr(self, '%s_button' % text, None)
        log.info("select_target_feature: %s" % text)
        if toggle_button:
            self.current_feature = text
            toggle_button.set_active(True)

    def _initialize_ui_states(self, widget, splash_window):
        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        for feature_button in ('overview_button', 'apps_button', 'admins_button', \
                               'tweaks_button', 'janitor_button'):
            button = getattr(self, feature_button)

            if feature_button == 'apps_button' and getpass.getuser() != 'tualatrix':
                button.hide()

            label = button.get_child().get_label()
            button.get_child().set_markup('<b>%s</b>' % label)
            button.get_child().set_use_underline(True)
        splash_window.destroy()

    def _crete_wait_page(self):
        vbox = Gtk.VBox()

        label = Gtk.Label()
        label.set_markup("<span size=\"xx-large\">%s</span>" % \
                        _('Please wait a moment...'))
        label.set_justify(Gtk.Justification.FILL)
        vbox.pack_start(label, False, False, 50)
        hbox = Gtk.HBox()
        vbox.pack_start(hbox, False, False, 0)

        vbox.show_all()

        return vbox

    def on_mainwindow_destroy(self, widget=None):
        allocation = widget.get_allocation()
        self.window_size_setting.set_value((allocation.width, allocation.height))

        Gtk.main_quit()
        try:
            proxy.exit()
        except Exception, e:
            log.error(e)
Exemplo n.º 18
0
class FeaturePage(Gtk.ScrolledWindow):

    __gsignals__ = {
        'module_selected': (GObject.SignalFlags.RUN_FIRST,
                            None,
                            (GObject.TYPE_STRING,))
    }

    _categories = None
    _boxes = []

    def __str__(self):
        return '<FeaturePage: %s>' % self._feature

    def __init__(self, feature_name):
        GObject.GObject.__init__(self,
                                 hscrollbar_policy=Gtk.PolicyType.NEVER,
                                 vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
        self.set_property('shadow-type', Gtk.ShadowType.NONE)
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting('com.ubuntu-tweak.tweak.%s' % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport()
        viewport.set_property('shadow-type', Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        self.connect('size-allocate', self.rebuild_boxes)

        self._setting.connect_notify(self.load_modules)

        self.show_all()

    def load_modules(self, *args, **kwargs):
        log.debug("Loading modules...")

        loader = ModuleLoader(self._feature)

        self._boxes = []
        for child in self._box.get_children():
            self._box.remove(child)

        for category, category_name in loader.get_categories():
            modules = loader.get_modules_by_category(category)
            if modules:
                module_to_loads = self._setting.get_value()

                for module in modules:
                    if module.is_user_extension() and module.get_name() not in module_to_loads:
                        modules.remove(module)

                category_box = CategoryBox(modules=modules, category_name=category_name)

                self._connect_signals(category_box)
                self._boxes.append(category_box)
                self._box.pack_start(category_box, False, False, 0)

        self.rebuild_boxes()

    def _connect_signals(self, category_box):
        for button in category_box.get_buttons():
            button.connect('clicked', self.on_button_clicked)

    def on_button_clicked(self, widget):
        log.info('Button clicked')
        module = widget.get_module()
        self.emit('module_selected', module.get_name())

    @log_func(log)
    def rebuild_boxes(self, widget=None, event=None):
        request = self.get_allocation()
        ncols = request.width / 164 # 32 + 120 + 6 + 4
        width = ncols * (164 + 2 * 4) + 40
        if width > request.width:
            ncols -= 1

        pos = 0
        children = self._box.get_children()
        for box in self._boxes:
            modules = box.get_modules()
            if len (modules) == 0:
                if box in children:
                    self._box.remove(box)
            else:
                if box not in children:
                    self._box.pack_start(box, False, False, 0)
                    self._box.reorder_child(box, pos)
                box.rebuild_table(ncols)
                pos += 1
Exemplo n.º 19
0
class PreferencesDialog(GuiBuilder):
    (CLIP_CHECK, CLIP_ICON, CLIP_NAME) = range(3)

    (TWEAKS_CHECK, TWEAKS_ICON, TWEAKS_NAME) = range(3)

    (JANITOR_CHECK, JANITOR_NAME) = range(2)

    page_dict = {'overview': 0, 'tweaks': 1, 'admins': 2, 'janitor': 3}

    def __init__(self, parent):
        GuiBuilder.__init__(self, file_name='preferences.ui')

        self.preferences_dialog.set_transient_for(parent)
        self.clips_setting = GSetting('com.ubuntu-tweak.tweak.clips')
        self.tweaks_setting = GSetting('com.ubuntu-tweak.tweak.tweaks')
        self.admins_setting = GSetting('com.ubuntu-tweak.tweak.admins')
        self.janitor_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.clips_location_setting = GSetting(
            'com.ubuntu-tweak.tweak.last-clip-location')

        auto_scan_label, auto_scan_switch = WidgetFactory.create(
            "Switch",
            label=_("Auto scan:"),
            key='com.ubuntu-tweak.janitor.auto-scan',
            backend="gsettings")
        pack = GridPack((auto_scan_label, auto_scan_switch))
        self.generic_alignment.add(pack)

        self.generic_alignment.show_all()

    def on_clip_toggle_render_toggled(self, cell, path):
        log.debug("on_clip_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.clip_model, path, self.CLIP_CHECK,
                                        self.CLIP_NAME, self.clips_setting)

    def on_tweak_toggle_renderer_toggled(self, cell, path):
        log.debug("on_tweaks_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.tweaks_model, path,
                                        self.TWEAKS_CHECK, self.TWEAKS_NAME,
                                        self.tweaks_setting)

    def on_admins_toggle_renderer_toggled(self, cell, path):
        log.debug("on_admins_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.admins_model, path,
                                        self.TWEAKS_CHECK, self.TWEAKS_NAME,
                                        self.admins_setting)

    def on_janitor_cell_renderer_toggled(self, cell, path):
        log.debug("on_admins_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.janitor_model, path,
                                        self.JANITOR_CHECK, self.JANITOR_NAME,
                                        self.janitor_setting)

    def on_toggle_renderer_toggled(self, model, path, check_id, name_id,
                                   setting):
        iter = model.get_iter(path)
        checked = not model[iter][check_id]
        model[iter][check_id] = checked

        self._do_update_model(model, check_id, name_id, setting)

    def _do_update_model(self, model, check_id, name_id, setting):
        model_list = []
        for row in model:
            if row[check_id]:
                model_list.append(row[name_id])

        log.debug("on_clip_toggle_render_toggled: %s" % model_list)
        setting.set_value(model_list)

    def run(self, feature='overview'):
        self._update_clip_model()

        for _feature in ModuleLoader.default_features:
            self._update_feature_model(_feature)

        if feature in self.page_dict:
            self.preference_notebook.set_current_page(self.page_dict[feature])

        return self.preferences_dialog.run()

    def hide(self):
        return self.preferences_dialog.hide()

    def on_move_up_button_clicked(self, widget):
        model, iter = self.clip_view.get_selection().get_selected()

        if iter:
            previous_path = str(int(model.get_string_from_iter(iter)) - 1)

            if int(previous_path) >= 0:
                previous_iter = model.get_iter_from_string(previous_path)
                model.move_before(iter, previous_iter)
                self._do_update_model(self.clip_model, self.CLIP_CHECK,
                                      self.CLIP_NAME, self.clips_setting)

    def on_move_down_button_clicked(self, widget):
        model, iter = self.clip_view.get_selection().get_selected()

        if iter:
            next_iter = model.iter_next(iter)
            model.move_after(iter, next_iter)
            self._do_update_model(self.clip_model, self.CLIP_CHECK,
                                  self.CLIP_NAME, self.clips_setting)

    def on_clip_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a clip extension'), Clip, 'clips',
                                  self.clips_setting, self._update_clip_model,
                                  _('"%s" is not a Clip Extension!'))

    def on_tweaks_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Tweaks Extension'), TweakModule,
                                  'tweaks', self.tweaks_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Tweaks Extension!'))

    def on_admins_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Admins Extension'), TweakModule,
                                  'admins', self.admins_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Admins Extension!'))

    def on_janitor_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Janitor Extension'),
                                  JanitorPlugin, 'janitor',
                                  self.janitor_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Janitor Extension!'))

    def on_install_extension(self, dialog_label, klass, feature, setting,
                             update_func, error_message):
        dialog = Gtk.FileChooserDialog(
            dialog_label,
            action=Gtk.FileChooserAction.OPEN,
            buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN,
                     Gtk.ResponseType.ACCEPT))
        filter = Gtk.FileFilter()
        filter.set_name(_('Ubuntu Tweak Extension (*.py, *.tar.gz)'))
        filter.add_pattern('*.py')
        filter.add_pattern('*.tar.gz')
        dialog.add_filter(filter)
        dialog.set_current_folder(self.clips_location_setting.get_value()
                                  or GLib.get_home_dir())

        filename = ''
        install_done = False
        not_extension = False

        if dialog.run() == Gtk.ResponseType.ACCEPT:
            filename = dialog.get_filename()
        dialog.destroy()

        if filename:
            self.clips_location_setting.set_value(os.path.dirname(filename))

            log.debug("Start to check the class in %s" % filename)
            if filename.endswith('.tar.gz'):
                tar_file = TarFile(filename)
                if tar_file.is_valid():
                    tar_file.extract(TEMP_ROOT)
                    #TODO if multi-root
                    if tar_file.get_root_name():
                        temp_dir = os.path.join(TEMP_ROOT,
                                                tar_file.get_root_name())

                if ModuleLoader.is_target_class(temp_dir, klass):
                    target = os.path.join(
                        ModuleLoader.get_user_extension_dir(feature),
                        os.path.basename(temp_dir))
                    copy = True
                    if os.path.exists(target):
                        dialog = QuestionDialog(message=_(
                            "Would you like to remove it then install again?"),
                                                title=_(
                                                    '"%s" has already installed'
                                                    %
                                                    os.path.basename(target)))
                        response = dialog.run()
                        dialog.destroy()

                        if response == Gtk.ResponseType.YES:
                            shutil.rmtree(target)
                        else:
                            copy = False

                    if copy:
                        log.debug("Now copying tree...")
                        shutil.move(temp_dir, target)
                    else:
                        shutil.rmtree(temp_dir)
                else:
                    not_extension = True
            else:
                if ModuleLoader.is_target_class(filename, klass):
                    shutil.copy(filename,
                                ModuleLoader.get_user_extension_dir(feature))
                    install_done = True
                else:
                    not_extension = True

        if install_done:
            update_func(feature)

            # To force empty the clips_setting to make load_cips
            value = setting.get_value()
            setting.set_value([''])
            setting.set_value(value)

        if not_extension:
            ErrorDialog(message=error_message %
                        os.path.basename(filename)).launch()

    def _update_clip_model(self, feature=None):
        clips = self.clips_setting.get_value()

        loader = ModuleLoader('clips')

        self.clip_model.clear()

        for clip_name in clips:
            ClipClass = loader.get_module(clip_name)

            self.clip_model.append(
                (True, ClipClass.get_pixbuf(), ClipClass.get_name()))

        for name, ClipClass in loader.module_table.items():
            if name not in clips:
                self.clip_model.append(
                    (False, ClipClass.get_pixbuf(), ClipClass.get_name()))

    def _update_feature_model(self, feature):
        module_list = getattr(self, '%s_setting' % feature).get_value() or []

        loader = ModuleLoader(feature, user_only=True)

        model = getattr(self, '%s_model' % feature)
        model.clear()

        for name, klass in loader.module_table.items():
            if klass.get_pixbuf():
                model.append(
                    (name
                     in module_list, klass.get_pixbuf(), klass.get_name()))
            else:
                model.append((name in module_list, klass.get_name()))
Exemplo n.º 20
0
class UbuntuTweakWindow(GuiBuilder):
    current_feature = 'overview'
    feature_dict = {}
    navigation_dict = {'tweaks': [None, None]}
    # the module name and page index: 'Compiz': 2
    loaded_modules = {}
    # reversed dict: 2: 'CompizClass'
    modules_index = {}

    def __init__(self, feature='', module=''):
        GuiBuilder.__init__(self, file_name='mainwindow.ui')

        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        Gtk.rc_parse(os.path.join(DATA_DIR, 'theme/ubuntu-tweak.rc'))

        tweaks_page = FeaturePage('tweaks')
        admins_page = FeaturePage('admins')
        clip_page = ClipPage()
#        apps_page = AppsPage()
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.rencently_used_settings = GSetting('com.ubuntu-tweak.tweak.rencently-used')

        self.feature_dict['overview'] = self.notebook.append_page(clip_page, Gtk.Label())
#        self.feature_dict['apps'] = self.notebook.append_page(apps_page, Gtk.Label())
        self.feature_dict['tweaks'] = self.notebook.append_page(tweaks_page, Gtk.Label())
        self.feature_dict['admins'] = self.notebook.append_page(admins_page, Gtk.Label())
        self.feature_dict['janitor'] = self.notebook.append_page(janitor_page, Gtk.Label())
        self.feature_dict['wait'] = self.notebook.append_page(self._crete_wait_page(),
                                                           Gtk.Label())

        # Always show welcome page at first
        self.mainwindow.connect('realize', self._initialize_ui_states)
        tweaks_page.connect('module_selected', self.on_module_selected)
        admins_page.connect('module_selected', self.on_module_selected)
        clip_page.connect('load_module', lambda widget, name: self.load_module(name))
        clip_page.connect('load_feature', lambda widget, name: self.select_target_feature(name))
        self.mainwindow.show()
        self.link_button.hide()

        if module:
            self.load_module(module)
        elif feature:
            self.select_target_feature(feature)

    def on_header_button_press_event(self, widget, event):
        self.mainwindow.begin_move_drag(event.button,
                                        event.x_root,
                                        event.y_root,
                                        event.time)

    def get_module_and_index(self, name):
        index = self.loaded_modules[name]

        return self.modules_index[index], index

    def select_target_feature(self, text):
        toggle_button = getattr(self, '%s_button' % text, None)
        log.info("select_target_feature: %s" % text)
        if toggle_button:
            self.current_feature = text
            toggle_button.set_active(True)

    def _initialize_ui_states(self, widget):
        #TODO implement the search feature
        self.search_entry.hide()

    def _crete_wait_page(self):
        vbox = Gtk.VBox()

        label = Gtk.Label()
        label.set_markup("<span size=\"xx-large\">%s</span>" % \
                        _('Please wait a moment...'))
        label.set_justify(Gtk.Justification.FILL)
        vbox.pack_start(label, False, False, 50)
        hbox = Gtk.HBox()
        vbox.pack_start(hbox, False, False, 0)

        vbox.show_all()

        return vbox

    def on_mainwindow_destroy(self, widget):
        allocation = widget.get_allocation()
        self.window_size_setting.set_value((allocation.width, allocation.height))

        Gtk.main_quit()
        try:
            proxy.exit()
        except Exception, e:
            log.error(e)
Exemplo n.º 21
0
class SourceEditor(TweakModule):
    __title__ = _('Source Editor')
    __desc__ = _('Manually edit your software sources to suit your needs.')
    __icon__ = 'system-software-update'
    __policykit__ = PK_ACTION_SOURCE
    __category__ = 'system'
    _authenticated = False

    def __init__(self):
        TweakModule.__init__(self, 'sourceeditor.ui')

        self.auto_backup_setting = GSetting(
            'com.ubuntu-tweak.tweak.auto-backup')

        self.textview = SourceView(SOURCES_LIST)
        self.textview.set_sensitive(False)
        self.sw1.add(self.textview)
        self.textview.get_buffer().connect('changed', self.on_buffer_changed)

        self.list_selection = self.list_view.get_selection()
        self.list_selection.connect("changed", self.on_selection_changed)

        self.infobar = Gtk.InfoBar()
        self.info_label = Gtk.Label(label='Current view the list')
        self.info_label.set_alignment(0, 0.5)
        self.infobar.get_content_area().add(self.info_label)
        self.infobar.connect("response", self.on_infobar_response)
        self.infobar.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
        self.infobar.hide()
        self.text_vbox.pack_start(self.infobar, False, False, 0)

        self.connect('realize', self.on_ui_realize)
        self.add_start(self.hpaned1)

    def on_ui_realize(self, widget):
        self.infobar.hide()
        self.update_source_model()
        self.list_selection.select_iter(self.list_model.get_iter_first())
        self.auto_backup_button.set_active(
            self.auto_backup_setting.get_value())
        self.auto_backup_button.connect('toggled',
                                        self.on_auto_backup_button_toggled)

    def set_infobar_backup_info(self, name, list_name):
        self.info_label.set_markup(
            _('You\'re viewing the backup "<b>%(backup_name)s</b>" for '
              '"<b>%(list_name)s</b>"') % {
                  'backup_name': name,
                  'list_name': list_name
              })

    def on_auto_backup_button_toggled(self, widget):
        self.auto_backup_setting.set_value(widget.get_active())

    def on_infobar_response(self, widget, response_id):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_path = model[iter][0]

            self.textview.set_path(list_path)
            self.textview.update_content()

            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

            self.infobar.hide()

    def on_selection_changed(self, selection):
        model, iter = selection.get_selected()

        if iter:
            self.textview.set_path(model[iter][0])
            self.update_sourceslist()
            self.update_backup_model()

    def update_source_model(self):
        model = self.list_model

        model.clear()

        model.append(('/etc/apt/sources.list', 'sources.list'))

        SOURCE_LIST_D = '/etc/apt/sources.list.d'

        if not os.path.exists(SOURCE_LIST_D):
            self.source_combo.set_active(0)
            return

        files = glob.glob(SOURCE_LIST_D + '/*.list')
        files.sort()

        for file in files:
            if os.path.isdir(file):
                continue
            model.append((file, os.path.basename(file)))

    def update_backup_model(self):
        def file_cmp(f1, f2):
            return cmp(os.stat(f1).st_ctime, os.stat(f2).st_ctime)

        model, iter = self.list_selection.get_selected()

        if iter:
            source_list = model[iter][0]

            self.backup_model.clear()

            files = glob.glob(source_list + '.*')
            files.sort(cmp=file_cmp, reverse=True)

            for path in files:
                if os.path.isdir(path):
                    continue
                self.backup_model.append((path, os.path.basename(path).split(
                    '.list.')[-1].split('.save')[0]))

            if not files:
                self.backup_model.append((None, _('No backup yet')))
                self.backup_edit_button.set_sensitive(False)
                self.backup_delete_button.set_sensitive(False)
                self.recover_button.set_sensitive(False)
                self.backup_view_button.set_sensitive(False)
                self.infobar.hide()
            elif self._authenticated == True:
                self.backup_edit_button.set_sensitive(True)
                self.backup_delete_button.set_sensitive(True)
                self.recover_button.set_sensitive(True)
                self.backup_view_button.set_sensitive(True)

            self.backup_combobox.set_active(0)

    def on_source_combo_changed(self, widget):
        model = widget.get_model()
        iter = widget.get_active_iter()

        if self.has_backup_value(iter):
            self.textview.set_path(model.get_value(iter, 0))
            self.update_sourceslist()

    def on_update_button_clicked(self, widget):
        self.set_busy()
        daemon = AptWorker(widget.get_toplevel(),
                           lambda t, s, d: self.unset_busy())
        daemon.update_cache()

    def update_sourceslist(self):
        self.textview.update_content()
        self.redo_button.set_sensitive(False)
        self.save_button.set_sensitive(False)

    def on_save_button_clicked(self, widget):
        text = self.textview.get_text().strip()

        if self.auto_backup_setting.get_value():
            proxy.backup_source(self.textview.get_path(),
                                self.get_time_stamp())
            self.update_backup_model()

        if proxy.edit_source(self.textview.get_path(), text) == 'error':
            ErrorDialog(message=_('Please check the permission of the '
                                  'sources.list file'),
                        title=_('Save failed!')).launch()
        else:
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

    def on_recover_button_clicked(self, widget):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_path = model[iter][0]
            list_name = model[iter][1]

            backup_iter = self.backup_combobox.get_active_iter()

            if backup_iter:
                backup_path = self.backup_model[backup_iter][0]
                backup_name = self.backup_model[backup_iter][1]

                dialog = QuestionDialog(message=_('Would you like to recover the '
                                        'backup "<b>%(backup_name)s</b>" for "<b>%(list_name)s</b>"?') % \
                                                {'backup_name': backup_name,
                                                 'list_name': list_name})
                response = dialog.run()
                dialog.destroy()

                if response == Gtk.ResponseType.YES:
                    if proxy.restore_source(backup_path, list_path):
                        self.infobar.response(Gtk.ResponseType.CLOSE)
                    else:
                        ErrorDialog(title=_('Recovery Failed!'),
                                    message=_(
                                        'You may need to check the permission '
                                        'of source list.')).launch()

    def on_backup_view_button_clicked(self, widget=None):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_name = model[iter][1]

            iter = self.backup_combobox.get_active_iter()

            if self.has_backup_value(iter):
                name = self.backup_model[iter][1]
                self.set_infobar_backup_info(name, list_name)

                self.textview.set_path(self.backup_model[iter][0])
                self.textview.update_content()
                self.save_button.set_sensitive(False)
                self.redo_button.set_sensitive(False)

                self.infobar.show()

    def on_backup_combobox_changed(self, widget):
        if self.infobar.get_visible():
            self.on_backup_view_button_clicked()

    def on_backup_button_clicked(self, widget):
        model, iter = self.list_selection.get_selected()

        if iter:
            path = model[iter][0]

            dialog = GetTextDialog(
                message=_('Please enter the name for your backup:'),
                text=self.get_time_stamp())
            response = dialog.run()
            dialog.destroy()
            backup_name = dialog.get_text()

            if response == Gtk.ResponseType.YES and backup_name:
                if self.is_valid_backup_name(backup_name):
                    if proxy.backup_source(path, backup_name):
                        self.update_backup_model()
                    else:
                        ErrorDialog(message=_('Backup Failed!')).launch()
                else:
                    ErrorDialog(message=_(
                        'Please only use alphanumeric characters'
                        ' and "_" and "-".'),
                                title=_('Backup name is invalid')).launch()

    def on_backup_delete_button_clicked(self, widget):
        iter = self.backup_combobox.get_active_iter()
        path = self.backup_model[iter][0]

        dialog = QuestionDialog(
            message=_('Would you like to delete the backup '
                      '"<b>%s</b>"?') % os.path.basename(path))
        response = dialog.run()
        dialog.destroy()

        if response == Gtk.ResponseType.YES:
            proxy.delete_source(path)
            self.update_backup_model()

    def on_backup_edit_button_clicked(self, widget):
        iter = self.backup_combobox.get_active_iter()
        path = self.backup_model[iter][0]
        name = self.backup_model[iter][1]

        dialog = GetTextDialog(
            message=_('Please enter a new name for your backup:'), text=name)
        response = dialog.run()
        dialog.destroy()
        new_name = dialog.get_text()

        if response == Gtk.ResponseType.YES and new_name and name != new_name:
            if self.is_valid_backup_name(new_name):
                proxy.rename_backup(path, name, new_name)
                self.update_backup_model()
            else:
                ErrorDialog(message=_('Please only use alphanumeric characters'
                                      ' and "_" and "-".'),
                            title=_('Backup name is invalid')).launch()

    def on_redo_button_clicked(self, widget):
        dialog = QuestionDialog(message=_(
            'The current content will be lost after reloading!\nDo you wish to continue?'
        ))
        if dialog.run() == Gtk.ResponseType.YES:
            self.textview.update_content()
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

        dialog.destroy()

    def on_buffer_changed(self, buffer):
        if buffer.get_modified():
            self.save_button.set_sensitive(True)
            self.redo_button.set_sensitive(True)
        else:
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

    def on_delete_button_clicked(self, widget):
        if self.textview.get_path() == SOURCES_LIST:
            ErrorDialog(_('You can\'t delete sources.list!')).launch()
        else:
            dialog = QuestionDialog(message=_(
                'The "%s" will be deleted!\nDo you wish to continue?') %
                                    self.textview.get_path())
            response = dialog.run()
            dialog.destroy()
            if response == Gtk.ResponseType.YES:
                model, iter = self.list_selection.get_selected()

                if iter:
                    list_path = model[iter][0]
                    proxy.delete_source(list_path)
                    self.update_source_model()
                    self.update_backup_model()

    def on_polkit_action(self, widget):
        self._authenticated = True
        self.textview.set_sensitive(True)
        self.delete_button.set_sensitive(True)
        self.recover_button.set_sensitive(True)
        self.backup_button.set_sensitive(True)
        self.backup_edit_button.set_sensitive(True)
        self.backup_delete_button.set_sensitive(True)
        self.backup_view_button.set_sensitive(True)

    def is_valid_backup_name(self, name):
        pattern = re.compile('[\w\-]+')

        match = pattern.search(name)

        return match and name == match.group()

    def has_backup_value(self, iter):
        return iter and self.backup_model[iter][0]

    def get_time_stamp(self):
        return time.strftime('%Y-%m-%d-%H-%M', time.localtime(time.time()))
Exemplo n.º 22
0
class UbuntuTweakWindow(GuiBuilder):
    current_feature = "overview"
    feature_dict = {}
    navigation_dict = {"tweaks": [None, None]}
    # the module name and page index: 'Compiz': 2
    loaded_modules = {}
    # reversed dict: 2: 'CompizClass'
    modules_index = {}

    def __init__(self, feature="", module=""):
        GuiBuilder.__init__(self, file_name="mainwindow.ui")

        tweaks_page = FeaturePage("tweaks")
        admins_page = FeaturePage("admins")
        clip_page = ClipPage()
        apps_page = AppsPage()
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.rencently_used_settings = GSetting("com.ubuntu-tweak.tweak.rencently-used")

        self.feature_dict["overview"] = self.notebook.append_page(clip_page, Gtk.Label())
        self.feature_dict["apps"] = self.notebook.append_page(apps_page, Gtk.Label())
        self.feature_dict["tweaks"] = self.notebook.append_page(tweaks_page, Gtk.Label())
        self.feature_dict["admins"] = self.notebook.append_page(admins_page, Gtk.Label())
        self.feature_dict["janitor"] = self.notebook.append_page(janitor_page, Gtk.Label())
        self.feature_dict["wait"] = self.notebook.append_page(self._crete_wait_page(), Gtk.Label())

        # Always show welcome page at first
        self.mainwindow.connect("realize", self._initialize_ui_states)
        tweaks_page.connect("module_selected", self.on_module_selected)
        admins_page.connect("module_selected", self.on_module_selected)
        clip_page.connect("load_module", lambda widget, name: self.do_load_module(name))
        clip_page.connect("load_feature", lambda widget, name: self.select_target_feature(name))
        self.mainwindow.show()
        self.link_button.hide()

        if module:
            self.do_load_module(module)
        elif feature:
            self.select_target_feature(feature)

    # TODO remove when natty is deprecated
    def on_header_button_press_event(self, widget, event):
        self.mainwindow.begin_move_drag(event.button, event.x_root, event.y_root, event.time)

    def get_module_and_index(self, name):
        index = self.loaded_modules[name]

        return self.modules_index[index], index

    def select_target_feature(self, text):
        toggle_button = getattr(self, "%s_button" % text, None)
        log.info("select_target_feature: %s" % text)
        if toggle_button:
            self.current_feature = text
            toggle_button.set_active(True)

    def _initialize_ui_states(self, widget):
        # TODO implement the search feature
        self.window_size_setting = GSetting("com.ubuntu-tweak.tweak.window-size")
        width, height = self.window_size_setting.get_value()
        if width >= 800 and height >= 480:
            self.mainwindow.set_default_size(width, height)

        self.search_entry.hide()

    def _crete_wait_page(self):
        vbox = Gtk.VBox()

        label = Gtk.Label()
        label.set_markup('<span size="xx-large">%s</span>' % _("Please wait a moment..."))
        label.set_justify(Gtk.Justification.FILL)
        vbox.pack_start(label, False, False, 50)
        hbox = Gtk.HBox()
        vbox.pack_start(hbox, False, False, 0)

        vbox.show_all()

        return vbox

    def on_mainwindow_destroy(self, widget):
        allocation = widget.get_allocation()
        self.window_size_setting.set_value((allocation.width, allocation.height))

        Gtk.main_quit()
        try:
            proxy.exit()
        except Exception, e:
            log.error(e)
Exemplo n.º 23
0
class SourceEditor(TweakModule):
    __title__ = _('Source Editor')
    __desc__ = _('Manually edit your software sources to suit your needs.')
    __icon__ = 'system-software-update'
    __category__ = 'system'

    def __init__(self):
        TweakModule.__init__(self, 'sourceeditor.ui')

        self.auto_backup_setting = GSetting('com.ubuntu-tweak.tweak.auto-backup')

        self.textview = SourceView(SOURCES_LIST)
        self.textview.set_sensitive(False)
        self.sw1.add(self.textview)
        self.textview.get_buffer().connect('changed', self.on_buffer_changed)

        un_lock = PolkitButton(PK_ACTION_SOURCE)
        un_lock.connect('authenticated', self.on_polkit_action)
        self._authenticated = False
        self.hbuttonbox2.pack_end(un_lock, False, False, 0)

        self.list_selection = self.list_view.get_selection()
        self.list_selection.connect("changed", self.on_selection_changed)

        self.infobar = Gtk.InfoBar()
        self.info_label = Gtk.Label('Current view the list')
        self.info_label.set_alignment(0, 0.5)
        self.infobar.get_content_area().add(self.info_label)
        self.infobar.connect("response", self.on_infobar_response)
        self.infobar.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
        self.infobar.hide()
        self.text_vbox.pack_start(self.infobar, False, False, 0)

        self.connect('realize', self.on_ui_realize)
        self.add_start(self.hbox1)

    def on_ui_realize(self, widget):
        self.infobar.hide()
        self.update_source_model()
        self.list_selection.select_iter(self.list_model.get_iter_first())
        self.auto_backup_button.set_active(self.auto_backup_setting.get_value())
        self.auto_backup_button.connect('toggled', self.on_auto_backup_button_toggled)

    def set_infobar_backup_info(self, name, list_name):
        self.info_label.set_markup(_('You\'re viewing the backup "<b>%s</b>" for'
                                   '"<b>%s</b>"') % (name, list_name))

    def on_auto_backup_button_toggled(self, widget):
        self.auto_backup_setting.set_value(widget.get_active())

    def on_infobar_response(self, widget, response_id):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_path = model[iter][0]

            self.textview.set_path(list_path)
            self.textview.update_content()

            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

            self.infobar.hide()

    def on_selection_changed(self, selection):
        model, iter = selection.get_selected()

        if iter:
            self.textview.set_path(model[iter][0])
            self.update_sourceslist()
            self.update_backup_model()

    def update_source_model(self):
        model = self.list_model

        model.clear()

        model.append(('/etc/apt/sources.list', 'sources.list'))

        SOURCE_LIST_D = '/etc/apt/sources.list.d'

        if not os.path.exists(SOURCE_LIST_D):
            self.source_combo.set_active(0)
            return

        files = glob.glob(SOURCE_LIST_D + '/*.list')
        files.sort()

        for file in files:
            if os.path.isdir(file):
                continue
            model.append((file, os.path.basename(file)))

    def update_backup_model(self):
        def file_cmp(f1, f2):
            return cmp(os.stat(f1).st_ctime, os.stat(f2).st_ctime)

        model, iter = self.list_selection.get_selected()

        if iter:
            source_list = model[iter][0]

            self.backup_model.clear()

            files = glob.glob(source_list + '.*')
            files.sort(cmp=file_cmp, reverse=True)

            for path in files:
                if os.path.isdir(path):
                    continue
                self.backup_model.append((path,
                    os.path.basename(path).split('.list.')[-1].split('.save')[0]))

            if not files:
                self.backup_model.append((None, _('No backup yet')))
                self.backup_edit_button.set_sensitive(False)
                self.backup_delete_button.set_sensitive(False)
                self.recover_button.set_sensitive(False)
                self.backup_view_button.set_sensitive(False)
                self.infobar.hide()
            elif self._authenticated == True:
                self.backup_edit_button.set_sensitive(True)
                self.backup_delete_button.set_sensitive(True)
                self.recover_button.set_sensitive(True)
                self.backup_view_button.set_sensitive(True)

            self.backup_combobox.set_active(0)

    def on_source_combo_changed(self, widget):
        model = widget.get_model()
        iter = widget.get_active_iter()

        if self.has_backup_value(iter):
            self.textview.set_path(model.get_value(iter, 0))
            self.update_sourceslist()

    def on_update_button_clicked(self, widget):
        self.set_busy()
        daemon = AptWorker(widget.get_toplevel(), lambda t, s, d: self.unset_busy())
        daemon.update_cache()

    def update_sourceslist(self):
        self.textview.update_content()
        self.redo_button.set_sensitive(False)
        self.save_button.set_sensitive(False)

    def on_save_button_clicked(self, widget):
        text = self.textview.get_text().strip()

        if self.auto_backup_setting.get_value():
            proxy.backup_source(self.textview.get_path(), self.get_time_stamp())
            self.update_backup_model()

        if proxy.edit_source(self.textview.get_path(), text) == 'error':
            ErrorDialog(message=_('Please check the permission of the '
                                  'sources.list file'),
                        title=_('Save failed!')).launch()
        else:
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

    def on_recover_button_clicked(self, widget):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_path = model[iter][0]
            list_name = model[iter][1]

            backup_iter = self.backup_combobox.get_active_iter()

            if backup_iter:
                backup_path = self.backup_model[backup_iter][0]
                backup_name = self.backup_model[backup_iter][1]

                dialog = QuestionDialog(message=_('Would you like to recover the '
                                        'backup "<b>%s</b>" for "<b>%s</b>"?') % (
                                backup_name, list_name))
                response = dialog.run()
                dialog.destroy()

                if response == Gtk.ResponseType.YES:
                    if proxy.restore_source(backup_path, list_path):
                        self.infobar.response(Gtk.ResponseType.CLOSE)
                    else:
                        ErrorDialog(title=_('Recovery Failed!'),
                                   message=_('You may need to check the permission '
                                             'of source list.')).launch()

    def on_backup_view_button_clicked(self, widget=None):
        model, iter = self.list_selection.get_selected()

        if iter:
            list_name = model[iter][1]

            iter = self.backup_combobox.get_active_iter()

            if self.has_backup_value(iter):
                name = self.backup_model[iter][1]
                self.set_infobar_backup_info(name, list_name)

                self.textview.set_path(self.backup_model[iter][0])
                self.textview.update_content()
                self.save_button.set_sensitive(False)
                self.redo_button.set_sensitive(False)

                self.infobar.show()

    def on_backup_combobox_changed(self, widget):
        if self.infobar.get_visible():
            self.on_backup_view_button_clicked()

    def on_backup_button_clicked(self, widget):
        model, iter = self.list_selection.get_selected()

        if iter:
            path = model[iter][0]

            dialog = GetTextDialog(message=_('Please enter the name for your backup:'),
                                   text=self.get_time_stamp())
            response = dialog.run()
            dialog.destroy()
            backup_name = dialog.get_text()

            if response == Gtk.ResponseType.YES and backup_name:
                if self.is_valid_backup_name(backup_name):
                    if proxy.backup_source(path, backup_name):
                        self.update_backup_model()
                    else:
                        ErrorDialog(message=_('Backup Failed!')).launch()
                else:
                    ErrorDialog(message=_('Please only use alphanumeric characters'
                                        ' and "_" and "-".'),
                                title=_('Backup name is invalid')).launch()

    def on_backup_delete_button_clicked(self, widget):
        iter = self.backup_combobox.get_active_iter()
        path = self.backup_model[iter][0]

        dialog = QuestionDialog(message=_('Would you like to delete the backup:'
                                          '<b>%s</b>?') % os.path.basename(path))
        response = dialog.run()
        dialog.destroy()

        if response == Gtk.ResponseType.YES:
            proxy.delete_source(path)
            self.update_backup_model()

    def on_backup_edit_button_clicked(self, widget):
        iter = self.backup_combobox.get_active_iter()
        path = self.backup_model[iter][0]
        name = self.backup_model[iter][1]

        dialog = GetTextDialog(message=_('Please enter a new name for your backup:'),
                               text=name)
        response = dialog.run()
        dialog.destroy()
        new_name = dialog.get_text()

        if response == Gtk.ResponseType.YES and new_name and name != new_name:
            if self.is_valid_backup_name(new_name):
                proxy.rename_backup(path, name, new_name)
                self.update_backup_model()
            else:
                ErrorDialog(message=_('Please only use alphanumeric characters'
                                    ' and "_" and "-".'),
                            title=_('Backup name is invalid')).launch()

    def on_redo_button_clicked(self, widget):
        dialog = QuestionDialog(message=_('The current content will be lost after reloading!\nDo you wish to continue?'))
        if dialog.run() == Gtk.ResponseType.YES:
            self.textview.update_content()
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

        dialog.destroy()

    def on_buffer_changed(self, buffer):
        if buffer.get_modified():
            self.save_button.set_sensitive(True)
            self.redo_button.set_sensitive(True)
        else:
            self.save_button.set_sensitive(False)
            self.redo_button.set_sensitive(False)

    def on_delete_button_clicked(self, widget):
        if self.textview.get_path() ==  SOURCES_LIST:
            ErrorDialog(_('You can\'t delete sources.list!')).launch()
        else:
            dialog = QuestionDialog(message=_('The "%s" will be deleted!\nDo you wish to continue?') % self.textview.get_path())
            response = dialog.run()
            dialog.destroy()
            if response == Gtk.ResponseType.YES:
                model, iter = self.list_selection.get_selected()

                if iter:
                    list_path = model[iter][0]
                    proxy.delete_source(list_path)
                    self.update_source_model()
                    self.update_backup_model()

    def on_polkit_action(self, widget):
        self._authenticated = True
        self.textview.set_sensitive(True)
        self.delete_button.set_sensitive(True)
        self.recover_button.set_sensitive(True)
        self.backup_button.set_sensitive(True)
        self.backup_edit_button.set_sensitive(True)
        self.backup_delete_button.set_sensitive(True)
        self.backup_view_button.set_sensitive(True)

    def is_valid_backup_name(self, name):
        pattern = re.compile('[\w\-]+')

        match = pattern.search(name)

        return match and name == match.group()

    def has_backup_value(self, iter):
        return iter and self.backup_model[iter][0]

    def get_time_stamp(self):
        return time.strftime('%Y-%m-%d-%H-%M', time.localtime(time.time()))
Exemplo n.º 24
0
class JanitorPage(Gtk.VBox, GuiBuilder):
    (JANITOR_CHECK, JANITOR_ICON, JANITOR_NAME, JANITOR_DISPLAY,
     JANITOR_PLUGIN, JANITOR_SPINNER_ACTIVE, JANITOR_SPINNER_PULSE) = range(7)

    (RESULT_CHECK, RESULT_ICON, RESULT_NAME, RESULT_DISPLAY, RESULT_DESC,
     RESULT_PLUGIN, RESULT_CRUFT) = range(7)

    max_janitor_view_width = 0

    def __init__(self):
        GObject.GObject.__init__(self)

        self.scan_tasks = []
        self.clean_tasks = []
        self._total_count = 0

        self.set_border_width(6)
        GuiBuilder.__init__(self, 'janitorpage.ui')

        self.autoscan_setting = GSetting('com.ubuntu-tweak.janitor.auto-scan')
        self.autoscan_setting.connect_notify(self.on_autoscan_button_toggled)
        self.plugins_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.view_width_setting = GSetting(
            'com.ubuntu-tweak.janitor.janitor-view-width')

        self.pack_start(self.vbox1, True, True, 0)

        self.connect('realize', self.setup_ui_tasks)
        self.janitor_view.get_selection().connect(
            'changed', self.on_janitor_selection_changed)
        self.plugins_setting.connect_notify(self.update_model, True)

        self.show()

    def on_move_handle(self, widget, gproperty):
        log.debug("on_move_handle: %d", widget.get_property('position'))
        self.view_width_setting.set_value(widget.get_property('position'))

        # cancel the size request, or it will fail to resize
        # TODO why the first scan will make it fail?
        self.janitor_view.set_size_request(self.max_janitor_view_width, -1)

    def is_auto_scan(self):
        return self.autoscan_setting.get_value()

    @log_func(log)
    def on_result_view_row_activated(self, treeview, path, column):
        iter = self.result_model.get_iter(path)
        cruft = self.result_model[iter][self.RESULT_CRUFT]
        display = self.result_model[iter][self.RESULT_DISPLAY]

        if 'red' in display:
            plugin = self.result_model[iter][self.RESULT_PLUGIN]
            error = plugin.get_property('error')
            self.result_model[iter][
                self.
                RESULT_DISPLAY] = '<span color="red"><b>%s</b></span>' % error
        elif hasattr(cruft, 'get_path'):
            path = cruft.get_path()
            if not os.path.isdir(path):
                path = os.path.dirname(path)
            os.system("xdg-open '%s' &" % path)

    def setup_ui_tasks(self, widget):
        self.janitor_model.set_sort_column_id(self.JANITOR_NAME,
                                              Gtk.SortType.ASCENDING)

        #add janitor columns
        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_janitor_check_button_toggled)
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active', self.JANITOR_CHECK)

        self.janitor_view.append_column(janitor_column)

        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererPixbuf()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'pixbuf', self.JANITOR_ICON)
        janitor_column.set_cell_data_func(renderer, self.icon_column_view_func,
                                          self.JANITOR_ICON)

        renderer = Gtk.CellRendererText()
        renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
        janitor_column.pack_start(renderer, True)
        janitor_column.add_attribute(renderer, 'markup', self.JANITOR_DISPLAY)

        renderer = Gtk.CellRendererSpinner()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active',
                                     self.JANITOR_SPINNER_ACTIVE)
        janitor_column.add_attribute(renderer, 'pulse',
                                     self.JANITOR_SPINNER_PULSE)

        self.janitor_view.append_column(janitor_column)
        #end janitor columns

        #new result columns
        result_display_renderer = self.builder.get_object(
            'result_display_renderer')
        result_display_renderer.set_property('ellipsize',
                                             Pango.EllipsizeMode.END)
        result_icon_renderer = self.builder.get_object('result_icon_renderer')
        self.result_column.set_cell_data_func(result_icon_renderer,
                                              self.icon_column_view_func,
                                              self.RESULT_ICON)
        #end new result columns

        auto_scan = self.autoscan_setting.get_value()
        log.info("Auto scan status: %s", auto_scan)

        self.scan_button.set_visible(not auto_scan)

        self.update_model()

        self._expand_janitor_view()

        self.hpaned1.connect('notify::position', self.on_move_handle)

    def _expand_janitor_view(self):
        self.janitor_view.expand_all()

        left_view_width = self.view_width_setting.get_value()
        log.debug("left_view_width is: %d, max_janitor_view_width is: %d" %
                  (left_view_width, self.max_janitor_view_width))

        if left_view_width:
            self.janitor_view.set_size_request(left_view_width, -1)
        elif self.max_janitor_view_width:
            self.janitor_view.set_size_request(self.max_janitor_view_width, -1)

    def set_busy(self):
        self.get_parent_window().set_cursor(
            Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def unset_busy(self):
        self.get_parent_window().set_cursor(None)

    def on_janitor_selection_changed(self, selection):
        model, iter = selection.get_selected()
        if iter:
            if self.janitor_model.iter_has_child(iter):
                iter = self.janitor_model.iter_children(iter)

            plugin = model[iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_view.get_selection().select_path(row.path)
                    log.debug("scroll_to_cell: %s" % row.path)
                    self.result_view.scroll_to_cell(row.path)

    def _is_scanning_or_cleaning(self):
        for row in self.janitor_model:
            for child_row in row.iterchildren():
                if child_row[self.JANITOR_SPINNER_ACTIVE]:
                    return True
        else:
            return False

    def on_janitor_check_button_toggled(self, cell, path):
        self.result_view.show()
        self.happy_box.hide()

        iter = self.janitor_model.get_iter(path)

        if self._is_scanning_or_cleaning():
            return

        checked = not self.janitor_model[iter][self.JANITOR_CHECK]

        if self.janitor_model.iter_has_child(iter):
            child_iter = self.janitor_model.iter_children(iter)
            while child_iter:
                self.janitor_model[child_iter][self.JANITOR_CHECK] = checked

                child_iter = self.janitor_model.iter_next(child_iter)

        self.janitor_model[iter][self.JANITOR_CHECK] = checked

        self._check_child_is_all_the_same(self.janitor_model, iter,
                                          self.JANITOR_CHECK, checked)

        if self.is_auto_scan():
            self._auto_scan_cruft(iter, checked)

    def _update_clean_button_sensitive(self):
        self.clean_button.set_sensitive(False)

        for row in self.result_model:
            for child_row in row.iterchildren():
                if child_row[self.RESULT_CHECK]:
                    self.clean_button.set_sensitive(True)
                    break

    def on_result_check_renderer_toggled(self, cell, path):
        iter = self.result_model.get_iter(path)
        checked = self.result_model[iter][self.RESULT_CHECK]

        if self._is_scanning_or_cleaning():
            return

        if self.result_model.iter_has_child(iter):
            child_iter = self.result_model.iter_children(iter)
            while child_iter:
                self.result_model[child_iter][self.RESULT_CHECK] = not checked

                child_iter = self.result_model.iter_next(child_iter)

        self.result_model[iter][self.RESULT_CHECK] = not checked

        self._check_child_is_all_the_same(self.result_model, iter,
                                          self.RESULT_CHECK, not checked)

        self._update_clean_button_sensitive()

    def _check_child_is_all_the_same(self, model, iter, column_id, status):
        iter = model.iter_parent(iter)

        if iter:
            child_iter = model.iter_children(iter)

            while child_iter:
                if status != model[child_iter][column_id]:
                    model[iter][column_id] = False
                    break
                child_iter = model.iter_next(child_iter)
            else:
                model[iter][column_id] = status

    def on_scan_button_clicked(self, widget=None):
        self.result_model.clear()
        self.clean_button.set_sensitive(False)

        scan_dict = OrderedDict()

        for row in self.janitor_model:
            for child_row in row.iterchildren():
                checked = child_row[self.JANITOR_CHECK]

                scan_dict[child_row.iter] = checked

        self.scan_tasks = list(scan_dict.items())
        self._total_count = 0
        self.result_view.show()
        self.happy_box.hide()

        self.set_busy()
        self.do_scan_task()

    def _auto_scan_cruft(self, iter, checked):
        self.set_busy()

        scan_dict = OrderedDict()

        if self.janitor_model.iter_has_child(iter):
            log.info('Scan cruft for all plugins')
            #Scan cruft for children
            child_iter = self.janitor_model.iter_children(iter)

            while child_iter:
                scan_dict[child_iter] = checked
                child_iter = self.janitor_model.iter_next(child_iter)
        else:
            scan_dict[iter] = checked

        self.scan_tasks = list(scan_dict.items())

        for plugin_iter, checked in self.scan_tasks:
            plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_model.remove(row.iter)

        self.do_scan_task()

    def do_scan_task(self):
        plugin_iter, checked = self.scan_tasks.pop(0)

        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        plugin.set_property('scan_finished', False)

        log.debug("do_scan_task for %s for status: %s" % (plugin, checked))

        if checked:
            log.info('Scan cruft for plugin: %s' % plugin.get_name())

            iter = self.result_model.append(
                None, (None, None, plugin.get_title(), '<b>%s</b>' %
                       _('Scanning cruft for "%s"...') % plugin.get_title(),
                       None, plugin, None))

            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_ACTIVE] = True
            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] = 0
            self.janitor_view.scroll_to_cell(
                self.janitor_model.get_path(plugin_iter))

            self._find_handler = plugin.connect('find_object',
                                                self.on_find_object,
                                                (plugin_iter, iter))
            self._scan_handler = plugin.connect('scan_finished',
                                                self.on_scan_finished,
                                                (plugin_iter, iter))
            self._error_handler = plugin.connect('scan_error',
                                                 self.on_scan_error,
                                                 (plugin_iter, iter))

            t = threading.Thread(target=plugin.get_cruft)
            GObject.timeout_add(50, self._on_spinner_timeout, plugin_iter, t)

            t.start()
        else:
            # Update the janitor title
            for row in self.janitor_model:
                for child_row in row.iterchildren():
                    if child_row[self.JANITOR_PLUGIN] == plugin:
                        child_row[self.JANITOR_DISPLAY] = plugin.get_title()

            if self.scan_tasks:
                self.do_scan_task()
            else:
                if self._total_count == 0:
                    self.result_view.hide()
                    self.happy_box.show()
                else:
                    self.result_view.show()
                    self.happy_box.hide()

                self.unset_busy()

    def _on_spinner_timeout(self, plugin_iter, thread):
        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        finished = plugin.get_property('scan_finished')

        self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] += 1

        if finished:
            for handler in (self._find_handler, self._scan_handler,
                            self._error_handler):
                if plugin.handler_is_connected(handler):
                    log.debug(
                        "Disconnect the cleaned signal, or it will clean many times: %s"
                        % plugin)
                    plugin.disconnect(handler)

            self.janitor_model[plugin_iter][
                self.JANITOR_SPINNER_ACTIVE] = False

            thread.join()

            if len(self.scan_tasks) != 0:
                log.debug("Pending scan tasks: %d" % len(self.scan_tasks))
                self.do_scan_task()
            else:
                log.debug("total_count is: %d" % self._total_count)
                if self._total_count == 0:
                    self.result_view.hide()
                    self.happy_box.show()
                else:
                    self.result_view.show()
                    self.happy_box.hide()

                self.unset_busy()

        return not finished

    @post_ui
    def on_find_object(self, plugin, cruft, count, iters):
        while Gtk.events_pending():
            Gtk.main_iteration()

        plugin_iter, result_iter = iters

        self.result_model.append(
            result_iter,
            (False, cruft.get_icon(), cruft.get_name(), cruft.get_name(),
             cruft.get_size_display(), plugin, cruft))

        self.result_view.expand_row(self.result_model.get_path(result_iter),
                                    True)

        # Update the janitor title
        if count:
            self.janitor_model[plugin_iter][
                self.JANITOR_DISPLAY] = "<b>[%d] %s</b>" % (count,
                                                            plugin.get_title())
        else:
            self.janitor_model[plugin_iter][
                self.JANITOR_DISPLAY] = "[0] %s" % plugin.get_title()

    @post_ui
    def on_scan_finished(self, plugin, result, count, size, iters):
        plugin.disconnect(self._find_handler)
        plugin.disconnect(self._scan_handler)
        plugin.set_property('scan_finished', True)

        plugin_iter, result_iter = iters

        if count == 0:
            self.result_model.remove(result_iter)
        else:
            self.result_model[result_iter][
                self.RESULT_DISPLAY] = "<b>%s</b>" % plugin.get_summary(count)
            if size != 0:
                self.result_model[result_iter][
                    self.RESULT_DESC] = "<b>%s</b>" % filesizeformat(size)

        # Update the janitor title
        self._total_count += count

        if count:
            self.janitor_model[plugin_iter][
                self.JANITOR_DISPLAY] = "<b>[%d] %s</b>" % (count,
                                                            plugin.get_title())
            self.result_view.collapse_row(
                self.result_model.get_path(result_iter))
        else:
            self.janitor_model[plugin_iter][
                self.JANITOR_DISPLAY] = "[0] %s" % plugin.get_title()

    @post_ui
    def on_scan_error(self, plugin, error, iters):
        plugin_iter, result_iter = iters

        self.janitor_model[plugin_iter][
            self.JANITOR_ICON] = icon.get_from_name('error', size=16)
        self.result_model[result_iter][
            self.RESULT_DISPLAY] = '<span color="red"><b>%s</b></span>' % _(
                'Scan error for "%s", double-click to see details'
            ) % plugin.get_title()

        plugin.set_property('scan_finished', True)
        plugin.set_property('error', error)

    @inline_callbacks
    def on_clean_button_clicked(self, widget):
        '''plugin_dict: {plugin: {cruft: iter}}'''
        try:
            yield PolkitAction(PK_ACTION_CLEAN).do_authenticate()
        except Exception, e:
            log.debug(e)
            return

        self.plugin_to_run = 0

        self.set_busy()
        self.clean_button.set_sensitive(False)

        plugin_dict = OrderedDict()

        for row in self.result_model:
            plugin = row[self.RESULT_PLUGIN]
            cruft_dict = OrderedDict()

            for child_row in row.iterchildren():
                checked = child_row[self.RESULT_CHECK]

                if checked:
                    cruft_dict[child_row[self.RESULT_CRUFT]] = child_row.iter

            if cruft_dict:
                plugin_dict[plugin] = cruft_dict

        self.clean_tasks = list(plugin_dict.items())

        self.do_real_clean_task()
        log.debug("All finished!")
Exemplo n.º 25
0
class UbuntuTweakWindow(GuiBuilder):
    current_feature = 'overview'
    feature_dict = {}
    navigation_dict = {'tweaks': [None, None]}
    # the module name and page index: 'Compiz': 2
    loaded_modules = {}
    # reversed dict: 2: 'CompizClass'
    modules_index = {}

    def __init__(self, feature='', module='', splash_window=None):
        GuiBuilder.__init__(self, file_name='mainwindow.ui')

        tweaks_page = FeaturePage('tweaks')
        admins_page = FeaturePage('admins')
        self.no_result_box.label = self.result_text
        self.search_page = SearchPage(self.no_result_box)
        clip_page = ClipPage()
        self.apps_page = AppsPage(self.back_button, self.next_button)
        janitor_page = JanitorPage()
        self.preferences_dialog = PreferencesDialog(self.mainwindow)

        self.recently_used_settings = GSetting('com.ubuntu-tweak.tweak.recently-used')

        self.feature_dict['overview'] = self.notebook.append_page(clip_page, Gtk.Label('overview'))
        self.feature_dict['apps'] = self.notebook.append_page(self.apps_page, Gtk.Label())
        self.feature_dict['tweaks'] = self.notebook.append_page(tweaks_page, Gtk.Label('tweaks'))
        self.feature_dict['admins'] = self.notebook.append_page(admins_page, Gtk.Label('admins'))
        self.feature_dict['janitor'] = self.notebook.append_page(janitor_page, Gtk.Label('janitor'))
        self.feature_dict['wait'] = self.notebook.append_page(self._crete_wait_page(),
                                                           Gtk.Label('wait'))
        self.feature_dict['search'] = self.notebook.append_page(self.search_page,
                                                           Gtk.Label('search'))

        # Always show welcome page at first
        self.mainwindow.connect('realize', self._initialize_ui_states, splash_window)
        self.back_button.connect('clicked', self.on_back_button_clicked)
        self.next_button.connect('clicked', self.on_next_button_clicked)
        tweaks_page.connect('module_selected', self.on_module_selected)
        self.search_page.connect('module_selected', self.on_module_selected)
        admins_page.connect('module_selected', self.on_module_selected)
        self.apps_page.connect('loaded', self.show_apps_page)
        clip_page.connect('load_module', lambda widget, name: self.do_load_module(name))
        clip_page.connect('load_feature', lambda widget, name: self.select_target_feature(name))

        self.mainwindow.show()

        if module:
            self.do_load_module(module)
        elif feature:
            self.select_target_feature(feature)

        accel_group = Gtk.AccelGroup()
        self.search_entry.add_accelerator('activate',
                                          accel_group,
                                          Gdk.KEY_f,
                                          Gdk.ModifierType.CONTROL_MASK,
                                          Gtk.AccelFlags.VISIBLE)
        self.mainwindow.add_accel_group(accel_group)
        thread.start_new_thread(self.preload_proxy_cache, ())

    def show_apps_page(self, widget):
        self.notebook.set_current_page(self.feature_dict['apps'])

    def preload_proxy_cache(self):
        #This function just called to make sure the cache is loaded as soon as possible
        proxy.is_package_installed('ubuntu-tweak')

    def on_search_entry_activate(self, widget):
        widget.grab_focus()
        self.on_search_entry_changed(widget)

    def on_search_entry_changed(self, widget):
        text = widget.get_text()
        self.set_current_module(None, None)

        if text:
            self.notebook.set_current_page(self.feature_dict['search'])
            self.search_page.search(text)
            self.search_entry.set_property('secondary-icon-name', 'edit-clear')
        else:
            self.on_feature_button_clicked(getattr(self, '%s_button' % self.current_feature), self.current_feature)
            self.search_page.clean()
            self.search_entry.set_property('secondary-icon-name', 'edit-find')

    def on_search_entry_icon_press(self, widget, icon_pos, event):
        widget.set_text('')

    def get_module_and_index(self, name):
        index = self.loaded_modules[name]

        return self.modules_index[index], index

    def select_target_feature(self, text):
        toggle_button = getattr(self, '%s_button' % text, None)
        log.info("select_target_feature: %s" % text)
        if toggle_button:
            self.current_feature = text
            toggle_button.set_active(True)

    def _initialize_ui_states(self, widget, splash_window):
        self.window_size_setting = GSetting('com.ubuntu-tweak.tweak.window-size')
        width, height = self.window_size_setting.get_value()
        if width >= 900 and height >= 506:
            self.mainwindow.set_default_size(width, height)

        for feature_button in ('overview_button', 'apps_button', 'admins_button', \
                               'tweaks_button', 'janitor_button'):
            button = getattr(self, feature_button)

            label = button.get_child().get_label()
            button.get_child().set_markup('<b>%s</b>' % label)
            button.get_child().set_use_underline(True)
        splash_window.destroy()

    def _crete_wait_page(self):
        vbox = Gtk.VBox()

        label = Gtk.Label()
        label.set_markup("<span size=\"xx-large\">%s</span>" % \
                        _('Please wait a moment...'))
        label.set_justify(Gtk.Justification.FILL)
        vbox.pack_start(label, False, False, 50)
        hbox = Gtk.HBox()
        vbox.pack_start(hbox, False, False, 0)

        vbox.show_all()

        return vbox

    def on_mainwindow_destroy(self, widget=None):
        allocation = widget.get_allocation()
        self.window_size_setting.set_value((allocation.width, allocation.height))

        Gtk.main_quit()
        try:
            proxy.exit()
        except Exception, e:
            log.error(e)
Exemplo n.º 26
0
class FeaturePage(Gtk.ScrolledWindow):

    __gsignals__ = {
        'module_selected': (GObject.SignalFlags.RUN_FIRST,
                            None,
                            (GObject.TYPE_STRING,))
    }

    _categories = None
    _boxes = []

    def __str__(self):
        return '<FeaturePage: %s>' % self._feature

    def __init__(self, feature_name):
        GObject.GObject.__init__(self,
                                 hscrollbar_policy=Gtk.PolicyType.NEVER,
                                 vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
        self.set_property('shadow-type', Gtk.ShadowType.NONE)
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting('com.ubuntu-tweak.tweak.%s' % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport()
        viewport.set_property('shadow-type', Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        # TODO this will cause Bug #880663 randomly, as current there's no user extension for features, just disable it
#        self._setting.connect_notify(self.load_modules)

        self.show_all()

    def load_modules(self, *args, **kwargs):
        log.debug("Loading modules...")

        loader = ModuleLoader(self._feature)

        self._boxes = []
        for child in self._box.get_children():
            self._box.remove(child)

        for category, category_name in loader.get_categories():
            modules = loader.get_modules_by_category(category)
            if modules:
                module_to_loads = self._setting.get_value()

                for module in modules:
                    if module.is_user_extension() and module.get_name() not in module_to_loads:
                        modules.remove(module)

                category_box = CategoryBox(modules=modules, category_name=category_name)

                self._connect_signals(category_box)
                self._boxes.append(category_box)
                self._box.pack_start(category_box, False, False, 0)

        self.rebuild_boxes()

    def _connect_signals(self, category_box):
        for button in category_box.get_buttons():
            button.connect('clicked', self.on_button_clicked)

    def on_button_clicked(self, widget):
        log.info('Button clicked')
        module = widget.get_module()
        self.emit('module_selected', module.get_name())

    def rebuild_boxes(self, widget=None, event=None):
        request = self.get_allocation()
        ncols = request.width / 164 # 32 + 120 + 6 + 4
        width = ncols * (164 + 2 * 4) + 40
        if width > request.width:
            ncols -= 1

        pos = 0
        children = self._box.get_children()
        for box in self._boxes:
            modules = box.get_modules()
            if len (modules) == 0:
                if box in children:
                    self._box.remove(box)
            else:
                if box not in children:
                    self._box.pack_start(box, False, False, 0)
                    self._box.reorder_child(box, pos)
                box.rebuild_table(ncols)
                pos += 1
Exemplo n.º 27
0
class JanitorPage(Gtk.VBox, GuiBuilder):
    (JANITOR_CHECK,
     JANITOR_ICON,
     JANITOR_NAME,
     JANITOR_DISPLAY,
     JANITOR_PLUGIN,
     JANITOR_SPINNER_ACTIVE,
     JANITOR_SPINNER_PULSE) = range(7)

    (RESULT_CHECK,
     RESULT_ICON,
     RESULT_NAME,
     RESULT_DISPLAY,
     RESULT_DESC,
     RESULT_PLUGIN,
     RESULT_CRUFT) = range(7)

    max_janitor_view_width = 0

    def __init__(self):
        GObject.GObject.__init__(self)

        self.scan_tasks = []
        self.clean_tasks = []

        self.set_border_width(6)
        GuiBuilder.__init__(self, 'janitorpage.ui')

        self.autoscan_setting = GSetting('com.ubuntu-tweak.tweak.auto-scan')
        self.janitor_setting = GSetting('com.ubuntu-tweak.tweak.janitor')

        self.pack_start(self.vbox1, True, True, 0)

        self.connect('realize', self.setup_ui_tasks)
        self.janitor_view.get_selection().connect('changed', self.on_janitor_selection_changed)
        self.janitor_setting.connect_notify(self.update_model, True)
        self.show()

    def is_auto_scan(self):
        return self.autoscan_button.get_active()

    def setup_ui_tasks(self, widget):
        self.janitor_model.set_sort_column_id(self.JANITOR_NAME, Gtk.SortType.ASCENDING)

        #add janitor columns
        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_janitor_check_button_toggled)
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active', self.JANITOR_CHECK)

        self.janitor_view.append_column(janitor_column)

        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererPixbuf()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'pixbuf', self.JANITOR_ICON)
        janitor_column.set_cell_data_func(renderer,
                                          self.icon_column_view_func,
                                          self.JANITOR_ICON)

        renderer = Gtk.CellRendererText()
        renderer.set_property('ellipsize', Pango.EllipsizeMode.MIDDLE)
        janitor_column.pack_start(renderer, True)
        janitor_column.add_attribute(renderer, 'markup', self.JANITOR_DISPLAY)

        renderer = Gtk.CellRendererSpinner()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active', self.JANITOR_SPINNER_ACTIVE)
        janitor_column.add_attribute(renderer, 'pulse', self.JANITOR_SPINNER_PULSE)

        self.janitor_view.append_column(janitor_column)
        #end janitor columns

        #add result columns
        result_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_result_check_renderer_toggled)
        result_column.pack_start(renderer, False)
        result_column.add_attribute(renderer, 'active', self.RESULT_CHECK)

        renderer = Gtk.CellRendererPixbuf()
        result_column.pack_start(renderer, False)
        result_column.add_attribute(renderer, 'pixbuf', self.RESULT_ICON)
        result_column.set_cell_data_func(renderer,
                                         self.icon_column_view_func,
                                         self.RESULT_ICON)

        renderer = Gtk.CellRendererText()
        renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
        result_column.pack_start(renderer, True)
        result_column.add_attribute(renderer, 'markup', self.RESULT_DISPLAY)

        renderer = Gtk.CellRendererText()
        result_column.pack_start(renderer, False)
        result_column.add_attribute(renderer, 'text', self.RESULT_DESC)

        self.result_view.append_column(result_column)
        #end result columns

        auto_scan = self.autoscan_setting.get_value()
        log.info("Auto scan status: %s", auto_scan)

        self.scan_button.set_visible(not auto_scan)
        self.autoscan_button.set_active(auto_scan)

        self.update_model()

        self._expand_janitor_view()

    def _expand_janitor_view(self):
        self.janitor_view.expand_all()
        if self.max_janitor_view_width:
            self.janitor_view.set_size_request(self.max_janitor_view_width, -1)

    def set_busy(self):
        self.get_parent_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def unset_busy(self):
        self.get_parent_window().set_cursor(None)

    def on_janitor_selection_changed(self, selection):
        model, iter = selection.get_selected()
        if iter:
            if self.janitor_model.iter_has_child(iter):
                iter = self.janitor_model.iter_children(iter)

            plugin = model[iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_view.get_selection().select_path(row.path)
                    self.result_view.scroll_to_cell(row.path)

    def on_janitor_check_button_toggled(self, cell, path):
        iter = self.janitor_model.get_iter(path)

        for row in self.janitor_model:
            for child_row in row.iterchildren():
                if child_row[self.JANITOR_SPINNER_ACTIVE]:
                    return

        checked = not self.janitor_model[iter][self.JANITOR_CHECK]

        if self.janitor_model.iter_has_child(iter):
            child_iter = self.janitor_model.iter_children(iter)
            while child_iter:
                self.janitor_model[child_iter][self.JANITOR_CHECK] = checked

                child_iter = self.janitor_model.iter_next(child_iter)

        self.janitor_model[iter][self.JANITOR_CHECK] = checked

        self._check_child_is_all_the_same(self.janitor_model, iter,
                                         self.JANITOR_CHECK, checked)

        if self.is_auto_scan():
            self._auto_scan_cruft(iter, checked)

    def _update_clean_button_sensitive(self):
        self.clean_button.set_sensitive(False)

        for row in self.result_model:
            for child_row in row.iterchildren():
                if child_row[self.RESULT_CHECK]:
                    self.clean_button.set_sensitive(True)
                    break

    def on_result_check_renderer_toggled(self, cell, path):
        iter = self.result_model.get_iter(path)
        checked = self.result_model[iter][self.RESULT_CHECK]

        if self.result_model.iter_has_child(iter):
            child_iter = self.result_model.iter_children(iter)
            while child_iter:
                self.result_model[child_iter][self.RESULT_CHECK] = not checked

                child_iter = self.result_model.iter_next(child_iter)

        self.result_model[iter][self.RESULT_CHECK] = not checked

        self._check_child_is_all_the_same(self.result_model, iter,
                                         self.RESULT_CHECK, not checked)

        self._update_clean_button_sensitive()

    def _check_child_is_all_the_same(self, model, iter, column_id, status):
        iter = model.iter_parent(iter)

        if iter:
            child_iter = model.iter_children(iter)

            while child_iter:
                if status != model[child_iter][column_id]:
                    model[iter][column_id] = False
                    break
                child_iter = model.iter_next(child_iter)
            else:
                model[iter][column_id] = status

    def on_scan_button_clicked(self, widget=None):
        self.result_model.clear()
        self.clean_button.set_sensitive(False)

        scan_dict = OrderedDict()

        for row in self.janitor_model:
            for child_row in row.iterchildren():
                checked = child_row[self.JANITOR_CHECK]

                scan_dict[child_row.iter] = checked

        self.set_busy()
        self.scan_tasks = list(scan_dict.items())
        self.do_scan_task()

    def _auto_scan_cruft(self, iter, checked):
        self.set_busy()

        scan_dict = OrderedDict()

        if self.janitor_model.iter_has_child(iter):
            log.info('Scan cruft for all plugins')
            #Scan cruft for children
            child_iter = self.janitor_model.iter_children(iter)

            while child_iter:
                scan_dict[child_iter] = checked
                child_iter = self.janitor_model.iter_next(child_iter)
        else:
            scan_dict[iter] = checked

        self.scan_tasks = list(scan_dict.items())

        for plugin_iter, checked in self.scan_tasks:
            plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_model.remove(row.iter)

        self.do_scan_task()

    def do_scan_task(self):
        plugin_iter, checked = self.scan_tasks.pop(0)

        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        plugin.set_data('scan_finished', False)

        log.debug("do_scan_task for %s for status: %s" % (plugin, checked))

        if checked:
            log.info('Scan cruft for plugin: %s' % plugin.get_name())

            iter = self.result_model.append(None, (None,
                                                   None,
                                                   plugin.get_title(),
                                                   "<b>%s</b>" % plugin.get_title(),
                                                   None,
                                                   plugin,
                                                   None))

            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_ACTIVE] = True
            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] = 0

            self._find_handler = plugin.connect('find_object', self.on_find_object, iter)
            self._scan_handler = plugin.connect('scan_finished', self.on_scan_finished, iter)
            self._error_handler = plugin.connect('error', self.on_scan_error, plugin_iter)

            t = threading.Thread(target=plugin.get_cruft)
            GObject.timeout_add(50, self._on_spinner_timeout, plugin_iter, t)

            t.start()
        else:
            # Update the janitor title
            for row in self.janitor_model:
                for child_row in row.iterchildren():
                    if child_row[self.JANITOR_PLUGIN] == plugin:
                        child_row[self.JANITOR_DISPLAY] = plugin.get_title()

            if self.scan_tasks:
                self.do_scan_task()
            else:
                self.unset_busy()

    def _on_spinner_timeout(self, plugin_iter, thread):
        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        finished = plugin.get_data('scan_finished')

        self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] += 1

        if finished:
            for handler in (self._find_handler, self._scan_handler):
                if plugin.handler_is_connected(handler):
                    log.debug("Disconnect the cleaned signal, or it will clean many times")
                    plugin.disconnect(handler)

            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_ACTIVE] = False

            for view in (self.janitor_view, self.result_view):
                view.hide()
                view.show()
            thread.join()

            if len(self.scan_tasks) != 0:
                self.do_scan_task()
            else:
                self.unset_busy()

        return not finished

    def on_find_object(self, plugin, cruft, result_iter):
        Gdk.threads_enter()
        while Gtk.events_pending():
            Gtk.main_iteration()

        self.result_model.append(result_iter, (False,
                                               cruft.get_icon(),
                                               cruft.get_name(),
                                               cruft.get_name(),
                                               cruft.get_size_display(),
                                               plugin,
                                               cruft))

        self.result_view.expand_row(self.result_model.get_path(result_iter), True)
        Gdk.threads_leave()

    def on_scan_finished(self, plugin, result, count, size, result_iter):
        Gdk.threads_enter()

        plugin.disconnect(self._find_handler)
        plugin.disconnect(self._scan_handler)
        plugin.set_data('scan_finished', True)

        if count == 0:
            self.result_model.remove(result_iter)
        else:
            self.result_model[result_iter][self.RESULT_DISPLAY] = "<b>%s</b>" % plugin.get_summary(count, size)

        # Update the janitor title
        for row in self.janitor_model:
            for child_row in row.iterchildren():
                if child_row[self.JANITOR_PLUGIN] == plugin:
                    if count:
                        child_row[self.JANITOR_DISPLAY] = "<b>%s (%d) </b>" % (plugin.get_title(), count)
                    else:
                        child_row[self.JANITOR_DISPLAY] = "%s (%d)" % (plugin.get_title(), count)

        Gdk.threads_leave()

    def on_scan_error(self, plugin, error, plugin_iter):
        Gdk.threads_enter()

        #TODO deal with the error
        self.janitor_model[plugin_iter][self.JANITOR_ICON] = icon.get_from_name('error', size=16)
        plugin.set_data('scan_finished', True)
        self.scan_tasks = []

        Gdk.threads_leave()

    def on_clean_button_clicked(self, widget):
        self.plugin_to_run = 0

        plugin_dict = OrderedDict()

        for row in self.result_model:
            plugin = row[self.RESULT_PLUGIN]
            cruft_list = []

            for child_row in row.iterchildren():
                checked = child_row[self.RESULT_CHECK]

                if checked:
                    cruft = child_row[self.RESULT_CRUFT]
                    cruft_list.append(cruft)

            if cruft_list:
                plugin_dict[plugin] = cruft_list

        self.clean_tasks = list(plugin_dict.items())

        self.do_real_clean_task()
        log.debug("All finished!")

    def do_real_clean_task(self):
        plugin, cruft_list = self.clean_tasks.pop(0)

        log.debug("Call %s to clean cruft" % plugin)
        self._plugin_handler = plugin.connect('cleaned', self.on_plugin_cleaned)
        self._error_handler = plugin.connect('error', self.on_clean_error)
        plugin.clean_cruft(self.get_toplevel(), cruft_list)

    def on_plugin_cleaned(self, plugin, cleaned):
        for handler in (self._plugin_handler, self._error_handler):
            if plugin.handler_is_connected(handler):
                log.debug("Disconnect the cleaned signal, or it will clean many times")
                plugin.disconnect(handler)

        if len(self.clean_tasks) == 0:
            self.on_scan_button_clicked()
        else:
            GObject.timeout_add(300, self.do_real_clean_task)

    def on_clean_error(self, plugin, error):
        self.clean_tasks = []

    def on_autoscan_button_toggled(self, widget):
        if widget.get_active():
            self.autoscan_setting.set_value(True)
            self.scan_button.hide()
        else:
            self.autoscan_setting.set_value(False)
            self.scan_button.show()

    def icon_column_view_func(self, cell_layout, renderer, model, iter, id):
        if model[iter][id] == None:
            renderer.set_property("visible", False)
        else:
            renderer.set_property("visible", True)

    def update_model(self, a=None, b=None, expand=False):
        self.janitor_model.clear()
        self.result_model.clear()
        size_list = []

        loader = ModuleLoader('janitor')
        plugin_to_load = self.janitor_setting.get_value()

        system_text = _('System')
        iter = self.janitor_model.append(None, (None,
                                                icon.get_from_name('ubuntu-logo'),
                                                system_text,
                                                "<b><big>%s</big></b>" % system_text,
                                                None,
                                                None,
                                                None))

        for plugin in loader.get_modules_by_category('system'):
            if plugin.is_user_extension() and plugin.get_name() not in plugin_to_load:
                log.debug("User extension: %s not in setting to load" % plugin.get_name())
                continue
            size_list.append(Gtk.Label(label=plugin.get_title()).get_layout().get_pixel_size()[0])
            self.janitor_model.append(iter, (False,
                                             None,
                                             plugin.get_title(),
                                             plugin.get_title(),
                                             plugin(),
                                             None,
                                             None))

        personal_text = _('Personal')

        iter = self.janitor_model.append(None, (None,
                                                icon.get_from_name('system-users'),
                                                personal_text,
                                                "<b><big>%s</big></b>" % personal_text,
                                                None,
                                                None,
                                                None))

        for plugin in loader.get_modules_by_category('personal'):
            if plugin.is_user_extension() and plugin.get_name() not in plugin_to_load:
                log.debug("User extension: %s not in setting to load" % plugin.get_name())
                continue
            size_list.append(Gtk.Label(label=plugin.get_title()).get_layout().get_pixel_size()[0])
            self.janitor_model.append(iter, (False,
                                             None,
                                             plugin.get_title(),
                                             plugin.get_title(),
                                             plugin(),
                                             None,
                                             None))
        if size_list:
            self.max_janitor_view_width = max(size_list) + 80

        if expand:
            self._expand_janitor_view()
Exemplo n.º 28
0
class PreferencesDialog(GuiBuilder):
    (CLIP_CHECK,
     CLIP_ICON,
     CLIP_NAME) = range(3)

    (TWEAKS_CHECK,
     TWEAKS_ICON,
     TWEAKS_NAME) = range(3)

    (JANITOR_CHECK,
     JANITOR_NAME) = range(2)

    page_dict = {'overview': 0,
                 'tweaks': 1,
                 'admins': 2,
                 'janitor': 3}

    def __init__(self, parent):
        GuiBuilder.__init__(self, file_name='preferences.ui')

        self.preferences_dialog.set_transient_for(parent)
        self.clips_setting = GSetting('com.ubuntu-tweak.tweak.clips')
        self.tweaks_setting = GSetting('com.ubuntu-tweak.tweak.tweaks')
        self.admins_setting = GSetting('com.ubuntu-tweak.tweak.admins')
        self.janitor_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.clips_location_setting = GSetting('com.ubuntu-tweak.tweak.last-clip-location')
        
        auto_scan_label, auto_scan_switch = WidgetFactory.create("Switch",
                                                label=_("Auto scan:"),
                                                key='com.ubuntu-tweak.janitor.auto-scan',
                                                backend="gsettings")
        pack = GridPack((auto_scan_label, auto_scan_switch))
        self.generic_alignment.add(pack)

        self.generic_alignment.show_all()

    def on_clip_toggle_render_toggled(self, cell, path):
        log.debug("on_clip_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.clip_model,
                                        path,
                                        self.CLIP_CHECK,
                                        self.CLIP_NAME,
                                        self.clips_setting)

    def on_tweak_toggle_renderer_toggled(self, cell, path):
        log.debug("on_tweaks_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.tweaks_model,
                                        path,
                                        self.TWEAKS_CHECK,
                                        self.TWEAKS_NAME,
                                        self.tweaks_setting)

    def on_admins_toggle_renderer_toggled(self, cell, path):
        log.debug("on_admins_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.admins_model,
                                        path,
                                        self.TWEAKS_CHECK,
                                        self.TWEAKS_NAME,
                                        self.admins_setting)

    def on_janitor_cell_renderer_toggled(self, cell, path):
        log.debug("on_admins_toggle_render_toggled")
        self.on_toggle_renderer_toggled(self.janitor_model,
                                        path,
                                        self.JANITOR_CHECK,
                                        self.JANITOR_NAME,
                                        self.janitor_setting)

    def on_toggle_renderer_toggled(self, model, path, check_id, name_id, setting):
        iter = model.get_iter(path)
        checked = not model[iter][check_id]
        model[iter][check_id] = checked

        self._do_update_model(model, check_id, name_id, setting)

    def _do_update_model(self, model, check_id, name_id, setting):
        model_list = []
        for row in model:
            if row[check_id]:
                model_list.append(row[name_id])

        log.debug("on_clip_toggle_render_toggled: %s" % model_list)
        setting.set_value(model_list)

    def run(self, feature='overview'):
        self._update_clip_model()

        for _feature in ModuleLoader.default_features:
            self._update_feature_model(_feature)

        if feature in self.page_dict:
            self.preference_notebook.set_current_page(self.page_dict[feature])

        return self.preferences_dialog.run()

    def hide(self):
        return self.preferences_dialog.hide()

    def on_move_up_button_clicked(self, widget):
        model, iter = self.clip_view.get_selection().get_selected()

        if iter:
            previous_path = str(int(model.get_string_from_iter(iter)) - 1)

            if int(previous_path) >= 0:
                previous_iter = model.get_iter_from_string(previous_path)
                model.move_before(iter, previous_iter)
                self._do_update_model(self.clip_model,
                                      self.CLIP_CHECK,
                                      self.CLIP_NAME,
                                      self.clips_setting)

    def on_move_down_button_clicked(self, widget):
        model, iter = self.clip_view.get_selection().get_selected()

        if iter:
            next_iter = model.iter_next(iter)
            model.move_after(iter, next_iter)
            self._do_update_model(self.clip_model,
                                  self.CLIP_CHECK,
                                  self.CLIP_NAME,
                                  self.clips_setting)

    def on_clip_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a clip extension'),
                                  Clip,
                                  'clips',
                                  self.clips_setting,
                                  self._update_clip_model,
                                  _('"%s" is not a Clip Extension!'))

    def on_tweaks_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Tweaks Extension'),
                                  TweakModule,
                                  'tweaks',
                                  self.tweaks_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Tweaks Extension!'))

    def on_admins_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Admins Extension'),
                                  TweakModule,
                                  'admins',
                                  self.admins_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Admins Extension!'))

    def on_janitor_install_button_clicked(self, widget):
        self.on_install_extension(_('Choose a Janitor Extension'),
                                  JanitorPlugin,
                                  'janitor',
                                  self.janitor_setting,
                                  self._update_feature_model,
                                  _('"%s" is not a Janitor Extension!'))

    def on_install_extension(self, dialog_label, klass, feature,
                             setting, update_func, error_message):
        dialog = Gtk.FileChooserDialog(dialog_label,
                                       action=Gtk.FileChooserAction.OPEN,
                                       buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                                                Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT))
        filter = Gtk.FileFilter()
        filter.set_name(_('Ubuntu Tweak Extension (*.py, *.tar.gz)'))
        filter.add_pattern('*.py')
        filter.add_pattern('*.tar.gz')
        dialog.add_filter(filter)
        dialog.set_current_folder(self.clips_location_setting.get_value() or
                                  GLib.get_home_dir())

        filename = ''
        install_done = False
        not_extension = False

        if dialog.run() == Gtk.ResponseType.ACCEPT:
            filename = dialog.get_filename()
        dialog.destroy()

        if filename:
            self.clips_location_setting.set_value(os.path.dirname(filename))

            log.debug("Start to check the class in %s" % filename)
            if filename.endswith('.tar.gz'):
                tar_file = TarFile(filename)
                if tar_file.is_valid():
                    tar_file.extract(TEMP_ROOT)
                    #TODO if multi-root
                    if tar_file.get_root_name():
                        temp_dir = os.path.join(TEMP_ROOT, tar_file.get_root_name())

                if ModuleLoader.is_target_class(temp_dir, klass):
                    target = os.path.join(ModuleLoader.get_user_extension_dir(feature), os.path.basename(temp_dir))
                    copy = True
                    if os.path.exists(target):
                        dialog = QuestionDialog(message=_("Would you like to remove it then install again?"),
                                                title=_('"%s" has already installed' % os.path.basename(target)))
                        response = dialog.run()
                        dialog.destroy()

                        if response == Gtk.ResponseType.YES:
                            shutil.rmtree(target)
                        else:
                            copy = False

                    if copy:
                        log.debug("Now copying tree...")
                        shutil.move(temp_dir, target)
                    else:
                        shutil.rmtree(temp_dir)
                else:
                    not_extension = True
            else:
                if ModuleLoader.is_target_class(filename, klass):
                    shutil.copy(filename, ModuleLoader.get_user_extension_dir(feature))
                    install_done = True
                else:
                    not_extension = True

        if install_done:
            update_func(feature)

            # To force empty the clips_setting to make load_cips
            value = setting.get_value()
            setting.set_value([''])
            setting.set_value(value)

        if not_extension:
            ErrorDialog(message=error_message % os.path.basename(filename)).launch()

    def _update_clip_model(self, feature=None):
        clips = self.clips_setting.get_value()

        loader = ModuleLoader('clips')

        self.clip_model.clear()

        for clip_name in clips:
            ClipClass = loader.get_module(clip_name)

            self.clip_model.append((True,
                                    ClipClass.get_pixbuf(),
                                    ClipClass.get_name()))

        for name, ClipClass in loader.module_table.items():
            if name not in clips:
                self.clip_model.append((False,
                                        ClipClass.get_pixbuf(),
                                        ClipClass.get_name()))

    def _update_feature_model(self, feature):
        module_list = getattr(self, '%s_setting' % feature).get_value() or []

        loader = ModuleLoader(feature, user_only=True)

        model = getattr(self, '%s_model' % feature)
        model.clear()

        for name, klass in loader.module_table.items():
            if klass.get_pixbuf():
                model.append((name in module_list,
                              klass.get_pixbuf(),
                              klass.get_name()))
            else:
                model.append((name in module_list,
                              klass.get_name()))
Exemplo n.º 29
0
class JanitorPage(Gtk.VBox, GuiBuilder):
    (JANITOR_CHECK,
     JANITOR_ICON,
     JANITOR_NAME,
     JANITOR_DISPLAY,
     JANITOR_PLUGIN,
     JANITOR_SPINNER_ACTIVE,
     JANITOR_SPINNER_PULSE) = range(7)

    (RESULT_CHECK,
     RESULT_ICON,
     RESULT_NAME,
     RESULT_DISPLAY,
     RESULT_DESC,
     RESULT_PLUGIN,
     RESULT_CRUFT) = range(7)

    max_janitor_view_width = 0

    def __init__(self):
        GObject.GObject.__init__(self)

        self.scan_tasks = []
        self.clean_tasks = []
        self._total_count = 0

        self.set_border_width(6)
        GuiBuilder.__init__(self, 'janitorpage.ui')

        self.autoscan_setting = GSetting('com.ubuntu-tweak.janitor.auto-scan')
        self.autoscan_setting.connect_notify(self.on_autoscan_button_toggled)
        self.plugins_setting = GSetting('com.ubuntu-tweak.janitor.plugins')
        self.view_width_setting = GSetting('com.ubuntu-tweak.janitor.janitor-view-width')

        self.pack_start(self.vbox1, True, True, 0)

        self.connect('realize', self.setup_ui_tasks)
        self.janitor_view.get_selection().connect('changed', self.on_janitor_selection_changed)
        self.plugins_setting.connect_notify(self.update_model, True)

        self.show()

    def on_move_handle(self, widget, gproperty):
        log.debug("on_move_handle: %d", widget.get_property('position'))
        self.view_width_setting.set_value(widget.get_property('position'))

        # cancel the size request, or it will fail to resize
        # TODO why the first scan will make it fail? 
        self.janitor_view.set_size_request(self.max_janitor_view_width, -1)

    def is_auto_scan(self):
        return self.autoscan_setting.get_value()

    @log_func(log)
    def on_result_view_row_activated(self, treeview, path, column):
        iter = self.result_model.get_iter(path)
        cruft = self.result_model[iter][self.RESULT_CRUFT]
        display = self.result_model[iter][self.RESULT_DISPLAY]

        if 'red' in display:
            plugin = self.result_model[iter][self.RESULT_PLUGIN]
            error = plugin.get_property('error')
            self.result_model[iter][self.RESULT_DISPLAY] = '<span color="red"><b>%s</b></span>' % error
        elif hasattr(cruft, 'get_path'):
            path = cruft.get_path()
            if not os.path.isdir(path):
                path = os.path.dirname(path)
            os.system("xdg-open '%s' &" % path)

    def setup_ui_tasks(self, widget):
        self.janitor_model.set_sort_column_id(self.JANITOR_NAME, Gtk.SortType.ASCENDING)

        #add janitor columns
        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererToggle()
        renderer.connect('toggled', self.on_janitor_check_button_toggled)
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active', self.JANITOR_CHECK)

        self.janitor_view.append_column(janitor_column)

        janitor_column = Gtk.TreeViewColumn()

        renderer = Gtk.CellRendererPixbuf()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'pixbuf', self.JANITOR_ICON)
        janitor_column.set_cell_data_func(renderer,
                                          self.icon_column_view_func,
                                          self.JANITOR_ICON)

        renderer = Gtk.CellRendererText()
        renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
        janitor_column.pack_start(renderer, True)
        janitor_column.add_attribute(renderer, 'markup', self.JANITOR_DISPLAY)

        renderer = Gtk.CellRendererSpinner()
        janitor_column.pack_start(renderer, False)
        janitor_column.add_attribute(renderer, 'active', self.JANITOR_SPINNER_ACTIVE)
        janitor_column.add_attribute(renderer, 'pulse', self.JANITOR_SPINNER_PULSE)

        self.janitor_view.append_column(janitor_column)
        #end janitor columns

        #new result columns
        result_display_renderer = self.builder.get_object('result_display_renderer')
        result_display_renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
        result_icon_renderer= self.builder.get_object('result_icon_renderer')
        self.result_column.set_cell_data_func(result_icon_renderer,
                                              self.icon_column_view_func,
                                              self.RESULT_ICON)
        #end new result columns

        auto_scan = self.autoscan_setting.get_value()
        log.info("Auto scan status: %s", auto_scan)

        self.scan_button.set_visible(not auto_scan)

        self.update_model()

        self._expand_janitor_view()

        self.hpaned1.connect('notify::position', self.on_move_handle)

    def _expand_janitor_view(self):
        self.janitor_view.expand_all()

        left_view_width = self.view_width_setting.get_value()
        log.debug("left_view_width is: %d, max_janitor_view_width is: %d" %
                  (left_view_width, self.max_janitor_view_width))

        if left_view_width:
            self.janitor_view.set_size_request(left_view_width, -1)
        elif self.max_janitor_view_width:
            self.janitor_view.set_size_request(self.max_janitor_view_width, -1)

    def set_busy(self):
        self.get_parent_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))

    def unset_busy(self):
        self.get_parent_window().set_cursor(None)

    def on_janitor_selection_changed(self, selection):
        model, iter = selection.get_selected()
        if iter:
            if self.janitor_model.iter_has_child(iter):
                iter = self.janitor_model.iter_children(iter)

            plugin = model[iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_view.get_selection().select_path(row.path)
                    log.debug("scroll_to_cell: %s" % row.path)
                    self.result_view.scroll_to_cell(row.path)

    def _is_scanning_or_cleaning(self):
        for row in self.janitor_model:
            for child_row in row.iterchildren():
                if child_row[self.JANITOR_SPINNER_ACTIVE]:
                    return True
        else:
            return False

    def on_janitor_check_button_toggled(self, cell, path):
        self.result_view.show()
        self.happy_box.hide()

        iter = self.janitor_model.get_iter(path)

        if self._is_scanning_or_cleaning():
            return

        checked = not self.janitor_model[iter][self.JANITOR_CHECK]

        if self.janitor_model.iter_has_child(iter):
            child_iter = self.janitor_model.iter_children(iter)
            while child_iter:
                self.janitor_model[child_iter][self.JANITOR_CHECK] = checked

                child_iter = self.janitor_model.iter_next(child_iter)

        self.janitor_model[iter][self.JANITOR_CHECK] = checked

        self._check_child_is_all_the_same(self.janitor_model, iter,
                                         self.JANITOR_CHECK, checked)

        if self.is_auto_scan():
            self._auto_scan_cruft(iter, checked)

    def _update_clean_button_sensitive(self):
        self.clean_button.set_sensitive(False)

        for row in self.result_model:
            for child_row in row.iterchildren():
                if child_row[self.RESULT_CHECK]:
                    self.clean_button.set_sensitive(True)
                    break

    def on_result_check_renderer_toggled(self, cell, path):
        iter = self.result_model.get_iter(path)
        checked = self.result_model[iter][self.RESULT_CHECK]

        if self._is_scanning_or_cleaning():
            return

        if self.result_model.iter_has_child(iter):
            child_iter = self.result_model.iter_children(iter)
            while child_iter:
                self.result_model[child_iter][self.RESULT_CHECK] = not checked

                child_iter = self.result_model.iter_next(child_iter)

        self.result_model[iter][self.RESULT_CHECK] = not checked

        self._check_child_is_all_the_same(self.result_model, iter,
                                         self.RESULT_CHECK, not checked)

        self._update_clean_button_sensitive()

    def _check_child_is_all_the_same(self, model, iter, column_id, status):
        iter = model.iter_parent(iter)

        if iter:
            child_iter = model.iter_children(iter)

            while child_iter:
                if status != model[child_iter][column_id]:
                    model[iter][column_id] = False
                    break
                child_iter = model.iter_next(child_iter)
            else:
                model[iter][column_id] = status

    def on_scan_button_clicked(self, widget=None):
        self.result_model.clear()
        self.clean_button.set_sensitive(False)

        scan_dict = OrderedDict()

        for row in self.janitor_model:
            for child_row in row.iterchildren():
                checked = child_row[self.JANITOR_CHECK]

                scan_dict[child_row.iter] = checked

        self.scan_tasks = list(scan_dict.items())
        self._total_count = 0
        self.result_view.show()
        self.happy_box.hide()

        self.set_busy()
        self.do_scan_task()

    def _auto_scan_cruft(self, iter, checked):
        self.set_busy()

        scan_dict = OrderedDict()

        if self.janitor_model.iter_has_child(iter):
            log.info('Scan cruft for all plugins')
            #Scan cruft for children
            child_iter = self.janitor_model.iter_children(iter)

            while child_iter:
                scan_dict[child_iter] = checked
                child_iter = self.janitor_model.iter_next(child_iter)
        else:
            scan_dict[iter] = checked

        self.scan_tasks = list(scan_dict.items())

        for plugin_iter, checked in self.scan_tasks:
            plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]

            for row in self.result_model:
                if row[self.RESULT_PLUGIN] == plugin:
                    self.result_model.remove(row.iter)

        self.do_scan_task()

    def do_scan_task(self):
        plugin_iter, checked = self.scan_tasks.pop(0)

        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        plugin.set_property('scan_finished', False)

        log.debug("do_scan_task for %s for status: %s" % (plugin, checked))

        if checked:
            log.info('Scan cruft for plugin: %s' % plugin.get_name())

            iter = self.result_model.append(None, (None,
                                                   None,
                                                   plugin.get_title(),
                                                   '<b>%s</b>' % _('Scanning cruft for "%s"...') % plugin.get_title(),
                                                   None,
                                                   plugin,
                                                   None))

            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_ACTIVE] = True
            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] = 0
            self.janitor_view.scroll_to_cell(self.janitor_model.get_path(plugin_iter))

            self._find_handler = plugin.connect('find_object', self.on_find_object, (plugin_iter, iter))
            self._scan_handler = plugin.connect('scan_finished', self.on_scan_finished, (plugin_iter, iter))
            self._error_handler = plugin.connect('scan_error', self.on_scan_error, (plugin_iter, iter))

            t = threading.Thread(target=plugin.get_cruft)
            GObject.timeout_add(50, self._on_spinner_timeout, plugin_iter, t)

            t.start()
        else:
            # Update the janitor title
            for row in self.janitor_model:
                for child_row in row.iterchildren():
                    if child_row[self.JANITOR_PLUGIN] == plugin:
                        child_row[self.JANITOR_DISPLAY] = plugin.get_title()

            if self.scan_tasks:
                self.do_scan_task()
            else:
                if self._total_count == 0:
                    self.result_view.hide()
                    self.happy_box.show()
                else:
                    self.result_view.show()
                    self.happy_box.hide()

                self.unset_busy()

    def _on_spinner_timeout(self, plugin_iter, thread):
        plugin = self.janitor_model[plugin_iter][self.JANITOR_PLUGIN]
        finished = plugin.get_property('scan_finished')

        self.janitor_model[plugin_iter][self.JANITOR_SPINNER_PULSE] += 1

        if finished:
            for handler in (self._find_handler,
                            self._scan_handler,
                            self._error_handler):
                if plugin.handler_is_connected(handler):
                    log.debug("Disconnect the cleaned signal, or it will clean many times: %s" % plugin)
                    plugin.disconnect(handler)

            self.janitor_model[plugin_iter][self.JANITOR_SPINNER_ACTIVE] = False

            thread.join()

            if len(self.scan_tasks) != 0:
                log.debug("Pending scan tasks: %d" % len(self.scan_tasks))
                self.do_scan_task()
            else:
                log.debug("total_count is: %d" % self._total_count)
                if self._total_count == 0:
                    self.result_view.hide()
                    self.happy_box.show()
                else:
                    self.result_view.show()
                    self.happy_box.hide()

                self.unset_busy()

        return not finished

    @post_ui
    def on_find_object(self, plugin, cruft, count, iters):
        while Gtk.events_pending():
            Gtk.main_iteration()

        plugin_iter, result_iter = iters

        self.result_model.append(result_iter, (False,
                                               cruft.get_icon(),
                                               cruft.get_name(),
                                               cruft.get_name(),
                                               cruft.get_size_display(),
                                               plugin,
                                               cruft))

        self.result_view.expand_row(self.result_model.get_path(result_iter), True)

        # Update the janitor title
        if count:
            self.janitor_model[plugin_iter][self.JANITOR_DISPLAY] = "<b>[%d] %s</b>" % (count, plugin.get_title())
        else:
            self.janitor_model[plugin_iter][self.JANITOR_DISPLAY] = "[0] %s" % plugin.get_title()

    @post_ui
    def on_scan_finished(self, plugin, result, count, size, iters):
        plugin.disconnect(self._find_handler)
        plugin.disconnect(self._scan_handler)
        plugin.set_property('scan_finished', True)

        plugin_iter, result_iter = iters

        if count == 0:
            self.result_model.remove(result_iter)
        else:
            self.result_model[result_iter][self.RESULT_DISPLAY] = "<b>%s</b>" % plugin.get_summary(count)
            if size != 0:
                self.result_model[result_iter][self.RESULT_DESC] = "<b>%s</b>" % filesizeformat(size)

        # Update the janitor title
        self._total_count += count

        if count:
            self.janitor_model[plugin_iter][self.JANITOR_DISPLAY] = "<b>[%d] %s</b>" % (count, plugin.get_title())
            self.result_view.collapse_row(self.result_model.get_path(result_iter))
        else:
            self.janitor_model[plugin_iter][self.JANITOR_DISPLAY] = "[0] %s" % plugin.get_title()

    @post_ui
    def on_scan_error(self, plugin, error, iters):
        plugin_iter, result_iter = iters

        self.janitor_model[plugin_iter][self.JANITOR_ICON] = icon.get_from_name('error', size=16)
        self.result_model[result_iter][self.RESULT_DISPLAY] = '<span color="red"><b>%s</b></span>' % _('Scan error for "%s", double-click to see details') % plugin.get_title()

        plugin.set_property('scan_finished', True)
        plugin.set_property('error', error)

    @inline_callbacks
    def on_clean_button_clicked(self, widget):
        '''plugin_dict: {plugin: {cruft: iter}}'''
        try:
            yield PolkitAction(PK_ACTION_CLEAN).do_authenticate()
        except Exception, e:
            log.debug(e)
            return

        self.plugin_to_run = 0

        self.set_busy()
        self.clean_button.set_sensitive(False)

        plugin_dict = OrderedDict()

        for row in self.result_model:
            plugin = row[self.RESULT_PLUGIN]
            cruft_dict = OrderedDict()

            for child_row in row.iterchildren():
                checked = child_row[self.RESULT_CHECK]

                if checked:
                    cruft_dict[child_row[self.RESULT_CRUFT]] =  child_row.iter

            if cruft_dict:
                plugin_dict[plugin] = cruft_dict

        self.clean_tasks = list(plugin_dict.items())

        self.do_real_clean_task()
        log.debug("All finished!")
Exemplo n.º 30
0
class FeaturePage(Gtk.ScrolledWindow):

    __gsignals__ = {"module_selected": (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_STRING,))}

    _categories = None
    _boxes = []

    def __init__(self, feature_name):
        GObject.GObject.__init__(
            self,
            shadow_type=Gtk.ShadowType.NONE,
            hscrollbar_policy=Gtk.PolicyType.NEVER,
            vscrollbar_policy=Gtk.PolicyType.AUTOMATIC,
        )
        self.set_border_width(12)

        self._feature = feature_name
        self._setting = GSetting("com.ubuntu-tweak.tweak.%s" % feature_name)
        self._categories = {}
        self._boxes = []

        self._box = Gtk.VBox(spacing=6)
        viewport = Gtk.Viewport(shadow_type=Gtk.ShadowType.NONE)
        viewport.add(self._box)
        self.add(viewport)

        self.load_modules()

        self.connect("draw", self.rebuild_boxes)

        self._setting.connect_notify(self.load_modules, True)

        self.show_all()

    def load_modules(self, a=None, b=None, remove=False):
        log.debug("Load modules, remove: %s" % remove)

        loader = ModuleLoader(self._feature)

        if remove:
            self._boxes = []
            for child in self._box.get_children():
                self._box.remove(child)

        for category, category_name in loader.get_categories():
            modules = loader.get_modules_by_category(category)
            if modules:
                module_to_loads = self._setting.get_value()

                for module in modules:
                    if module.is_user_extension() and module.get_name() not in module_to_loads:
                        modules.remove(module)

                category_box = CategoryBox(modules=modules, category_name=category_name)

                self._connect_signals(category_box)
                self._boxes.append(category_box)
                self._box.pack_start(category_box, False, False, 0)

        if remove:
            self.rebuild_boxes()

    def _connect_signals(self, category_box):
        for button in category_box.get_buttons():
            button.connect("clicked", self.on_button_clicked)

    def on_button_clicked(self, widget):
        log.info("Button clicked")
        module = widget.get_module()
        self.emit("module_selected", module.get_name())

    def rebuild_boxes(self, widget=None, event=None):
        request = self.get_allocation()
        ncols = request.width / 164  # 32 + 120 + 6 + 4
        width = ncols * (164 + 2 * 4) + 40
        if width > request.width:
            ncols -= 1

        pos = 0
        last_box = None
        children = self._box.get_children()
        for box in self._boxes:
            modules = box.get_modules()
            if len(modules) == 0:
                if box in children:
                    self._box.remove(box)
            else:
                if box not in children:
                    self._box.pack_start(box, False, False, 0)
                    self._box.reorder_child(box, pos)
                box.rebuild_table(ncols)
                pos += 1

                last_box = box