📄 gui.py
字号:
if operation == model[__iter][2]: iterc = model.iter_children(__iter) if None == iterc: #print "debug: no children" return None while iterc: tup = (model[iterc][2], model[iterc][1]) #print "debug: get_operation_options: tuple = '%s'" % (tup,) ret.append(tup) iterc = model.iter_next(iterc) return ret __iter = model.iter_next(__iter) return None def set_sensitive(self, true): """Disable commands while an operation is running""" self.actiongroup.set_sensitive(true) self.toolbar.set_sensitive(true) self.view.set_sensitive(true) def run_operations(self, __widget): """Event when the 'delete' toolbar button is clicked.""" # fixme: should present this dialog after finding operations if not True == delete_confirmation_dialog(self.window): return self.preview_or_run_operations(True) def clean_pathname(self, pathname, really_delete, __iter): """Clean a single pathname""" total_bytes = 0 try: bytes = FileUtilities.getsize(pathname) except: print "debug: error getting size of '%s'" % (pathname,) else: tag = None try: if really_delete: FileUtilities.delete(pathname) except: line = str(sys.exc_info()[1]) + " " + pathname + "\n" tag = 'error' else: total_bytes += bytes line = FileUtilities.bytes_to_human(bytes) + " " + pathname + "\n" gtk.gdk.threads_enter() self.append_text(line, tag, __iter) gtk.gdk.threads_leave() return total_bytes def clean_operation(self, operation, really_delete, __iter): """Perform a single cleaning operation""" total_bytes = 0 operation_options = self.get_operation_options(operation) print "debug: clean_operation('%s'), options = '%s'" % (operation, operation_options) if operation_options: for (option, value) in operation_options: backends[operation].set_option(option, value) # standard operation try: for pathname in backends[operation].list_files(): total_bytes += self.clean_pathname(pathname, really_delete, __iter) except: err = _("Exception while getting running operation '%s': '%s'") % (operation, str(sys.exc_info()[1])) print err gtk.gdk.threads_enter() self.append_text(err + "\n", 'error', __iter) gtk.gdk.threads_leave() # special operation try: ret = backends[operation].other_cleanup(really_delete) except: err = _("Exception while getting running operation '%s': '%s'") % (operation, str(sys.exc_info()[1])) print err gtk.gdk.threads_enter() self.append_text(err + "\n", 'error', __iter) gtk.gdk.threads_leave() else: if None == ret: return total_bytes gtk.gdk.threads_enter() if really_delete: total_bytes += ret[0] line = "* " + FileUtilities.bytes_to_human(ret[0]) + " " + ret[1] + "\n" else: line = _("Special operation: ") + ret + "\n" self.textbuffer.insert(__iter, line) gtk.gdk.threads_leave() return total_bytes @threaded def preview_or_run_operations(self, really_delete): """Preview operations or run operations (delete files)""" operations = self.get_selected_operations() if 0 == len(operations): gtk.gdk.threads_enter() dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _("You must select an operation")) dialog.run() dialog.destroy() gtk.gdk.threads_leave() return gtk.gdk.threads_enter() self.set_sensitive(False) self.textbuffer.set_text("") __iter = self.textbuffer.get_iter_at_offset(0) self.progressbar.show() gtk.gdk.threads_leave() total_bytes = 0 count = 0 for operation in operations: gtk.gdk.threads_enter() self.progressbar.set_fraction(1.0 * count / len(operations)) if really_delete: self.progressbar.set_text(_("Please wait. Scanning and deleting: ") + operation) else: self.progressbar.set_text(_("Please wait. Scanning: ") + operation) gtk.gdk.threads_leave() total_bytes += self.clean_operation(operation, really_delete, __iter) count += 1 gtk.gdk.threads_enter() self.progressbar.set_text("") self.progressbar.set_fraction(1) self.progressbar.set_text(_("Done.")) self.textbuffer.insert(__iter, "\n" + _("Total size: ") \ + FileUtilities.bytes_to_human(total_bytes)) self.set_sensitive(True) gtk.gdk.threads_leave() def about(self, __event): """Create and show the about dialog""" gtk.about_dialog_set_url_hook(lambda dialog, link: open_url(link)) dialog = gtk.AboutDialog() dialog.set_comments(_("Program to clean unnecessary files")) dialog.set_copyright("Copyright (C) 2009 Andrew Ziem") try: dialog.set_license(open(license_filename).read()) except: dialog.set_license(_("GNU General Public License version 3 or later.\nSee http://www.gnu.org/licenses/gpl-3.0.txt")) dialog.set_name(APP_NAME) dialog.set_translator_credits(_("translator-credits")) dialog.set_version(APP_VERSION) dialog.set_website("http://bleachbit.sourceforge.net") dialog.run() dialog.hide() def create_operations_box(self): """Create and return the operations box (which holds a tree view)""" scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) self.tree_store = TreeInfoModel() display = TreeDisplayModel() mdl = self.tree_store.get_model() self.view = display.make_view(mdl) self.view.get_selection().connect("changed", self.on_selection_changed) scrolled_window.add(self.view) return scrolled_window def cb_preferences_dialog(self, action): """Callback for preferences dialog""" pref = PreferencesDialog(self.window) pref.run() def create_menubar(self): """Create the menu bar (file, help)""" # Create a UIManager instance uimanager = gtk.UIManager() # Add the accelerator group to the toplevel window accelgroup = uimanager.get_accel_group() self.window.add_accel_group(accelgroup) # Create an ActionGroup actiongroup = gtk.ActionGroup('UIManagerExample') self.actiongroup = actiongroup # Create actions entries = [('Quit', gtk.STOCK_QUIT, _('_Quit'), None, _('Quit BleachBit'), lambda *dummy: gtk.main_quit()), ('File', None, _('_File')), ('Preferences', gtk.STOCK_PREFERENCES, _("Preferences"), None, _("Configure BleachBit"), self.cb_preferences_dialog),# ('Preferences', gtk.STOCK_PREFERENCES, _("Preferences")), ('Edit', None, _("_Edit")), ('About', gtk.STOCK_ABOUT, _('_About'), None, _('Show about'), self.about), ('Help', None, _("_Help"))] actiongroup.add_actions(entries) actiongroup.get_action('Quit').set_property('short-label', '_Quit') # Add the actiongroup to the uimanager uimanager.insert_action_group(actiongroup, 0) # Add a UI description uimanager.add_ui_from_string(self.ui) # Create a MenuBar menubar = uimanager.get_widget('/MenuBar') return menubar def create_toolbar(self): """Create the toolbar""" toolbar = gtk.Toolbar() toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) toolbar.set_style(gtk.TOOLBAR_BOTH) toolbar.set_border_width(5) # create tooltips tooltips = gtk.Tooltips() tooltips.enable() # create the delete button icon = gtk.Image() icon.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_LARGE_TOOLBAR) run_button = gtk.ToolButton(icon_widget = icon, label = _("Delete")) run_button.connect("clicked", self.run_operations) toolbar.insert(run_button, -1) run_button.set_tooltip(tooltips, _("Delete files in the selected operations")) # create the preview button preview_icon = gtk.Image() preview_icon.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_LARGE_TOOLBAR) preview_button = gtk.ToolButton(icon_widget = preview_icon, label = _("Preview")) preview_button.connect("clicked", lambda *dummy: self.preview_or_run_operations(False)) toolbar.insert(preview_button, -1) preview_button.set_tooltip(tooltips, _("Preview files in the selected operations (without deleting any files)")) return toolbar def create_window(self): """Create the main application window""" self.window = gtk.Window() self.window.connect('destroy', lambda w: gtk.main_quit()) self.window.resize(800, 600) self.window.set_title(APP_NAME) if os.path.exists(appicon_path): self.window.set_icon_from_file(appicon_path) vbox = gtk.VBox() self.window.add(vbox) # add menubar vbox.pack_start(self.create_menubar(), False) # add toolbar self.toolbar = self.create_toolbar() vbox.pack_start(self.toolbar, False) # split main window hbox = gtk.HBox(homogeneous=False, spacing=10) vbox.pack_start(hbox, True) # add operations to left operations = self.create_operations_box() hbox.pack_start(operations, False) # create the right side of the window right_box = gtk.VBox() self.progressbar = gtk.ProgressBar() right_box.pack_start(self.progressbar, False) # add output display on right self.textbuffer = gtk.TextBuffer() swindow = gtk.ScrolledWindow() swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) textview = gtk.TextView(self.textbuffer) textview.set_editable(False) textview.set_wrap_mode(gtk.WRAP_WORD) swindow.add(textview) right_box.add(swindow) hbox.add(right_box) # add markup tags tt = self.textbuffer.get_tag_table() style_operation = gtk.TextTag('operation') style_operation.set_property('size-points', 14) style_operation.set_property('weight', 700) tt.add(style_operation) style_option_label = gtk.TextTag('option_label') style_option_label.set_property('weight', 700) tt.add(style_option_label) style_operation = gtk.TextTag('error') style_operation.set_property('foreground', '#b00000') tt.add(style_operation) # done self.window.show_all() self.progressbar.hide() return def enable_online_update(self, url): """Create a button to launch browser to initiate software update""" icon = gtk.Image() icon.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_LARGE_TOOLBAR) update_button = gtk.ToolButton(icon_widget = icon, label = _("Update BleachBit")) update_button.show_all() update_button.connect("clicked", lambda toolbutton, url: open_url(url), url) self.toolbar.insert(update_button, -1) try: import pynotify except: print "debug: pynotify not available" else: if pynotify.init(APP_NAME): notify = pynotify.Notification(_("BleachBit update is available"), _("Click 'Update BleachBit' for more information")) # this doesn't align the notification properly #n.attach_to_widget(update_button) notify.attach_to_widget(self.toolbar) notify.show() @threaded def check_online_updates(self): """Check for software updates in background""" update = Update.Update() if update.is_update_available(): gobject.idle_add(self.enable_online_update, update.get_update_info_url()) def __init__(self): self.create_window() gtk.gdk.threads_init() if options.get("first_start"): pref = PreferencesDialog(self.window) pref.run() options.set('first_start', False) if online_update_notification_enabled and options.get("check_online_updates"): self.check_online_updates()if __name__ == '__main__': gui = GUI() gtk.main()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -