def get_autostart_path(): """Return the path of the BleachBit shortcut in the user's startup folder""" try: startupdir = shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_STARTUP) except: # example of failure # https://www.bleachbit.org/forum/error-windows-7-x64-bleachbit-091 logger = logging.getLogger(__name__) logger.exception('exception in get_autostart_path()') msg = 'Error finding user startup folder: %s ' % (str( sys.exc_info()[1])) import GuiBasic GuiBasic.message_dialog(None, msg) # as a fallback, guess # Windows XP: C:\Documents and Settings\(username)\Start Menu\Programs\Startup # Windows 7: # C:\Users\(username)\AppData\Roaming\Microsoft\Windows\Start # Menu\Programs\Startup startupdir = os.path.expandvars( '$USERPROFILE\\Start Menu\\Programs\\Startup') if not os.path.exists(startupdir): startupdir = os.path.expandvars( '$APPDATA\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup' ) return os.path.join(startupdir, 'bleachbit.lnk')
def preview_or_run_operations(self, really_delete, operations=None): """Preview operations or run operations (delete files)""" assert(isinstance(really_delete, bool)) import Worker self.start_time = None if None == operations: operations = {} for operation in self.get_selected_operations(): operations[operation] = self.get_operation_options(operation) assert(isinstance(operations, dict)) if 0 == len(operations): GuiBasic.message_dialog(self.window, _("You must select an operation"), gtk.MESSAGE_WARNING, gtk.BUTTONS_OK) return try: self.set_sensitive(True) self.textbuffer.set_text("") self.progressbar.show() print "STOP NOW" print self,stop_now self.worker = Worker.Worker(self, really_delete, operations, self.stop_now) except: traceback.print_exc() err = str(sys.exc_info()[1]) self.append_text(err + "\n", 'error') else: self.start_time = time.time() worker = self.worker.run() gobject.idle_add(worker.next)
def environ(varname, csidl): try: os.environ[varname] = shell.SHGetSpecialFolderPath(None, csidl) except: traceback.print_exc() msg = 'Error setting environemnt variable "%s": %s ' % (varname, str(sys.exc_info()[1])) import GuiBasic GuiBasic.message_dialog(None, msg)
def environ(varname, csidl): try: os.environ[varname] = shell.SHGetSpecialFolderPath(None, csidl) except: traceback.print_exc() msg = 'Error setting environemnt variable "%s": %s ' % ( varname, str(sys.exc_info()[1])) import GuiBasic GuiBasic.message_dialog(None, msg)
def create_menubar(self): """Create the menu bar (file, help)""" # Create a UIManager instance uimanager = gtk.UIManager() # Add the accelerator group to the top level 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 = ( ('ShredFiles', None, _('_Shred Files'), None, None, self.cb_shred_file), ('ShredFolders', None, _('Sh_red Folders'), None, None, self.cb_shred_file), ('WipeFreeSpace', None, _('_Wipe Free Space'), None, None, self.cb_wipe_free_space), ('ShredQuit', None, _('S_hred Settings and Quit'), None, None, self.cb_shred_quit), ('Quit', gtk.STOCK_QUIT, _('_Quit'), None, None, lambda *dummy: gtk.main_quit()), ('File', None, _('_File')), ('Preferences', gtk.STOCK_PREFERENCES, _( "Preferences"), None, None, self.cb_preferences_dialog), ('Edit', None, _("_Edit")), ('HelpContents', gtk.STOCK_HELP, _('Help Contents'), 'F1', None, lambda link: GuiBasic.open_url( help_contents_url, self.window)), ('ReleaseNotes', gtk.STOCK_INFO, _('_Release Notes'), None, None, lambda link: GuiBasic.open_url( release_notes_url, self.window)), ('SystemInformation', None, _('_System Information'), None, None, lambda foo: self.diagnostic_dialog(self.window)), ('About', gtk.STOCK_ABOUT, _( '_About'), None, None, 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 set_cleaner(self, path, model, parent_window, value=None): """Activate or deactive option of cleaner.""" if None == value: # if not value given, toggle current value value = not model[path][1] assert(type(value) is types.BooleanType) assert(type(model) is gtk.TreeStore) cleaner_id = None i = path if type(i) is str: # type is either str or gtk.TreeIter i = model.get_iter(path) parent = model.iter_parent(i) if None != parent: # this is an option (child), not a cleaner (parent) cleaner_id = model[parent][2] option_id = model[path][2] if cleaner_id and value: # when toggling an option, present any warnings warning = backends[cleaner_id].get_warning(option_id) # TRANSLATORS: %(cleaner) may be Firefox, System, etc. # %(option) may be cache, logs, cookies, etc. # %(warning) may be 'This option is really slow' msg = _("Warning regarding %(cleaner)s - %(option)s:\n\n%(warning)s") % \ {'cleaner': model[parent][0], 'option': model[path][0], 'warning': warning} if warning: resp = GuiBasic.message_dialog(parent_window, msg, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL) if gtk.RESPONSE_OK != resp: # user cancelled, so don't toggle option return model[path][1] = value
def about(self, __event): """Create and show the about dialog""" if 'nt' != os.name and (2, 16, 6) != gtk.gtk_version: # workaround for broken GTK+ # (https://bugs.launchpad.net/bleachbit/+bug/797012) gtk.about_dialog_set_url_hook(lambda dialog, link: GuiBasic.open_url(link, self.window, False)) dialog = gtk.AboutDialog() dialog.set_comments(_("Program to clean unnecessary files")) dialog.set_copyright("Copyright (C) 2014 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) # TRANSLATORS: Maintain the names of translators here. # Launchpad does this automatically for translations # typed in Launchpad. This is a special string shown # in the 'About' box. dialog.set_translator_credits(_("translator-credits")) dialog.set_version(APP_VERSION) dialog.set_website(APP_URL) dialog.set_transient_for(self.window) if appicon_path and os.path.exists(appicon_path): icon = gtk.gdk.pixbuf_new_from_file(appicon_path) dialog.set_logo(icon) dialog.run() dialog.hide()
def get_autostart_path(): """Return the path of the BleachBit shortcut in the user's startup folder""" try: startupdir = shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_STARTUP) except: # example of failure http://bleachbit.sourceforge.net/forum/error-windows-7-x64-bleachbit-091 traceback.print_exc() msg = 'Error finding user startup folder: %s ' % (str(sys.exc_info()[1])) import GuiBasic GuiBasic.message_dialog(None, msg) # as a fallback, guess # Windows XP: C:\Documents and Settings\(username)\Start Menu\Programs\Startup # Windows 7: C:\Users\(username)\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup startupdir = os.path.expandvars('$USERPROFILE\\Start Menu\\Programs\\Startup') if not os.path.exists(startupdir): startupdir = os.path.expandvars('$APPDATA\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup') return os.path.join(startupdir, 'bleachbit.lnk')
def cb_shred_file(self, action): """Callback for shredding a file or folder""" # get list of files if "ShredFiles" == action.get_name(): paths = GuiBasic.browse_files(self.window, _("Choose files to shred")) elif "ShredFolders" == action.get_name(): paths = GuiBasic.browse_folder( self.window, _("Choose folder to shred"), multiple=True, stock_button=gtk.STOCK_DELETE ) else: raise RuntimeError("Unexpected kind in cb_shred_file") if not paths: return self.shred_paths(paths)
def add_drive_cb(button): """Callback for adding a drive""" title = _("Choose a folder") pathname = GuiBasic.browse_folder(self.parent, title, multiple=False, stock_button=gtk.STOCK_ADD) if pathname: liststore.append([pathname]) pathnames.append(pathname) options.set_list('shred_drives', pathnames)
def cb_shred_file(self, action): """Callback for shredding a file or folder""" # get list of files if 'ShredFiles' == action.get_name(): paths = GuiBasic.browse_files(self.window, _("Choose files to shred")) elif 'ShredFolders' == action.get_name(): paths = GuiBasic.browse_folder(self.window, _("Choose folder to shred"), multiple=True, stock_button=gtk.STOCK_DELETE) else: raise RuntimeError("Unexpected kind in cb_shred_file") if not paths: return self.shred_paths(paths)
def run_operations(self, __widget): """Event when the 'delete' toolbar button is clicked.""" # fixme: should present this dialog after finding operations # Disable delete confirmation message. # if the option is selected under preference. self.stop_now = False print "Cleane clicked" , self.stop_now if not options.get("no_popup"): if not GuiBasic.delete_confirmation_dialog(self.window, True): return self.preview_or_run_operations(True)
def cb_wipe_free_space(self, action): """callback to wipe free space in arbitrary folder""" path = GuiBasic.browse_folder(self.window, _("Choose a folder"), multiple=False, stock_button=gtk.STOCK_OK) if not path: # user cancelled return backends["_gui"] = Cleaner.create_wipe_cleaner(path) # execute operations = {"_gui": ["free_disk_space"]} self.preview_or_run_operations(True, operations)
def add_custom_file_cb(button): """Callback for adding a file""" title = _("Choose a file") pathname = GuiBasic.browse_file(self.parent, title) if pathname: for this_pathname in pathnames: if pathname == this_pathname[1]: print "warning: '%s' already exists in whitelist" % pathname return liststore.append([_('File'), pathname]) pathnames.append(['file', pathname]) options.set_custom_paths(pathnames)
def cb_run_option(self, widget, really_delete, cleaner_id, option_id): """Callback from context menu to delete/preview a single option""" operations = {cleaner_id: [option_id]} # preview if not really_delete: self.preview_or_run_operations(False, operations) return # delete if GuiBasic.delete_confirmation_dialog(self.window, mention_preview=False): self.preview_or_run_operations(True, operations) return
def add_custom_folder_cb(button): """Callback for adding a folder""" title = _("Choose a folder") pathname = GuiBasic.browse_folder(self.parent, title, multiple=False, stock_button=gtk.STOCK_ADD) if pathname: for this_pathname in pathnames: if pathname == this_pathname[1]: print "warning: '%s' already exists in whitelist" % pathname return liststore.append([_('Folder'), pathname]) pathnames.append(['folder', pathname]) options.set_custom_paths(pathnames)
def cb_wipe_free_space(self, action): """callback to wipe free space in arbitrary folder""" path = GuiBasic.browse_folder(self.window, _("Choose a folder"), multiple=False, stock_button=gtk.STOCK_OK) if not path: # user cancelled return backends['_gui'] = Cleaner.create_wipe_cleaner(path) # execute operations = {'_gui': ['free_disk_space']} self.preview_or_run_operations(True, operations)
def shred_paths(self, paths): """Shred file or folders""" # create a temporary cleaner object backends['_gui'] = Cleaner.create_simple_cleaner(paths) # preview and confirm operations = {'_gui': ['files']} self.preview_or_run_operations(False, operations) if GuiBasic.delete_confirmation_dialog(self.window, mention_preview=False): # delete self.preview_or_run_operations(True, operations) return True return False
// dialog 실행 dialog.show_all() while True: if gtk.RESPONSE_ACCEPT != dialog.run(): sys.exit(0) delete = [] for row in liststore: b = row[0] path = row[1] if b: delete.append(path) if 0 == len(delete): # no files selected to delete break import GuiBasic if not GuiBasic.delete_confirmation_dialog(parent, mention_preview=False): continue for path in delete: logger.info("deleting unrecognized CleanerML '%s'", path) os.remove(path) break dialog.destroy() // 문자열에 대한 해시의 16진수 digest 반환 def hashdigest(string): return hashlib.sha512(string).hexdigest()
def create_menubar(self): """Create the menu bar (file, help)""" # Create a UIManager instance uimanager = gtk.UIManager() # Add the accelerator group to the top level 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 = ( ("ShredFiles", None, _("_Shred Files"), None, None, self.cb_shred_file), ("ShredFolders", None, _("Sh_red Folders"), None, None, self.cb_shred_file), ("WipeFreeSpace", None, _("_Wipe Free Space"), None, None, self.cb_wipe_free_space), ("ShredQuit", None, _("S_hred Settings and Quit"), None, None, self.cb_shred_quit), ("Quit", gtk.STOCK_QUIT, _("_Quit"), None, None, lambda *dummy: gtk.main_quit()), ("File", None, _("_File")), ("Preferences", gtk.STOCK_PREFERENCES, _("Preferences"), None, None, self.cb_preferences_dialog), ("Edit", None, _("_Edit")), ( "HelpContents", gtk.STOCK_HELP, _("Help Contents"), "F1", None, lambda link: GuiBasic.open_url(help_contents_url, self.window), ), ( "ReleaseNotes", gtk.STOCK_INFO, _("_Release Notes"), None, None, lambda link: GuiBasic.open_url(release_notes_url, self.window), ), ( "SystemInformation", None, _("_System Information"), None, None, lambda foo: self.diagnostic_dialog(self.window), ), ("About", gtk.STOCK_ABOUT, _("_About"), None, None, 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 cleaner_change_dialog(changes, parent): """Present a dialog regarding the change of cleaner definitions""" def toggled(cell, path, model): """Callback for clicking the checkbox""" __iter = model.get_iter_from_string(path) value = not model.get_value(__iter, 0) model.set(__iter, 0, value) import pygtk pygtk.require('2.0') import gtk dialog = gtk.Dialog(title=_("Security warning"), parent=parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) dialog.set_default_size(600, 500) # create warning warnbox = gtk.HBox() image = gtk.Image() image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) warnbox.pack_start(image, False) # TRANSLATORS: Cleaner definitions are XML data files that define # which files will be cleaned. label = gtk.Label( _("These cleaner definitions are new or have changed. Malicious definitions can damage your system. If you do not trust these changes, delete the files or quit.")) label.set_line_wrap(True) warnbox.pack_start(label, True) dialog.vbox.pack_start(warnbox, False) # create tree view liststore = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING) treeview = gtk.TreeView(model=liststore) renderer0 = gtk.CellRendererToggle() renderer0.set_property('activatable', True) renderer0.connect('toggled', toggled, liststore) # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( gtk.TreeViewColumn(_p('column_label', 'Delete'), renderer0, active=0)) renderer1 = gtk.CellRendererText() # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( gtk.TreeViewColumn(_p('column_label', 'Filename'), renderer1, text=1)) # populate tree view for change in changes: liststore.append([False, change[0]]) # populate dialog with widgets scrolled_window = gtk.ScrolledWindow() scrolled_window.add_with_viewport(treeview) dialog.vbox.pack_start(scrolled_window) dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) dialog.add_button(gtk.STOCK_QUIT, gtk.RESPONSE_CLOSE) # run dialog dialog.show_all() while True: if gtk.RESPONSE_ACCEPT != dialog.run(): sys.exit(0) delete = [] for row in liststore: b = row[0] path = row[1] if b: delete.append(path) if 0 == len(delete): # no files selected to delete break import GuiBasic if not GuiBasic.delete_confirmation_dialog(parent, mention_preview=False): # confirmation not accepted, so do not delete files continue for path in delete: print "info: deleting unrecognized CleanerML '%s'" % path os.remove(path) break dialog.destroy()
def cleaner_change_dialog(changes, parent): """Present a dialog regarding the change of cleaner definitions""" def toggled(cell, path, model): """Callback for clicking the checkbox""" __iter = model.get_iter_from_string(path) value = not model.get_value(__iter, 0) model.set(__iter, 0, value) # TODO: move to GuiBasic from bleachbit.GuiBasic import Gtk from gi.repository import GObject dialog = Gtk.Dialog(title=_("Security warning"), transient_for=parent, modal=True, destroy_with_parent=True) dialog.set_default_size(600, 500) # create warning warnbox = Gtk.Box() image = Gtk.Image() image.set_from_icon_name("dialog-warning", Gtk.IconSize.DIALOG) warnbox.pack_start(image, False, True, 0) # TRANSLATORS: Cleaner definitions are XML data files that define # which files will be cleaned. label = Gtk.Label( label=_("These cleaner definitions are new or have changed. Malicious definitions can damage your system. If you do not trust these changes, delete the files or quit.")) label.set_line_wrap(True) warnbox.pack_start(label, True, True, 0) dialog.vbox.pack_start(warnbox, False, True, 0) # create tree view liststore = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING) treeview = Gtk.TreeView(model=liststore) renderer0 = Gtk.CellRendererToggle() renderer0.set_property('activatable', True) renderer0.connect('toggled', toggled, liststore) # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( Gtk.TreeViewColumn(_p('column_label', 'Delete'), renderer0, active=0)) renderer1 = Gtk.CellRendererText() # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( Gtk.TreeViewColumn(_p('column_label', 'Filename'), renderer1, text=1)) # populate tree view for change in changes: liststore.append([False, change[0]]) # populate dialog with widgets scrolled_window = Gtk.ScrolledWindow() scrolled_window.add(treeview) dialog.vbox.pack_start(scrolled_window, True, True, 0) dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT) dialog.add_button(Gtk.STOCK_QUIT, Gtk.ResponseType.CLOSE) # run dialog dialog.show_all() while True: if Gtk.ResponseType.ACCEPT != dialog.run(): sys.exit(0) delete = [] for row in liststore: b = row[0] path = row[1] if b: delete.append(path) if 0 == len(delete): # no files selected to delete break import GuiBasic if not GuiBasic.delete_confirmation_dialog(parent, mention_preview=False): # confirmation not accepted, so do not delete files continue for path in delete: logger.info("deleting unrecognized CleanerML '%s'", path) os.remove(path) break dialog.destroy()
def run_operations(self, __widget): """Event when the 'delete' toolbar button is clicked.""" # fixme: should present this dialog after finding operations if not GuiBasic.delete_confirmation_dialog(self.window, True): return self.preview_or_run_operations(True)
def cleaner_change_dialog(changes, parent): """Present a dialog regarding the change of cleaner definitions 클리너 정의의 변경에 관한 다이얼로그 제시""" def toggled(cell, path, model): """Callback for clicking the checkbox 체크박스를 클릭하기 위한 콜백함수""" __iter = model.get_iter_from_string(path) # path_sring으로 표시되는 경로를 가리키는 gtk.TreeIter를 추출 value = not model.get_value(__iter, 0) # ??? model.set(__iter, 0, value) # ??? import pygtk pygtk.require('2.0') import gtk dialog = gtk.Dialog(title=_("Security warning"), parent=parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) dialog.set_default_size(600, 500) # create warning warnbox = gtk.HBox() image = gtk.Image() image.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) warnbox.pack_start(image, False) # TRANSLATORS: Cleaner definitions are XML data files that define # which files will be cleaned. label = gtk.Label( _("These cleaner definitions are new or have changed. Malicious definitions can damage your system. If you do not trust these changes, delete the files or quit." )) label.set_line_wrap(True) warnbox.pack_start(label, True) dialog.vbox.pack_start(warnbox, False) # create tree view import gobject liststore = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING) treeview = gtk.TreeView(model=liststore) renderer0 = gtk.CellRendererToggle() renderer0.set_property('activatable', True) renderer0.connect('toggled', toggled, liststore) # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( gtk.TreeViewColumn(_p('column_label', 'Delete'), renderer0, active=0)) renderer1 = gtk.CellRendererText() # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( gtk.TreeViewColumn(_p('column_label', 'Filename'), renderer1, text=1)) # populate tree view for change in changes: liststore.append([False, change[0]]) # populate dialog with widgets scrolled_window = gtk.ScrolledWindow() scrolled_window.add_with_viewport(treeview) dialog.vbox.pack_start(scrolled_window) dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) dialog.add_button(gtk.STOCK_QUIT, gtk.RESPONSE_CLOSE) # run dialog dialog.show_all() while True: if gtk.RESPONSE_ACCEPT != dialog.run(): sys.exit(0) delete = [] for row in liststore: b = row[0] path = row[1] if b: delete.append(path) if 0 == len(delete): # no files selected to delete break import GuiBasic if not GuiBasic.delete_confirmation_dialog(parent, mention_preview=False): # confirmation not accepted, so do not delete files continue for path in delete: logger.info("deleting unrecognized CleanerML '%s'", path) os.remove(path) break dialog.destroy()
def cleaner_change_dialog(changes, parent): """Present a dialog regarding the change of cleaner definitions""" def toggled(cell, path, model): """Callback for clicking the checkbox""" __iter = model.get_iter_from_string(path) value = not model.get_value(__iter, 0) model.set(__iter, 0, value) # TODO: move to GuiBasic from bleachbit.GuiBasic import Gtk from gi.repository import GObject dialog = Gtk.Dialog(title=_("Security warning"), transient_for=parent, modal=True, destroy_with_parent=True) dialog.set_default_size(600, 500) # create warning warnbox = Gtk.Box() image = Gtk.Image() image.set_from_icon_name("dialog-warning", Gtk.IconSize.DIALOG) warnbox.pack_start(image, False, True, 0) # TRANSLATORS: Cleaner definitions are XML data files that define # which files will be cleaned. label = Gtk.Label(label=_( "These cleaner definitions are new or have changed. Malicious definitions can damage your system. If you do not trust these changes, delete the files or quit." )) label.set_line_wrap(True) warnbox.pack_start(label, True, True, 0) dialog.vbox.pack_start(warnbox, False, True, 0) # create tree view liststore = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING) treeview = Gtk.TreeView(model=liststore) renderer0 = Gtk.CellRendererToggle() renderer0.set_property('activatable', True) renderer0.connect('toggled', toggled, liststore) # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( Gtk.TreeViewColumn(_p('column_label', 'Delete'), renderer0, active=0)) renderer1 = Gtk.CellRendererText() # TRANSLATORS: This is the column label (header) in the tree view for the # security dialog treeview.append_column( Gtk.TreeViewColumn(_p('column_label', 'Filename'), renderer1, text=1)) # populate tree view for change in changes: liststore.append([False, change[0]]) # populate dialog with widgets scrolled_window = Gtk.ScrolledWindow() scrolled_window.add(treeview) dialog.vbox.pack_start(scrolled_window, True, True, 0) dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT) dialog.add_button(Gtk.STOCK_QUIT, Gtk.ResponseType.CLOSE) # run dialog dialog.show_all() while True: if Gtk.ResponseType.ACCEPT != dialog.run(): sys.exit(0) delete = [] for row in liststore: b = row[0] path = row[1] if b: delete.append(path) if 0 == len(delete): # no files selected to delete break import GuiBasic if not GuiBasic.delete_confirmation_dialog(parent, mention_preview=False): # confirmation not accepted, so do not delete files continue for path in delete: logger.info("deleting unrecognized CleanerML '%s'", path) os.remove(path) break dialog.destroy()