class BoardWidget(QWidget): def __init__(self, *args, **kwargs): engine = kwargs.pop('engine') super(BoardWidget, self).__init__(*args, **kwargs) self.setupEngine(engine) self.setupUi() def setupEngine(self, engine): self.engine = engine self.engine.playerMoved.connect(self.handlePlayerMoved) def setupUi(self): grid = QGridLayout() grid.setSpacing(GRID_SPACING) self.setLayout(grid) self.buttonGroup = QButtonGroup() for position in self.engine.board.positions: button = GameButton(position) self.buttonGroup.addButton(button, position) grid.addWidget(button, position / 3, position % 3) self.buttonGroup.buttonClicked['int'].connect(self.engine.handleInput) size = 4 * GRID_SPACING + 3 * BUTTON_SIZE self.setFixedSize(size, size) def handlePlayerMoved(self, position, player): self.buttonGroup.buttons()[position].markPlayer(player) def resetUi(self): for button in self.buttonGroup.buttons(): button.clearText()
class ActionsPane(QWidget): def __init__(self): super().__init__() self.group = QButtonGroup() self.group.setExclusive(False) self.scope_widget = ActionsScope() self.action_buttons = QVBoxLayout() self.big_red_button = QPushButton("Automate !!!", clicked=self.automate) self.big_red_button.setStyleSheet("QPushButton { background-color : red}") self.layout = QVBoxLayout() self.setLayout(self.layout) self.layout.addWidget(self.scope_widget) self.layout.addLayout(self.action_buttons) self.layout.addStretch() self.layout.addWidget(self.big_red_button) def registerAction(self, action): button = ActionButton(action) self.group.addButton(button.checkbox) self.action_buttons.addWidget(button) def getCheckedActions(self): return [btn.parent().action for btn in self.group.buttons() if btn.isChecked()] def automate(self, event): for action in self.getCheckedActions(): action.on_triggered()
class ScopeBox(QGroupBox): title = None button_type = None def __init__(self): if self.title is None or self.button_type is None: raise Exception("Still too abstract!") super().__init__(title=self.title) self.populate_button_id() self.build_layout() self.populate_box() self.select_default() if self.button_type == 'check': self.group.setExclusive(False) def populate_button_id(self): pass def build_layout(self): self.group = QButtonGroup() self.layout = QVBoxLayout() self.setLayout(self.layout) def populate_box(self): keys = list(self.button_id.keys()) keys.sort() BtnClass = None if self.button_type == 'check': BtnClass = QCheckBox elif self.button_type == 'radio': BtnClass = QRadioButton for key in keys: btn = BtnClass(key) self.layout.addWidget(btn) self.group.addButton(btn, self.button_id[key]) def select_default(self): pass def getSelection(self): selection = None if self.button_type == 'radio': selection = self.group.checkedId() elif self.button_type == 'check': selection = [] for btn in self.group.buttons(): if btn.isChecked(): selection.append(btn.text()) return selection
class DBDatabasesWidget(QWidget): """Displays a list of Databases""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.db = None self.setWindowTitle("Databases") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setHeaderLabels(["Server", "User", ""]) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(False) self.tree.setColumnWidth(C.widget, 20) self.connect(self.tree, SIGNAL('itemSelectionChanged()'), self.on_tree_selection_changed) self.connect(self.tree, SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.on_tree_double_clicked) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def on_open_server(self, butt): self.emit(SIGNAL("open_server"), butt.property("server").toString()) def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.server, srv['server']) item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.widget, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers()
class OptionWidget(EditorWidget): widgettype = 'Option Row' def __init__(self, *args, **kwargs): super(OptionWidget, self).__init__(*args, **kwargs) self._bindvalue = None self.group = QButtonGroup() self.group.buttonClicked.connect(self.emitvaluechanged) def createWidget(self, parent=None): widget = QWidget(parent) return widget def _buildfromlist(self, listconfig, multiselect): def chunks(l, n): """ Yield successive n-sized chunks from l. """ for i in xrange(0, len(l), n): yield l[i:i+n] items = listconfig['items'] wrap = self.config.get('wrap', 0) showcolor = self.config.get('always_color', False) if wrap > 0: rows = list(chunks(items, wrap)) else: rows = [items] for rowcount, row in enumerate(rows): for column, item in enumerate(row): parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data button = QPushButton() button.setCheckable(multiselect) self.group.setExclusive(not multiselect) icon = QIcon() try: path = parts[2] if path.startswith("#"): # Colour the button with the hex value. # If show color is enabled we always show the color regardless of selection. print showcolor if not showcolor: style = """ QPushButton::checked {{ border: 3px solid rgb(137, 175, 255); background-color: {colour}; }}""".format(colour=path) else: style = """ QPushButton::checked {{ border: 3px solid rgb(137, 175, 255); }} QPushButton {{ background-color: {colour}; }}""".format(colour=path) button.setStyleSheet(style) elif path.endswith("_icon"): icon = QIcon(":/icons/{}".format(path)) else: icon = QIcon(path) except: icon = QIcon() button.setCheckable(True) button.setText(desc) button.setProperty("value", data) button.setIcon(icon) button.setIconSize(QSize(24, 24)) if isinstance(self.widget.layout(), QBoxLayout): self.widget.layout().addWidget(button) else: self.widget.layout().addWidget(button, rowcount, column) self.group.addButton(button) def initWidget(self, widget, config): if not widget.layout(): widget.setLayout(QGridLayout()) widget.layout().setContentsMargins(0, 0, 0, 0) def updatefromconfig(self): super(OptionWidget, self).updatefromconfig() for button in self.group.buttons(): self.group.removeButton(button) self.widget.layout().removeWidget(button) button.deleteLater() button.setParent(None) listconfig = self.config['list'] multiselect = self.config.get('multi', False) self._buildfromlist(listconfig, multiselect) super(OptionWidget, self).endupdatefromconfig() def validate(self, *args): button = self.group.checkedButton() if button: return True return False @property def buttons(self): return self.group.buttons() @property def nullvalues(self): return ['NULL'] @property def multioption(self): return self.config.get('multi', False) def setvalue(self, value): def set_button(setvalue): for button in self.group.buttons(): buttonvalue = button.property("value") if (setvalue is None and buttonvalue in self.nullvalues) or buttonvalue == str(setvalue): button.setChecked(True) self.emitvaluechanged() return if value in self.nullvalues: value = None if self.multioption and value: values = value.split(';') else: values = [value] for value in values: set_button(value) def value(self): def _returnvalue(): if self.multioption: _values = [] checked = [button for button in self.group.buttons() if button.isChecked()] for button in checked: value = button.property("value") _values.append(value) if not _values: return None return ";".join(_values) else: checked = self.group.checkedButton() if not checked: return None value = checked.property("value") return value returnvalue = _returnvalue() if returnvalue in self.nullvalues: returnvalue = None return returnvalue
class OptionWidget(EditorWidget): widgettype = 'Option Row' def __init__(self, *args): super(OptionWidget, self).__init__(*args) self._bindvalue = None self.group = QButtonGroup() self.group.setExclusive(True) self.group.buttonClicked.connect(self.emitvaluechanged) def createWidget(self, parent): widget = QWidget(parent) return widget def _buildfromlist(self, listconfig): items = listconfig['items'] for item in items: parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data button = QPushButton() icon = QIcon() try: path = parts[2] if path.startswith("#"): # Colour the button with the hex value style = """ QPushButton:checked {{ border: 3px solid rgb(137, 175, 255); background-color: {colour}; }}""".format(colour=path) button.setStyleSheet(style) elif path.endswith("_icon"): icon = QIcon(":/icons/{}".format(path)) else: icon = QIcon(path) except: icon = QIcon() button.setCheckable(True) button.setText(desc) button.setProperty("value", data) button.setIcon(icon) button.setIconSize(QSize(24, 24)) self.widget.layout().addWidget(button) self.group.addButton(button) def initWidget(self, widget): if not widget.layout(): widget.setLayout(QHBoxLayout()) widget.layout().setContentsMargins(0, 0, 0, 0) def updatefromconfig(self): super(OptionWidget, self).updatefromconfig() for button in self.group.buttons(): self.group.removeButton(button) self.widget.layout().removeWidget(button) button.deleteLater() button.setParent(None) listconfig = self.config['list'] self._buildfromlist(listconfig) super(OptionWidget, self).endupdatefromconfig() def validate(self, *args): button = self.group.checkedButton() if button: return True return False @property def nullvalues(self): return ['NULL'] def setvalue(self, value): if value in self.nullvalues: value = None for button in self.group.buttons(): buttonvalue = button.property("value") if (value is None and buttonvalue in self.nullvalues) or buttonvalue == str(value): button.setChecked(True) self.emitvaluechanged() return def value(self): button = self.group.checkedButton() if not button: return None value = button.property("value") if value in self.nullvalues: value = None return value
class XNavigationEdit(XLineEdit): """ """ navigationChanged = Signal() __designer_icon__ = projexui.resources.find('img/ui/navigate.png') def __init__( self, parent = None ): super(XNavigationEdit, self).__init__( parent ) # define custom properties self._separator = '/' self._partsEditingEnabled = True self._originalText = '' self._scrollWidget = QScrollArea(self) self._partsWidget = QWidget(self._scrollWidget) self._buttonGroup = QButtonGroup(self) self._scrollAmount = 0 self._navigationModel = None # create the completer tree palette = self.palette() palette.setColor(palette.Base, palette.color(palette.Window)) palette.setColor(palette.Text, palette.color(palette.WindowText)) bg = palette.color(palette.Highlight) abg = bg.darker(115) fg = palette.color(palette.HighlightedText) sbg = 'rgb(%s, %s, %s)' % (bg.red(), bg.green(), bg.blue()) sabg = 'rgb(%s, %s, %s)' % (abg.red(), abg.green(), abg.blue()) sfg = 'rgb(%s, %s, %s)' % (fg.red(), fg.green(), fg.blue()) style = 'QTreeView::item:hover { '\ ' color: %s;'\ ' background: qlineargradient(x1:0,'\ ' y1:0,'\ ' x2:0,'\ ' y2:1,'\ ' stop: 0 %s,'\ ' stop: 1 %s);'\ '}' % (sfg, sbg, sabg) self._completerTree = QTreeView(self) self._completerTree.setStyleSheet(style) self._completerTree.header().hide() self._completerTree.setFrameShape(QTreeView.Box) self._completerTree.setFrameShadow(QTreeView.Plain) self._completerTree.setPalette(palette) self._completerTree.setEditTriggers(QTreeView.NoEditTriggers) self._completerTree.setWindowFlags(Qt.Popup) self._completerTree.installEventFilter(self) self._completerTree.setRootIsDecorated(False) self._completerTree.setItemsExpandable(False) # create the editing widget layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addStretch() self._scrollWidget.setFrameShape( QScrollArea.NoFrame ) self._scrollWidget.setFocusPolicy(Qt.NoFocus) self._scrollWidget.setWidget(self._partsWidget) self._scrollWidget.setWidgetResizable(True) self._scrollWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scrollWidget.setAlignment(Qt.AlignTop | Qt.AlignRight) self._scrollWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scrollWidget.setContentsMargins(0, 0, 0, 0) self._scrollWidget.setViewportMargins(0, 0, 0, 0) self._scrollWidget.move(2, 2) self._partsWidget.setLayout(layout) self._partsWidget.setCursor(Qt.ArrowCursor) self._partsWidget.setAutoFillBackground(True) self._partsWidget.setFixedHeight(self.height() - 12) palette = self._partsWidget.palette() palette.setColor(palette.Background, palette.color(palette.Base)) self._partsWidget.setPalette(palette) # create connections self._completerTree.clicked.connect( self.navigateToIndex ) self._buttonGroup.buttonClicked.connect( self.handleButtonClick ) self._scrollWidget.horizontalScrollBar().valueChanged.connect( self.scrollParts ) def acceptEdit( self ): """ Accepts the current text and rebuilds the parts widget. """ if ( self._partsWidget.isVisible() ): return False use_completion = self.completer().popup().isVisible() completion = self.completer().currentCompletion() self._completerTree.hide() self.completer().popup().hide() if ( use_completion ): self.setText(completion) else: self.rebuild() return True def cancelEdit( self ): """ Rejects the current edit and shows the parts widget. """ if ( self._partsWidget.isVisible() ): return False self._completerTree.hide() self.completer().popup().hide() self.setText(self._originalText) return True def currentItem( self ): """ Returns the current navigation item from the current path. :return <XNavigationItem> || None """ model = self.navigationModel() if ( not model ): return None return model.itemByPath(self.text()) def eventFilter( self, object, event ): """ Filters the events for the inputed object through this edit. :param object | <QObject> event | <QEvent> :return <bool> | consumed """ if ( event.type() == event.KeyPress ): if ( event.key() == Qt.Key_Escape ): self._completerTree.hide() self.completer().popup().hide() self.cancelEdit() elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ): self.acceptEdit() return True elif ( event.key() == Qt.Key_Tab ): if ( self.completer().popup().isVisible() ): text = str(self.completer().currentCompletion()) super(XNavigationEdit, self).setText(text) return True else: self.acceptEdit() return False elif ( event.type() == event.MouseButtonPress ): if ( not self._completerTree.rect().contains(event.pos()) ): self._completerTree.hide() self.completer().popup().hide() self.cancelEdit() return False def focusOutEvent( self, event ): """ Overloads the focus out event to cancel editing when the widget loses focus. :param event | <QFocusEvent> """ super(XNavigationEdit, self).focusOutEvent(event) self.cancelEdit() def handleButtonClick( self, button ): """ Handle the event when a user clicks on one of the part buttons. :param button | <QToolButton> """ path = button.property('path') is_completer = button.property('is_completer') # popup a completion menu if ( unwrapVariant(is_completer) ): model = self.navigationModel() if ( not model ): return sep = self.separator() path = str(unwrapVariant(path)) item = model.itemByPath(path, includeRoot = True) if ( not item ): return curr_path = str(self.text()).strip(self.separator()) curr_path = curr_path.replace(path, '').strip(self.separator()) child_name = '' if ( curr_path ): child_name = curr_path.split(self.separator())[0] index = model.indexFromItem(item) self._completerTree.move(QCursor.pos()) self._completerTree.setRootIndex(index) self._completerTree.verticalScrollBar().setValue(0) if ( child_name ): child_item = None for i in range(item.rowCount()): child = item.child(i) if ( child.text() == child_name ): child_item = child break if ( child_item ): child_index = model.indexFromItem(child_item) self._completerTree.setCurrentIndex(child_index) self._completerTree.scrollTo(child_index) self._completerTree.show() self._completerTree.setUpdatesEnabled(True) else: self.setText(unwrapVariant(path)) def keyPressEvent( self, event ): """ Overloads the key press event to listen for escape calls to cancel the parts editing. :param event | <QKeyPressEvent> """ if ( self.scrollWidget().isHidden() ): if ( event.key() == Qt.Key_Escape ): self.cancelEdit() return elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ): self.acceptEdit() return elif ( event.key() == Qt.Key_A and event.modifiers() == Qt.ControlModifier ): self.startEdit() super(XNavigationEdit, self).keyPressEvent(event) def mouseDoubleClickEvent( self, event ): """ Overloads the system to enable editing when a user double clicks. :param event | <QMouseEvent> """ super(XNavigationEdit, self).mouseDoubleClickEvent(event) self.startEdit() def navigationModel( self ): """ Returns the navigation model linked with this edit. :return <XNavigationModel> || None """ return self._navigationModel def navigateToIndex( self, index ): """ Navigates to the inputed action's path. :param action | <QAction> """ self._completerTree.hide() item = self._navigationModel.itemFromIndex(index) self.setText(self._navigationModel.itemPath(item)) def parts( self ): """ Returns the parts that are used for this system. :return [<str>, ..] """ path = str(self.text()).strip(self.separator()) if ( not path ): return [] return path.split(self.separator()) def partsWidget( self ): """ Returns the widget that contains the parts system. :return <QScrollArea> """ return self._partsWidget def startEdit( self ): """ Rebuilds the pathing based on the parts. """ self._originalText = self.text() self.scrollWidget().hide() self.setFocus() self.selectAll() def rebuild( self ): """ Rebuilds the parts widget with the latest text. """ navitem = self.currentItem() if ( navitem ): navitem.initialize() self.setUpdatesEnabled(False) self.scrollWidget().show() self._originalText = '' partsw = self.partsWidget() for button in self._buttonGroup.buttons(): self._buttonGroup.removeButton(button) button.close() button.setParent(None) button.deleteLater() # create the root button layout = partsw.layout() parts = self.parts() button = QToolButton(partsw) button.setAutoRaise(True) button.setMaximumWidth(12) button.setArrowType(Qt.RightArrow) button.setProperty('path', wrapVariant('')) button.setProperty('is_completer', wrapVariant(True)) last_button = button self._buttonGroup.addButton(button) layout.insertWidget(0, button) # check to see if we have a navigation model setup if ( self._navigationModel ): last_item = self._navigationModel.itemByPath(self.text()) show_last = last_item and last_item.rowCount() > 0 else: show_last = False # load the navigation system count = len(parts) for i, part in enumerate(parts): path = self.separator().join(parts[:i+1]) button = QToolButton(partsw) button.setAutoRaise(True) button.setText(part) if ( self._navigationModel ): item = self._navigationModel.itemByPath(path) if ( item ): button.setIcon(item.icon()) button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) button.setProperty('path', wrapVariant(path)) button.setProperty('is_completer', wrapVariant(False)) self._buttonGroup.addButton(button) layout.insertWidget((i * 2) + 1, button) # determine if we should show the final button if ( show_last or i < (count - 1) ): button = QToolButton(partsw) button.setAutoRaise(True) button.setMaximumWidth(12) button.setArrowType(Qt.RightArrow) button.setProperty('path', wrapVariant(path)) button.setProperty('is_completer', wrapVariant(True)) self._buttonGroup.addButton(button) layout.insertWidget((i * 2) + 2, button) last_button = button if ( self.scrollWidget().width() < partsw.width() ): self.scrollParts(partsw.width() - self.scrollWidget().width()) self.setUpdatesEnabled(True) self.navigationChanged.emit() def resizeEvent( self, event ): """ Resizes the current widget and its parts widget. :param event | <QResizeEvent> """ super(XNavigationEdit, self).resizeEvent(event) w = self.width() h = self.height() self._scrollWidget.resize(w - 4, h - 4) if ( self._scrollWidget.width() < self._partsWidget.width() ): self.scrollParts( self._partsWidget.width() - self._scrollWidget.width() ) def scrollParts( self, amount ): """ Scrolls the parts to offset the scrolling amount. :param amount | <int> """ change = self._scrollAmount - amount self._partsWidget.scroll(change, 0) self._scrollAmount = amount def scrollWidget( self ): """ Returns the scrolling widget. :return <QScrollArea> """ return self._scrollWidget def separator( self ): """ Returns the separation character that is used for this edit. :return <str> """ return self._separator def setTopLevelItems( self, items ): """ Initializes the navigation system to start with the inputed root \ item. :param item | <XNavigationItem> """ if ( not self._navigationModel ): self.setNavigationModel(XNavigationModel(self)) self._navigationModel.setTopLevelItems(items) def setNavigationModel( self, model ): """ Sets the navigation model for this edit. :param model | <XNavigationModel> """ self._navigationModel = model self._completerTree.setModel(model) if ( model ): model.setSeparator(self.separator()) completer = XNavigationCompleter(model, self) self.setCompleter(completer) completer.popup().installEventFilter(self) else: self.setCompleter(None) self.rebuild() def setParts( self, parts ): """ Sets the path for this edit widget by providing the parts to the path. :param parts | [<str>, ..] """ self.setText(self.separator().join(map(str, parts))) def setSeparator( self, separator ): """ Sets the separator to the inputed character. :param separator | <str> """ self._separator = separator if ( self._navigationModel ): self._navigationModel.setSeparator(separator) self.rebuild() def setText( self, text ): """ Sets the text for this edit to the inputed text. :param text | <str> """ super(XNavigationEdit, self).setText(text) self.scrollWidget().show() if ( text == '' or self._originalText != text ): self.rebuild()
class FilteringModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'methods': [True, False, False], 'recent_sw_files': [], 'min_df': None, 'max_df': None, } English, Custom, DocumentFrequency = 0, 1, 2 filtering_values = { English: 'english', Custom: [], DocumentFrequency: (None, None), } filter_names = { English: 'English stop words', Custom: 'Custom stop words', DocumentFrequency: 'Filter by token frequency', } filtering_methods = [True, False, False] dlgFormats = 'Only text files (*.txt)' recent_sw_files = [] def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__( self, 'Token filtering', True, data.get('is_enabled') ) self.group = QButtonGroup(self, exclusive=False) # --- English --- cb = QCheckBox(self, text=self.filter_names[self.English]) self.add_to_content_area(cb) self.group.addButton(cb, self.English) # --- Custom --- cb = QCheckBox(self, text=self.filter_names[self.Custom]) self.add_to_content_area(cb) self.group.addButton(cb, self.Custom) # File browser. file_browser_layout = QHBoxLayout() file_browser_layout.setContentsMargins(20, 0, 0, 0) self.sw_file_combo = QComboBox() self.sw_file_combo.setMinimumWidth(200) file_browser_layout.addWidget(self.sw_file_combo) self.sw_file_combo.activated[int].connect(self.select_file) self.browse_button = QPushButton(self) self.browse_button.clicked.connect(self.browse_file) self.browse_button.setIcon(self.style() .standardIcon(QStyle.SP_DirOpenIcon)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) file_browser_layout.addWidget(self.browse_button) # Reload button self.reload_button = QPushButton(self) self.reload_button.clicked.connect(self.on_reload_button_clicked) self.reload_button.setIcon(self.style() .standardIcon(QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) file_browser_layout.addWidget(self.reload_button) self.add_layout_to_content_area(file_browser_layout) # --- DF --- df_info_text = """ Remove all tokens that appear in less than 'min-df' documents. Remove all tokens that appear in more than 'max-df' documents. Values can be either integers or floats (ratio of documents). """ cb = QCheckBox(self, text=self.filter_names[self.DocumentFrequency]) self.add_to_content_area(cb) self.group.addButton(cb, self.DocumentFrequency) df_info_text = QLabel(df_info_text) df_info_text.setContentsMargins(0,0,0,0) df_info_text.setStyleSheet(""" font-size: 11px; font-style: italic; """) self.add_to_content_area(df_info_text) # Min/Max-Df setter. df_setter_layout = QHBoxLayout() df_setter_layout.setContentsMargins(20, 0, 0, 0) self.min_df_input = QLineEdit() self.min_df_input.textChanged.connect(self.update_df_parameters) self.max_df_input = QLineEdit() self.max_df_input.textChanged.connect(self.update_df_parameters) df_setter_layout.addWidget(QLabel('Min-df:')) df_setter_layout.addWidget(self.min_df_input) df_setter_layout.addWidget(QLabel('Max-df:')) df_setter_layout.addWidget(self.max_df_input) self.add_layout_to_content_area(df_setter_layout) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the widget to its previous state. self.restore_data(data) def str_to_num(self, s): if not s: return None try: return int(s) except ValueError: pass # Not an int. Continue. try: return float(s) except ValueError: # Not a float either. self.send_message('Input "{}" cannot be cast into a number.' .format(s)) return None def send_message(self, message): # Sends a message with the "message" signal, to the main widget. self.error_signal.emit(message) # --- File selection. def select_file(self, n): if n < len(self.recent_sw_files): name = self.recent_sw_files[n] del self.recent_sw_files[n] self.recent_sw_files.insert(0, name) if len(self.recent_sw_files) > 0: self.set_file_list() self.open_file(self.recent_sw_files[0]) def set_file_list(self): self.sw_file_combo.clear() if not self.recent_sw_files: self.sw_file_combo.addItem('(none)') else: for file in self.recent_sw_files: self.sw_file_combo.addItem(os.path.split(file)[1]) def browse_file(self): # Opens the file browser, starting at the home directory. start_file = os.path.expanduser('~/') # Get the file path from the browser window. path = QFileDialog.getOpenFileName(self, 'Open a stop words source', start_file, self.dlgFormats) if not path: return if path in self.recent_sw_files: self.recent_sw_files.remove(path) self.recent_sw_files.insert(0, path) self.set_file_list() self.open_file(path) def update_df_parameters(self): min_df = None if not self.min_df_input.text() else self.min_df_input.text() max_df = None if not self.max_df_input.text() else self.max_df_input.text() self.filtering_values[self.DocumentFrequency] = (min_df, max_df) self.notify_on_change() def open_file(self, path): try: with open(path) as f: # Read most recent. self.filtering_values[self.Custom] = [sw.strip() for sw in f.read().splitlines()] self.notify_on_change() except Exception: # Raise an exception otherwise. self.send_message('Could not open "{}".' .format(path)) def on_reload_button_clicked(self): if self.recent_sw_files: self.select_file(0) # END File selection. def group_button_clicked(self): self.filtering_methods = [ch_box.isChecked() for ch_box in self.group.buttons()] self.enable_choice_settings() # Emit the signal. self.notify_on_change() def enable_choice_settings(self): self.sw_file_combo.setEnabled(self.filtering_methods[1]) self.browse_button.setEnabled(self.filtering_methods[1]) self.reload_button.setEnabled(self.filtering_methods[1]) self.min_df_input.setEnabled(self.filtering_methods[2]) self.max_df_input.setEnabled(self.filtering_methods[2]) def get_pp_setting(self): flag_english = self.filtering_methods[0] flag_custom = self.filtering_methods[1] flag_df = self.filtering_methods[2] if flag_english and flag_custom: # Use custom. stop_words = { 'stop_words': stopwords.words('english') + self.filtering_values[self.Custom] } elif flag_english and not flag_custom: stop_words = { 'stop_words': 'english' } elif flag_custom: stop_words = { 'stop_words': self.filtering_values[self.Custom] } else: stop_words = {} if flag_df: stop_words.update({ 'min_df': self.str_to_num(self.min_df_input.text()), 'max_df': self.str_to_num(self.max_df_input.text()), }) return stop_words def restore_data(self, data): self.recent_sw_files = data.get('recent_sw_files') self.min_df_input.setText(data.get('min_df')) self.max_df_input.setText(data.get('max_df')) self.filtering_methods = data.get('methods') for flag, ch_box in zip(self.filtering_methods, self.group.buttons()): ch_box.setChecked(flag) self.enable_choice_settings() # Enable the settings if set. self.set_file_list() # Fill the combo box with the recent sw files. self.select_file(0) # Select the first file. def export_data(self): return { 'is_enabled': self.enabled, 'methods': self.filtering_methods, 'recent_sw_files': self.recent_sw_files, 'min_df': self.min_df_input.text(), 'max_df': self.max_df_input.text(), }
class PeriodicTableWidget(QWidget): selectionChanged = pyqtSignal() def __init__(self, parent=None): QWidget.__init__(self, parent) # Widgets, layouts and signals self._group = QButtonGroup() layout = QGridLayout() layout.setSpacing(0) ## Element for z, position in _ELEMENT_POSITIONS.items(): widget = ElementPushButton(z) widget.setStyle(QStyleFactory.create("windows")) widget.setCheckable(True) layout.addWidget(widget, *position) self._group.addButton(widget, z) ## Labels layout.addWidget(QLabel(''), 7, 0) # Dummy layout.addWidget(QLabel('*'), 5, 2, Qt.AlignRight) layout.addWidget(QLabel('*'), 8, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 6, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 9, 2, Qt.AlignRight) for row in [0, 1, 2, 3, 4, 5, 6, 8, 9]: layout.setRowStretch(row, 1) self.setLayout(layout) # Signals self._group.buttonClicked.connect(self.selectionChanged) # Default self.setColorFunction(_category_color_function) def setColorFunction(self, func): if not callable(func): raise ValueError('Not a function') self._color_function = func # Redraw for widget in self._group.buttons(): z = self._group.id(widget) bcolor = func(z) fcolor = 'white' if _calculate_brightness(bcolor) < 128 else 'black' sheet = 'background-color: %s; color: %s' % (bcolor.name(), fcolor) widget.setStyleSheet(sheet) def colorFunction(self): return self._color_function def setSelection(self, selection): self.selectionChanged.emit() # def selection(self): selection = None for widget in self._group.buttons(): if widget.isChecked(): selection = self._group.id(widget) if selection != None: return [selection, get_symbol(selection)] else: return None
class DefaultSelectParameterWidget(SelectParameterWidget): """Widget class for Default Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor :param parameter: A DefaultSelectParameter object. :type parameter: DefaultSelectParameter """ super(DefaultSelectParameterWidget, self).__init__(parameter, parent) self.default_layout = QHBoxLayout() self.radio_button_layout = QHBoxLayout() self.radio_button_widget = QWidget() self.default_label = QLabel(tr('Default')) # Create radio button group self.default_input_button_group = QButtonGroup() # Define string enabler for radio button self.radio_button_enabler = self.input.itemData(0, Qt.UserRole) for i in range(len(self._parameter.default_labels)): if '%s' in self._parameter.default_labels[i]: label = (self._parameter.default_labels[i] % self._parameter.default_values[i]) else: label = self._parameter.default_labels[i] radio_button = QRadioButton(label) self.radio_button_layout.addWidget(radio_button) self.default_input_button_group.addButton(radio_button, i) if self._parameter.default_value == \ self._parameter.default_values[i]: radio_button.setChecked(True) # Create double spin box for custom value self.custom_value = QDoubleSpinBox() if self._parameter.default_values[-1]: self.custom_value.setValue(self._parameter.default_values[-1]) has_min = False if self._parameter.minimum is not None: has_min = True self.custom_value.setMinimum(self._parameter.minimum) has_max = False if self._parameter.maximum is not None: has_max = True self.custom_value.setMaximum(self._parameter.maximum) if has_min and has_max: step = (self._parameter.maximum - self._parameter.minimum) / 100.0 self.custom_value.setSingleStep(step) self.radio_button_layout.addWidget(self.custom_value) self.toggle_custom_value() # Reset the layout self.input_layout.setParent(None) self.help_layout.setParent(None) self.label.setParent(None) self.inner_input_layout.setParent(None) self.input_layout = QGridLayout() self.input_layout.setSpacing(0) self.input_layout.addWidget(self.label, 0, 0) self.input_layout.addLayout(self.inner_input_layout, 0, 1) self.input_layout.addWidget(self.default_label, 1, 0) self.input_layout.addLayout(self.radio_button_layout, 1, 1) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) # check every added combobox, it could have been toggled by # the existing keyword self.toggle_input() # Connect # noinspection PyUnresolvedReferences self.input.currentIndexChanged.connect(self.toggle_input) self.default_input_button_group.buttonClicked.connect( self.toggle_custom_value) def raise_invalid_type_exception(self): message = 'Expecting element type of %s' % ( self._parameter.element_type.__name__) err = ValueError(message) return err def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultSelectParameter from the current state of widget. """ current_index = self.input.currentIndex() selected_value = self.input.itemData(current_index, Qt.UserRole) if hasattr(selected_value, 'toPyObject'): selected_value = selected_value.toPyObject() try: self._parameter.value = selected_value except ValueError: err = self.raise_invalid_type_exception() raise err radio_button_checked_id = self.default_input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.default = None # The last radio button (custom) is checked, get the value from the # line edit elif (radio_button_checked_id == len(self._parameter.default_values) - 1): self._parameter.default_values[radio_button_checked_id] \ = self.custom_value.value() self._parameter.default = self.custom_value.value() else: self._parameter.default = self._parameter.default_values[ radio_button_checked_id] return self._parameter def set_default(self, default): """Set default value by item's string. :param default: The default. :type default: str, int :returns: True if success, else False. :rtype: bool """ # Find index of choice try: default_index = self._parameter.default_values.index(default) self.default_input_button_group.button(default_index).setChecked( True) except ValueError: last_index = len(self._parameter.default_values) - 1 self.default_input_button_group.button(last_index).setChecked(True) self.custom_value.setValue(default) self.toggle_custom_value() def toggle_custom_value(self): radio_button_checked_id = self.default_input_button_group.checkedId() if (radio_button_checked_id == len(self._parameter.default_values) - 1): self.custom_value.setDisabled(False) else: self.custom_value.setDisabled(True) def toggle_input(self): """Change behaviour of radio button based on input.""" current_index = self.input.currentIndex() # If current input is not a radio button enabler, disable radio button. if self.input.itemData(current_index, Qt.UserRole) != (self.radio_button_enabler): self.disable_radio_button() # Otherwise, enable radio button. else: self.enable_radio_button() def set_selected_radio_button(self): """Set selected radio button to 'Do not report'.""" dont_use_button = self.default_input_button_group.button( len(self._parameter.default_values) - 2) dont_use_button.setChecked(True) def disable_radio_button(self): """Disable radio button group and custom value input area.""" checked = self.default_input_button_group.checkedButton() if checked: self.default_input_button_group.setExclusive(False) checked.setChecked(False) self.default_input_button_group.setExclusive(True) for button in self.default_input_button_group.buttons(): button.setDisabled(True) self.custom_value.setDisabled(True) def enable_radio_button(self): """Enable radio button and custom value input area then set selected radio button to 'Do not report'. """ for button in self.default_input_button_group.buttons(): button.setEnabled(True) self.set_selected_radio_button() self.custom_value.setEnabled(True)
class OptionWidget(EditorWidget): widgettype = 'Option Row' def __init__(self, *args): super(OptionWidget, self).__init__(*args) self._bindvalue = None self.group = QButtonGroup() self.group.setExclusive(True) self.group.buttonClicked.connect(self.emitvaluechanged) def createWidget(self, parent): widget = QWidget(parent) widget.setLayout(QHBoxLayout()) widget.layout().setContentsMargins(0,0,0,0) return widget def _buildfromlist(self, listconfig): items = listconfig['items'] for item in items: parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data try: path = parts[2] if path.endswith("_icon"): icon = QIcon(":/icons/{}".format(path)) else: icon = QIcon(path) except: icon = QIcon() button = QPushButton() button.setCheckable(True) button.setText(desc) button.setProperty("value", data) button.setIcon(icon) button.setIconSize(QSize(24,24)) self.widget.layout().addWidget(button) self.group.addButton(button) def initWidget(self, widget): pass def updatefromconfig(self): super(OptionWidget, self).updatefromconfig() listconfig = self.config['list'] self._buildfromlist(listconfig) super(OptionWidget, self).endupdatefromconfig() def validate(self, *args): button = self.group.checkedButton() if button: self.raisevalidationupdate(True) else: self.raisevalidationupdate(False) self.emitvaluechanged() def setvalue(self, value): for button in self.group.buttons(): if button.property("value") == value: button.setChecked(True) return def value(self): button = self.group.checkedButton() if not button: return None return button.property("value")
class DBDatabasesWidget(QWidget): """Displays a list of Databases""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.db = None self.setWindowTitle("Databases") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setHeaderLabels(["Server", "User", ""]) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(False) self.tree.setColumnWidth(C.widget, 20) self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed ) self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked ) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def on_open_server(self, butt): self.emit(SIGNAL("open_server"), butt.property("server").toString()) def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.server, srv['server']) item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.widget, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers()
class OptionWidget(EditorWidget): widgettype = 'Option Row' def __init__(self, *args): super(OptionWidget, self).__init__(*args) self._bindvalue = None self.group = QButtonGroup() self.group.setExclusive(True) self.group.buttonClicked.connect(self.emitvaluechanged) def createWidget(self, parent): widget = QWidget(parent) widget.setLayout(QHBoxLayout()) widget.layout().setContentsMargins(0, 0, 0, 0) return widget def _buildfromlist(self, listconfig): items = listconfig['items'] for item in items: parts = item.split(';') data = parts[0] try: desc = parts[1] except IndexError: desc = data try: path = parts[2] if path.endswith("_icon"): icon = QIcon(":/icons/{}".format(path)) else: icon = QIcon(path) except: icon = QIcon() button = QPushButton() button.setCheckable(True) button.setText(desc) button.setProperty("value", data) button.setIcon(icon) button.setIconSize(QSize(24, 24)) self.widget.layout().addWidget(button) self.group.addButton(button) def initWidget(self, widget): pass def updatefromconfig(self): super(OptionWidget, self).updatefromconfig() listconfig = self.config['list'] self._buildfromlist(listconfig) super(OptionWidget, self).endupdatefromconfig() def validate(self, *args): button = self.group.checkedButton() if button: return True return False def setvalue(self, value): for button in self.group.buttons(): if button.property("value") == str(value): button.setChecked(True) return def value(self): button = self.group.checkedButton() if not button: return None return button.property("value")
class DBServersWidget(QWidget): """Displays a list of servers""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed ) self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked ) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.node, srv['server']) #item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.butt, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers() def on_open_server(self, butt): # self.emit(SIGNAL("open_server"), butt.property("server").toString()) srv_ki = str(butt.property("server").toString()) server = G.settings.get_server(srv_ki) db = QSqlDatabase.addDatabase("QMYSQL", srv_ki) db.setHostName(server['server']) db.setUserName(server['user']) db.setPassword(server['passwd']) ok = db.open() if ok: #self.connections[srv_ki] = self.load_databases(srv_ki) print "open", ok def load_databases(self, srv_ki): """Load databases into tree node for server; executes 'show databases;' or aslike """ sql = "show databases;" query = QSqlQuery(QSqlDatabase.database(srv_ki)) ok = query.exec_(sql) print ok, sql, query.result() # Get the parent node, ie the server node pItem = self.tree.findItems(srv_ki, Qt.MatchExactly, C.node)[0] ## Assumed value(0) is the table.. we need the defs (ie mysql case) while query.next(): table_name = query.value(0).toString() nuItem = QTreeWidgetItem(pItem) nuItem.setText(C.node, table_name) #print table_name self.tree.setItemExpanded(pItem, True)
class CategoriesTab(QWidget): """ Widget for displaying the categories tab in the SettingsDialog. This is embedded into the SettingsDialog. The user can add or remove a category using several options. For some reason, PyQt does not recognize QButtonGroup objects, hence they need to be defined explicitely. Also, a reference to FinanceagerWindow is stored as private attribute self.__parent because later referencing does not work otherwise. """ def __init__(self, parent=None): super(CategoriesTab, self).__init__(parent) loadUi(__file__, self) self.__parent = parent self.removeFromMonthButtons = QButtonGroup() self.removeFromMonthButtons.addButton(self.removeAllMonthsButton) self.removeFromMonthButtons.addButton( self.removeAllMonthsFromNowButton) self.removeFromMonthButtons.addButton(self.removeCurrentMonthButton) self.addToMonthButtons = QButtonGroup() self.addToMonthButtons.addButton(self.addAllMonthsButton) self.addToMonthButtons.addButton(self.addAllMonthsFromNowButton) self.addToMonthButtons.addButton(self.addCurrentMonthButton) self.expAndRecButtons = QButtonGroup() self.expAndRecButtons.addButton(self.expendituresButton) self.expAndRecButtons.addButton(self.receiptsButton) self.removeCategoryCombo.addItems(self.categoriesStringList()) # CONNECTIONS self.addCategoryGroup.clicked.connect( self.newCategoryLineEdit.setFocus) def categoriesStringList(self): """ Returns a sorted list of all the categories that occur in the parentwidget's (== FinanceagerWindow's) tabs. Used for both populating the removeCategoryCombo and preventing the user from adding an already existing category. The latter is important in order to avoid ambiguities when removing a category. :return list(str) """ categories = set() tabWidget = self.__parent.monthsTabWidget for m in range(12): monthTab = tabWidget.widget(m) categories = categories.union(monthTab.categoriesStringList()) categories = list(categories) categories.sort() return categories def checkForUniqueCategory(self, name): """ Called from updateChangesToApply() to verify that the given category name is unique. Pops up a warning and resets newCategoryLineEdit if not. :param name | str :return uniqueCategory | bool """ #FIXME this also prevents adding a category that exists in any other month! if name in self.categoriesStringList(): QMessageBox.warning( self.__parent, 'Name conflict', 'This category name already exists. Please enter a unique name.' ) self.newCategoryLineEdit.setText('') self.newCategoryLineEdit.setFocus() return False else: return True def updateChangesToApply(self, changes): """ Checks for checked GroupBoxes. Creates a tuple consisting of a function string and a tuple that contains name, typ and option. Those three are fetched from the tab's widgets. function: 'addCategory' | 'removeCategory' name: new category name | category to delete option: 0 (all months) | 1 (all months from now) | 2 (current month) typ: 0 (expenditure) | 1 (receipt) The tuple is eventually evaluated by SettingsDialog.applyChanges() if the dialog is not cancelled. :param changes | set """ if self.addCategoryGroup.isChecked(): name = unicode(self.newCategoryLineEdit.text()).strip() if len(name): if self.checkForUniqueCategory(name): typ = self.expAndRecButtons.buttons().index( self.expAndRecButtons.checkedButton()) option = self.addToMonthButtons.buttons().index( self.addToMonthButtons.checkedButton()) changes.add(('addCategory', (name, typ, option))) if self.removeCategoryGroup.isChecked(): name = unicode(self.removeCategoryCombo.currentText()) option = self.removeFromMonthButtons.buttons().index( self.removeFromMonthButtons.checkedButton()) changes.add(('removeCategory', (name, option)))
def __init__(self): # Inicializo el parent y audio module super(EGPSWindow, self).__init__() self.audio_mod = AudioModule(OUTPUT_FILE_PATH) # Titulo, tamano y tamano fijo (no resize) win_height = 130 + len(TRANSFER_FUNCTIONS) * 40 self.setWindowTitle("EGPS-1") self.setGeometry(70, 70, 600, win_height) self.setFixedSize(600, win_height) # Funcion y lista de parametros para la creacion de las labels labels_func = self.create_label nm_px_py_labels = [("Transductor de entrada", 10, 105), ("Grabacion", 400, 120), ("Salida", 400, 330), ("Archivo de entrada", 10, 10), ("Transductor de salida", 200, 105), ("Entrada a procesar", 400, 230)] # Funcion y lista de parametros para la creacion de radiobuttons in_bq = QButtonGroup(self) out_bq = QButtonGroup(self) process_bq = QButtonGroup(self) radio_buttons_func = self.create_radio_button nm_px_py_cb_radio_buttons = [ ("Archivo de entrada", 405, 255, PROCESS_GROUP, process_bq), ("Grabacion", 405, 280, PROCESS_GROUP, process_bq) ] #Creacion de los radio buttons para el grupo de transductores de entrada y de salida for index, transfer_function in enumerate(TRANSFER_FUNCTIONS.keys()): nm_px_py_cb_radio_buttons.append( (transfer_function, 30, 125 + index * 40, INPUT_GROUP, in_bq)) nm_px_py_cb_radio_buttons.append( (transfer_function, 220, 125 + index * 40, OUTPUT_GROUP, out_bq)) # Funcion y lista de parametros para la creacion de los pushbuttons push_buttons_func = self.define_push_button nm_px_py_callb_push_buttons = [ ("", 55, 70, self.audio_mod.stop_file, STOP_IMAGE_PATH, True), ("Elegir archivo", 15, 35, self.select_file), ("", 15, 70, self.audio_mod.play_file, PLAY_IMAGE_PATH, True), ("", 405, 145, self.audio_mod.rec, REC_IMAGE_PATH, True), ("", 445, 145, self.audio_mod.stop_rec, STOP_IMAGE_PATH, True), ("", 485, 145, self.audio_mod.play_rec, PLAY_IMAGE_PATH, True), ("", 525, 145, self.rec_file_save, SAVE_IMAGE_PATH, True), ("", 405, 355, self.out_file_play, PLAY_IMAGE_PATH, True), ("", 445, 355, self.audio_mod.stop_out, STOP_IMAGE_PATH, True), ("", 485, 355, self.out_file_save, SAVE_IMAGE_PATH, True) ] # Se define una lista de tuplas con (constructor, lista de parametros del constructor) para los diferentes # tipos de elementos elements_constructors = [ (labels_func, nm_px_py_labels), (radio_buttons_func, nm_px_py_cb_radio_buttons), (push_buttons_func, nm_px_py_callb_push_buttons) ] for const, params_list in elements_constructors: for params in params_list: const(*params) # Se eligen los radiobuttons iniciales self.input_output = dict() self.input_output[INPUT_GROUP] = str(in_bq.buttons()[0].text()) self.input_output[OUTPUT_GROUP] = str(out_bq.buttons()[1].text()) self.input_output[PROCESS_GROUP] = str(process_bq.buttons()[0].text()) in_bq.buttons()[0].setChecked(True) out_bq.buttons()[1].setChecked(True) process_bq.buttons()[0].setChecked(True) # Se define el pop up para salir de la aplicacion self.msg_box = QMessageBox() self.msg_box.setWindowTitle("Salir") self.msg_box.setText("Esta seguro que desea salir?") self.msg_box.addButton("Si", QMessageBox.AcceptRole) self.msg_box.addButton("No", QMessageBox.RejectRole) # Error para formato incorrecto self.wrong_file_box = QMessageBox() self.wrong_file_box.setWindowTitle("Error") self.wrong_file_box.setText("El archivo tiene formato incorrecto") # Error para el path file self.no_data_box = QMessageBox() self.no_data_box.setWindowTitle("Error") self.no_data_box.setText( "No se puede utilizar la ruta indicada o los datos son inexistentes" ) # Create select play file self.path_label = QLabel(os.path.abspath(OUTPUT_FILE_PATH), self) self.path_label.move(128, 40) self.path_label.resize(self.path_label.minimumSizeHint()) # Metodo del parent QWidget. QWidget -> QMainWindow -> EGPSWindow self.show()
class DefaultSelectParameterWidget(SelectParameterWidget): """Widget class for Default Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor :param parameter: A DefaultSelectParameter object. :type parameter: DefaultSelectParameter """ super(DefaultSelectParameterWidget, self).__init__(parameter, parent) self.default_layout = QHBoxLayout() self.radio_button_layout = QHBoxLayout() self.radio_button_widget = QWidget() self.default_label = QLabel(tr('Default')) # Create radio button group self.default_input_button_group = QButtonGroup() # Define string enabler for radio button self.radio_button_enabler = self.input.itemData(0, Qt.UserRole) for i in range(len(self._parameter.default_labels)): if '%s' in self._parameter.default_labels[i]: label = ( self._parameter.default_labels[i] % self._parameter.default_values[i]) else: label = self._parameter.default_labels[i] radio_button = QRadioButton(label) self.radio_button_layout.addWidget(radio_button) self.default_input_button_group.addButton(radio_button, i) if self._parameter.default_value == \ self._parameter.default_values[i]: radio_button.setChecked(True) # Create double spin box for custom value self.custom_value = QDoubleSpinBox() if self._parameter.default_values[-1]: self.custom_value.setValue(self._parameter.default_values[-1]) has_min = False if self._parameter.minimum is not None: has_min = True self.custom_value.setMinimum(self._parameter.minimum) has_max = False if self._parameter.maximum is not None: has_max = True self.custom_value.setMaximum(self._parameter.maximum) if has_min and has_max: step = (self._parameter.maximum - self._parameter.minimum) / 100.0 self.custom_value.setSingleStep(step) self.radio_button_layout.addWidget(self.custom_value) self.toggle_custom_value() # Reset the layout self.input_layout.setParent(None) self.help_layout.setParent(None) self.label.setParent(None) self.inner_input_layout.setParent(None) self.input_layout = QGridLayout() self.input_layout.setSpacing(0) self.input_layout.addWidget(self.label, 0, 0) self.input_layout.addLayout(self.inner_input_layout, 0, 1) self.input_layout.addWidget(self.default_label, 1, 0) self.input_layout.addLayout(self.radio_button_layout, 1, 1) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) # check every added combobox, it could have been toggled by # the existing keyword self.toggle_input() # Connect # noinspection PyUnresolvedReferences self.input.currentIndexChanged.connect(self.toggle_input) self.default_input_button_group.buttonClicked.connect( self.toggle_custom_value) def raise_invalid_type_exception(self): message = 'Expecting element type of %s' % ( self._parameter.element_type.__name__) err = ValueError(message) return err def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultSelectParameter from the current state of widget. """ current_index = self.input.currentIndex() selected_value = self.input.itemData(current_index, Qt.UserRole) if hasattr(selected_value, 'toPyObject'): selected_value = selected_value.toPyObject() try: self._parameter.value = selected_value except ValueError: err = self.raise_invalid_type_exception() raise err radio_button_checked_id = self.default_input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.default = None # The last radio button (custom) is checked, get the value from the # line edit elif (radio_button_checked_id == len(self._parameter.default_values) - 1): self._parameter.default_values[radio_button_checked_id] \ = self.custom_value.value() self._parameter.default = self.custom_value.value() else: self._parameter.default = self._parameter.default_values[ radio_button_checked_id] return self._parameter def set_default(self, default): """Set default value by item's string. :param default: The default. :type default: str, int :returns: True if success, else False. :rtype: bool """ # Find index of choice try: default_index = self._parameter.default_values.index(default) self.default_input_button_group.button(default_index).setChecked( True) except ValueError: last_index = len(self._parameter.default_values) - 1 self.default_input_button_group.button(last_index).setChecked( True) self.custom_value.setValue(default) self.toggle_custom_value() def toggle_custom_value(self): radio_button_checked_id = self.default_input_button_group.checkedId() if (radio_button_checked_id == len(self._parameter.default_values) - 1): self.custom_value.setDisabled(False) else: self.custom_value.setDisabled(True) def toggle_input(self): """Change behaviour of radio button based on input.""" current_index = self.input.currentIndex() # If current input is not a radio button enabler, disable radio button. if self.input.itemData(current_index, Qt.UserRole) != ( self.radio_button_enabler): self.disable_radio_button() # Otherwise, enable radio button. else: self.enable_radio_button() def set_selected_radio_button(self): """Set selected radio button to 'Do not report'.""" dont_use_button = self.default_input_button_group.button( len(self._parameter.default_values) - 2) dont_use_button.setChecked(True) def disable_radio_button(self): """Disable radio button group and custom value input area.""" checked = self.default_input_button_group.checkedButton() if checked: self.default_input_button_group.setExclusive(False) checked.setChecked(False) self.default_input_button_group.setExclusive(True) for button in self.default_input_button_group.buttons(): button.setDisabled(True) self.custom_value.setDisabled(True) def enable_radio_button(self): """Enable radio button and custom value input area then set selected radio button to 'Do not report'. """ for button in self.default_input_button_group.buttons(): button.setEnabled(True) self.set_selected_radio_button() self.custom_value.setEnabled(True)
class FilteringModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'methods': [True, False, False], 'recent_sw_files': [], 'min_df': None, 'max_df': None, } English, Custom, DocumentFrequency = 0, 1, 2 filtering_values = { English: 'english', Custom: [], DocumentFrequency: (None, None), } filter_names = { English: 'English stop words', Custom: 'Custom stop words', DocumentFrequency: 'Filter by token frequency', } filtering_methods = [True, False, False] dlgFormats = 'Only text files (*.txt)' recent_sw_files = [] def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__(self, 'Token filtering', True, data.get('is_enabled')) self.group = QButtonGroup(self, exclusive=False) # --- English --- cb = QCheckBox(self, text=self.filter_names[self.English]) self.add_to_content_area(cb) self.group.addButton(cb, self.English) # --- Custom --- cb = QCheckBox(self, text=self.filter_names[self.Custom]) self.add_to_content_area(cb) self.group.addButton(cb, self.Custom) # File browser. file_browser_layout = QHBoxLayout() file_browser_layout.setContentsMargins(20, 0, 0, 0) self.sw_file_combo = QComboBox() self.sw_file_combo.setMinimumWidth(200) file_browser_layout.addWidget(self.sw_file_combo) self.sw_file_combo.activated[int].connect(self.select_file) self.browse_button = QPushButton(self) self.browse_button.clicked.connect(self.browse_file) self.browse_button.setIcon(self.style().standardIcon( QStyle.SP_DirOpenIcon)) self.browse_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) file_browser_layout.addWidget(self.browse_button) # Reload button self.reload_button = QPushButton(self) self.reload_button.clicked.connect(self.on_reload_button_clicked) self.reload_button.setIcon(self.style().standardIcon( QStyle.SP_BrowserReload)) self.reload_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) file_browser_layout.addWidget(self.reload_button) self.add_layout_to_content_area(file_browser_layout) # --- DF --- df_info_text = """ Remove all tokens that appear in less than 'min-df' documents. Remove all tokens that appear in more than 'max-df' documents. Values can be either integers or floats (ratio of documents). """ cb = QCheckBox(self, text=self.filter_names[self.DocumentFrequency]) self.add_to_content_area(cb) self.group.addButton(cb, self.DocumentFrequency) df_info_text = QLabel(df_info_text) df_info_text.setContentsMargins(0, 0, 0, 0) df_info_text.setStyleSheet(""" font-size: 11px; font-style: italic; """) self.add_to_content_area(df_info_text) # Min/Max-Df setter. df_setter_layout = QHBoxLayout() df_setter_layout.setContentsMargins(20, 0, 0, 0) self.min_df_input = QLineEdit() self.min_df_input.textChanged.connect(self.update_df_parameters) self.max_df_input = QLineEdit() self.max_df_input.textChanged.connect(self.update_df_parameters) df_setter_layout.addWidget(QLabel('Min-df:')) df_setter_layout.addWidget(self.min_df_input) df_setter_layout.addWidget(QLabel('Max-df:')) df_setter_layout.addWidget(self.max_df_input) self.add_layout_to_content_area(df_setter_layout) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the widget to its previous state. self.restore_data(data) def str_to_num(self, s): if not s: return None try: return int(s) except ValueError: pass # Not an int. Continue. try: return float(s) except ValueError: # Not a float either. self.send_message( 'Input "{}" cannot be cast into a number.'.format(s)) return None def send_message(self, message): # Sends a message with the "message" signal, to the main widget. self.error_signal.emit(message) # --- File selection. def select_file(self, n): if n < len(self.recent_sw_files): name = self.recent_sw_files[n] del self.recent_sw_files[n] self.recent_sw_files.insert(0, name) if len(self.recent_sw_files) > 0: self.set_file_list() self.open_file(self.recent_sw_files[0]) def set_file_list(self): self.sw_file_combo.clear() if not self.recent_sw_files: self.sw_file_combo.addItem('(none)') else: for file in self.recent_sw_files: self.sw_file_combo.addItem(os.path.split(file)[1]) def browse_file(self): # Opens the file browser, starting at the home directory. start_file = os.path.expanduser('~/') # Get the file path from the browser window. path = QFileDialog.getOpenFileName(self, 'Open a stop words source', start_file, self.dlgFormats) if not path: return if path in self.recent_sw_files: self.recent_sw_files.remove(path) self.recent_sw_files.insert(0, path) self.set_file_list() self.open_file(path) def update_df_parameters(self): min_df = None if not self.min_df_input.text( ) else self.min_df_input.text() max_df = None if not self.max_df_input.text( ) else self.max_df_input.text() self.filtering_values[self.DocumentFrequency] = (min_df, max_df) self.notify_on_change() def open_file(self, path): try: with open(path) as f: # Read most recent. self.filtering_values[self.Custom] = [ sw.strip() for sw in f.read().splitlines() ] self.notify_on_change() except Exception: # Raise an exception otherwise. self.send_message('Could not open "{}".'.format(path)) def on_reload_button_clicked(self): if self.recent_sw_files: self.select_file(0) # END File selection. def group_button_clicked(self): self.filtering_methods = [ ch_box.isChecked() for ch_box in self.group.buttons() ] self.enable_choice_settings() # Emit the signal. self.notify_on_change() def enable_choice_settings(self): self.sw_file_combo.setEnabled(self.filtering_methods[1]) self.browse_button.setEnabled(self.filtering_methods[1]) self.reload_button.setEnabled(self.filtering_methods[1]) self.min_df_input.setEnabled(self.filtering_methods[2]) self.max_df_input.setEnabled(self.filtering_methods[2]) def get_pp_setting(self): flag_english = self.filtering_methods[0] flag_custom = self.filtering_methods[1] flag_df = self.filtering_methods[2] if flag_english and flag_custom: # Use custom. stop_words = { 'stop_words': stopwords.words('english') + self.filtering_values[self.Custom] } elif flag_english and not flag_custom: stop_words = {'stop_words': 'english'} elif flag_custom: stop_words = {'stop_words': self.filtering_values[self.Custom]} else: stop_words = {} if flag_df: stop_words.update({ 'min_df': self.str_to_num(self.min_df_input.text()), 'max_df': self.str_to_num(self.max_df_input.text()), }) return stop_words def restore_data(self, data): self.recent_sw_files = data.get('recent_sw_files') self.min_df_input.setText(data.get('min_df')) self.max_df_input.setText(data.get('max_df')) self.filtering_methods = data.get('methods') for flag, ch_box in zip(self.filtering_methods, self.group.buttons()): ch_box.setChecked(flag) self.enable_choice_settings() # Enable the settings if set. self.set_file_list() # Fill the combo box with the recent sw files. self.select_file(0) # Select the first file. def export_data(self): return { 'is_enabled': self.enabled, 'methods': self.filtering_methods, 'recent_sw_files': self.recent_sw_files, 'min_df': self.min_df_input.text(), 'max_df': self.max_df_input.text(), }
class DBServersWidget(QWidget): """Displays a list of servers""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect(self.tree, SIGNAL('itemSelectionChanged()'), self.on_tree_selection_changed) self.connect(self.tree, SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.on_tree_double_clicked) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.node, srv['server']) #item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.butt, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers() def on_open_server(self, butt): # self.emit(SIGNAL("open_server"), butt.property("server").toString()) srv_ki = str(butt.property("server").toString()) server = G.settings.get_server(srv_ki) db = QSqlDatabase.addDatabase("QMYSQL", srv_ki) db.setHostName(server['server']) db.setUserName(server['user']) db.setPassword(server['passwd']) ok = db.open() if ok: #self.connections[srv_ki] = self.load_databases(srv_ki) print "open", ok def load_databases(self, srv_ki): """Load databases into tree node for server; executes 'show databases;' or aslike """ sql = "show databases;" query = QSqlQuery(QSqlDatabase.database(srv_ki)) ok = query.exec_(sql) print ok, sql, query.result() # Get the parent node, ie the server node pItem = self.tree.findItems(srv_ki, Qt.MatchExactly, C.node)[0] ## Assumed value(0) is the table.. we need the defs (ie mysql case) while query.next(): table_name = query.value(0).toString() nuItem = QTreeWidgetItem(pItem) nuItem.setText(C.node, table_name) #print table_name self.tree.setItemExpanded(pItem, True)
class PrivacyConfirmationDialog(QDialog): POLICY_ONCE = 0 POLICY_FOREVER = 1 SCOPE_PEER_CATEGORY = 0 SCOPE_PEER = 1 SCOPE_EVERYONE_CATEGORY = 2 SCOPE_EVERYONE = 3 def __init__(self, parent, title, peerName, peerID, action, category, msgData): super(PrivacyConfirmationDialog, self).__init__(parent) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self._peerID = peerID self._peerName = peerName self._action = action self._category = category if category is not None else PrivacySettings.NO_CATEGORY self._useCategories = self._action.usesPrivacyCategories() layout = QVBoxLayout(self) layout.setContentsMargins(15, 15, 15, 10) messageLabel = QLabel(self._createMessage(msgData), self) messageLabel.setWordWrap(True) policyWidget = self._initPolicyWidget() scopeWidget = self._initScopeWidget(peerName, category) buttonBox = self._initButtonBox() bottomWidget = QWidget(self) bottomLayout = QHBoxLayout(bottomWidget) bottomLayout.setContentsMargins(0, 0, 0, 0) bottomLayout.setSpacing(0) self._timeoutLabel = QLabel(bottomWidget) bottomLayout.addWidget(self._timeoutLabel, 1) bottomLayout.addWidget(buttonBox) layout.addWidget(messageLabel) layout.addWidget(policyWidget, 0) layout.addWidget(scopeWidget) layout.addWidget(bottomWidget, 1) self.setWindowTitle(title) size = self.sizeHint() self.setMaximumHeight(size.height()) self._setPolicy(0) if action.getTimeout() is not None and action.getTimeout() > 0: self._timeout = action.getTimeout() self._timer = QTimer(self) self._timer.timeout.connect(self._decrementTimer) self._timer.start(1000) else: self._timer = None @loggingSlot() def _decrementTimer(self): self._timeout -= 1 if self._timeout <= 0: self.reject() self._timeoutLabel.setText(u"%d s" % self._timeout) def _createMessage(self, msgData): message = self._action.getConfirmationMessage(self._peerID, self._peerName, msgData) if message is None: # create default message if self._action.usesPrivacyCategories(): if self._category == PrivacySettings.NO_CATEGORY: message = "%s wants to perform the following action: %s (uncategorized)" % ( self._peerName, self._action.getName(), ) else: message = "%s wants to perform the following action: %s, in category %s" % ( self._peerName, self._action.getName(), self._category, ) else: message = "%s wants to perform the following action: %s" % (self._peerName, self._action.getName()) return message def _initPolicyWidget(self): policyWidget = QWidget(self) self._policyGroup = QButtonGroup(self) once = QRadioButton("Once", policyWidget) once.setChecked(True) once.clicked.connect(partial(self._setPolicy, self.POLICY_ONCE)) self._policyGroup.addButton(once) forever = QRadioButton("Forever", policyWidget) forever.clicked.connect(partial(self._setPolicy, self.POLICY_FOREVER)) self._policyGroup.addButton(forever) policyLayout = QHBoxLayout(policyWidget) policyLayout.setContentsMargins(5, 0, 5, 0) policyLayout.addWidget(once, 0) policyLayout.addWidget(forever, 1, Qt.AlignLeft) return policyWidget def _initScopeWidget(self, peerName, category): scopeWidget = QWidget(self) self._scopeGroup = QButtonGroup(self) if not self._useCategories: thisPeer = QRadioButton(peerName, scopeWidget) thisPeer.clicked.connect(partial(self._setScope, self.SCOPE_PEER)) self._scopeGroup.addButton(thisPeer) everyone = QRadioButton(u"Everyone", scopeWidget) everyone.clicked.connect(partial(self._setScope, self.SCOPE_EVERYONE)) self._scopeGroup.addButton(everyone) else: if self._category == PrivacySettings.NO_CATEGORY: catDesc = u"uncategorized" else: catDesc = u"category %s" % category b = QRadioButton(u"%s, %s" % (peerName, catDesc), scopeWidget) b.clicked.connect(partial(self._setScope, self.SCOPE_PEER_CATEGORY)) self._scopeGroup.addButton(b) b = QRadioButton(u"%s, all categories" % (peerName), scopeWidget) b.clicked.connect(partial(self._setScope, self.SCOPE_PEER)) self._scopeGroup.addButton(b) b = QRadioButton(u"Everyone, %s" % (catDesc), scopeWidget) b.clicked.connect(partial(self._setScope, self.SCOPE_EVERYONE_CATEGORY)) self._scopeGroup.addButton(b) b = QRadioButton(u"Everyone, all categories", scopeWidget) b.clicked.connect(partial(self._setScope, self.SCOPE_EVERYONE)) self._scopeGroup.addButton(b) self._scopeGroup.buttons()[0].click() scopeLayout = QVBoxLayout(scopeWidget) scopeLayout.setContentsMargins(5, 0, 5, 0) for button in self._scopeGroup.buttons(): scopeLayout.addWidget(button, 0) return scopeWidget def _initButtonBox(self): cancelButton = QPushButton("Deny", self) cancelButton.clicked.connect(self.reject) okButton = QPushButton("Accept", self) okButton.clicked.connect(self.accept) buttonBox = QDialogButtonBox(Qt.Horizontal, self) buttonBox.addButton(cancelButton, QDialogButtonBox.RejectRole) buttonBox.addButton(okButton, QDialogButtonBox.AcceptRole) return buttonBox def _setPolicy(self, policy): self._policy = policy for button in self._scopeGroup.buttons(): button.setEnabled(policy == self.POLICY_FOREVER) def _setScope(self, scope): self._scope = scope def _clickNext(self, group): curIdx = group.buttons().index(group.checkedButton()) if curIdx + 1 < len(group.buttons()): group.buttons()[curIdx + 1].click() def _clickPrev(self, group): curIdx = group.buttons().index(group.checkedButton()) if curIdx - 1 >= 0: group.buttons()[curIdx - 1].click() def keyPressEvent(self, event): if event.key() == Qt.Key_Right: self._clickNext(self._policyGroup) event.accept() elif event.key() == Qt.Key_Left: self._clickPrev(self._policyGroup) event.accept() elif event.key() == Qt.Key_Up: self._clickPrev(self._scopeGroup) event.accept() elif event.key() == Qt.Key_Down: self._clickNext(self._scopeGroup) event.accept() else: return QDialog.keyPressEvent(self, event) def _storeDecision(self, accepted): # store decision if not self._useCategories: if self._scope == self.SCOPE_PEER: PrivacySettings.get().addException( self._action, None, PrivacySettings.POLICY_NOBODY_EX, self._peerID, 1 if accepted else 0, categoryPolicy=PrivacySettings.CATEGORY_NEVER, ) elif self._scope == self.SCOPE_EVERYONE: PrivacySettings.get().setPolicy( self._action, None, PrivacySettings.POLICY_EVERYBODY if accepted else PrivacySettings.POLICY_NOBODY, categoryPolicy=PrivacySettings.CATEGORY_NEVER, ) else: if self._scope == self.SCOPE_PEER_CATEGORY: PrivacySettings.get().addException( self._action, self._category, PrivacySettings.POLICY_NOBODY_EX, self._peerID, 1 if accepted else 0, categoryPolicy=PrivacySettings.CATEGORY_ALWAYS, ) elif self._scope == self.SCOPE_PEER: PrivacySettings.get().addException( self._action, None, PrivacySettings.POLICY_PEER_EXCEPTION, self._peerID, 1 if accepted else 0, categoryPolicy=PrivacySettings.CATEGORY_NEVER, ) elif self._scope == self.SCOPE_EVERYONE_CATEGORY: PrivacySettings.get().setPolicy( self._action, self._category, PrivacySettings.POLICY_EVERYBODY if accepted else PrivacySettings.POLICY_NOBODY, categoryPolicy=PrivacySettings.CATEGORY_ALWAYS, ) elif self._scope == self.SCOPE_EVERYONE: PrivacySettings.get().setPolicy( self._action, None, PrivacySettings.POLICY_EVERYBODY if accepted else PrivacySettings.POLICY_NOBODY, categoryPolicy=PrivacySettings.CATEGORY_NEVER, ) def _finish(self): if self._timer is not None: self._timer.stop() self._timer = None @loggingSlot() def accept(self): self._finish() if self._action is not None and self._policy == self.POLICY_FOREVER: self._storeDecision(True) return QDialog.accept(self) @loggingSlot() def reject(self): self._finish() if self._action is not None and self._policy == self.POLICY_FOREVER: self._storeDecision(False) return QDialog.reject(self)