def create_toolbar(self): """Create the toolbar""" toolbar = gtk.Toolbar() # create the preview button preview_icon = gtk.Image() preview_icon.set_from_stock( gtk.STOCK_FIND, gtk.ICON_SIZE_LARGE_TOOLBAR) # TRANSLATORS: This is the preview button on the main window. It # previews changes. preview_button = gtk.ToolButton( icon_widget=preview_icon, label=_p('button', "Preview")) preview_button.connect( "clicked", lambda *dummy: self.preview_or_run_operations(False)) toolbar.insert(preview_button, -1) preview_button.set_tooltip_text( _("Preview files in the selected operations (without deleting any files)")) preview_button.set_is_important(True) # create the delete button icon = gtk.Image() icon.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_LARGE_TOOLBAR) # TRANSLATORS: This is the clean button on the main window. # It makes permanent changes: usually deleting files, sometimes # altering them. run_button = gtk.ToolButton( icon_widget=icon, label=_p("button", "Clean")) run_button.connect("clicked", self.run_operations) toolbar.insert(run_button, -1) run_button.set_tooltip_text( _("Clean files in the selected operations")) run_button.set_is_important(True) return toolbar
def create_toolbar(self): """Create the toolbar""" toolbar = gtk.Toolbar() # create the preview button preview_icon = gtk.Image() preview_icon.set_from_stock( gtk.STOCK_FIND, gtk.ICON_SIZE_LARGE_TOOLBAR) # TRANSLATORS: This is the preview button on the main window. It # previews changes. preview_button = gtk.ToolButton( icon_widget=preview_icon, label=_p('button', "Preview")) preview_button.connect( "clicked", lambda *dummy: self.preview_or_run_operations(False)) toolbar.insert(preview_button, -1) preview_button.set_tooltip_text( _("Preview files in the selected operations (without deleting any files)")) preview_button.set_is_important(True) # create the delete button icon = gtk.Image() icon.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_LARGE_TOOLBAR) # TRANSLATORS: This is the clean button on the main window. # It makes permanent changes: usually deleting files, sometimes # altering them. run_button = gtk.ToolButton( icon_widget=icon, label=_p("button", "Clean")) run_button.connect("clicked", self.run_operations) toolbar.insert(run_button, -1) run_button.set_tooltip_text( _("Clean files in the selected operations")) run_button.set_is_important(True) # create the stop icon = gtk.Image() icon.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_LARGE_TOOLBAR) # TRANSLATORS: This is the clean button on the main window. # It makes permanent changes: usually deleting files, sometimes # altering them. run_button = gtk.ToolButton( icon_widget=icon, label=_p("button", "Stop!")) run_button.connect("clicked", self.run_operations_stop) toolbar.insert(run_button, -1) run_button.set_tooltip_text( _("STOP the running operations")) run_button.set_is_important(True) return toolbar
def __locations_page(self, page_type): """Return a widget containing a list of files and folders""" def add_whitelist_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_whitelist_paths(pathnames) def add_whitelist_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_whitelist_paths(pathnames) def remove_whitelist_path_cb(button): """Callback for removing a path""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][1] liststore.remove(_iter) for this_pathname in pathnames: if this_pathname[1] == pathname: pathnames.remove(this_pathname) options.set_whitelist_paths(pathnames) 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 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 remove_custom_path_cb(button): """Callback for removing a path""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][1] liststore.remove(_iter) for this_pathname in pathnames: if this_pathname[1] == pathname: pathnames.remove(this_pathname) options.set_custom_paths(pathnames) vbox = gtk.VBox() # load data if LOCATIONS_WHITELIST == page_type: pathnames = options.get_whitelist_paths() elif LOCATIONS_CUSTOM == page_type: pathnames = options.get_custom_paths() liststore = gtk.ListStore(str, str) for paths in pathnames: type_code = paths[0] type_str = None if type_code == 'file': type_str = _('File') elif type_code == 'folder': type_str = _('Folder') else: raise RuntimeError("Invalid type code: '%s'" % type_code) path = paths[1] liststore.append([type_str, path]) if LOCATIONS_WHITELIST == page_type: # TRANSLATORS: "Paths" is used generically to refer to both files # and folders notice = gtk.Label( _("Theses paths will not be deleted or modified.")) elif LOCATIONS_CUSTOM == page_type: notice = gtk.Label( _("These locations can be selected for deletion.")) vbox.pack_start(notice) # create treeview treeview = gtk.TreeView(liststore) # create column views self.renderer0 = gtk.CellRendererText() self.column0 = gtk.TreeViewColumn(_("Type"), self.renderer0, text=0) treeview.append_column(self.column0) self.renderer1 = gtk.CellRendererText() # TRANSLATORS: In the tree view "Path" is used generically to refer to a # file, a folder, or a pattern describing either self.column1 = gtk.TreeViewColumn(_("Path"), self.renderer1, text=1) treeview.append_column(self.column1) treeview.set_search_column(1) # finish tree view swindow = gtk.ScrolledWindow() swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swindow.set_size_request(300, 200) swindow.add(treeview) vbox.pack_start(swindow, False) # buttons that modify the list button_add_file = gtk.Button(_p('button', 'Add file')) if LOCATIONS_WHITELIST == page_type: button_add_file.connect("clicked", add_whitelist_file_cb) elif LOCATIONS_CUSTOM == page_type: button_add_file.connect("clicked", add_custom_file_cb) button_add_folder = gtk.Button(_p('button', 'Add folder')) if LOCATIONS_WHITELIST == page_type: button_add_folder.connect("clicked", add_whitelist_folder_cb) elif LOCATIONS_CUSTOM == page_type: button_add_folder.connect("clicked", add_custom_folder_cb) button_remove = gtk.Button(_p('button', 'Remove')) if LOCATIONS_WHITELIST == page_type: button_remove.connect("clicked", remove_whitelist_path_cb) elif LOCATIONS_CUSTOM == page_type: button_remove.connect("clicked", remove_custom_path_cb) button_box = gtk.HButtonBox() button_box.set_layout(gtk.BUTTONBOX_START) button_box.pack_start(button_add_file) button_box.pack_start(button_add_folder) button_box.pack_start(button_remove) vbox.pack_start(button_box, False) # return page return vbox
def __drives_page(self): """Return widget containing the drives page""" 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 remove_drive_cb(button): """Callback for removing a drive""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][0] liststore.remove(_iter) pathnames.remove(pathname) options.set_list('shred_drives', pathnames) vbox = gtk.VBox() # TRANSLATORS: 'free' means 'unallocated' notice = gtk.Label( _("Choose a writable folder for each drive for which to overwrite free space.")) notice.set_line_wrap(True) vbox.pack_start(notice, False) liststore = gtk.ListStore(str) pathnames = options.get_list('shred_drives') if pathnames: pathnames = sorted(pathnames) if not pathnames: pathnames = [] for pathname in pathnames: liststore.append([pathname]) treeview = gtk.TreeView(model=liststore) crt = gtk.CellRendererText() tvc = gtk.TreeViewColumn(None, crt, text=0) treeview.append_column(tvc) vbox.pack_start(treeview) # TRANSLATORS: In the preferences dialog, this button adds a path to # the list of paths button_add = gtk.Button(_p('button', 'Add')) button_add.connect("clicked", add_drive_cb) # TRANSLATORS: In the preferences dialog, this button removes a path # from the list of paths button_remove = gtk.Button(_p('button', 'Remove')) button_remove.connect("clicked", remove_drive_cb) button_box = gtk.HButtonBox() button_box.set_layout(gtk.BUTTONBOX_START) button_box.pack_start(button_add) button_box.pack_start(button_remove) vbox.pack_start(button_box, False) return vbox
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) 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 __locations_page(self, page_type): """Return a widget containing a list of files and folders""" def add_whitelist_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_whitelist_paths(pathnames) def add_whitelist_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_whitelist_paths(pathnames) def remove_whitelist_path_cb(button): """Callback for removing a path""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][1] liststore.remove(_iter) for this_pathname in pathnames: if this_pathname[1] == pathname: pathnames.remove(this_pathname) options.set_whitelist_paths(pathnames) 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 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 remove_custom_path_cb(button): """Callback for removing a path""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][1] liststore.remove(_iter) for this_pathname in pathnames: if this_pathname[1] == pathname: pathnames.remove(this_pathname) options.set_custom_paths(pathnames) vbox = gtk.VBox() # load data if LOCATIONS_WHITELIST == page_type: pathnames = options.get_whitelist_paths() elif LOCATIONS_CUSTOM == page_type: pathnames = options.get_custom_paths() liststore = gtk.ListStore(str, str) for paths in pathnames: type_code = paths[0] type_str = None if type_code == 'file': type_str = _('File') elif type_code == 'folder': type_str = _('Folder') else: raise RuntimeError("Invalid type code: '%s'" % type_code) path = paths[1] liststore.append([type_str, path]) if LOCATIONS_WHITELIST == page_type: # TRANSLATORS: "Paths" is used generically to refer to both files # and folders notice = gtk.Label( _("Theses paths will not be deleted or modified.")) elif LOCATIONS_CUSTOM == page_type: notice = gtk.Label( _("These locations can be selected for deletion.")) vbox.pack_start(notice, False) # create treeview treeview = gtk.TreeView(liststore) # create column views self.renderer0 = gtk.CellRendererText() self.column0 = gtk.TreeViewColumn(_("Type"), self.renderer0, text=0) treeview.append_column(self.column0) self.renderer1 = gtk.CellRendererText() # TRANSLATORS: In the tree view "Path" is used generically to refer to a # file, a folder, or a pattern describing either self.column1 = gtk.TreeViewColumn(_("Path"), self.renderer1, text=1) treeview.append_column(self.column1) treeview.set_search_column(1) # finish tree view swindow = gtk.ScrolledWindow() swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) swindow.set_size_request(300, 200) swindow.add(treeview) vbox.pack_start(swindow) # buttons that modify the list button_add_file = gtk.Button(_p('button', 'Add file')) if LOCATIONS_WHITELIST == page_type: button_add_file.connect("clicked", add_whitelist_file_cb) elif LOCATIONS_CUSTOM == page_type: button_add_file.connect("clicked", add_custom_file_cb) button_add_folder = gtk.Button(_p('button', 'Add folder')) if LOCATIONS_WHITELIST == page_type: button_add_folder.connect("clicked", add_whitelist_folder_cb) elif LOCATIONS_CUSTOM == page_type: button_add_folder.connect("clicked", add_custom_folder_cb) button_remove = gtk.Button(_p('button', 'Remove')) if LOCATIONS_WHITELIST == page_type: button_remove.connect("clicked", remove_whitelist_path_cb) elif LOCATIONS_CUSTOM == page_type: button_remove.connect("clicked", remove_custom_path_cb) button_box = gtk.HButtonBox() button_box.set_layout(gtk.BUTTONBOX_START) button_box.pack_start(button_add_file) button_box.pack_start(button_add_folder) button_box.pack_start(button_remove) vbox.pack_start(button_box, False) # return page return vbox
def __drives_page(self): """Return widget containing the drives page""" 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 remove_drive_cb(button): """Callback for removing a drive""" treeselection = treeview.get_selection() (model, _iter) = treeselection.get_selected() if None == _iter: # nothing selected return pathname = model[_iter][0] liststore.remove(_iter) pathnames.remove(pathname) options.set_list('shred_drives', pathnames) vbox = gtk.VBox() # TRANSLATORS: 'free' means 'unallocated' notice = gtk.Label( _("Choose a writable folder for each drive for which to overwrite free space." )) notice.set_line_wrap(True) vbox.pack_start(notice, False) liststore = gtk.ListStore(str) pathnames = options.get_list('shred_drives') if pathnames: pathnames = sorted(pathnames) if not pathnames: pathnames = [] for pathname in pathnames: liststore.append([pathname]) treeview = gtk.TreeView(model=liststore) crt = gtk.CellRendererText() tvc = gtk.TreeViewColumn(None, crt, text=0) treeview.append_column(tvc) vbox.pack_start(treeview) # TRANSLATORS: In the preferences dialog, this button adds a path to # the list of paths button_add = gtk.Button(_p('button', 'Add')) button_add.connect("clicked", add_drive_cb) # TRANSLATORS: In the preferences dialog, this button removes a path # from the list of paths button_remove = gtk.Button(_p('button', 'Remove')) button_remove.connect("clicked", remove_drive_cb) button_box = gtk.HButtonBox() button_box.set_layout(gtk.BUTTONBOX_START) button_box.pack_start(button_add) button_box.pack_start(button_remove) vbox.pack_start(button_box, False) return vbox