class ChooseBlogDialog(QDialog, Ui_ChooseBlogDialog): def __init__(self, available_blogs, addToDB): QDialog.__init__(self) Ui_ChooseBlogDialog.__init__(self) self.func = addToDB self.setupUi(self) radioboxLayout = QVBoxLayout() self.radiobuttonGroup = QButtonGroup() self.radios = [] for blog in available_blogs: radio = BlogRadio("Blog Title: %s, Url: %s" %(blog.blogname, blog.homeurl), blog) self.radiobuttonGroup.addButton(radio) radioboxLayout.addWidget(radio) self.radios.append(radio) self.chooseBlogFrame.setLayout(radioboxLayout) self.adjustSize() connect(self.chooseBlogButtonBox, SIGNAL("accepted()"), self.addBlog) #AddBlogDialog.accept) connect(self.chooseBlogButtonBox, SIGNAL("rejected()"), self.reject)#AddBlogDialog.reject) def addBlog(self): if self.radiobuttonGroup.checkedButton(): self.func(self.radiobuttonGroup.checkedButton().blog) self.accept() else: QMessageBox.warning(self, "Choose A Blog", "Please choose a blog and click OK. If you do not want to add a blog, Please click 'Cancel'", QMessageBox.Ok, QMessageBox.Ok) pass
class TokenizerModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'method': 0, } NLTKTokenizer, NLTKPunctTokenizer, TwitterTokenizer = 0, 1, 2 tokenizer_values = { NLTKTokenizer: 'default', NLTKPunctTokenizer: 'no_punct', TwitterTokenizer: 'twitter' } tokenizer_names = { NLTKTokenizer: 'NLTK tokenizer', NLTKPunctTokenizer: 'NLTK tokenizer (no punctuation)', TwitterTokenizer: 'Twitter tokenizer', } tokenizer_method = 0 def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__( self, 'Tokenizer', False, data.get('is_enabled') ) self.group = QButtonGroup(self, exclusive=True) for method in [ self.NLTKTokenizer, self.NLTKPunctTokenizer, self.TwitterTokenizer, ]: rb = QRadioButton(self, text=self.tokenizer_names[method]) self.add_to_content_area(rb) self.group.addButton(rb, method) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the previous state, after starting off the layout. self.restore_data(data) def group_button_clicked(self): self.tokenizer_method = self.group.checkedId() self.notify_on_change() def restore_data(self, data): self.tokenizer_method = data.get('method') b = self.group.button(self.tokenizer_method) b.setChecked(True) def export_data(self): return { 'is_enabled': self.enabled, 'method': self.tokenizer_method, } def get_pp_setting(self): return { 'tokenizer': self.tokenizer_values.get(self.tokenizer_method) }
def choice(self, title, msg, choices): vbox = QVBoxLayout() self.set_layout(vbox) vbox.addWidget(QLabel(title)) gb2 = QGroupBox(msg) vbox.addWidget(gb2) vbox2 = QVBoxLayout() gb2.setLayout(vbox2) group2 = QButtonGroup() for i, c in enumerate(choices): button = QRadioButton(gb2) button.setText(c[1]) vbox2.addWidget(button) group2.addButton(button) group2.setId(button, i) if i == 0: button.setChecked(True) vbox.addStretch(1) vbox.addLayout(Buttons(CancelButton(self), OkButton(self, _('Next')))) if not self.exec_(): return wallet_type = choices[group2.checkedId()][0] return wallet_type
class TransformationModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'method': 0, } PorterStemmer, SnowballStemmer, Lemmatizer = 0, 1, 2 transformation_values = { PorterStemmer: PS, SnowballStemmer: SS, Lemmatizer: LM, } transformation_method = 0 def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__( self, 'Stemming', True, data.get('is_enabled') ) self.group = QButtonGroup(self, exclusive=True) for method in [ self.PorterStemmer, self.SnowballStemmer, self.Lemmatizer ]: rb = QRadioButton( self, text=self.transformation_values[method].name ) self.add_to_content_area(rb) self.group.addButton(rb, method) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the previous state, after starting off the layout. self.restore_data(data) def group_button_clicked(self): self.transformation_method = self.group.checkedId() self.notify_on_change() def restore_data(self, data): self.transformation_method = data.get('method') b = self.group.button(self.transformation_method) b.setChecked(True) def export_data(self): return { 'is_enabled': self.enabled, 'method': self.transformation_method, } def get_pp_setting(self): return { 'transformation': self.transformation_values.get( self.transformation_method ) }
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 RadioBooleanFilter(QWidget, Control): """ Boolean filter (Only/Exclude) """ def __init__(self, tree, dataset, master, parent=None): QWidget.__init__(self, parent) Control.__init__(self, tree, dataset, master) self.setLayout(QVBoxLayout()) self.buttonGroup = QButtonGroup(self) self.values = [] for i, option in enumerate(tree.subelements_top("Option")): rb = QRadioButton(option.displayName, self) self.buttonGroup.addButton(rb) self.buttonGroup.setId(rb, i) self.layout().addWidget(rb) self.values.append(option.value) self.buttonGroup.button(0).setChecked(True) def value(self): return {"excluded": "%i" % self.buttonGroup.checkedId()} def get_filter(self): return self.tree.internalName, self.value() def query(self): return [("Filter", self.tree, self.value())] def setControlValue(self, name, value): for i, v in enumerate(self.values): if v == value: button = self.buttonGroup.button(i) button.setChecked(True) break
def __init__(self, iface_name, parent=None): IfaceWizardPage.__init__(self, parent) self.q_netobject = QNetObject.getInstance() self.setSubTitle("What kind of interface do you want to configure?") box = QVBoxLayout(self) self.ethernet = "ethernet", "Activate ethernet interface %s" % iface_name , QRadioButton() self.vlan = "vlan", "Create a VLAN interface", QRadioButton() group = QButtonGroup(self) form = QFormLayout() options = (self.ethernet, self.vlan) for item in options: group.addButton(item[2]) form.addRow(item[1], item[2]) self.registerField(item[0], item[2]) self.ethernet[2].setChecked(Qt.Checked) box.addLayout(form) box.addStretch() box.addWidget( HelpMissingFunction("""\ All interfaces but one (%s) are configured. In order to be able to activate an ethernet interface for bonding agregation, \ you must deconfigure at least one ethernet interface first \ (which may be in use by vlans or bondings).""" % iface_name) )
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 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 TokenizerModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'method': 0, } NLTKTokenizer, NLTKPunctTokenizer, TwitterTokenizer = 0, 1, 2 tokenizer_values = { NLTKTokenizer: 'default', NLTKPunctTokenizer: 'no_punct', TwitterTokenizer: 'twitter' } tokenizer_names = { NLTKTokenizer: 'NLTK tokenizer', NLTKPunctTokenizer: 'NLTK tokenizer (no punctuation)', TwitterTokenizer: 'Twitter tokenizer', } tokenizer_method = 0 def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__(self, 'Tokenizer', False, data.get('is_enabled')) self.group = QButtonGroup(self, exclusive=True) for method in [ self.NLTKTokenizer, self.NLTKPunctTokenizer, self.TwitterTokenizer, ]: rb = QRadioButton(self, text=self.tokenizer_names[method]) self.add_to_content_area(rb) self.group.addButton(rb, method) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the previous state, after starting off the layout. self.restore_data(data) def group_button_clicked(self): self.tokenizer_method = self.group.checkedId() self.notify_on_change() def restore_data(self, data): self.tokenizer_method = data.get('method') b = self.group.button(self.tokenizer_method) b.setChecked(True) def export_data(self): return { 'is_enabled': self.enabled, 'method': self.tokenizer_method, } def get_pp_setting(self): return {'tokenizer': self.tokenizer_values.get(self.tokenizer_method)}
class TransformationModule(PreprocessorModule): DEFAULT_SETTINGS = { 'is_enabled': True, 'method': 0, } PorterStemmer, SnowballStemmer, Lemmatizer = 0, 1, 2 transformation_values = { PorterStemmer: PS, SnowballStemmer: SS, Lemmatizer: LM, } transformation_method = 0 def __init__(self, data): data = data or self.DEFAULT_SETTINGS PreprocessorModule.__init__(self, 'Stemming', True, data.get('is_enabled')) self.group = QButtonGroup(self, exclusive=True) for method in [ self.PorterStemmer, self.SnowballStemmer, self.Lemmatizer ]: rb = QRadioButton(self, text=self.transformation_values[method].name) self.add_to_content_area(rb) self.group.addButton(rb, method) self.group.buttonClicked.connect(self.group_button_clicked) # Restore the previous state, after starting off the layout. self.restore_data(data) def group_button_clicked(self): self.transformation_method = self.group.checkedId() self.notify_on_change() def restore_data(self, data): self.transformation_method = data.get('method') b = self.group.button(self.transformation_method) b.setChecked(True) def export_data(self): return { 'is_enabled': self.enabled, 'method': self.transformation_method, } def get_pp_setting(self): return { 'transformation': self.transformation_values.get(self.transformation_method) }
class AxisWidgetContainer(GridWidget): def __init__(self, axisModel, parent = None): super(AxisWidgetContainer, self).__init__(["_Axis", "_Value_", "_X(24)", "_Y(24)"], parent) self.axisModel = axisModel self.xGroup = QButtonGroup() self.yGroup = QButtonGroup() self.xGroup.buttonClicked.connect(self.showXAxisButtonClicked) self.yGroup.buttonClicked.connect(self.showYAxisButtonClicked) axis = 0 for axis in range(axisModel.currentJoystickNumAxes()): self.__createTextWidgetForAxis__(axis) if axis > 0: self.graphWidget = AxisGraphWidget(self) self.addWidget(self.graphWidget, 3, 0, 1, 2) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) def __createTextWidgetForAxis__(self, axis): textWidget = AxisTextWidget(axis, self) self.axisModel.addAxisObserver(textWidget, axis) showInX = QRadioButton() showInY = QRadioButton() showInX.setObjectName(str(axis)) showInY.setObjectName(str(axis)) showInX.setLayoutDirection(Qt.RightToLeft) showInY.setLayoutDirection(Qt.RightToLeft) showInX.setMaximumSize(24, 24) showInY.setMaximumSize(24, 24) self.xGroup.addButton(showInX) self.yGroup.addButton(showInY) gridLayout = QGridLayout() gridLayout.addWidget(textWidget, 0, 0, 1, 2) gridLayout.addWidget(showInX, 0, 2, 1, 1) gridLayout.addWidget(showInY, 0, 3, 1, 1) self.addLayoutToScrollArea(gridLayout) def showXAxisButtonClicked(self, button): if button.isChecked(): self.graphWidget.setXAxis(int(button.objectName())) self.axisModel.addAxisObserver(self.graphWidget, int(button.objectName())) else: self.axisModel.removeAxisObserver(self.graphWidget, int(button.objectName())) def showYAxisButtonClicked(self, button): if button.isChecked(): self.graphWidget.setYAxis(int(button.objectName())) self.axisModel.addAxisObserver(self.graphWidget, int(button.objectName())) else: self.axisModel.removeAxisObserver(self.graphWidget, int(button.objectName()))
def __init__(self): super(IntroductionPage, self).__init__() self.setTitle(self.tr("Creación de un nuevo Proyecto")) self.setSubTitle(self.tr("Información básica del Proyecto")) container = QVBoxLayout(self) hbox = QHBoxLayout() # Nombre hbox.addWidget(QLabel(self.tr("Nombre del Proyecto:"))) self.line_name = QLineEdit() hbox.addWidget(self.line_name) container.addLayout(hbox) # Ubicación group = QGroupBox(self.tr("Ubicación:")) box = QVBoxLayout(group) button_group = QButtonGroup(self) radio_buttons = [ self.tr("Directorio por defecto"), self.tr("Otro") ] for _id, radiob in enumerate(radio_buttons): radio_button = QRadioButton(radiob) button_group.addButton(radio_button, _id) box.addWidget(radio_button) if _id == 0: # El primero checked por defecto radio_button.setChecked(True) container.addWidget(group) self.line_location = QLineEdit() container.addWidget(self.line_location) hbox = QHBoxLayout() hbox.addWidget(QLabel(self.tr("Archivo del Proyecto: "))) self._project_filename = QLineEdit() hbox.addWidget(self._project_filename) container.addLayout(hbox) hbox = QHBoxLayout() hbox.addWidget(QLabel(self.tr("Archivo resultante: "))) self._resulting_filename = QLineEdit() hbox.addWidget(self._resulting_filename) container.addLayout(hbox) # Conexiones self.connect(button_group, SIGNAL("buttonClicked(int)"), self._update_location) self.connect(self.line_name, SIGNAL("textChanged(const QString&)"), self._on_project_name_changed) self.connect(self.line_name, SIGNAL("textChanged(const QString&)"), lambda: self.emit(SIGNAL("completeChanged()"))) self._update_location(0)
def __init__(self, model, key, radiobuttonswithvalues): Mapping.__init__(self, model, key) self.radiobuttonswithvalues = radiobuttonswithvalues buttongroup = None for radiobutton, correspondingvalue in self.radiobuttonswithvalues.items(): # Tiresome extra setup to ensure that exactly one button is ever checked if buttongroup is None: buttongroup = QButtonGroup(radiobutton.parent()) buttongroup.addButton(radiobutton) # NB: default-argument indirection below to solve closure capture issues radiobutton.connect(radiobutton, SIGNAL("clicked()"), lambda cv=correspondingvalue: self.updateModelValue(cv))
def add_node(self, parentItem, path, type): item = QTreeWidgetItem(parentItem) item.setText(0, path_leaf(path)) buttonGroup = QButtonGroup() isNewFile = type is "UNTRACKED" isModifiedFile = type is "MODIFIED" isMissing = type is "MISSING" isDirectory = type is "DIR" if isNewFile: item.setText(1, type) item.setForeground(1, QBrush(QColor(0, 255, 0))) if isModifiedFile: item.setText(1, type) item.setForeground(1, QBrush(QColor(0, 0, 255))) if isMissing: item.setText(1, type) item.setForeground(1, QBrush(QColor(255, 0, 0))) if isDirectory: for i in range(self.tree.columnCount()): item.setBackground(i, QBrush(QColor(230, 230, 255))) # must keep reference to buttonGroup for its callback to work parent_data = self.retrieve_data(parentItem) if parent_data != None: path = os.path.join(parent_data[0], path) self.attach_data(item, (path, buttonGroup, type)) for i in range(self.uncheckableColumns, self.tree.columnCount()): if i == self.tree.columnCount() - 7 and isMissing: continue # option to add not enabled for missing files if i == self.tree.columnCount() - 4 and isNewFile: continue # option to resolve not enabled for new files if i == self.tree.columnCount() - 3 and not isMissing: continue # option to stop tracking enabled only for missing files if i == self.tree.columnCount() - 2 and not isNewFile: continue # option to delete enabled only for untracked files if i == self.tree.columnCount() - 2 and isDirectory: continue # option to delete not enabled for directories, too dangerous button = QRadioButton() buttonGroup.addButton(button, i - self.uncheckableColumns) # id is the index button.treeItem = item self.tree.setItemWidget(item, i, button) buttonGroup.buttonClicked.connect(self.tree_item_radio_clicked) return item
def __init__(self, parent = None): super(StrokeStyleWidget, self).__init__(parent) self.setupUi(self) capGroup = QButtonGroup(self) capGroup.addButton(self.squareCapButton, Qt.SquareCap) capGroup.addButton(self.roundCapButton, Qt.RoundCap) capGroup.addButton(self.flatCapButton, Qt.FlatCap) capGroup.setExclusive(True) capGroup.buttonClicked[int].connect(self.capStyleChanged) joinGroup = QButtonGroup(self) joinGroup.addButton(self.roundJoinButton, Qt.RoundJoin) joinGroup.addButton(self.miterJoinButton, Qt.MiterJoin) joinGroup.addButton(self.bevelJoinButton, Qt.BevelJoin) joinGroup.setExclusive(True) joinGroup.buttonClicked[int].connect(self.joinStyleChanged) self.widthSpinner.valueChanged.connect(self.strokeWidthChanged)
def addLogOrLogTypeOption(self): self.logsInWellRadioButton = QRadioButton() if self._logSet is None: self.logsInWellRadioButton.setText(self.SHOW_LOGS_IN_WELL) else: self.logsInWellRadioButton.setText(self.SHOW_LOGS_IN_LOG_SET) self.allLogTypesRadioButton = QRadioButton() self.allLogTypesRadioButton.setText(self.SHOW_ALL_LOG_TYPES) topButtonLayout = QHBoxLayout() self._dataListToListWidget.topButtonHolderWidget.setLayout(topButtonLayout) topButtonLayout.addWidget(self.logsInWellRadioButton) topButtonLayout.addWidget(self.allLogTypesRadioButton) topButtonGroup = QButtonGroup() topButtonGroup.addButton(self.logsInWellRadioButton) topButtonGroup.addButton(self.allLogTypesRadioButton) self.logsInWellRadioButton.setChecked(True)
class InputRadioGroup(QWidget): """Create an horizontal radio group""" def __init__(self, parent=None, option_list=None, default_select=0): super(InputRadioGroup, self).__init__(parent=parent) layout = QHBoxLayout(self) self.group = QButtonGroup() for idx, op in enumerate(option_list): self.op = QRadioButton(_(op)) if idx == default_select: self.op.setChecked(True) layout.addWidget(self.op) self.group.addButton(self.op) self.setLayout(layout) @pyqtProperty(str) def currentItemData(self): return str(abs(int(self.group.checkedId())) - 1)
def __init__(self, parent=None): IfaceWizardPage.__init__(self, parent) self.setSubTitle("What kind of interface do you want to configure?") self.ethernet = "ethernet", "Activate ethernet interface", QRadioButton() self.vlan = "vlan", "Create a VLAN interface", QRadioButton() self.bonding = "bonding", QLabel("Create a bonding interface"), QRadioButton() group = QButtonGroup(self) form = QFormLayout(self) options = (self.ethernet, self.vlan, self.bonding) for item in options: group.addButton(item[2]) form.addRow(item[1], item[2]) self.registerField(item[0], item[2]) self.ethernet[2].setChecked(Qt.Checked)
def __init__(self, result): QDialog.__init__(self) self.layout = QVBoxLayout(self) self.result = result observation_window = result.observation_window group = QButtonGroup(self) use_simu_duration = QRadioButton("Use entire simulation.") use_simu_duration.setChecked( observation_window[0] == 0 and observation_window[1] == result.model.duration) group.addButton(use_simu_duration) self.layout.addWidget(use_simu_duration) use_custom = QRadioButton("Use a custom observation window:") use_custom.setChecked(not use_simu_duration.isChecked()) group.addButton(use_custom) self.layout.addWidget(use_custom) self._slider = QxtSpanSliderWidget( 0, result.model.now() // result.model.cycles_per_ms, self) self._slider.setSpan( observation_window[0] // result.model.cycles_per_ms, observation_window[1] // result.model.cycles_per_ms) self._slider.setEnabled(use_custom.isChecked()) group.buttonClicked.connect( lambda x: self._slider.setEnabled(x == use_custom)) self.layout.addWidget(self._slider) buttons = QWidget(self) buttons_layout = QHBoxLayout() buttons.setLayout(buttons_layout) buttons_layout.addStretch() ok_button = QPushButton("Ok") cancel_button = QPushButton("Cancel") ok_button.clicked.connect(self.accept) cancel_button.clicked.connect(self.reject) buttons_layout.addWidget(ok_button) buttons_layout.addWidget(cancel_button) self.layout.addWidget(buttons)
class CategoryButtons(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) Layout = QHBoxLayout(self) self.group = QButtonGroup(self) for i, (k, color) in enumerate(ORDERED): button = QPushButton(k) palette = QPalette(button.palette()) palette.setColor(QPalette.Button, color) button.setPalette(palette) self.group.addButton(button) self.group.setId(button, i) Layout.addWidget(button) QObject.connect(self.group, SIGNAL('buttonClicked(QAbstractButton *)'), self.clicked) def clicked(self, button): category = ORDERED[self.group.id(button)][0] self.emit(SIGNAL('selected(QString &)'), category)
class SingleMethodModule(PreprocessorModule): method_index = settings.Setting(0) initialize_methods = True def setup_method_layout(self): self.group = QButtonGroup(self, exclusive=True) if self.initialize_methods: self.methods = [method() for method in self.methods] for i, method in enumerate(self.methods): rb = QRadioButton(self, text=self.textify(method.name)) rb.setChecked(i == self.method_index) rb.setToolTip(self.get_tooltip(method)) self.group.addButton(rb, i) self.method_layout.addWidget(rb, i, 0) self.group.buttonClicked.connect(self.update_value) def get_value(self): self.method_index = self.group.checkedId() return self.methods[self.method_index]
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent = None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setupSoQt() self.buttonGroup = QButtonGroup(self.groupBox) self.buttonGroup.addButton(self.button_x, 0) self.buttonGroup.addButton(self.button_y, 1) self.buttonGroup.addButton(self.button_z, 2) self.connect(self.buttonGroup, SIGNAL("buttonClicked(int)"), self.change_axis) self.connect(self.button, SIGNAL("clicked()"), self.change_color) self.connect(self.checkbox, SIGNAL("clicked()"), self.rotate) def change_axis(self, axis): self.rotxyz.axis = axis def change_color(self): self.material.diffuseColor = (random(), random(), random()) def rotate(self): self.gate.enable = not self.gate.enable.getValue() def setupSoQt(self): root = SoSeparator() self.rotxyz = SoRotationXYZ() self.gate = SoGate(SoMFFloat.getClassTypeId()) self.elapsedTime = SoElapsedTime() self.gate.enable = False self.gate.input.connectFrom(self.elapsedTime.timeOut) self.rotxyz.angle.connectFrom(self.gate.output) self.material = SoMaterial() self.material.diffuseColor = (0.0, 1.0, 1.0) self.cone = SoCone() root.addChild(self.rotxyz) root.addChild(self.material) root.addChild(self.cone) self.exam = SoQtExaminerViewer(self.examiner) self.exam.setSceneGraph(root)
class BrowserPage(QWidget): def __init__(self, base): QWidget.__init__(self) current_browser = base.core.get_default_browser() description = QLabel(i18n.get('web_browser_tab_description')) description.setWordWrap(True) self.command = QLineEdit() self.default_browser = RadioButton(i18n.get('use_default_browser'), self) self.default_browser.selected.connect(self.__on_defaul_selected) self.custom_browser = RadioButton(i18n.get('set_custom_browser'), self) self.custom_browser.selected.connect(self.__on_custom_selected) custom_label = QLabel(i18n.get('command')) self.open_button = QPushButton(i18n.get('open')) self.test_button = QPushButton(i18n.get('test')) self.test_button.clicked.connect(self.__on_test) command_box = QHBoxLayout() command_box.setSpacing(5) command_box.addWidget(custom_label) command_box.addWidget(self.command, 1) #command_box.addWidget(self.open_button) command_box.addWidget(self.test_button) self.button_group = QButtonGroup() self.button_group.addButton(self.default_browser.radiobutton) self.button_group.addButton(self.custom_browser.radiobutton) self.button_group.setExclusive(True) vbox = QVBoxLayout() vbox.setSpacing(0) vbox.setContentsMargins(5, 5, 5, 0) vbox.addWidget(description) vbox.addSpacing(15) vbox.addWidget(self.default_browser) vbox.addSpacing(10) vbox.addWidget(self.custom_browser) vbox.addLayout(command_box) vbox.addStretch(1) self.setLayout(vbox) if current_browser == '': self.default_browser.set_value(True) self.command.setText('') self.__on_defaul_selected() else: self.custom_browser.set_value(True) self.command.setText(current_browser) self.__on_custom_selected() def __on_test(self): cmd = str(self.command.text()) if cmd != '': subprocess.Popen([cmd, 'http://turpial.org.ve/']) def __on_defaul_selected(self): self.open_button.setEnabled(False) self.test_button.setEnabled(False) self.command.setEnabled(False) def __on_custom_selected(self): self.open_button.setEnabled(True) self.test_button.setEnabled(True) self.command.setEnabled(True) def get_config(self): if self.default_browser.get_value(): cmd = '' else: cmd = str(self.command.text()) return {'cmd': cmd}
def __init__(self, parent, item): Ui_QgsComposerItemWidgetBase.__init__(self, parent, item) # self.setupUi( self ) self.mItem = item self.mFreezeXPosSpin = False self.mFreezeYPosSpin = False self.mFreezeWidthSpin = False self.mFreezeHeightSpin = False self.mFreezePageSpin = False #make button exclusive buttonGroup = QButtonGroup(self) buttonGroup.addButton(self.mUpperLeftCheckBox) buttonGroup.addButton(self.mUpperMiddleCheckBox) buttonGroup.addButton(self.mUpperRightCheckBox) buttonGroup.addButton(self.mMiddleLeftCheckBox) buttonGroup.addButton(self.mMiddleCheckBox) buttonGroup.addButton(self.mMiddleRightCheckBox) buttonGroup.addButton(self.mLowerLeftCheckBox) buttonGroup.addButton(self.mLowerMiddleCheckBox) buttonGroup.addButton(self.mLowerRightCheckBox) buttonGroup.setExclusive(True) # self.mXLineEdit.setValidator( QDoubleValidator( 0 ) ) # self.mYLineEdit.setValidator( QDoubleValidator( 0 ) ) # self.mWidthLineEdit.setValidator( QDoubleValidator( 0 ) ) # self.mHeightLineEdit.setValidator( QDoubleValidator( 0 ) ) self.setValuesForGuiElements() self.connect(self.mItem.composition(), SIGNAL("paperSizeChanged()"), self.setValuesForGuiPositionElements) self.connect(self.mItem, SIGNAL("sizeChanged()"), self.setValuesForGuiPositionElements) self.connect(self.mItem, SIGNAL("itemChanged()"), self.setValuesForGuiNonPositionElements) self.connect(self.mTransparencySlider, SIGNAL("valueChanged( int )"), self.mTransparencySpnBx, SLOT("setValue( int )")) self.updateVariables() self.connect(self.mVariableEditor, SIGNAL("scopeChanged()"), self.variablesChanged) # listen out for variable edits # QgsApplication* app = qobject_cast<QgsApplication*>( QgsApplication.instance() ); # if ( app ) # { # self.connect( app, SIGNAL( settingsChanged() ), this, SLOT( updateVariables() ) ); # } # self.connect( QgsProject.instance(), SIGNAL( variablesChanged() ), this, SLOT( updateVariables() ) ); if (self.mItem.composition()): self.connect(self.mItem.composition(), SIGNAL("variablesChanged()"), self.updateVariables) #self.connect atlas signals to data defined buttons atlas = self.atlasComposition() if (atlas): #repopulate data defined buttons if atlas layer changes self.connect(atlas, SIGNAL("coverageLayerChanged( QgsVectorLayer* )"), self.populateDataDefinedButtons) self.connect(atlas, SIGNAL("toggled( bool )"), self.populateDataDefinedButtons) #self.connect data defined buttons self.connect(self.mXPositionDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mXPositionDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mYPositionDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mYPositionDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mWidthDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mWidthDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mHeightDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mHeightDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mItemRotationDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mItemRotationDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mTransparencyDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mTransparencyDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mBlendModeDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mBlendModeDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) self.connect(self.mExcludePrintsDDBtn, SIGNAL("dataDefinedChanged( const QString& )"), self.updateDataDefinedProperty) self.connect(self.mExcludePrintsDDBtn, SIGNAL("dataDefinedActivated( bool )"), self.updateDataDefinedProperty) #content in QgsComposerItemWidget.h file self.mFrameColorButton.colorChanged.connect( self.on_mFrameColorButton_colorChanged) self.mBackgroundColorButton.clicked.connect( self.on_mBackgroundColorButton_clicked) self.mBackgroundColorButton.colorChanged.connect( self.on_mBackgroundColorButton_colorChanged) self.connect(self.mOutlineWidthSpinBox, SIGNAL("valueChanged( double )"), self.on_mOutlineWidthSpinBox_valueChanged) self.mFrameGroupBox.toggled.connect(self.on_mFrameGroupBox_toggled) self.mFrameJoinStyleCombo.currentIndexChanged.connect( self.on_mFrameJoinStyleCombo_currentIndexChanged) self.mBackgroundGroupBox.toggled.connect( self.on_mBackgroundGroupBox_toggled) self.mItemIdLineEdit.editingFinished.connect( self.on_mItemIdLineEdit_editingFinished) self.mPageSpinBox.valueChanged.connect( self.on_mPageSpinBox_valueChanged) self.mXPosSpin.valueChanged.connect(self.on_mXPosSpin_valueChanged) self.mYPosSpin.valueChanged.connect(self.on_mYPosSpin_valueChanged) self.mWidthSpin.valueChanged.connect(self.on_mWidthSpin_valueChanged) self.mHeightSpin.valueChanged.connect(self.on_mHeightSpin_valueChanged) self.mUpperLeftCheckBox.stateChanged.connect( self.on_mUpperLeftCheckBox_stateChanged) self.mUpperMiddleCheckBox.stateChanged.connect( self.on_mUpperMiddleCheckBox_stateChanged) self.mUpperRightCheckBox.stateChanged.connect( self.on_mUpperRightCheckBox_stateChanged) self.mMiddleLeftCheckBox.stateChanged.connect( self.on_mMiddleLeftCheckBox_stateChanged) self.mMiddleCheckBox.stateChanged.connect( self.on_mMiddleCheckBox_stateChanged) self.mMiddleRightCheckBox.stateChanged.connect( self.on_mMiddleRightCheckBox_stateChanged) self.mLowerLeftCheckBox.stateChanged.connect( self.on_mLowerLeftCheckBox_stateChanged) self.mLowerMiddleCheckBox.stateChanged.connect( self.on_mLowerMiddleCheckBox_stateChanged) self.mLowerRightCheckBox.stateChanged.connect( self.on_mLowerRightCheckBox_stateChanged) self.mBlendModeCombo.currentIndexChanged.connect( self.on_mBlendModeCombo_currentIndexChanged) self.mTransparencySpnBx.valueChanged.connect( self.on_mTransparencySpnBx_valueChanged) self.connect(self.mItemRotationSpinBox, SIGNAL("valueChanged( double )"), self.on_mItemRotationSpinBox_valueChanged) self.mExcludeFromPrintsCheckBox.toggled.connect( self.on_mExcludeFromPrintsCheckBox_toggled)
class LdapWidget(DirectoryWidget): def __init__(self, config, specific_config, mainwindow, parent=None): assert config is not None assert specific_config is not None DirectoryWidget.__init__(self, config, specific_config, mainwindow, parent) self.buildInterface(config) self.updateView(self.specific_config) def buildInterface(self, config): #<server uri> self.uri = QLineEdit() self.texts.add(self.uri) self.connect(self.uri, SIGNAL('textChanged(QString)'), self.setUri) self.connect(self.uri, SIGNAL('textChanged(QString)'), self.signalModified) self.connect(self.uri, SIGNAL('textEdited(QString)'), self.helpURI) self.connect(self.uri, SIGNAL('editingFinished()'), self.noHelpURI) self.connect(self.uri, SIGNAL('editingFinished()'), self.updateUri) self.form.addRow(tr('LDAP Server(s) uri'), self.uri) self.uri.setToolTip(help_uri_tooltip) self.connect(self.uri, SIGNAL('returnPressed()'), self.signalModified) self.uri_message_area = MessageArea() self.empty_uri_label = QLabel() self.form.addRow(self.empty_uri_label, self.uri_message_area) self.empty_uri_label.hide() self.uri_message_area.hide() self.uri_message_area.setMessage(help_uri_title, help_uri_message_area) self.numeric_uri_warning = MessageArea() empty = QLabel() self.form.addRow(empty, self.numeric_uri_warning) empty.hide() self.numeric_uri_warning.hide() self.numeric_uri_warning.warning(numeric_warning_title, numeric_warning) self.numeric_uri_warning.setWidth(60) #</server uri> #<other fields> for args in self._genTextFieldsData(): text_input = self.addTextInput(*args[1:]) setattr(self, args[0], text_input) self.connect(text_input, SIGNAL('editingFinished(QString)'), self.valid) #</other fields> self.ssl_box = self.mkSslBox() self.connect(self.ssl_box, SIGNAL('toggled(bool)'), self.toggleSsl) self.form.addRow(self.ssl_box) self.form.addRow(separator()) test_widget = QPushButton(tr("Test this configuration")) self.form.addRow("", test_widget) test_widget.connect(test_widget, SIGNAL('clicked()'), self.test_ldap) def _genTextFieldsData(self): return ( ('dn_users', tr('LDAP DN for users'), self.setDnUsers), ('dn_groups', tr('LDAP DN for groups'), self.setDnGroups), ('user', tr('DN used to log in on the LDAP server'), self.setUser), ('password', tr('Password used to log in on the LDAP server'), self.setPassword, False) ) def test_ldap(self): dc, base, uri, filter, password = self.specific_config.generateTest() if uri is None or uri == '': QMessageBox.critical( self, "Missing data", "Please fill URI field" ) return if dc is None: dc == '' filter, ok = QInputDialog.getText( self, tr("LDAP Filter"), tr("Please enter a filter:"), QLineEdit.Normal, filter ) if not ok: return async = self.mainwindow.client.async() async.call( 'nuauth', 'testLDAP', dc, base, uri, unicode(filter), password, callback = self.success_test, errback = self.error_test ) def success_test(self, result): ans_no = tr("OK") ans_yes = tr("Show the server's answer") show_details = QMessageBox.question( self, tr('LDAP test results'), tr('LDAP test completed without error'), ans_no, ans_yes ) if show_details == 0: return title = tr('LDAP test results') QMessageBox.information( self, title, '<span><h2>%s</h2><pre>%s</pre></span>' % (title, unicode(result)) ) def error_test(self, result): basic_text = tr('LDAP test completed with an error') formatted_text = u"""\ <span> %s <pre> %s </pre> </span> """ % (basic_text, unicode(result)) QMessageBox.warning( self, tr('LDAP test results'), formatted_text ) def helpURI(self, text): self.uri_message_area.show() def noHelpURI(self): self.uri_message_area.hide() def toggleSsl(self, value): if value: self.selectCustomOrNupki(NUPKI) else: self.specific_config.custom_or_nupki = SSL_DISABLED self.signalModified() def setUri(self, uris_text): self.specific_config.setUri(self.readString(uris_text)) self.signalModified() self.numeric_uri_warning.setVisible(ip_in_ldapuri(self.specific_config.uri)) def setUser(self, user): self.specific_config.user = self.readString(user) def setPassword(self, password): self.specific_config.password = self.readString(password) def setDnUsers(self, dn): self.specific_config.dn_users = self.readString(dn) def setDnGroups(self, dn): self.specific_config.dn_groups = self.readString(dn) def mkSslBox(self): group = QGroupBox(tr("Check server certificate")) group.setCheckable(True) box = QVBoxLayout(group) #id 0 nupki = QRadioButton(tr("Upload certificate")) #id 1 custom = QRadioButton(tr("Use an internal PKI")) hbox = QHBoxLayout() box.addLayout(hbox) self.nupki_or_custom = QButtonGroup() self.connect(self.nupki_or_custom, SIGNAL('buttonClicked(int)'), self.toggleCustomOrNupki) for index, radio in enumerate((custom, nupki)): hbox.addWidget(radio) self.nupki_or_custom.addButton(radio, index) self.file_selector_widget = QWidget() vbox = QVBoxLayout(self.file_selector_widget) selector_label = QLabel(tr("Manually uploaded LDAP certificate")) vbox.addWidget(selector_label) add_cert_trigger = AddButton(text=tr("Upload a certificate")) vbox.addWidget(add_cert_trigger) vbox.addWidget(separator()) self.has_cert_message = QLabel( tr("There is no manually uploaded server certificate") ) self.del_cert = RemButton( tr("Delete certificate file from server") ) vbox.addWidget(self.has_cert_message) vbox.addWidget(self.del_cert) self.connect(add_cert_trigger, SIGNAL('clicked()'), self.upload_server_cert) self.connect(self.del_cert, SIGNAL('clicked()'), self.delete_server_cert) self.nupki_message = MessageArea() self.nupki_message.setMessage(tr("Warning"), tr( "There is no server certificate in the internal PKI.<br/>" "Please import or generate one using an internal PKI." ) ) for anti_button, widget in ((custom, self.nupki_message), (nupki, self.file_selector_widget)): box.addWidget(widget) self.connect(anti_button, SIGNAL('toggled(bool)'), widget.setVisible) self.selectCustomOrNupki(CUSTOM) return group def upload_server_cert(self): dialog = UploadDialog( selector_label=tr("LDAP certificate"), filter=tr("Certificate file (*.crt *.pem *)") ) accepted = dialog.exec_() if accepted != QDialog.Accepted: return filename = dialog.filename if not filename: return with open(filename, 'rb') as fd: content = fd.read() content = encodeFileContent(content) self.mainwindow.addToInfoArea(tr('Uploading of a certificate file for the ldap server')) async = self.mainwindow.client.async() async.call("nuauth", "upload_ldap_server_cert", content, callback = self.success_upload, errback = self.error_upload ) def success_upload(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] Success!')) self.specific_config.server_cert_set = True self.setServerCert() self.signalModified() def error_upload(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] Error!'), COLOR_ERROR) self.mainwindow.addToInfoArea(tr('[LDAP server cert upload] %s') % value, COLOR_ERROR) def setServerCert(self): if self.specific_config.server_cert_set: self.del_cert.show() self.has_cert_message.hide() else: self.del_cert.hide() self.has_cert_message.show() def delete_server_cert(self): confirm_box = QMessageBox(self) confirm_box.setText( tr( "Please confirm the deletion of the " "manually uploaded LDAP server certificate." ) ) confirm_box.setInformativeText( tr("Do you really want to delete the certificate file?") ) confirm_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) confirm_box.setDefaultButton(QMessageBox.Cancel) confirm = confirm_box.exec_() if confirm != QMessageBox.Ok: return async = self.mainwindow.client.async() async.call("nuauth", "delete_ldap_server_cert", callback = self.success_delete, errback = self.error_delete ) def success_delete(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] Success!')) self.specific_config.server_cert_set = False self.setServerCert() self.signalModified() def error_delete(self, value): self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] Error!'), COLOR_ERROR) self.mainwindow.addToInfoArea(tr('[LDAP server cert deletion] %s') % value, COLOR_ERROR) def toggleCustomOrNupki(self, id): if id == 0: self.specific_config.custom_or_nupki = NUPKI else: self.specific_config.custom_or_nupki = CUSTOM self.signalModified() def selectCustomOrNupki(self, custom_or_nupki): if custom_or_nupki == CUSTOM: self.file_selector_widget.setEnabled(True) self.nupki_message.hide() id = 1 else: custom_or_nupki = NUPKI self.file_selector_widget.hide() id = 0 self.nupki_or_custom.button(id).setChecked(True) def setSslData(self, config): ssl_enabled = (SSL_DISABLED != config.custom_or_nupki) self.ssl_box.setChecked(ssl_enabled) if ssl_enabled: self.selectCustomOrNupki(config.custom_or_nupki) def updateUri(self, config=None): if config is None: config = self.specific_config self.setText(self.uri, config.uri) def updateView(self, config=None): if config is None: config = self.specific_config self.updateUri(config=config) self.setSslData(config) #never copy this one: self.setDefaultText(self.dn_users, self.specific_config.dn_users) self.setDefaultText(self.dn_groups, self.specific_config.dn_groups) self.setDefaultText(self.user, config.user) self.setDefaultText(self.password, config.password) self.setServerCert()
class AutoFieldsDockWidget( QDockWidget, Ui_AutoFieldsDockWidget ): """ Class in charge of all the UI logic """ def __init__( self, parent, iface, autoFieldManager, messageManager, language='en' ): self.iface = iface self.msg = messageManager self.language = language QDockWidget.__init__( self, parent ) # Set up the user interface from Designer. self.setupUi( self ) self.autoFieldManager = autoFieldManager self.geometryDict = ['points','lines','polygons'] self.fieldTypesDict = ['Integer','Real','String','Date'] self.root = QgsProject.instance().layerTreeRoot() # UI stuff that wasn't set/initialized in Qt-Designer self.tblLayers.setColumnWidth( 0, 24 ) self.tblLayers.setColumnWidth( 1, 140 ) self.tblLayers.setColumnWidth( 2, 110 ) self.tblLayers.horizontalHeader().setResizeMode( 0, QHeaderView.Fixed ) self.tblLayers.sortItems(1, Qt.AscendingOrder) self.cboField.setEnabled( False ) self.cboFieldType.setItemData( 0, QVariant.Int, Qt.UserRole ) self.cboFieldType.setItemData( 1, QVariant.Double, Qt.UserRole ) self.cboFieldType.setItemData( 2, QVariant.String, Qt.UserRole ) self.cboFieldType.setItemData( 3, QVariant.Date, Qt.UserRole ) self.fieldTypeChanged( self.cboFieldType.currentIndex() ) # Update length/precision controls self.btnGroup = QButtonGroup() self.btnGroup.addButton( self.optXCoord ) self.btnGroup.addButton( self.optYCoord ) self.btnGroup.addButton( self.optLength ) self.btnGroup.addButton( self.optPerimeter ) self.btnGroup.addButton( self.optArea ) self.btnGroup.addButton( self.optDate ) self.btnGroup.addButton( self.optCustomExpression ) #self.btnGroup.addButton( self.optSpatialValue ) self.updateExpressionControls( self.optCustomExpression ) self.frameFields.setEnabled( False ) self.frameExpression.setEnabled( False ) self.populateLayersTable() QgsMapLayerRegistry.instance().legendLayersAdded.connect( self.populateLayersTable ) QgsMapLayerRegistry.instance().layersRemoved.connect( self.populateLayersTable ) # Also listen to Layer Tree node position changes self.root.addedChildren.connect( self.populateLayersTable ) self.root.removedChildren.connect( self.populateLayersTable ) self.tblLayers.itemSelectionChanged.connect( self.updateFieldAndExpressionControls ) self.optNewField.toggled.connect( self.newFieldToggled ) self.cboField.currentIndexChanged.connect( self.fieldChanged ) self.cboFieldType.currentIndexChanged.connect( self.fieldTypeChanged ) self.btnSaveAutoField.clicked.connect( self.saveAutoField ) self.btnNewCustomExpression.clicked.connect( self.setCustomExpression ) self.btnGroup.buttonClicked.connect( self.updateExpressionControls ) self.expressionDlg = None # 'List of AutoFields' Tab settings = QSettings() check = settings.value( self.autoFieldManager.settingsPrefix + "/showOnlyEnabledAutoFields", True, type=bool ) self.chkOnlyEnabledAutoFields.setChecked( check ) check = settings.value( self.autoFieldManager.settingsPrefix + "/calculateOnExistingFeatures", True, type=bool ) self.chkCalculateOnExisting.setChecked( check ) self.btnRemoveAutoFields.setEnabled( False ) self.tblAutoFields.sortItems(0, Qt.AscendingOrder) self.populateAutoFieldsTable() self.autoFieldManager.autoFieldCreated.connect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldRemoved.connect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldEnabled.connect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldDisabled.connect( self.populateAutoFieldsTable ) self.tblAutoFields.itemSelectionChanged.connect( self.updateRemoveAutoFieldButton ) self.chkOnlyEnabledAutoFields.toggled.connect( self.saveShowOnlyEnabledPreference ) self.chkCalculateOnExisting.toggled.connect( self.saveCalculateOnExistingPreference ) self.btnRemoveAutoFields.clicked.connect( self.removeAutoFieldFromTable ) # Context menu self.tblAutoFields.setContextMenuPolicy( Qt.CustomContextMenu ) self.tblAutoFields.customContextMenuRequested.connect( self.openAutoFieldContextMenu ) # About Tab self.btnHelp.clicked.connect( self.openDocumentation ) def populateLayersTable( self, foo=None, foo2=None, foo3=None ): """ List vector layers that support changes in attributes and are writable. Arguments are 3 and optional because this function listens to several SIGNALs. """ # Initialize Layers Table self.tblLayers.clearContents() self.tblLayers.setRowCount( 0 ) vLayers = [] for layer in QgsMapLayerRegistry.instance().mapLayers().values(): if layer.type() == QgsMapLayer.VectorLayer: if layer.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues: if not layer.isReadOnly(): if layer.geometryType() < 3: # Avoid UnknownGeometry and NoGeometry vLayers.append( layer ) self.tblLayers.setRowCount( len( vLayers ) ) self.tblLayers.setColumnCount( 3 ) self.tblLayers.setSortingEnabled( False ) for row, lyr in enumerate( vLayers ): item = QTableWidgetItem( QIcon( ":/plugins/AutoFields/icons/" + \ self.geometryDict[lyr.geometryType()] + ".png"), str( lyr.geometryType() ) ) self.tblLayers.setItem( row, 0, item ) item = QTableWidgetItem( lyr.name() ) item.setData( Qt.UserRole, lyr.id() ) self.tblLayers.setItem( row, 1, item ) tmpTreeLayer = self.root.findLayer( lyr.id() ) if tmpTreeLayer: group = tmpTreeLayer.parent().name() self.tblLayers.setItem(row, 2, QTableWidgetItem( group if group else QApplication.translate("AutoFieldsDockWidgetPy", "< root >" ) ) ) self.tblLayers.setSortingEnabled( True ) def updateFieldAndExpressionControls( self ): """ After a selection is changed, reflect possible values in field controls """ self.msg.show( "New selection " + str(len( self.tblLayers.selectedItems() ) / 3), 'info', True ) if not self.tblLayers.selectedItems(): self.frameFields.setEnabled( False ) self.frameExpression.setEnabled( False ) return else: self.frameFields.setEnabled( True ) self.frameExpression.setEnabled( True ) # List common fields in cboField and get geometries selected geometryTypeSet = self.updateFieldList() # Update expression controls if 0 in geometryTypeSet and len( geometryTypeSet ) == 1: # Points self.optXCoord.setEnabled( True ) self.optYCoord.setEnabled( True ) self.optLength.setEnabled( False ) self.optPerimeter.setEnabled( False ) self.optArea.setEnabled( False ) elif 1 in geometryTypeSet and len( geometryTypeSet ) == 1: # Lines self.optXCoord.setEnabled( False ) self.optYCoord.setEnabled( False ) self.optLength.setEnabled( True ) self.optPerimeter.setEnabled( False ) self.optArea.setEnabled( False ) elif 2 in geometryTypeSet and len( geometryTypeSet ) == 1: # Polygons self.optXCoord.setEnabled( False ) self.optYCoord.setEnabled( False ) self.optLength.setEnabled( False ) self.optPerimeter.setEnabled( True ) self.optArea.setEnabled( True ) else: self.optXCoord.setEnabled( False ) self.optYCoord.setEnabled( False ) self.optLength.setEnabled( False ) self.optPerimeter.setEnabled( False ) self.optArea.setEnabled( False ) if not self.btnGroup.checkedButton().isEnabled(): self.optCustomExpression.setChecked( True ) # Default selection self.updateExpressionControls( self.optCustomExpression ) self.expressionDlg = None # Initialize the dialog def updateFieldList( self ): """ Update field list and return geometries selected """ commonFields = [] geometryTypeSet = set() bFirstFlag = True for item in self.tblLayers.selectedItems(): if item.column() == 1: # It's the layer name item self.msg.show( "ID " + item.data( Qt.UserRole ), 'info', True ) # Get layer id layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) ) geometryTypeSet.add( layer.geometryType() ) tmpFields = [field.name() for field in layer.dataProvider().fields()] # Get field names stored in the provider if bFirstFlag: # Initialize commonFields commonFields = tmpFields bFirstFlag = False else: # Intersect fields if commonFields: # Avoid intersecting if no common fields commonFields = list( set( commonFields ) & set( tmpFields ) ) commonFields.sort() self.msg.show( "FIELDS: "+ str(commonFields), 'info', True) self.cboField.clear() if not commonFields: self.optExistingField.setEnabled( False ) self.optNewField.setChecked( True ) else: self.optExistingField.setEnabled( True ) self.cboField.addItems( commonFields ) return geometryTypeSet def newFieldToggled( self ): """ Alternate between controls of new field and existing field """ newIsChecked = self.optNewField.isChecked() self.cboField.setEnabled( not newIsChecked ) self.lblFieldName.setEnabled( newIsChecked ) self.lblFieldType.setEnabled( newIsChecked ) self.txtFieldName.setEnabled( newIsChecked ) self.cboFieldType.setEnabled( newIsChecked ) if newIsChecked: self.fieldTypeChanged( self.cboFieldType.currentIndex() ) else: self.lblFieldLength.setEnabled( newIsChecked ) self.lblFieldPrecision.setEnabled( newIsChecked ) self.txtFieldLength.setEnabled( newIsChecked ) self.txtFieldPrecision.setEnabled( newIsChecked ) self.expressionDlg = None # Initialize the dialog def fieldTypeChanged( self, idx ): """ Update field length and field precision controls' state and values """ text = self.fieldTypesDict[idx] if text == 'Integer': self.txtFieldLength.setRange( 1, 10 ) self.txtFieldLength.setEnabled( True ) self.txtFieldPrecision.setEnabled( False ) self.lblFieldLength.setEnabled( True ) self.lblFieldPrecision.setEnabled( False ) elif text == 'Real': self.txtFieldLength.setRange( 1, 20 ) self.txtFieldPrecision.setRange( 0, 15 ) self.txtFieldLength.setEnabled( True ) self.txtFieldPrecision.setEnabled( True ) self.lblFieldLength.setEnabled( True ) self.lblFieldPrecision.setEnabled( True ) elif text == 'String': self.txtFieldLength.setRange( 1, 255 ) self.txtFieldLength.setEnabled( True ) self.txtFieldPrecision.setEnabled( False ) self.lblFieldLength.setEnabled( True ) self.lblFieldPrecision.setEnabled( False ) else: # Date self.txtFieldLength.setEnabled( False ) self.txtFieldPrecision.setEnabled( False ) self.lblFieldLength.setEnabled( False ) self.lblFieldPrecision.setEnabled( False ) def fieldChanged( self, idx ): """ Just to initialize the expression dialog if selected field changes """ self.expressionDlg = None # Initialize the dialog def saveAutoField( self ): """ Do some validation and then call AutoFieldManager """ # Check layers if not self.tblLayers.selectedItems(): self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Warning] Please first select a layer." ), 'warning' ) return # Check expression expression = u'' if self.optXCoord.isChecked(): expression = u'$x' elif self.optYCoord.isChecked(): expression = u'$y' elif self.optLength.isChecked(): expression = u'$length' elif self.optPerimeter.isChecked(): expression = u'$perimeter' elif self.optArea.isChecked(): expression = u'$area' elif self.optDate.isChecked(): expression = u'now()' elif self.optCustomExpression.isChecked(): if self.expressionDlg: expression = self.expressionDlg.expression if not self.expressionDlg or not expression: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Warning] Please first set a valid custom expression." ), 'warning' ) return else: # optSpatialValue pass # Check fields fieldName = '' if self.optNewField.isChecked(): if self.txtFieldName.text(): fieldName = self.txtFieldName.text().strip() newField = QgsField( fieldName, self.cboFieldType.itemData( self.cboFieldType.currentIndex(), Qt.UserRole) ) length = self.txtFieldLength.value() precision = self.txtFieldPrecision.value() # Ensure length and precision are valid values when dealing with Real numbers if self.fieldTypesDict[self.cboFieldType.currentIndex()] == 'Real': if precision > length: precision = length newField.setLength( length ) newField.setPrecision( precision ) for item in self.tblLayers.selectedItems(): if item.column() == 1: # It's the layer name item layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) ) if layer.fieldNameIndex( fieldName ) != -1: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Error] The field " ) + fieldName + \ QApplication.translate( "AutoFieldsDockWidgetPy", " already exists in layer " ) + layer.name() + ". " + \ QApplication.translate( "AutoFieldsDockWidgetPy", " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ), 'warning' ) else: res = layer.dataProvider().addAttributes( [ newField ] ) if res: layer.updateFields() # Check if fieldName is preserved by the provider after field creation. if layer.fieldNameIndex( fieldName ) == -1: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Error] The field " ) + fieldName + \ QApplication.translate( "AutoFieldsDockWidgetPy", " was probably created with another name by the layer (" ) + \ layer.name() + \ QApplication.translate( "AutoFieldsDockWidgetPy", ") provider. " ) + \ QApplication.translate( "AutoFieldsDockWidgetPy", " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ), 'warning' ) else: self.doSaveAutoField( layer, fieldName, expression ) else: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Error] Couldn't create " ) + newField.name() + \ QApplication.translate( "AutoFieldsDockWidgetPy", " field in " ) + layer.name() + \ QApplication.translate( "AutoFieldsDockWidgetPy", " layer." ), 'warning' ) # Some fields might have been created, update the field list once self.updateFieldList() else: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "[Warning] Please first set a name for the new field." ), 'warning' ) return else: fieldName = self.cboField.currentText() for item in self.tblLayers.selectedItems(): if item.column() == 1: # It's the layer name item layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) ) self.doSaveAutoField( layer, fieldName, expression ) def doSaveAutoField( self, layer, fieldName, expression ): """ Repetitive logic to save or overwrite an AutoField """ # Check if the field is an AutoField and ask if we should overwrite it res = True bCalculateOnExisting = self.chkCalculateOnExisting.isChecked() if self.autoFieldManager.isFieldAnAutoField( layer, fieldName ): reply = QMessageBox.question( self.iface.mainWindow(), QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ), QApplication.translate( "AutoFieldsDockWidgetPy", "The field '" ) + \ fieldName + QApplication.translate( "AutoFieldsDockWidgetPy", "' from layer '" ) + layer.name() + \ QApplication.translate( "AutoFieldsDockWidgetPy", "' is already an AutoField.\nDo you want to overwrite it?" ), QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) if reply == QMessageBox.Yes: res = self.autoFieldManager.overwriteAutoField( layer, fieldName, expression, calculateOnExisting=bCalculateOnExisting ) else: res = self.autoFieldManager.createAutoField( layer, fieldName, expression, calculateOnExisting=bCalculateOnExisting ) if not res: # res will only be False if create/overwriteAutoField return False self.msg.show( "[Error] The AutoField for layer '" + layer.name() + \ "' and field '" + fieldName + "' couldn't be created.", 'warning', True ) def setCustomExpression( self ): """ Initialize and show the expression builder dialog """ layer = None if len( self.tblLayers.selectedItems() ) / 3 == 1: # Single layer selected? for item in self.tblLayers.selectedItems(): if item.column() == 1: # It's the layer name item layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) ) if not self.expressionDlg: self.expressionDlg = ExpressionBuilderDialog( self.iface.mainWindow() ) context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.globalScope() ) context.appendScope( QgsExpressionContextUtils.projectScope() ) # Initialize dialog with layer-based names and variables if single layer selected if len( self.tblLayers.selectedItems() ) / 3 == 1: context.appendScope( QgsExpressionContextUtils.layerScope( layer ) ) self.expressionDlg.expressionBuilderWidget.setLayer( layer ) self.expressionDlg.expressionBuilderWidget.loadFieldNames() # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py da = QgsDistanceArea() da.setSourceCrs( layer.crs().srsid() ) da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() ) da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] ) self.expressionDlg.expressionBuilderWidget.setGeomCalculator( da ) # If this layer-field is an AutoField, get its expression if self.optExistingField.isChecked(): fieldName = self.cboField.currentText() expression = self.autoFieldManager.getFieldExpression( layer, fieldName ) self.expressionDlg.expressionBuilderWidget.setExpressionText( expression ) self.expressionDlg.expression = expression # To remember it when closing/opening self.expressionDlg.expressionBuilderWidget.setExpressionContext( context ) self.expressionDlg.show() def updateExpressionControls( self, button ): """ Enable/disable push buttons when appropriate """ if button.objectName() == 'optCustomExpression': self.btnNewCustomExpression.setEnabled( True ) #self.btnNewSpatialValue.setEnabled( False ) #elif button.objectName() == 'optSpatialValue': #self.btnNewCustomExpression.setEnabled( False ) #self.btnNewSpatialValue.setEnabled( True ) else: self.btnNewCustomExpression.setEnabled( False ) #self.btnNewSpatialValue.setEnabled( False ) def populateAutoFieldsTable( self, autoFieldId=None ): """ Listens to any modification on AutoFields to update the list """ dictAutoFields = self.autoFieldManager.listAutoFields() if autoFieldId: # Just update this one if not autoFieldId in dictAutoFields: # AutoField removed self.msg.show( "[Info] Removing AutoField from table.", 'info', True ) # Iterate through AF rows and remove row where data matches AFID deleteRow = self.findRowOfItemDataInAutoFieldsTable( autoFieldId, 0) if deleteRow != -1: self.tblAutoFields.removeRow( deleteRow ) else: # if it's in the table: remove it and re-add it (from new dict) deleteRow = self.findRowOfItemDataInAutoFieldsTable( autoFieldId, 0) if deleteRow != -1: self.msg.show( "[Info] Refreshing AutoField status in table.", 'info', True ) self.tblAutoFields.removeRow( deleteRow ) self.addAutoFieldToAutoFieldsTable( autoFieldId, dictAutoFields[autoFieldId] ) else: # New AutoField, just add it to table self.msg.show( "[Info] Adding new AutoField to table.", 'info', True ) self.addAutoFieldToAutoFieldsTable( autoFieldId, dictAutoFields[autoFieldId] ) else: # Initialize AutoFields Table self.tblAutoFields.clearContents() self.tblAutoFields.setRowCount( 0 ) #self.tblAutoFields.setRowCount( len( dictAutoFields ) ) self.tblAutoFields.setColumnCount( 4 ) self.tblAutoFields.setSortingEnabled( False ) for key in dictAutoFields.keys(): autoField = dictAutoFields[key] self.addAutoFieldToAutoFieldsTable( key, autoField, False ) self.tblAutoFields.setSortingEnabled( True ) def findRowOfItemDataInAutoFieldsTable( self, data, col ): """ Get the row number that matches its data to a given data (check only the given column) """ for numRow in range( self.tblAutoFields.rowCount() ): item = self.tblAutoFields.item( numRow, col ) if item.data( Qt.UserRole ) == data: return numRow return -1 def addAutoFieldToAutoFieldsTable( self, autoFieldId, autoField, freezeSorting=True ): """ Add a whole row to the AutoFields table """ if self.chkOnlyEnabledAutoFields.isChecked() and not autoField['enabled']: return if freezeSorting: self.tblAutoFields.setSortingEnabled( False ) row = self.tblAutoFields.rowCount() self.tblAutoFields.insertRow( row ) name = autoField['layer'] if 'layerId' in autoField: lyr = QgsMapLayerRegistry.instance().mapLayer( autoField['layerId'] ) name = lyr.name() item = QTableWidgetItem( name ) item.setData( Qt.UserRole, autoFieldId ) item.setData( Qt.ToolTipRole, autoField['layer'] ) if not autoField['enabled']: item.setForeground( QBrush( Qt.gray ) ) self.tblAutoFields.setItem( row, 0, item ) item = QTableWidgetItem( autoField['field'] ) if not autoField['enabled']: item.setForeground( QBrush( Qt.gray ) ) self.tblAutoFields.setItem( row, 1, item ) item = QTableWidgetItem( autoField['expression'] ) if not autoField['enabled']: item.setForeground( QBrush( Qt.gray ) ) self.tblAutoFields.setItem( row, 2, item ) item = QTableWidgetItem( QApplication.translate( "AutoFieldsDockWidgetPy", "Enabled" ) if autoField['enabled'] else QApplication.translate( "AutoFieldsDockWidgetPy", "Disabled" ) ) item.setData( Qt.UserRole, 'enabled' if autoField['enabled'] else 'disabled' ) if not autoField['enabled']: item.setForeground( QBrush( Qt.gray ) ) self.tblAutoFields.setItem( row, 3, item ) if freezeSorting: self.tblAutoFields.setSortingEnabled( True ) def openAutoFieldContextMenu( self, position ): bLayers = False layers = QgsMapLayerRegistry.instance().mapLayers().values() for layer in layers: if layer.type() == QgsMapLayer.VectorLayer: if layer.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures: bLayers = True break item = self.tblAutoFields.itemAt( position ) if item: row = item.row() self.menu = QMenu() self.action = QAction( "Assign this AutoField to another layer", None ) self.action.setObjectName('action') if self.tblAutoFields.item( row, 3 ).data( Qt.UserRole ) == 'enabled': self.action.setEnabled( False ) self.menu.addAction( self.action ) action = self.menu.exec_(self.tblAutoFields.mapToGlobal(position)) if action and action.objectName() == 'action': if not bLayers: self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy", "First load some vector layers to QGIS to be able to assign disabled AutoFields." ), 'warning' ) return autoFieldId = self.tblAutoFields.item( row, 0 ).data( Qt.UserRole ) bCalculateOnExisting = self.chkCalculateOnExisting.isChecked() dlg = AssignAutoFieldToLayerDialog( self.iface.mainWindow(), self.autoFieldManager, autoFieldId, bCalculateOnExisting ) dlg.show() def updateRemoveAutoFieldButton( self ): """ Enable/disable button to remove AutoFields when appropriate """ self.btnRemoveAutoFields.setEnabled( len( self.tblAutoFields.selectedItems() ) / 4 ) def removeAutoFieldFromTable( self ): """ Show a confirmation dialog for all AutoFields selected. If confirmed, remove AutoFields from table. """ # Column 0 has the AutoField id autoFieldsToRemove = [ item.data( Qt.UserRole ) for item in self.tblAutoFields.selectedItems() if item.column() == 0 ] reply = QMessageBox.question( self.iface.mainWindow(), QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ), QApplication.translate( "AutoFieldsDockWidgetPy", "Do you really want to remove " ) + \ str(len( autoFieldsToRemove )) + \ (" AutoFields?" if len( autoFieldsToRemove ) > 1 else " AutoField?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) if reply == QMessageBox.Yes: for autoFieldId in autoFieldsToRemove: self.autoFieldManager.removeAutoField( autoFieldId ) def saveShowOnlyEnabledPreference( self, status ): """ Saves the preference in QSettings and updates list of AutoFields """ settings = QSettings() settings.setValue( self.autoFieldManager.settingsPrefix + "/showOnlyEnabledAutoFields" , status ) self.populateAutoFieldsTable() def saveCalculateOnExistingPreference( self, status ): """ Saves the preference in QSettings """ settings = QSettings() settings.setValue( self.autoFieldManager.settingsPrefix + "/calculateOnExistingFeatures" , status ) def openDocumentation( self ): """ Open a browser to show documentation page """ import webbrowser webbrowser.open( "http://geotux.tuxfamily.org/index.php/"+ self.language +"/geo-blogs/item/333-autofields-plugin-for-qgis" ) def disconnectAll( self ): """ Terminates all SIGNAL/SLOT connections created by this class """ QgsMapLayerRegistry.instance().legendLayersAdded.disconnect( self.populateLayersTable ) QgsMapLayerRegistry.instance().layersRemoved.disconnect( self.populateLayersTable ) self.root.addedChildren.disconnect( self.populateLayersTable ) self.root.removedChildren.disconnect( self.populateLayersTable ) self.tblLayers.itemSelectionChanged.disconnect( self.updateFieldAndExpressionControls ) self.optNewField.toggled.disconnect( self.newFieldToggled ) self.cboField.currentIndexChanged.disconnect( self.fieldChanged ) self.cboFieldType.currentIndexChanged.disconnect( self.fieldTypeChanged ) self.btnSaveAutoField.clicked.disconnect( self.saveAutoField ) self.btnNewCustomExpression.clicked.disconnect( self.setCustomExpression ) self.btnGroup.buttonClicked.disconnect( self.updateExpressionControls ) self.autoFieldManager.autoFieldCreated.disconnect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldRemoved.disconnect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldEnabled.disconnect( self.populateAutoFieldsTable ) self.autoFieldManager.autoFieldDisabled.disconnect( self.populateAutoFieldsTable ) self.tblAutoFields.itemSelectionChanged.disconnect( self.updateRemoveAutoFieldButton ) self.chkOnlyEnabledAutoFields.toggled.disconnect( self.saveShowOnlyEnabledPreference ) self.btnRemoveAutoFields.clicked.disconnect( self.removeAutoFieldFromTable )
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 AddBookmarkDialog(utils.Dialog): def __init__(self, parent, hex_widget): utils.Dialog.__init__(self, parent, name='add_bookmark_dialog') self.hexWidget = hex_widget self.ui = Ui_AddBookmarkDialog() self.ui.setupUi(self) self._canCreateBookmark = True self._isColorChoosen = False self._groupMark = QButtonGroup() self._groupMark.addButton(self.ui.btnMarkCaret) self._groupMark.addButton(self.ui.btnMarkSelection) if self.hexWidget.hasSelection: self.ui.btnMarkSelection.setChecked(True) else: self.ui.btnMarkCaret.setChecked(True) self._groupBind = QButtonGroup() self._groupBind.addButton(self.ui.btnBoundToPosition) self._groupBind.addButton(self.ui.btnBoundToData) self.ui.btnBoundToData.setChecked(True) self._bookmarkColor = QColor(Qt.red) self.ui.btnMarkCaret.toggled.connect(self._updateOk) self.ui.btnMarkSelection.toggled.connect(self._updateOk) self.ui.btnMarkCaret.toggled.connect(self._updateColor) self.ui.btnMarkSelection.toggled.connect(self._updateColor) self.ui.btnSelectColor.clicked.connect(self._selectBookmarkColor) self._updateOk() bookmark_name = '' if self._canCreateBookmark: bookmark_range = self.createBookmark() # find existing bookmarks that contain this one c_bookmarks = [b for b in self.hexWidget.bookmarks if b.contains(bookmark_range)] if c_bookmarks: c_bookmark = min(c_bookmarks, key=lambda x: x.size) bookmark_name = c_bookmark.name + '.' if bookmark_name: self.ui.txtName.setText(bookmark_name) else: bookmark_name = utils.tr('bookmark{0}').format(currentBookmarkIndex) self.ui.txtName.setText(bookmark_name) self.ui.txtName.selectAll() self._updateColor() def _updateColorButton(self): pixmap = QPixmap(32, 32) pixmap.fill(self._bookmarkColor) self.ui.btnSelectColor.setIcon(QIcon(pixmap)) def _updateOk(self): if self.ui.btnMarkCaret.isChecked(): caret_pos = self.hexWidget.caretPosition enabled = caret_pos >= 0 else: enabled = self.hexWidget.hasSelection self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enabled) self._canCreateBookmark = enabled def _updateColor(self): if self._canCreateBookmark and not self._isColorChoosen: bookmark_range = self.createBookmark() i_bookmarks = [b for b in self.hexWidget.bookmarks if b.intersectsWith(bookmark_range)] distance = settings.globalSettings()[appsettings.HexWidget_RandomColorDistance] used_colors = [b.backgroundColor for b in i_bookmarks] + [self.hexWidget.theme.backgroundColor, self.hexWidget.theme.textColor] for i in range(100): bookmark_color = utils.generateRandomColor() if all(colorsDistance(bookmark_color, color) >= distance for color in used_colors): break else: # we have not found acceptable color... Let's just find color that is not equal to existing. while bookmark_color not in used_colors: bookmark_color = utils.generateRandomColor() self._bookmarkColor = bookmark_color self._updateColorButton() def _selectBookmarkColor(self): color = QColorDialog.getColor(self._bookmarkColor, self, utils.tr('Select color for bookmark')) if color.isValid(): self._bookmarkColor = color self._updateColorButton() def createBookmark(self): bookmark = None if self.ui.btnMarkCaret.isChecked(): caret_pos = self.hexWidget.caretPosition if caret_pos >= 0: bookmark = hexwidget.BookmarkedRange(self.hexWidget, caret_pos, 1, hexwidget.DataRange.UnitBytes, self._boundTo) elif self.hexWidget.selectionRanges: select_range = self.hexWidget.selectionRanges[0] if select_range: bookmark = hexwidget.BookmarkedRange(self.hexWidget, select_range.start, select_range.length, select_range.unit, self._boundTo) if bookmark is not None: bookmark.name = self.ui.txtName.text() bookmark.backgroundColor = self._bookmarkColor return bookmark @property def _boundTo(self): return hexwidget.DataRange.BoundToPosition if self.ui.btnBoundToPosition.isChecked() else hexwidget.DataRange.BoundToData def accept(self): global currentBookmarkIndex currentBookmarkIndex += 1 utils.Dialog.accept(self)
def create_widgets(self): # Name self.name = QLabel("Title:") self.name_edit = QLineEdit(str(self._default_name)) self.name_button = QPushButton("Default") # Min self.min = QLabel("Min:") self.min_edit = QLineEdit(str(self._default_min)) self.min_button = QPushButton("Default") # Max self.max = QLabel("Max:") self.max_edit = QLineEdit(str(self._default_max)) self.max_button = QPushButton("Default") # Format self.format = QLabel("Format (e.g. %.3f, %g, %.6e):") self.format_edit = QLineEdit(str(self._format)) self.format_button = QPushButton("Default") # Scale self.scale = QLabel("Scale:") self.scale_edit = QLineEdit(str(self._scale)) self.scale_button = QPushButton("Default") if self._default_scale == 0.0: self.scale_edit.setEnabled(False) self.scale_button.setEnabled(False) #tip = QtGui.QToolTip() #tip.setTe #self.format_edit.toolTip(tip) #--------------------------------------- # nlabels self.nlabels = QLabel("Number of Labels:") self.nlabels_edit = QLineEdit(str(self._nlabels)) self.nlabels_button = QPushButton("Default") self.labelsize = QLabel("Label Size:") self.labelsize_edit = QLineEdit(str(self._labelsize)) self.labelsize_button = QPushButton("Default") self.ncolors = QLabel("Number of Colors:") self.ncolors_edit = QLineEdit(str(self._ncolors)) self.ncolors_button = QPushButton("Default") self.colormap = QLabel("Color Map:") self.colormap_edit = QComboBox(self) self.colormap_button = QPushButton("Default") for key in colormap_keys: self.colormap_edit.addItem(key) self.colormap_edit.setCurrentIndex(colormap_keys.index(self._colormap)) # red/blue or blue/red self.low_to_high_radio = QRadioButton('Low -> High') self.high_to_low_radio = QRadioButton('High -> Low') widget = QWidget(self) low_to_high_group = QButtonGroup(widget) low_to_high_group.addButton(self.low_to_high_radio) low_to_high_group.addButton(self.high_to_low_radio) self.low_to_high_radio.setChecked(self._default_is_low_to_high) self.high_to_low_radio.setChecked(not self._default_is_low_to_high) # horizontal / vertical self.horizontal_radio = QRadioButton("Horizontal") self.vertical_radio = QRadioButton("Vertical") widget = QWidget(self) horizontal_vertical_group = QButtonGroup(widget) horizontal_vertical_group.addButton(self.horizontal_radio) horizontal_vertical_group.addButton(self.vertical_radio) self.horizontal_radio.setChecked(self._default_is_horizontal) self.vertical_radio.setChecked(not self._default_is_horizontal) # on / off self.show_radio = QRadioButton("Show") self.hide_radio = QRadioButton("Hide") widget = QWidget(self) show_hide_group = QButtonGroup(widget) show_hide_group.addButton(self.show_radio) show_hide_group.addButton(self.hide_radio) self.show_radio.setChecked(self._default_is_shown) self.hide_radio.setChecked(not self._default_is_shown) # closing self.apply_button = QPushButton("Apply") self.ok_button = QPushButton("OK") self.cancel_button = QPushButton("Cancel")
class PetaBencanaDialog(QDialog, FORM_CLASS): """Downloader for PetaBencana data. .. versionadded: 3.3 """ def __init__(self, parent=None, iface=None): """Constructor for import dialog. .. versionadded: 3.3 :param parent: Optional widget to use as parent. :type parent: QWidget :param iface: An instance of QGisInterface. :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) title = self.tr('PetaBencana Downloader') self.setWindowTitle(title) self.iface = iface self.source = None self.radio_button_group = QButtonGroup() self.radio_button_group.addButton(self.radio_button_production) self.radio_button_group.addButton(self.radio_button_development) self.radio_button_group.setExclusive(True) self.radio_button_production.setChecked(True) self.populate_combo_box() developer_mode = setting('developer_mode', False, bool) if not developer_mode: self.radio_button_widget.hide() self.source_label.hide() self.output_group.adjustSize() # signals self.radio_button_production.clicked.connect(self.populate_combo_box) self.radio_button_development.clicked.connect(self.populate_combo_box) # creating progress dialog for download self.progress_dialog = QProgressDialog(self) self.progress_dialog.setAutoClose(False) self.progress_dialog.setWindowTitle(title) # Set up things for context help self.help_button = self.button_box.button(QtGui.QDialogButtonBox.Help) # Allow toggling the help button self.help_button.setCheckable(True) self.help_button.toggled.connect(self.help_toggled) self.main_stacked_widget.setCurrentIndex(1) # set up the validator for the file name prefix expression = QRegExp('^[A-Za-z0-9-_]*$') validator = QRegExpValidator(expression, self.filename_prefix) self.filename_prefix.setValidator(validator) self.time_stamp = None self.restore_state() @pyqtSlot() @pyqtSignature('bool') # prevents actions being handled twice def help_toggled(self, flag): """Show or hide the help tab in the stacked widget. .. versionadded: 3.3 :param flag: Flag indicating whether help should be shown or hidden. :type flag: bool """ if flag: self.help_button.setText(self.tr('Hide Help')) self.show_help() else: self.help_button.setText(self.tr('Show Help')) self.hide_help() def hide_help(self): """Hide the usage info from the user. .. versionadded:: 3.3 """ self.main_stacked_widget.setCurrentIndex(1) def show_help(self): """Show usage info to the user. .. versionadded: 3.3 """ # Read the header and footer html snippets self.main_stacked_widget.setCurrentIndex(0) header = html_header() footer = html_footer() string = header message = peta_bencana_help() string += message.to_html() string += footer self.help_web_view.setHtml(string) def restore_state(self): """Read last state of GUI from configuration file. .. versionadded: 3.3 """ settings = QSettings() try: last_path = settings.value('directory', type=str) except TypeError: last_path = '' self.output_directory.setText(last_path) def save_state(self): """Store current state of GUI to configuration file. .. versionadded: 3.3 """ settings = QSettings() settings.setValue('directory', self.output_directory.text()) @pyqtSignature('') # prevents actions being handled twice def on_directory_button_clicked(self): """Show a dialog to choose directory. .. versionadded: 3.3 """ # noinspection PyCallByClass,PyTypeChecker self.output_directory.setText( QFileDialog.getExistingDirectory( self, self.tr('Select download directory'))) def accept(self): """Do PetaBencana download and display it in QGIS. .. versionadded: 3.3 """ self.save_state() try: self.require_directory() except CanceledImportDialogError: return QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) source = self.define_url() # save the file as json first name = 'jakarta_flood.json' output_directory = self.output_directory.text() output_prefix = self.filename_prefix.text() overwrite = self.overwrite_flag.isChecked() date_stamp_flag = self.include_date_flag.isChecked() output_base_file_path = self.get_output_base_path( output_directory, output_prefix, date_stamp_flag, name, overwrite) title = self.tr("Can't access API") try: self.download(source, output_base_file_path) # Open downloaded file as QgsMapLayer layer = QgsVectorLayer(output_base_file_path, 'flood', 'ogr', False) except Exception as e: disable_busy_cursor() QMessageBox.critical(self, title, str(e)) return self.time_stamp = time.strftime('%d-%b-%Y %H:%M:%S') # Now save as shp name = 'jakarta_flood.shp' output_base_file_path = self.get_output_base_path( output_directory, output_prefix, date_stamp_flag, name, overwrite) QgsVectorFileWriter.writeAsVectorFormat(layer, output_base_file_path, 'CP1250', None, 'ESRI Shapefile') # Get rid of the GeoJSON layer and rather use local shp del layer self.copy_style(output_base_file_path) self.copy_keywords(output_base_file_path) layer = self.add_flooded_field(output_base_file_path) # check if the layer has feature or not if layer.featureCount() <= 0: city = self.city_combo_box.currentText() message = self.tr('There are no floods data available on {city} ' 'at this time.').format(city=city) display_warning_message_box(self, self.tr('No data'), message) disable_busy_cursor() else: # add the layer to the map registry = QgsMapLayerRegistry.instance() registry.addMapLayer(layer) disable_busy_cursor() self.done(QDialog.Accepted) def add_flooded_field(self, shapefile_path): """Create the layer from the local shp adding the flooded field. .. versionadded:: 3.3 Use this method to add a calculated field to a shapefile. The shapefile should have a field called 'count' containing the number of flood reports for the field. The field values will be set to 0 if the count field is < 1, otherwise it will be set to 1. :param shapefile_path: Path to the shapefile that will have the flooded field added. :type shapefile_path: basestring :return: A vector layer with the flooded field added. :rtype: QgsVectorLayer """ layer = QgsVectorLayer(shapefile_path, self.tr('Jakarta Floods'), 'ogr') # Add a calculated field indicating if a poly is flooded or not # from PyQt4.QtCore import QVariant layer.startEditing() # Add field with integer from 0 to 4 which represents the flood # class. Its the same as 'state' field except that is being treated # as a string. # This is used for cartography flood_class_field = QgsField('floodclass', QVariant.Int) layer.dataProvider().addAttributes([flood_class_field]) layer.commitChanges() layer.startEditing() flood_class_idx = layer.fieldNameIndex('floodclass') flood_class_expression = QgsExpression('to_int(state)') context = QgsExpressionContext() context.setFields(layer.pendingFields()) flood_class_expression.prepare(context) # Add field with boolean flag to say if the area is flooded # This is used by the impact function flooded_field = QgsField('flooded', QVariant.Int) layer.dataProvider().addAttributes([flooded_field]) layer.commitChanges() layer.startEditing() flooded_idx = layer.fieldNameIndex('flooded') flood_flag_expression = QgsExpression('state > 0') flood_flag_expression.prepare(context) for feature in layer.getFeatures(): context.setFeature(feature) feature[flood_class_idx] = flood_class_expression.evaluate(context) feature[flooded_idx] = flood_flag_expression.evaluate(context) layer.updateFeature(feature) layer.commitChanges() return layer def copy_keywords(self, shapefile_path): """Copy keywords from the OSM resource directory to the output path. .. versionadded: 3.3 In addition to copying the template, tokens within the template will be replaced with new values for the date token and title token. :param shapefile_path: Path to the shapefile that will have the flooded field added. :type shapefile_path: basestring """ source_xml_path = resources_path('petabencana', 'flood-keywords.xml') output_xml_path = shapefile_path.replace('shp', 'xml') LOGGER.info('Copying xml to: %s' % output_xml_path) title_token = '[TITLE]' new_title = self.tr('Jakarta Floods - %s' % self.time_stamp) date_token = '[DATE]' new_date = self.time_stamp with open(source_xml_path) as source_file, \ open(output_xml_path, 'w') as output_file: for line in source_file: line = line.replace(date_token, new_date) line = line.replace(title_token, new_title) output_file.write(line) @staticmethod def copy_style(shapefile_path): """Copy style from the OSM resource directory to the output path. .. versionadded: 3.3 :param shapefile_path: Path to the shapefile that should get the path added. :type shapefile_path: basestring """ source_qml_path = resources_path('petabencana', 'flood-style.qml') output_qml_path = shapefile_path.replace('shp', 'qml') LOGGER.info('Copying qml to: %s' % output_qml_path) copy(source_qml_path, output_qml_path) def get_output_base_path(self, output_directory, output_prefix, with_date_stamp, feature_type, overwrite): """Get a full base name path to save the shapefile. TODO: This is cut & paste from OSM - refactor to have one method :param output_directory: The directory where to put results. :type output_directory: str :param output_prefix: The prefix to add for the shapefile. :type output_prefix: str :param with_date_stamp: Whether to add a datestamp in between the file prefix and the feature_type for the shapefile name. :type output_prefix: str :param feature_type: What kind of data will be downloaded. Will be used for the shapefile name. :type feature_type: str :param overwrite: Boolean to know if we can overwrite existing files. :type overwrite: bool :return: The base path. :rtype: str """ if with_date_stamp and self.time_stamp is not None: time_stamp = self.time_stamp.replace(' ', '-') time_stamp = time_stamp.replace(':', '-') time_stamp += '-' feature_type = time_stamp + feature_type path = os.path.join(output_directory, '%s%s' % (output_prefix, feature_type)) if overwrite: # If a shapefile exists, we must remove it (only the .shp) shp = '%s.shp' % path if os.path.isfile(shp): os.remove(shp) else: separator = '-' suffix = self.get_unique_file_path_suffix('%s.shp' % path, separator) if suffix: path = os.path.join( output_directory, '%s%s%s%s' % (output_prefix, feature_type, separator, suffix)) return path @staticmethod def get_unique_file_path_suffix(file_path, separator='-', i=0): """Return the minimum number to suffix the file to not overwrite one. Example : /tmp/a.txt exists. - With file_path='/tmp/b.txt' will return 0. - With file_path='/tmp/a.txt' will return 1 (/tmp/a-1.txt) TODO: This is cut & paste from OSM - refactor to have one method :param file_path: The file to check. :type file_path: str :param separator: The separator to add before the prefix. :type separator: str :param i: The minimum prefix to check. :type i: int :return: The minimum prefix you should add to not overwrite a file. :rtype: int """ basename = os.path.splitext(file_path) if i != 0: file_path_test = os.path.join( '%s%s%s%s' % (basename[0], separator, i, basename[1])) else: file_path_test = file_path if os.path.isfile(file_path_test): return PetaBencanaDialog.get_unique_file_path_suffix( file_path, separator, i + 1) else: return i def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. TODO: This is cut & paste from OSM - refactor to have one method :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ path = self.output_directory.text() if os.path.exists(path): return title = self.tr('Directory %s not exist') % path question = self.tr( 'Directory %s not exist. Do you want to create it?') % path # noinspection PyCallByClass,PyTypeChecker answer = QMessageBox.question(self, title, question, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: if len(path) != 0: os.makedirs(path) else: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box( self, self.tr('InaSAFE error'), self.tr('Output directory can not be empty.')) raise CanceledImportDialogError() else: raise CanceledImportDialogError() def load_shapefile(self, feature_type, base_path): """Load downloaded shape file to QGIS Main Window. TODO: This is cut & paste from OSM - refactor to have one method :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param base_path: The base path of the shape file (without extension). :type base_path: str :raises: FileMissingError - when buildings.shp not exist """ path = '%s.shp' % base_path if not os.path.exists(path): message = self.tr( '%s does not exist. The server does not have any data for ' 'this extent.' % path) raise FileMissingError(message) self.iface.addVectorLayer(path, feature_type, 'ogr') canvas_srid = self.canvas.mapSettings().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if QGis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_bar( self.iface, self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326. ' 'You should enable \'on the fly\' to display ' 'correctly your layers')) def reject(self): """Redefinition of the method. It will call the super method. """ super(PetaBencanaDialog, self).reject() def download(self, url, output_path): """Download file from API url and write to output path. :param url: URL of the API. :type url: str :param output_path: Path of output file, :type output_path: str """ request_failed_message = self.tr( "Can't access PetaBencana API: {source}").format(source=url) downloader = FileDownloader(url, output_path) result, message = downloader.download() if not result: display_warning_message_box( self, self.tr('Download error'), self.tr(request_failed_message + '\n' + message)) if result == QNetworkReply.OperationCanceledError: display_warning_message_box(self, self.tr('Download error'), self.tr(message)) # The function below might be usefull for future usage. # def get_available_area(self): # """Function to automatically get the available area on API. # *still cannot get string data from QByteArray* # """ # available_area = [] # network_manager = QgsNetworkAccessManager.instance() # api_url = QUrl('https://data.petabencana.id/cities') # api_request = QNetworkRequest(api_url) # api_response = network_manager.get(api_request) # data = api_response.readAll() # json_response = QScriptEngine().evaluate(data) # geometries = json_response.property('output').property('geometries') # iterator = QScriptValueIterator(geometries) # while iterator.hasNext(): # iterator.next() # geometry = iterator.value() # geometry_code = ( # geometry.property('properties').property('code').toString()) # available_area.append(geometry_code) def populate_combo_box(self): """Populate combobox for selecting city.""" if self.radio_button_production.isChecked(): self.source = production_api['url'] available_data = production_api['available_data'] else: self.source = development_api['url'] available_data = development_api['available_data'] self.city_combo_box.clear() for index, data in enumerate(available_data): self.city_combo_box.addItem(data['name']) self.city_combo_box.setItemData(index, data['code'], Qt.UserRole) def define_url(self): """Define API url based on which source is selected. :return: Valid url of selected source. :rtype: str """ current_index = self.city_combo_box.currentIndex() city_code = self.city_combo_box.itemData(current_index, Qt.UserRole) source = (self.source).format(city_code=city_code) return source
class ImportJobsDialog(QDialog): """ Dialog class to choose the imported job """ def __init__(self, jobs, selected): """ Constructor :param jobs: all the jobs available for import """ QDialog.__init__(self) self.__jobs = jobs self.__selected = selected self.setWindowTitle( QCoreApplication.translate("VDLTools", "What to process")) self.__layout = QGridLayout() self.__okButton = QPushButton( QCoreApplication.translate("VDLTools", "OK")) self.__okButton.setMinimumHeight(20) self.__okButton.setMinimumWidth(100) self.__cancelButton = QPushButton( QCoreApplication.translate("VDLTools", "Cancel")) self.__cancelButton.setMinimumHeight(20) self.__cancelButton.setMinimumWidth(100) self.__layout.addWidget(self.__okButton, 100, 1) self.__layout.addWidget(self.__cancelButton, 100, 2) self.__group = QButtonGroup() self.__jobButton = None if len(self.__jobs) > 0: self.__jobButton = QRadioButton( QCoreApplication.translate("VDLTools", "Job(s)")) self.__layout.addWidget(self.__jobButton, 0, 1) self.__group.addButton(self.__jobButton) self.__jobButton.setChecked(True) self.__jobsLabels = [] self.__jobsChecks = [] self.__scrollLayout = QGridLayout() for i in range(len(self.__jobs)): label = QLabel(self.__jobs[i]) label.setMinimumHeight(20) label.setMinimumWidth(50) self.__jobsLabels.append(label) self.__scrollLayout.addWidget(self.__jobsLabels[i], i + 1, 1) check = QCheckBox() check.setChecked(False) self.__jobsChecks.append(check) self.__scrollLayout.addWidget(self.__jobsChecks[i], i + 1, 2) widget = QWidget() widget.setLayout(self.__scrollLayout) scroll = QScrollArea() scroll.setWidgetResizable(True) scroll.setWidget(widget) self.__layout.addWidget(scroll, 1, 0, 1, 2) self.__pointsButton = None if self.__selected: self.__pointsButton = QRadioButton( QCoreApplication.translate("VDLTools", "Selected Point(s)")) self.__layout.addWidget(self.__pointsButton, len(self.__jobs) + 2, 1) self.__group.addButton(self.__pointsButton) if len(self.__jobs) == 0: self.__pointsButton.setChecked(True) self.setLayout(self.__layout) def okButton(self): """ To get the ok button instance :return: ok button instance """ return self.__okButton def jobsRadio(self): """ To get the jobs radio button :return: jobs radio button """ return self.__jobButton def pointsRadio(self): """ To get the points radio button :return: points radio button """ return self.__pointsButton def enableJobs(self, enable): """ To display/hide the available jobs :param enable: if we want to display/hide """ for i in range(len(self.__jobs)): if enable: label = QLabel(self.__jobs[i]) label.setMinimumHeight(20) label.setMinimumWidth(50) self.__jobsLabels[i] = label self.__layout.addWidget(self.__jobsLabels[i], i + 1, 1) check = QCheckBox() check.setChecked(False) self.__jobsChecks[i] = check self.__layout.addWidget(self.__jobsChecks[i], i + 1, 2) else: self.__layout.removeWidget(self.__jobsLabels[i]) self.__jobsLabels[i].deleteLater() self.__jobsLabels[i] = None self.__layout.removeWidget(self.__jobsChecks[i]) self.__jobsChecks[i].deleteLater() self.__jobsChecks[i] = None def cancelButton(self): """ To get the cancel button instance :return: cancel button instance """ return self.__cancelButton def jobs(self): """ To get the selected jobs :return: selected jobs """ jobs = [] for i in range(len(self.__jobs)): if self.__jobsChecks[i].isChecked(): jobs.append(self.__jobs[i]) return jobs
class QuestionDlg(QDialog): def __init__(self, parent=None): super(QuestionDlg,self).__init__(parent) # self.setStyleSheet("background-image:url('image/panelbg.jpg'); border: 2px; border-radius 2px;") # self.createDb() # return self.db = QSqlDatabase.addDatabase("QSQLITE"); self.db.setDatabaseName("studentNew.db") if not self.db.open(): QMessageBox.warning(None, "错误", "数据库连接失败: %s" % self.db.lastError().text()) sys.exit(1) self.g_curClassName = "" self.deleteTmpdata() self.setWindowFlags(Qt.CustomizeWindowHint) # self.setStyleSheet("border: 2px; border-radius 2px;") # self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet("background-color: rgba(132, 171, 208, 200);") self.tabWidget=QTabWidget(self) self.tabWidget.currentChanged.connect(self.changeTab) # tabWidget.setTabShape(QTabWidget.Triangular) self.tabWidget.setStyleSheet("QTabWidget::pane{border-width:1px;border-color:rgb(48, 104, 151);\ border-style: outset;background-color: rgb(132, 171, 208);\ background: transparent;} \ QTabWidget::tab-bar{border-width:0px;}\ QTabBar::tab { height: 60px; width: 260px; color:rgb(0, 0, 255); font-size:20px; font-weight:bold;} \ QTabBar::tab:hover{background:rgb(255,255, 255, 100);} \ QTabBar::tab:selected{border-color:green;background-color:white;color:green;}") # tabWidget.setStyleSheet("QTabBar::tab:hover{background:rgb(255,255, 255, 100);}") self.btngroup = QButtonGroup() self.popMenu = QMenu(self) entry1 = self.popMenu.addAction("正确") self.connect(entry1,SIGNAL('triggered()'), lambda : self.answerRight()) entry2 = self.popMenu.addAction("错误") self.connect(entry2,SIGNAL('triggered()'), lambda : self.answerWrong()) entry3 = self.popMenu.addAction("替换") self.connect(entry3,SIGNAL('triggered()'), lambda : self.resetStudent()) # Create the first tab page. self.w1=QWidget() self.w1.setAccessibleName("w1tab") self.genOneTab() # Create the second tab page. self.w2=QWidget() self.w2.setAccessibleName("w2tab") self.genTwoTab() self.tabWidget.addTab(self.w1,"") self.tabWidget.addTab(self.w2,"班级学生信息管理") self.tabWidget.resize(940,700) btnclose = QPushButton(self) btnclose.setToolTip("关闭") btnclose.setText("╳") btnclose.setGeometry(915, 5, 20, 20) btnclose.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255)") btnclose.clicked.connect(self.close) btnMinimized = QPushButton(self) btnMinimized.setToolTip("最小化") btnMinimized.setText("▁") btnMinimized.setGeometry(890, 5, 20, 20) btnMinimized.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255)") btnMinimized.clicked.connect(lambda: self.showMinimized()) self.btnSysMenu = QPushButton(self) # self.btnSysMenu.setText("▼") self.btnSysMenu.setGeometry(865, 5, 20, 20) self.btnSysMenu.setToolTip("系统设置") self.btnSysMenu.clicked.connect(lambda: self.showMinimized()) menufont = QFont("宋体", 10) popMenu = QMenu(self) entry1 = popMenu.addAction("所有学生提问信息清零") entry1.setFont(menufont) self.connect(entry1,SIGNAL('triggered()'), self.initStudent) entry2 = popMenu.addAction("清除本堂课提问人员") entry2.setFont(menufont) self.connect(entry2,SIGNAL('triggered()'), self.deleteTmpdata) entry3 = popMenu.addAction("关于...") entry3.setFont(menufont) self.connect(entry3,SIGNAL('triggered()'), self.aboutMe) entry4 = popMenu.addAction("导出...") entry4.setFont(menufont) self.connect(entry4,SIGNAL('triggered()'), self.exportNotice) self.btnSysMenu.setMenu(popMenu) self.btnSysMenu.setStyleSheet("QPushButton::menu-indicator {image: url('image/sysmenu.png');subcontrol-position: right center;} ") # self.btnSysMenu.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255);") authorinfo = QLabel(self.tabWidget) # authorinfo.setToolTip("关闭") authorinfo.setText("程序设计:汕头市大华路第一小学 赵小娜,有任何问题请反馈至[email protected]。") authorinfo.setGeometry(20, 665, 470, 26) authorinfo.setFont(QFont('Courier New')) authorinfo.setStyleSheet("background-color:rgba(255, 255, 255,160); font-size:12px;border: 1px solid rgb(60,200,255,200);color:rgba(0,0,0,220);border-radius:12px;") self.setWindowTitle("课堂随机提问") self.setWindowIcon(QIcon("image/start.ico")) self.setGeometry(100, 20, 940, 700) # self.changeTab() screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2) self.btn_start.setMyarg('start') # print(self.btn_start.getMyarg()) self.connect(self.btn_start, SIGNAL("clicked()"), self.startChoice) # self.connect(self.w1title, SIGNAL("currentIndexChanged(int)"), self.changeTitle) # self.connect(self.btn_start2, SIGNAL("clicked()"), self.startChoice) # self.connect(self.w2title, SIGNAL("currentIndexChanged(int)"), self.changeTitle) self.btngroup.buttonClicked[int].connect(self.btns_click) # self.connect(self.btn_start, SIGNAL("myslot(PyQt_PyObject)"), self.myslot) # self.connect(self.btngroup, SIGNAL("buttonClicked(int)"), lambda:self.btns_click()) def myslot(self, text): # print(text, self.dict_choices) self.g_curbtn = text if self.g_curbtn not in self.dict_choices: self.btnSysMenu.setFocus() return # print(self.btngroup.button(int(self.g_curbtn)).parent()) # print(type(self.btngroup.button(int(self.g_curbtn)).parentWidget())) pos = self.btngroup.button(int(self.g_curbtn)).parent().mapToGlobal(self.btngroup.button(int(self.g_curbtn)).pos()) width = self.btngroup.button(int(self.g_curbtn)).rect().height() # print("-----", pos, width) pos.setY(pos.y()+width-5) indx = 0 for istate in self.dict_choices[self.g_curbtn]: if istate == '1': self.popMenu.actions()[indx].setEnabled(True) elif istate == '0': self.popMenu.actions()[indx].setEnabled(False) indx += 1 self.popMenu.exec_(pos) self.btnSysMenu.setFocus() # def on_context_menu(self, point): # print(point) # self.popMenu.exec_(self.button.mapToGlobal(point)) def btns_click(self, btnid): # curclassname = self.tabWidget.tabText(0) query = QSqlQuery(self.db) # cur = conn.cursor() today = datetime.date.today() self.g_curbtn = str(btnid).zfill(2) if self.g_curbtn not in self.dict_choices: self.btngroup.button(int(self.g_curbtn)).setStyleSheet(stylesheetstr_new) query.exec_("select count(*) from tmprecord where stusn='" + str(self.g_curbtn) + "'") query.next() if query.value(0) == 0: query.prepare("insert into tmprecord (classname, stusn, datequestion) values (:classname, :stusn, :datequestion)") query.bindValue(":classname", self.g_curClassName) query.bindValue(":stusn", self.g_curbtn) query.bindValue(":datequestion", today) query.exec_() self.dict_choices[self.g_curbtn] = "111" else: self.btngroup.button(int(self.g_curbtn)).setStyleSheet(stylesheetstr_old) self.btngroup.button(int(self.g_curbtn)).setIcon(QIcon()) query.exec_("delete from tmprecord where stusn='"+ str(self.g_curbtn) + "'") self.dict_choices.pop(self.g_curbtn) self.btnSysMenu.setFocus() def exportNotice(self): query = QSqlQuery(self.db) query.exec_("select stusn, stuname, classname, rightquestions, wrongquestions from student" ) lstInfo = [["学号","姓名", "班级", "回答正确次数", "回答错误次数"]] while(query.next()): lstInfo.append([query.value(0),query.value(1),query.value(2),query.value(3),query.value(4)]) from xlwt import Workbook,easyxf book = Workbook(encoding='ascii') # 'pattern: pattern solid, fore_colour white;' style = easyxf( 'font: height 280, name 黑体;' 'align: vertical center, horizontal center;' ) style2 = easyxf('font: height 260, name 仿宋_GB2312, bold True; align: vertical center, horizontal left;') style3 = easyxf('font: height 260, name 仿宋_GB2312, bold True; align: vertical center, horizontal left, wrap True;') sheet1 = book.add_sheet('学生提问情况汇总',cell_overwrite_ok=True) # sheet1.write(0,7,flagtxt, easyxf('font: height 200, name 黑体;align: vertical center, horizontal right;')) sheet1.write_merge(0,0,0,4, '学生提问情况汇总表',style) sheet1.row(0).height_mismatch = 1 sheet1.row(0).height = 5*256 sheet1.col(0).width = 10*256 sheet1.col(1).width = 25*256 sheet1.col(2).width = 25*256 sheet1.col(3).width = 20*256 sheet1.col(4).width = 20*256 tmprows = 1 for item in lstInfo: stusn = item[0] stuname = item[1] classname = item[2] rightquestions = item[3] wrongquestions = item[4] sheet1.write(tmprows,0,stusn, style2) sheet1.write(tmprows,1,stuname, style2) sheet1.write(tmprows,2,classname, style2) sheet1.write(tmprows,3,rightquestions, style2) sheet1.write(tmprows,4,wrongquestions, style2) tmprows += 1 # print(tmprows) sheet1.header_str = "".encode() sheet1.footer_str = "".encode() # book.save('d:/simple.xls') # print(QDir.home().dirName() , QDir.homePath ()) filename = QDir.homePath () + "\学生提问情况汇总表.xls" try: book.save(filename) except Exception as e: QMessageBox.warning(self, "写入错误", "错误号:"+str(e.errno)+"\n错误描述:"+e.strerror+"\n请关闭已经打开的%s文档!" % filename) QMessageBox.about (self, "导出成功", "请查看文档:%s" % filename) def aboutMe(self): strinfo = """本软件采用python3.4编写,界面采用qt4.8的python绑定。 \n版本所有:汕头市大华路第一小学赵小娜老师。 \n有任何问题请反馈至[email protected]。 """ QMessageBox.information(None, "关于", strinfo) def initStudent(self): query = QSqlQuery(self.db) ret = query.exec_("update student set wrongquestions=0") ret = query.exec_("update student set rightquestions=0") QMessageBox.information(None, "提示", "已清除所有学生的累计提问情况。") def deleteTmpdata(self): query = QSqlQuery(self.db) ret = query.exec_("delete from tmprecord where 1=1" ) if self.g_curClassName != "": QMessageBox.information(None, "提示", "已清除本次软件启动后的所有已提问过的学生。") def changeTab(self): # pass curtab = self.tabWidget.currentIndex() # print(curtab, "-") if curtab == 1: ## when click the second tab page ,then pass. return # cur = conn.cursor() query = QSqlQuery(self.db) ## if current classname is null, then set current tabpage display the first class of classtable if self.g_curClassName == "": ret = query.exec_("select classname from classtable") query.next() self.g_curClassName = query.value(0) self.tabWidget.setTabText(0, self.g_curClassName) # print(1) strwhere = " and classname like '" + self.g_curClassName + "' ORDER BY stusn" self.g_curbtn = "" self.dict_choices = {} self.studentSnlst = [] ## clearn the question data of temp record . ret= query.exec_("delete from tmprecord where 1=1") ret = query.exec_("select stusn, stuname from student where 1=1 " + strwhere) ## now update the global data "self.btngroup" for indx in range(0, 56): self.btngroup.button(indx+1).setText("") self.btngroup.button(indx+1).setMyarg(None) self.btngroup.button(indx+1).setStyleSheet(stylesheetstr_old) self.btngroup.button(indx+1).setIcon(QIcon()) self.btngroup.button(indx+1).setEnabled(False) self.studentSnlst.append([indx+1,]) inum = 0 while (query.next()): inum += 1 self.btngroup.button(inum).setText(query.value(1)) self.btngroup.button(inum).setMyarg(query.value(0)) self.btngroup.button(inum).setStyleSheet(stylesheetstr_old) self.btngroup.button(inum).setIcon(QIcon()) self.btngroup.button(inum).setEnabled(True) # print(inum, len(self.btngroup.buttons())) self.group_animation = groupAnimation(self.studentSnlst, self.btngroup) def mousePressEvent(self, event): # print('a') if event.button() == Qt.RightButton: QDialog.mousePressEvent(self,event) return # print(event.sender(), event.button()) self.offset = event.pos() # print(self.offset) def mouseMoveEvent(self, event): # print('sss') if hasattr(self, 'offset'): x=event.globalX() y=event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x-x_w, y-y_w) else: pass #######======= studentModel ============############### def newStudent(self): # Calc the missing number: row = self.StudentModel.rowCount() if row > 0: oldNumList = [] for i in range(0, row): oldNumList.append(int(self.StudentModel.index(i,2).data())) allNumberList = list(range(1, oldNumList[-1]+1)) for i in range(0, allNumberList[-1]): if oldNumList[i] != allNumberList[i]: missingNum = allNumberList[i] break if len(oldNumList) == len(allNumberList): missingNum = allNumberList[i] +1 else: missingNum = 1 self.StudentModel.insertRow(row) self.StudentView.scrollToBottom() self.StudentModel.setData(self.StudentModel.index(row, 1), self.g_curClassName) self.StudentModel.setData(self.StudentModel.index(row, 2), str(missingNum).zfill(2)) self.StudentModel.setData(self.StudentModel.index(row, 4), 0) self.StudentModel.setData(self.StudentModel.index(row, 5), 0) def removeStudent(self): index = self.StudentView.currentIndex() row = index.row() if QMessageBox.question(self, "删除确认", "是否要删除当前选中记录?", "确定", "取消") == 0: self.StudentModel.removeRows(row, 1) self.StudentModel.submitAll() self.StudentModel.database().commit() def revertStudent(self): self.StudentModel.revertAll() self.StudentModel.database().rollback() def saveStudent(self): self.StudentModel.database().transaction() if self.StudentModel.submitAll(): self.StudentModel.database().commit() # print("save success! ->commit") else: self.StudentModel.revertAll() self.StudentModel.database().rollback() #######======= classModel ============############### def newClass(self): row = self.ClassnameModel.rowCount() self.ClassnameModel.insertRow(row) def removeClass(self): index = self.ClassnameView.currentIndex() row = index.row() curClassname = index.sibling(index.row(),0).data() strwhere = "classname like '" + curClassname + "'" self.StudentModel.setFilter(strwhere) self.StudentModel.select() # print(self.StudentModel.rowCount(), "----", ) if QMessageBox.question(self, "删除确认", "删除班级意味着会删除本班所有人员信息。是否要删除当前选中记录?", "确定", "取消") == 0: self.ClassnameModel.removeRows(row, 1) self.ClassnameModel.submitAll() self.ClassnameModel.database().commit() self.StudentModel.removeRows(0, self.StudentModel.rowCount()) self.StudentModel.submitAll() self.StudentModel.database().commit() def revertClass(self): self.ClassnameModel.revertAll() self.ClassnameModel.database().rollback() def saveClass(self): query = QSqlQuery(self.db) # record the old class name lstOldClassName = {} lstOldClassid = [] query.exec_("select rowid, classname from classtable" ) while(query.next()): lstOldClassName[query.value(0)] = query.value(1) lstOldClassid.append(query.value(0)) # print(lstOldClassName) # Update the class Table self.ClassnameModel.database().transaction() if self.ClassnameModel.submitAll(): self.ClassnameModel.database().commit() # print("save success! ->commit") else: QMessageBox.warning(None, "错误", "请检查班级中名称,不能出现同名班级!") self.ClassnameModel.revertAll() self.ClassnameModel.database().rollback() # print(lstOldClassid) lstNewClassName = {} query.exec_("select rowid, classname from classtable where rowid in " + str(tuple(lstOldClassid)) ) while(query.next()): lstNewClassName[query.value(0)] = query.value(1) # print(lstOldClassName, '=========') # print(lstNewClassName, '~~~~~~~~~') for i in lstOldClassName: oldclassname = lstOldClassName[i] newclassname = lstNewClassName[i] if oldclassname != newclassname: # print(oldclassname, newclassname, '++++++++') # print("update student set classname=" + newclassname + " where classname='" + oldclassname + "'") query.exec_("update student set classname='" + newclassname + "' where classname='" + oldclassname + "'") self.StudentModel.setFilter("classname = '" + newclassname + "'") self.StudentModel.select() lstClassName = [] query.exec_("select classname from classtable" ) while(query.next()): lstClassName.append(query.value(0)) self.StudentView.setItemDelegateForColumn(1, ComboBoxDelegate(self, lstClassName, self.db)) def dbclick(self, indx): if type(indx.sibling(indx.row(),0).data()) != QPyNullVariant: classname = indx.sibling(indx.row(),0).data() strwhere = "classname like '" + classname + "'" self.StudentModel.setFilter(strwhere) self.StudentModel.setSort(2, Qt.AscendingOrder) self.StudentModel.select() self.g_curClassName = classname self.tabWidget.setTabText(0, self.g_curClassName) def dbclick2(self, indx): if indx.column() == 2: self.StudentView.setEditTriggers(QAbstractItemView.NoEditTriggers) else: self.StudentView.setEditTriggers(QAbstractItemView.DoubleClicked) def genTwoTab(self, tabtitle=""): # Create the tab title sytle. tabtitle = QLabel() tabtitle.setFont(QFont('Courier New', 20)) tabtitle.setText("班级学生信息管理") tabtitle.setStyleSheet("border: 1px solid blue; color:rgba(0,0,255, 220);\ background-color:rgba(201,201,201,60);\ border-radius: 6px; \ padding: 1px 18px 1px 20px;\ min-width: 8em;") tabtitle.setMinimumHeight(50); titleLayout = QHBoxLayout() titleLayout.addWidget(tabtitle) titleLayout.setAlignment(tabtitle, Qt.AlignCenter) # Create the classnameView self.ClassnameView = QTableView() self.ClassnameModel = QSqlTableModel(self.ClassnameView) self.ClassnameModel.setTable("classtable") # self.ClassnameModel.setRelation(2, QSqlRelation("mentalmodel", "id", "name")); self.ClassnameModel.setEditStrategy(QSqlTableModel.OnManualSubmit) self.ClassnameModel.select() self.ClassnameModel.setHeaderData(0, Qt.Horizontal, "班级名称") # for indx, iheader in enumerate(["classid", "classname"]): # self.ClassnameModel.setHeaderData(indx+1, Qt.Horizontal, iheader) self.ClassnameView.setModel(self.ClassnameModel) # self.ClassnameView.setColumnHidden(0, True) # self.ClassnameView.show() self.ClassnameView.verticalHeader().setFixedWidth(30) self.ClassnameView.verticalHeader().setStyleSheet("color: red;font-size:20px; "); self.ClassnameView.setStyleSheet("QTableView{background-color: rgb(250, 250, 200, 0);" "alternate-background-color: rgb(141, 163, 0);}" "QTableView::item:hover {background-color: rgba(100,200,220,100);} ") self.ClassnameView.setStyleSheet("font-size:16px; "); self.ClassnameView.setSelectionMode(QAbstractItemView.SingleSelection) # self.ClassnameView.dataChanged.connect(self.dataChanged) # self.ClassnameView.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # the second list self.StudentView = QTableView() self.StudentModel = QSqlTableModel(self.StudentView) self.StudentModel.setTable("student") # self.StudentModel.setRelation(2, QSqlRelation("mentalmodel", "id", "name")); self.StudentModel.setEditStrategy(QSqlTableModel.OnManualSubmit) # self.StudentModel.select() query = QSqlQuery(self.db) strwhere = " 1=1 " if self.g_curClassName == "": ret = query.exec_("select classname from classtable") query.next() firstClassName = query.value(0) strwhere += " and classname like '" + firstClassName + "'" self.StudentModel.setFilter(strwhere) self.StudentModel.select() for indx, iheader in enumerate(["班级名称", "学生编号", "学生姓名", "答对次数", "答错次数"]): self.StudentModel.setHeaderData(indx+1, Qt.Horizontal, iheader) self.StudentView.setModel(self.StudentModel) self.StudentView.setColumnHidden(0, True) # query = QSqlQuery(self.db) lstClassName = [] query.exec_("select classname from classtable" ) while(query.next()): lstClassName.append(query.value(0)) self.StudentView.setItemDelegateForColumn(1, ComboBoxDelegate(self, lstClassName, self.db)) # self.StudentView.show() self.StudentView.verticalHeader().setFixedWidth(30) self.StudentView.verticalHeader().setStyleSheet("color: red;font-size:20px; background-color: rgb(250, 250, 200, 100)"); self.StudentView.setStyleSheet("QTableView{background-color: rgb(250, 250, 200, 0);" "alternate-background-color: rgb(141, 163, 250);}" "QTableView::item:hover {background-color: rgba(10,200,100,200);} " ) self.StudentView.setStyleSheet("font-size:16px;") self.StudentView.setSelectionMode(QAbstractItemView.SingleSelection) self.StudentView.doubleClicked.connect(self.dbclick2) btn_lst1_layout = QGridLayout() newusrbtn = QPushButton("新增") savebtn = QPushButton("保存") revertbtn = QPushButton("撤销") removebtn = QPushButton("删除") btn_lst1_layout.addWidget(newusrbtn, 0, 0) btn_lst1_layout.addWidget(savebtn, 0, 1) btn_lst1_layout.addWidget(revertbtn, 1, 0) btn_lst1_layout.addWidget(removebtn, 1, 1) newusrbtn.clicked.connect(self.newClass) savebtn.clicked.connect(self.saveClass) revertbtn.clicked.connect(self.revertClass) removebtn.clicked.connect(self.removeClass) self.ClassnameView.doubleClicked.connect(self.dbclick) btnbox2 = QDialogButtonBox(Qt.Horizontal) newusrbtn2 = QPushButton("新增") savebtn2 = QPushButton("保存") revertbtn2 = QPushButton("撤销") removebtn2 = QPushButton("删除") btnbox2.addButton(newusrbtn2, QDialogButtonBox.ActionRole); btnbox2.addButton(savebtn2, QDialogButtonBox.ActionRole); btnbox2.addButton(revertbtn2, QDialogButtonBox.ActionRole); btnbox2.addButton(removebtn2, QDialogButtonBox.ActionRole); newusrbtn2.clicked.connect(self.newStudent) savebtn2.clicked.connect(self.saveStudent) revertbtn2.clicked.connect(self.revertStudent) removebtn2.clicked.connect(self.removeStudent) # left list layout lst_layout_1 = QVBoxLayout() lst_layout_1.addWidget(self.ClassnameView) lst_layout_1.addLayout(btn_lst1_layout) lst_layout_2 = QVBoxLayout() lst_layout_2.addWidget(self.StudentView) lst_layout_2.addWidget(btnbox2) lstlayout = QHBoxLayout() lstlayout.setMargin(5) # lstlayout.addLayout(findbox) lstlayout.addLayout(lst_layout_1, 2) lstlayout.setMargin(5) lstlayout.addLayout(lst_layout_2, 5) labelClass = QLabel("") labelClass.setStyleSheet("background-color:rgba(255, 255, 255,0); color:rgba(0,0,0,0);") labelClass.setFixedHeight(40) # labelClass.setFixedWidth(100) # labelClass.setFont(QFont('宋体', 10)) bottomlayout = QHBoxLayout() bottomlayout.addWidget(labelClass) tab2layout = QVBoxLayout() tab2layout.addLayout(titleLayout) tab2layout.addLayout(lstlayout) tab2layout.addLayout(bottomlayout) self.w2.setLayout(tab2layout) self.w2.setStyleSheet("background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #228888);") def genOneTab(self): tabtitle = QLabel() # tabtitle.setFixedHeight(40) # tabtitle.setFixedWidth(160) self.btn_start = MyButton("开始") self.choicenum_text = QComboBox() self.choicenum_text.setObjectName('w1combonums') # self.w1title.setStyleSheet("background-image:url('image/panelbg.jpg');") # Set the title style tabtitle.setFont(QFont('Courier New', 20)) tabtitle.setText("随堂提问演板") tabtitle.setStyleSheet("border: 1px solid blue; color:rgba(0,0,255, 220);\ background-color:rgba(201,201,201,60);\ border-radius: 6px; \ padding: 1px 18px 1px 20px;\ min-width: 8em;") tabtitle.setMinimumHeight(50); titleLayout = QHBoxLayout() titleLayout.addWidget(tabtitle) titleLayout.setAlignment(tabtitle, Qt.AlignCenter) btnlayout = QGridLayout() tmpnum = 0 for inum in range(0,56): irow = tmpnum // g_cols icol = tmpnum % g_cols tmpnum += 1 btnlayout.setRowMinimumHeight(irow, 80) tmpbtn = MyButton("") tmpbtn.setMyarg(None) # tmpbtn.setFixedHeight(20) tmpbtn.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)) tmpbtn.setStyleSheet("border: 1px solid rgb(55,55,255,100);background-color: rgba(255,255,255,20);font-size:16px;") self.connect(tmpbtn, SIGNAL("myslot(PyQt_PyObject)"), self.myslot) tmpbtn.setAutoDefault(False) self.btngroup.addButton(tmpbtn, inum+1) # stusn is from 1 start btnlayout.addWidget(tmpbtn, irow, icol) self.btn_start.setIcon(QIcon("image/start.png")) self.btn_start.setStyleSheet("border: 1px solid yellow;") self.btn_start.setFixedHeight(40) self.btn_start.setFixedWidth(100) self.btn_start.setFont(QFont('宋体', 18)) # self.choicenum_text.setFixedHeight(45) # self.choicenum_text.setFixedWidth(60) ## Set the combox number style self.choicenum_text.setFont(QFont('Courier New', 20)) self.choicenum_text.setFixedHeight(45) self.choicenum_text.setStyleSheet("border: 2px solid blue; color:red;font-weight:light;font-size:26px;\ border-radius: 6px; \ min-width: 2em; ") self.choicenum_text.setEditable(True) self.choicenum_text.lineEdit().setReadOnly(True); self.choicenum_text.lineEdit().setAlignment(Qt.AlignCenter); model = self.choicenum_text.model() for row in list(range(1, 7)): item = QStandardItem(str(row)) item.setTextAlignment(Qt.AlignCenter) item.setForeground(QColor('red')) item.setBackground(QColor(0,200,50, 130)) model.appendRow(item) self.choicenum_text.setCurrentIndex(2) # self.choicenum_text.setStyleSheet ("QComboBox::drop-down {border-width: 100px;}") # self.choicenum_text.setStyleSheet ("QComboBox::down-arrow {image: url(image/downarrow.png);top: 10px;left: 1px;}") bottomlayout = QHBoxLayout() bottomlayout.setSizeConstraint(QLayout.SetFixedSize) bottomlayout.addStretch(10) bottomlayout.addWidget(self.btn_start) bottomlayout.setSpacing(5) bottomlayout.addWidget(self.choicenum_text) tab1layout = QVBoxLayout() tab1layout.addLayout(titleLayout) tab1layout.addLayout(btnlayout) tab1layout.addLayout(bottomlayout) self.w1.setLayout(tab1layout) self.w1.setStyleSheet("background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #228888);") def startChoice(self, usernum="", oldbtn=""): # print(oldbtn, 1) if oldbtn == "": self.dict_choices = {} strwhere = " and classname like '" + self.g_curClassName + "'" allstudent = [] lstrecord = [] query = QSqlQuery(self.db) query.exec_("select stusn from tmprecord where 1=1 " + strwhere) while(query.next()): lstrecord.append(query.value(0)) # print(lstrecord, 'record', "select stusn from student where stusn not in " + str(tuple(lstrecord))) query.exec_("select stusn from student where stusn not in " + str(tuple(lstrecord)) + strwhere) while(query.next()): allstudent.append(query.value(0)) if usernum == "": nums = int(self.choicenum_text.currentText()) else: nums = usernum if nums >= len(allstudent): query.exec_("delete from tmprecord where 1=1 " + strwhere) #delete tmp date no today allstudent = [] query.exec_("select stusn from student where 1=1 " + strwhere) while(query.next()): allstudent.append(query.value(0)) if oldbtn == "": random.seed() lstchoices = random.sample(allstudent, nums) for ibtn in lstchoices: self.dict_choices[ibtn] = "111" self.group_animation.start() QTimer.singleShot(1200, self.stopmovie) else: random.seed() otherbtn = random.sample(allstudent, 1)[0] # self.btngroup.button(int(otherbtn)).setFocus() self.dict_choices.pop(oldbtn) self.dict_choices[otherbtn] = '111' self.stopmovie() self.btnSysMenu.setFocus() def stopmovie(self): self.group_animation.stop() for isn in self.studentSnlst: # print(isn) self.btngroup.button(int(isn[0])).setStyleSheet(stylesheetstr_old) self.btngroup.button(int(isn[0])).setIcon(QIcon()) classname = self.tabWidget.tabText(0) query = QSqlQuery(self.db) today = datetime.date.today() for ibtn in self.dict_choices: self.btngroup.button(int(ibtn)).setStyleSheet(stylesheetstr_new) query.exec_("select count(*) from tmprecord where stusn='" + str(ibtn) + "'") query.next() if query.value(0) == 0: query.prepare("insert into tmprecord (classname, stusn, datequestion) values (:classname, :stusn, :datequestion)") query.bindValue(":classname", classname) query.bindValue(":stusn", ibtn) query.bindValue(":datequestion", today) query.exec_() def answerRight(self): # print(self.g_curbtn) value = self.g_curbtn if value not in self.dict_choices: return self.btngroup.button(int(value)).setIcon(QIcon("image/smile.png")) self.btngroup.button(int(value)).setIconSize(QSize(20,20)) query = QSqlQuery(self.db) query.exec_("select rightquestions from student where stusn='" + value + "'") query.next() studentRightQuestions = query.value(0) + 1 query.exec_("update student set rightquestions=" + str(studentRightQuestions) + " where stusn='" + value + "'") ########### if self.dict_choices[value] == "101": query.exec_("select wrongquestions from student where stusn='" + value + "'") query.next() studentWrongQuestions = query.value(0) - 1 query.exec_("update student set wrongquestions=" + str(studentWrongQuestions) + " where stusn='" + value + "'") self.dict_choices[value] = "011" def answerWrong(self): value = self.g_curbtn if value not in self.dict_choices: return self.btngroup.button(int(value)).setIcon(QIcon("image/cry.png")) self.btngroup.button(int(value)).setIconSize(QSize(20,20)) # self.btngroup.button(int(value)).setStyleSheet("border-image: url(image/ex_stu.png);") query = QSqlQuery(self.db) query.exec_("select wrongquestions from student where stusn='" + value + "'") query.next() studentWrongQuestions = query.value(0) + 1 query.exec_("update student set wrongquestions=" + str(studentWrongQuestions) + " where stusn='" + value + "'") if self.dict_choices[value] == "011": query.exec_("select rightquestions from student where stusn='" + value + "'") query.next() studentRightQuestions = query.value(0) - 1 query.exec_("update student set rightquestions=" + str(studentRightQuestions) + " where stusn='" + value + "'") self.dict_choices[value] = "101" def resetStudent(self): value = self.g_curbtn if value not in self.dict_choices: return query = QSqlQuery(self.db) if self.dict_choices[value] == "011": query.exec_("select rightquestions from student where stusn='" + value + "'") query.next() studentRightQuestions = query.value(0) - 1 query.exec_("update student set rightquestions=" + str(studentRightQuestions) + " where stusn='" + value + "'") if self.dict_choices[value] == "101": query.exec_("select wrongquestions from student where stusn='" + value + "'") query.next() studentWrongQuestions = query.value(0) - 1 query.exec_("update student set wrongquestions=" + str(studentWrongQuestions) + " where stusn='" + value + "'") self.startChoice(usernum=1, oldbtn=value) # print("---reset___") # curmenu.actions()[0].setEnabled(True) # curmenu.actions()[1].setEnabled(True) # self.choiceOneStudent(value) def createDb(self): conn = sqlite3.connect("studentNew.db") cur = conn.cursor() sqlstr = 'create table student (id integer primary key, \ classname varchar(20), \ stusn varchar(20), \ stuname varchar(20), \ rightquestions integer, \ wrongquestions integer, \ FOREIGN KEY(classname) REFERENCES classtable(classname))' # print(sqlstr) sqlstr2 = 'create table tmprecord (id integer primary key, \ classname varchar(20), \ stusn varchar(20), \ datequestion date)' sqlstr3 = 'create table classtable (classname varchar(20) PRIMARY KEY)' cur.execute(sqlstr3) conn.commit() cur.execute(sqlstr2) conn.commit() cur.execute(sqlstr) conn.commit() strdelete = "delete from student where 1=1" cur.execute(strdelete) conn.commit() strdelete = "delete from tmprecord where 1=1" cur.execute(strdelete) conn.commit() # print(sqlstr2) # cur.execute(sqlstr) # conn.commit() # cur.execute(sqlstr2) # conn.commit() # insert example data strsql = "insert into classtable values (?)" cur.execute(strsql, ("三(3)班",)) conn.commit() cur.execute(strsql, ("三(4)班",)) conn.commit() a03lst = ["曾忆谊","赵佳泉","翁文秀","林珑","郑铭洁","林泽思","吴崇霖","陈思嘉","欧阳月孜","郭展羽","詹伟哲","黄佳仪","杨秋霞","周奕子","林楚杰","欧伊涵","许腾誉","陈唯凯","陈树凯","林彦君","张钰佳","高锴","杨博凯","林妙菲","林楚鸿","陈展烯","姚静茵","吴欣桐","范思杰","肖佳","马思广","许一帆","姚奕帆","陈海珣","吴黛莹","吴育桐","肖凯帆","林欣阳","叶茂霖","姚楷臻","陈嘉豪","陈琦","杨子楷","陈炎宏","陈幸仪","杨景畅","罗暖婷","郑馨"] a04lst = ["罗恩琪","王可","曾祥威","谢濡婷","温嘉凯","许洁仪","肖欣淇","陈凯佳","林天倩","李乐海","吴文慧","黄文婷","万誉","陈进盛","张裕涵","陈振嘉","王巧玲","林珮琪","陈炜楷","杨健","赵泽锴","张凤临","蔡子丹","陈烨杰","廖妍希","林树超","夏培轩","陈锦森","李星","蔡依婷","姚容创","姚凯扬","沈嘉克","周凡","张玉川","邱金迅","陈菲敏","陈星翰","朱煜楷","郑泽洪","钱剑非","罗奕丰","陈杜炜","林知钦"] strsql = "insert into student values (?, ?, ?, ?,?,?)" for i in list(range(0,len(a03lst))): cur.execute(strsql, (None, "三(3)班", str(i+1).zfill(2), a03lst[i], 0, 0)) conn.commit() strsql = "insert into student values (?, ?, ?, ?,?,?)" for i in list(range(0,len(a04lst))): cur.execute(strsql, (None, "三(4)班", str(i+1).zfill(2), a04lst[i], 0, 0)) conn.commit() cur.close()
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 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 DefaultValueParameterWidget(GenericParameterWidget): """Widget class for Default Value Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A DefaultValueParameter object. :type parameter: DefaultValueParameter """ super(DefaultValueParameterWidget, self).__init__(parameter, parent) self.radio_button_layout = QHBoxLayout() # Create radio button group self.input_button_group = QButtonGroup() for i in range(len(self._parameter.labels)): if '%s' in self._parameter.labels[i]: label = ( self._parameter.labels[i] % self._parameter.options[i]) else: label = self._parameter.labels[i] radio_button = QRadioButton(label) self.radio_button_layout.addWidget(radio_button) self.input_button_group.addButton(radio_button, i) if self._parameter.value == \ self._parameter.options[i]: radio_button.setChecked(True) # Create double spin box for custom value self.custom_value = QDoubleSpinBox() self.custom_value.setSingleStep(0.1) if self._parameter.options[-1]: self.custom_value.setValue(self._parameter.options[-1]) self.radio_button_layout.addWidget(self.custom_value) self.toggle_custom_value() self.inner_input_layout.addLayout(self.radio_button_layout) # Connect # noinspection PyUnresolvedReferences self.input_button_group.buttonClicked.connect( self.toggle_custom_value) def raise_invalid_type_exception(self): """Raise invalid type.""" 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 DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.value = None # The last radio button (custom) is checked, get the value from the # line edit elif radio_button_checked_id == len(self._parameter.options) - 1: self._parameter.options[radio_button_checked_id] = \ self.custom_value.value() self._parameter.value = self.custom_value.value() else: self._parameter.value = self._parameter.options[ radio_button_checked_id] return self._parameter def set_value(self, value): """Set value by item's string. :param value: The value. :type value: str, int :returns: True if success, else False. :rtype: bool """ # Find index of choice try: value_index = self._parameter.options.index(value) self.input_button_group.button(value_index).setChecked(True) except ValueError: last_index = len(self._parameter.options) - 1 self.input_button_group.button(last_index).setChecked( True) self.custom_value.setValue(value) self.toggle_custom_value() def toggle_custom_value(self): """Enable or disable the custom value line edit.""" radio_button_checked_id = self.input_button_group.checkedId() if (radio_button_checked_id == len(self._parameter.options) - 1): self.custom_value.setDisabled(False) else: self.custom_value.setDisabled(True)
class DateTimePickerWidget(datepicker_widget, QWidget): ok = pyqtSignal() cancel = pyqtSignal() """ A custom date picker with a time and date picker """ def __init__(self, parent=None, mode="DateTime"): super(DateTimePickerWidget, self).__init__(parent) self.setupUi(self) self.mode = mode self.group = QButtonGroup() self.group.setExclusive(True) self.group.addButton(self.ambutton) self.group.addButton(self.pmbutton) self.ambutton.toggled.connect(self.isDirty) self.pmbutton.toggled.connect(self.isDirty) self.datepicker.selectionChanged.connect(self.isDirty) self.hourpicker.itemSelectionChanged.connect(self.isDirty) self.minutepicker.itemSelectionChanged.connect(self.isDirty) self.setasnowbutton.pressed.connect(self.setAsNow) self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint) self.okButton.pressed.connect(self.ok.emit) self.closebutton.pressed.connect(self.cancel.emit) def setMinValue(self, mindate): self.datepicker.setMinimumDate(mindate) def setmode(self, mode): if mode == "Date": self.timesection.hide() elif mode == "Time": self.datepicker.hide() def isDirty(self, *args): date = self.getSelectedDate() time = self.getSelectedTime() datetime = QDateTime(date, time) if self.mode == "Date": value = datetime.toString("ddd d MMM yyyy") elif self.mode == "Time": value = datetime.toString("hh:mm ap") else: value = datetime.toString("ddd d MMM yyyy 'at' hh:mm ap") self.label.setText("Set as: {}".format(value)) def setDateTime(self, datetime): """ Set the picker to datatime datetime - The QDateTime with the value to set. """ self.setTime(datetime.time()) self.setDate(datetime.date()) def setAsNow(self): """ Set the current date and time on the picker as now. """ now = QDateTime.currentDateTime() self.setDateTime(now) def setTime(self, time): """ Set just the time part of the picker """ hour = time.hour() if hour > 12: hour = hour - 12 if hour == 0: hour = hour + 12 minute = time.minute() minute = int(round(minute / 5.0) * 5.0) amap = time.toString("AP") utils.log("Hour %s Minute %s" % (hour, minute)) try: houritems = self.hourpicker.findItems(str(hour), Qt.MatchFixedString) self.hourpicker.setCurrentItem(houritems[0]) except IndexError: utils.log("Can't find hour") try: minuteitems = self.minutepicker.findItems(str(minute), Qt.MatchFixedString) self.minutepicker.setCurrentItem(minuteitems[0]) except IndexError: utils.log("Can't find minute") if amap == "PM": self.pmbutton.toggle() def setDate(self, date): """ Set just the date part of the picker """ self.datepicker.setSelectedDate(date) def getSelectedTime(self): """ Returns the currently selected data and time """ try: hour = self.hourpicker.currentItem().text() except AttributeError: hour = "" try: minute = self.minutepicker.currentItem().text() except AttributeError: minute = "" zone = self.ambutton.isChecked() and "AM" or "PM" return QTime.fromString("%s%s%s" % (hour, minute, zone), "hmAP") def getSelectedDate(self): """ Returns just the date part of the picker """ return self.datepicker.selectedDate() @property def value(self): datetime = QDateTime() datetime.setDate(self.getSelectedDate()) datetime.setTime(self.getSelectedTime()) return datetime @value.setter def value(self, value): if value is None: self.setAsNow() return if isinstance(value, basestring): value = QDateTime.fromString(value, Qt.ISODate) self.setDate(value.date()) self.setTime(value.time())
class TabBarWidget(QWidget): """ A tab bar widget using tool buttons as tabs. """ # TODO: A uniform size box layout. currentChanged = Signal(int) def __init__(self, parent=None, **kwargs): QWidget.__init__(self, parent, **kwargs) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.setLayout(layout) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__tabs = [] self.__currentIndex = -1 self.__changeOnHover = False self.__iconSize = QSize(26, 26) self.__group = QButtonGroup(self, exclusive=True) self.__group.buttonPressed[QAbstractButton].connect( self.__onButtonPressed) self.setMouseTracking(True) self.__sloppyButton = None self.__sloppyRegion = QRegion() self.__sloppyTimer = QTimer(self, singleShot=True) self.__sloppyTimer.timeout.connect(self.__onSloppyTimeout) def setChangeOnHover(self, changeOnHover): """ If set to ``True`` the tab widget will change the current index when the mouse hovers over a tab button. """ if self.__changeOnHover != changeOnHover: self.__changeOnHover = changeOnHover def changeOnHover(self): """ Does the current tab index follow the mouse cursor. """ return self.__changeOnHover def count(self): """ Return the number of tabs in the widget. """ return len(self.__tabs) def addTab(self, text, icon=None, toolTip=None): """ Add a new tab and return it's index. """ return self.insertTab(self.count(), text, icon, toolTip) def insertTab(self, index, text, icon=None, toolTip=None): """ Insert a tab at `index` """ button = TabButton(self, objectName="tab-button") button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) button.setIconSize(self.__iconSize) button.setMouseTracking(True) self.__group.addButton(button) button.installEventFilter(self) tab = _Tab(text, icon, toolTip, button, None, None) self.layout().insertWidget(index, button) self.__tabs.insert(index, tab) self.__updateTab(index) if self.currentIndex() == -1: self.setCurrentIndex(0) return index def removeTab(self, index): """ Remove a tab at `index`. """ if index >= 0 and index < self.count(): self.layout().takeItem(index) tab = self.__tabs.pop(index) self.__group.removeButton(tab.button) tab.button.removeEventFilter(self) if tab.button is self.__sloppyButton: self.__sloppyButton = None self.__sloppyRegion = QRegion() tab.button.deleteLater() if self.currentIndex() == index: if self.count(): self.setCurrentIndex(max(index - 1, 0)) else: self.setCurrentIndex(-1) def setTabIcon(self, index, icon): """ Set the `icon` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(icon=icon) self.__updateTab(index) def setTabToolTip(self, index, toolTip): """ Set `toolTip` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(toolTip=toolTip) self.__updateTab(index) def setTabText(self, index, text): """ Set tab `text` for tab at `index` """ self.__tabs[index] = self.__tabs[index]._replace(text=text) self.__updateTab(index) def setTabPalette(self, index, palette): """ Set the tab button palette. """ self.__tabs[index] = self.__tabs[index]._replace(palette=palette) self.__updateTab(index) def setCurrentIndex(self, index): """ Set the current tab index. """ if self.__currentIndex != index: self.__currentIndex = index self.__sloppyRegion = QRegion() self.__sloppyButton = None if index != -1: self.__tabs[index].button.setChecked(True) self.currentChanged.emit(index) def currentIndex(self): """ Return the current index. """ return self.__currentIndex def button(self, index): """ Return the `TabButton` instance for index. """ return self.__tabs[index].button def setIconSize(self, size): if self.__iconSize != size: self.__iconSize = size for tab in self.__tabs: tab.button.setIconSize(self.__iconSize) def __updateTab(self, index): """ Update the tab button. """ tab = self.__tabs[index] b = tab.button if tab.text: b.setText(tab.text) if tab.icon is not None and not tab.icon.isNull(): b.setIcon(tab.icon) if tab.palette: b.setPalette(tab.palette) def __onButtonPressed(self, button): for i, tab in enumerate(self.__tabs): if tab.button is button: self.setCurrentIndex(i) break def __calcSloppyRegion(self, current): """ Given a current mouse cursor position return a region of the widget where hover/move events should change the current tab only on a timeout. """ p1 = current + QPoint(0, 2) p2 = current + QPoint(0, -2) p3 = self.pos() + QPoint(self.width() + 10, 0) p4 = self.pos() + QPoint(self.width() + 10, self.height()) return QRegion(QPolygon([p1, p2, p3, p4])) def __setSloppyButton(self, button): """ Set the current sloppy button (a tab button inside sloppy region) and reset the sloppy timeout. """ if not button.isChecked(): self.__sloppyButton = button delay = self.style().styleHint(QStyle.SH_Menu_SubMenuPopupDelay, None) # The delay timeout is the same as used by Qt in the QMenu. self.__sloppyTimer.start(delay) else: self.__sloppyTimer.stop() def __onSloppyTimeout(self): if self.__sloppyButton is not None: button = self.__sloppyButton self.__sloppyButton = None if not button.isChecked(): index = [tab.button for tab in self.__tabs].index(button) self.setCurrentIndex(index) def eventFilter(self, receiver, event): if event.type() == QEvent.MouseMove and \ isinstance(receiver, TabButton): pos = receiver.mapTo(self, event.pos()) if self.__sloppyRegion.contains(pos): self.__setSloppyButton(receiver) else: if not receiver.isChecked(): index = [tab.button for tab in self.__tabs].index(receiver) self.setCurrentIndex(index) #also update sloppy region if mouse is moved on the same icon self.__sloppyRegion = self.__calcSloppyRegion(pos) return QWidget.eventFilter(self, receiver, event) def leaveEvent(self, event): self.__sloppyButton = None self.__sloppyRegion = QRegion() return QWidget.leaveEvent(self, event)
def __init__(self, type_image=None, nb_bands=None): # creating interface Dialog = QDialog() self.bandsUi = Ui_Dialog() self.bandsUi.setupUi(Dialog) # screen = QApplication.desktop().screenGeometry() # self.move( screen.center() - self.rect().center() ) groupButton1 = QButtonGroup() groupButton1.addButton(self.bandsUi.radioButton_formosat) groupButton1.addButton(self.bandsUi.radioButton_pleiades) groupButton1.addButton(self.bandsUi.radioButton_spot) groupButton1.addButton(self.bandsUi.radioButton_autre) self.red = None self.green = None self.blue = None self.pir = None self.mir = None self.satellite = "Non renseigné" # connect the qdialog button box # QObject.connect(self.bandsUi.buttonBox, SIGNAL("accepted()"), self.set_bands) # QObject.connect(self.bandsUi.buttonBox, SIGNAL("rejected()"), self.reset_bands) self.bandsUi.checkBox_blue.stateChanged.connect(self.blue_checkbox_changed) self.bandsUi.checkBox_mir.stateChanged.connect(self.mir_checkbox_changed) self.bandsUi.radioButton_formosat.toggled.connect(self.define_formosat) self.bandsUi.radioButton_pleiades.toggled.connect(self.define_pleiade) self.bandsUi.radioButton_spot.toggled.connect(self.define_spot) self.bandsUi.radioButton_autre.toggled.connect(self.define_other) QObject.connect(self.bandsUi.spinBox_blue, SIGNAL("valueChanged(int)"), self.update_blue) QObject.connect(self.bandsUi.spinBox_red, SIGNAL("valueChanged(int)"), self.update_red) QObject.connect(self.bandsUi.spinBox_green, SIGNAL("valueChanged(int)"), self.update_green) QObject.connect(self.bandsUi.spinBox_pir, SIGNAL("valueChanged(int)"), self.update_pir) QObject.connect(self.bandsUi.spinBox_mir, SIGNAL("valueChanged(int)"), self.update_mir) # QObject.connect( spinBox_mir, SIGNAL( "valueChanged(int)" ), lambda x:self.mir = x) QObject.connect(self.bandsUi.buttonBox, SIGNAL("rejected()"), self.cancel) # settrace() if nb_bands: self.nb_bands = nb_bands self.custom_from_nb_of_bands(nb_bands) else: self.nb_bands = -1 gray_other = False if type_image: if type_image == "Spot 5" or type_image == "spot": logger.info("define spot") # self.define_spot(False) self.bandsUi.radioButton_spot.setChecked(True) self.bandsUi.radioButton_formosat.setEnabled(False) self.bandsUi.radioButton_pleiades.setEnabled(False) gray_other = True elif type_image == "PHR 1A": logger.info("define pleiade") # self.define_pleiade() self.bandsUi.radioButton_pleiades.setChecked(True) self.bandsUi.radioButton_formosat.setEnabled(False) self.bandsUi.radioButton_spot.setEnabled(False) gray_other = True elif type_image == "Formosat 2": logger.info("define formosat") # self.define_formosat(False) self.bandsUi.radioButton_formosat.setChecked(True) self.bandsUi.radioButton_spot.setEnabled(False) self.bandsUi.radioButton_pleiades.setEnabled(False) gray_other = True else: logger.info("define others") self.bandsUi.radioButton_autre.setChecked(True) self.set_spinbox_read_only(False) if gray_other: self.gray_other() # execute the dialog Dialog.exec_()
class PlotWidget(QtGui.QWidget, plot_widget_class): """Wrapper widget for PyQtGraph adding some extra buttons""" def __init__(self, parent=None, fps=100, title="", *args): super(PlotWidget, self).__init__(*args) self.setupUi(self) # Limit the plot update to 10Hz self._ts = time() self._delay = 0.1 # Check if we could import PyQtGraph, if not then stop here if not _pyqtgraph_found: self.can_enable = False return else: self.can_enable = True self._items = {} self._last_item = 0 self.setSizePolicy(QtGui.QSizePolicy( QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding)) self.setMinimumSize(self.minimumSizeHint()) self.parent = parent pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') self._plot_widget = pg.PlotWidget() self._plot_widget.hideButtons() self._plot_widget.setLabel('bottom', "Time", "ms") self._plot_widget.addLegend() self._plot_widget.getViewBox().disableAutoRange(ViewBox.XAxis) self._plot_widget.getViewBox().sigRangeChangedManually.connect(self._manual_range_change) self._plot_widget.getViewBox().setMouseEnabled(x=False, y=True) self._plot_widget.getViewBox().setMouseMode(ViewBox.PanMode) self.plotLayout.addWidget(self._plot_widget) #self.saveToFile.clicked.connect(self.saveToFileSignal) self._x_min = 0 self._x_max = 500 self._enable_auto_y.setChecked(True) self._enable_samples_x.setChecked(True) self._last_ts = None self._dtime = None self._x_range = (float(self._range_x_min.text()), float(self._range_x_max.text())) self._nbr_samples = int(self._nbr_of_samples_x.text()) self._nbr_of_samples_x.valueChanged.connect(self._nbr_samples_changed) self._range_y_min.valueChanged.connect(self._y_range_changed) self._range_y_max.valueChanged.connect(self._y_range_changed) self._y_btn_group = QButtonGroup() self._y_btn_group.addButton(self._enable_auto_y) self._y_btn_group.addButton(self._enable_range_y) self._y_btn_group.setExclusive(True) self._y_btn_group.buttonClicked.connect(self._y_mode_change) self._x_btn_group = QButtonGroup() self._x_btn_group.addButton(self._enable_range_x) self._x_btn_group.addButton(self._enable_samples_x) self._x_btn_group.addButton(self._enable_seconds_x) self._x_btn_group.addButton(self._enable_manual_x) self._x_btn_group.setExclusive(True) self._x_btn_group.buttonClicked.connect(self._x_mode_change) self._draw_graph = True self._auto_redraw.stateChanged.connect(self._auto_redraw_change) def _auto_redraw_change(self, state): """Callback from the auto redraw checkbox""" if state == 0: self._draw_graph = False else: self._draw_graph = True def _x_mode_change(self, box): """Callback when user changes the X-axis mode""" if box == self._enable_range_x: logger.info("Enable range x") self._x_range = (float(self._range_x_min.text()), float(self._range_x_max.text())) else: self._range_x_min.setEnabled(False) self._range_x_max.setEnabled(False) def _y_mode_change(self, box): """Callback when user changes the Y-axis mode""" if box == self._enable_range_y: self._range_y_min.setEnabled(True) self._range_y_max.setEnabled(True) y_range = (float(self._range_y_min.value()), float(self._range_y_max.value())) self._plot_widget.getViewBox().setRange(yRange=y_range) else: self._range_y_min.setEnabled(False) self._range_y_max.setEnabled(False) if box == self._enable_auto_y: self._plot_widget.getViewBox().enableAutoRange(ViewBox.YAxis) def _manual_range_change(self, obj): """Callback from pyqtplot when users changes the range of the plot using the mouse""" [[x_min,x_max],[y_min,y_max]] = self._plot_widget.getViewBox().viewRange() self._range_y_min.setValue(y_min) self._range_y_max.setValue(y_max) self._range_y_min.setEnabled(True) self._range_y_max.setEnabled(True) self._enable_range_y.setChecked(True) def _y_range_changed(self, val): """Callback when user changes Y range manually""" _y_range = (float(self._range_y_min.value()), float(self._range_y_max.value())) self._plot_widget.getViewBox().setRange(yRange=_y_range, padding=0) def _nbr_samples_changed(self, val): """Callback when user changes the number of samples to be shown""" self._nbr_samples = val def set_title(self, title): """ Set the title of the plot. title - the new title """ self._plot_widget.setTitle(title) def add_curve(self, title, pen='r'): """ Add a new curve to the plot. title - the name of the data pen - color of curve (using r for red and so on..) """ self._items[title] = PlotItemWrapper(self._plot_widget.plot(name=title, pen=pen)) def add_data(self, data, ts): """ Add new data to the plot. data - dictionary sent from logging layer containing variable/value pairs ts - timestamp of the data in ms """ if not self._last_ts: self._last_ts = ts elif not self._last_ts: self._dtime = ts - self._last_ts self._last_ts = ts x_min_limit = 0 x_max_limit = 0 # We are adding new datasets, calculate what we should show. if self._enable_samples_x.isChecked(): x_min_limit = max(0, self._last_item-self._nbr_samples) x_max_limit = max(self._last_item, self._nbr_samples) for name in self._items: self._items[name].add_point(data[name], ts) if self._draw_graph and time() > self._ts + self._delay: [self._x_min, self._x_max] = self._items[name].show_data(x_min_limit, x_max_limit) if time() > self._ts + self._delay: self._ts = time() if self._enable_samples_x.isChecked() and self._dtime and self._last_item < self._nbr_samples: self._x_max = self._x_min + self._nbr_samples * self._dtime self._last_item = self._last_item + 1 self._plot_widget.getViewBox().setRange(xRange=(self._x_min, self._x_max)) def removeAllDatasets(self): """Reset the plot by removing all the datasets""" for item in self._items: self._plot_widget.removeItem(self._items[item]) self._plot_widget.plotItem.legend.items = [] self._items = {} self._last_item = 0 self._last_ts = None self._dtime = None self._plot_widget.clear()
def __init__(self, type_image=None, nb_bands=None): # creating interface Dialog = QDialog() self.bandsUi = Ui_Dialog() self.bandsUi.setupUi(Dialog) # screen = QApplication.desktop().screenGeometry() # self.move( screen.center() - self.rect().center() ) groupButton1 = QButtonGroup() groupButton1.addButton(self.bandsUi.radioButton_formosat) groupButton1.addButton(self.bandsUi.radioButton_pleiades) groupButton1.addButton(self.bandsUi.radioButton_spot) groupButton1.addButton(self.bandsUi.radioButton_autre) self.red = None self.green = None self.blue = None self.pir = None self.mir = None self.satellite = "Non renseigné" # connect the qdialog button box # QObject.connect(self.bandsUi.buttonBox, SIGNAL("accepted()"), self.set_bands) # QObject.connect(self.bandsUi.buttonBox, SIGNAL("rejected()"), self.reset_bands) self.bandsUi.checkBox_blue.stateChanged.connect( self.blue_checkbox_changed) self.bandsUi.checkBox_mir.stateChanged.connect( self.mir_checkbox_changed) self.bandsUi.radioButton_formosat.toggled.connect(self.define_formosat) self.bandsUi.radioButton_pleiades.toggled.connect(self.define_pleiade) self.bandsUi.radioButton_spot.toggled.connect(self.define_spot) self.bandsUi.radioButton_autre.toggled.connect(self.define_other) QObject.connect(self.bandsUi.spinBox_blue, SIGNAL("valueChanged(int)"), self.update_blue) QObject.connect(self.bandsUi.spinBox_red, SIGNAL("valueChanged(int)"), self.update_red) QObject.connect(self.bandsUi.spinBox_green, SIGNAL("valueChanged(int)"), self.update_green) QObject.connect(self.bandsUi.spinBox_pir, SIGNAL("valueChanged(int)"), self.update_pir) QObject.connect(self.bandsUi.spinBox_mir, SIGNAL("valueChanged(int)"), self.update_mir) # QObject.connect( spinBox_mir, SIGNAL( "valueChanged(int)" ), lambda x:self.mir = x) QObject.connect(self.bandsUi.buttonBox, SIGNAL("rejected()"), self.cancel) # settrace() if nb_bands: self.nb_bands = nb_bands self.custom_from_nb_of_bands(nb_bands) else: self.nb_bands = -1 gray_other = False if type_image: if type_image == "Spot 5" or type_image == "spot": logger.info("define spot") # self.define_spot(False) self.bandsUi.radioButton_spot.setChecked(True) self.bandsUi.radioButton_formosat.setEnabled(False) self.bandsUi.radioButton_pleiades.setEnabled(False) gray_other = True elif type_image == "PHR 1A": logger.info("define pleiade") # self.define_pleiade() self.bandsUi.radioButton_pleiades.setChecked(True) self.bandsUi.radioButton_formosat.setEnabled(False) self.bandsUi.radioButton_spot.setEnabled(False) gray_other = True elif type_image == "Formosat 2": logger.info("define formosat") # self.define_formosat(False) self.bandsUi.radioButton_formosat.setChecked(True) self.bandsUi.radioButton_spot.setEnabled(False) self.bandsUi.radioButton_pleiades.setEnabled(False) gray_other = True else: logger.info("define others") self.bandsUi.radioButton_autre.setChecked(True) self.set_spinbox_read_only(False) if gray_other: self.gray_other() # execute the dialog Dialog.exec_()
class QTSeedEditor(QDialog): """ DICOM viewer. """ @staticmethod def get_line(mode='h'): line = QFrame() if mode == 'h': line.setFrameStyle(QFrame.HLine) elif mode == 'v': line.setFrameStyle(QFrame.VLine) line.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) return line def initUI(self, shape, vscale, height=600, mode='seed'): """ Initialize UI. Parameters ---------- shape : (int, int, int) Shape of data matrix. vscale : (float, float, float) Voxel scaling. height : int Maximal slice height in pixels. mode : str Editor mode. """ self.slab = {} # picture grid = height / float(shape[1] * vscale[1]) mgrid = (grid * vscale[0], grid * vscale[1]) self.slice_box = SliceBox(shape[:-1], mgrid, mode) self.slice_box.setScrollFun(self.scrollSlices) self.connect(self.slice_box, SIGNAL('focus_slider'), self.focusSliceSlider) # sliders self.allow_select_slice = True self.n_slices = shape[2] self.slider = QSlider(Qt.Vertical) self.slider.valueChanged.connect(self.sliderSelectSlice) self.slider.label = QLabel() self.slider.setRange(1, self.n_slices) self.slider_cw = {} self.slider_cw['c'] = QSlider(Qt.Horizontal) self.slider_cw['c'].valueChanged.connect(self.changeC) self.slider_cw['c'].label = QLabel() self.slider_cw['w'] = QSlider(Qt.Horizontal) self.slider_cw['w'].valueChanged.connect(self.changeW) self.slider_cw['w'].label = QLabel() self.view_label = QLabel('View size: %d x %d' % self.img_aview.shape[:-1]) self.voxel_label = QLabel('Voxel size [mm]:\n %.2f x %.2f x %.2f'\ % tuple(self.voxel_size[np.array(self.act_transposition)])) # combo_view_options = VIEW_TABLE.keys() # combo_view = QComboBox(self) # combo_view.activated[str].connect(self.setView) # combo_view.addItems(combo_view_options) #radio button group for choosing seed class ------------------------ self.current_class = 1 self.slice_box.seed_mark = self.current_class number_group = QGroupBox(QString('Class markers')) vbox_NG = QVBoxLayout() r1 = QRadioButton('class 1') r1.setStyleSheet('QRadioButton {color: red}') r1.setChecked(True) r2 = QRadioButton('class 2') r2.setStyleSheet('QRadioButton {color: green}') r3 = QRadioButton('class 3') r3.setStyleSheet('QRadioButton {color: blue}') r4 = QRadioButton('class 4') r4.setStyleSheet('QRadioButton {color: cyan}') r5 = QRadioButton('class 5') r5.setStyleSheet('QRadioButton {color: magenta}') vbox_NG.addWidget(r1) vbox_NG.addWidget(r2) vbox_NG.addWidget(r3) vbox_NG.addWidget(r4) vbox_NG.addWidget(r5) number_group.setLayout(vbox_NG) self.button_group = QButtonGroup() self.button_group.addButton(r1, 1) self.button_group.addButton(r2, 2) self.button_group.addButton(r3, 3) self.button_group.addButton(r4, 4) self.button_group.addButton(r5, 5) self.connect(self.button_group, SIGNAL("buttonClicked(int)"), self.change_seed_class) #------------------------------------------------------------------- # buttons # btn_save = QPushButton('Save', self) # btn_save.clicked.connect(self.save) btn_quit = QPushButton("Quit", self) btn_quit.clicked.connect(self.quit) # btn_crop = QPushButton('Crop', self) # btn_crop.clicked.connect(self.crop) combo_dmask = QComboBox(self) combo_dmask.activated.connect(self.changeMask) self.mask_points_tab, aux = self.init_draw_mask(DRAW_MASK, mgrid) for icon, label in aux: combo_dmask.addItem(icon, label) self.slice_box.setMaskPoints( self.mask_points_tab[combo_dmask.currentIndex()]) self.status_bar = QStatusBar() vopts = [] vmenu = [] appmenu = [] # btn_recalc = QPushButton("Recalculate", self) # btn_recalc.clicked.connect(self.recalculate) # appmenu.append(QLabel('<b>Segmentation mode</b><br><br><br>' + # 'Select the region of interest<br>' + # 'using the mouse buttons.<br><br>')) # appmenu.append(btn_recalc) # appmenu.append(QLabel()) # self.volume_label = QLabel('Volume [mm3]:\n unknown') # appmenu.append(self.volume_label) # btn_crop = QPushButton("Crop", self) # btn_crop.clicked.connect(self.crop) # appmenu.append(btn_crop) btn_save = QPushButton("Save Seeds", self) btn_save.clicked.connect(self.saveSeeds) appmenu.append(btn_save) btn_del = QPushButton("Delete Seeds", self) btn_del.clicked.connect(self.deleteSliceSeeds) appmenu.append(btn_del) # combo_contour_options = ['fill', 'contours', 'off'] # combo_contour = QComboBox(self) # combo_contour.activated[str].connect(self.changeContourMode) # combo_contour.addItems(combo_contour_options) # self.changeContourMode(combo_contour_options[combo_contour.currentIndex()]) # vopts.append(QLabel('Selection mode:')) # vopts.append(combo_contour) # btn_reset = QPushButton("Reset Seeds", self) # btn_reset.clicked.connect(self.resetSliceDraw) # # appmenu.append(None) # appmenu.append(btn_reset) hbox = QHBoxLayout() vbox = QVBoxLayout() vbox_left = QVBoxLayout() vbox_app = QVBoxLayout() hbox.addWidget(self.slice_box) hbox.addWidget(self.slider) vbox_left.addWidget(self.slider.label) vbox_left.addWidget(self.view_label) vbox_left.addWidget(self.voxel_label) # vbox_left.addWidget(QLabel()) # vbox_left.addWidget(QLabel('View plane:')) # vbox_left.addWidget(combo_view) vbox_left.addWidget(self.get_line()) vbox_left.addWidget(self.slider_cw['c'].label) vbox_left.addWidget(self.slider_cw['c']) vbox_left.addWidget(self.slider_cw['w'].label) vbox_left.addWidget(self.slider_cw['w']) vbox_left.addWidget(self.get_line()) vbox_left.addWidget(QLabel('Drawing mask:')) vbox_left.addWidget(combo_dmask) for ii in vopts: vbox_left.addWidget(ii) for ii in vmenu: if ii is None: vbox_left.addStretch(1) else: vbox_left.addWidget(ii) for ii in appmenu: if ii is None: vbox_app.addStretch(1) else: vbox_app.addWidget(ii) vbox_left.addWidget(self.get_line()) vbox_left.addWidget(number_group) # vbox_app.addWidget(btn_crop) vbox_app.addStretch(1) # vbox_app.addWidget(btn_save) vbox_app.addWidget(btn_quit) hbox.addLayout(vbox_left) hbox.addWidget(self.get_line('v')) hbox.addLayout(vbox_app) vbox.addLayout(hbox) vbox.addWidget(self.status_bar) self.setLayout(vbox) self.setWindowTitle('Seed Editor') self.show() def __init__(self, img, seeds_fname='seeds.npy', actualSlice=0, seeds=None, contours=None, mode='seed', modeFun=None, voxelSize=[1, 1, 1]): """ Initiate Editor Parameters ---------- img : array DICOM data matrix. actualSlice : int Index of actual slice. seeds : array Seeds, user defined regions of interest. contours : array Computed segmentation. mode : str Editor modes: 'seed' - seed editor 'crop' - manual crop 'draw' - drawing modeFun : fun Mode function invoked by user button. voxelSize : tuple of float voxel size [mm] """ QDialog.__init__(self) self.mode = mode self.mode_fun = modeFun self.seeds_fname = seeds_fname # self.datapath = datapath self.actual_view = 'axial' self.act_transposition = VIEW_TABLE[self.actual_view] self.last_view_position = {} for ii in VIEW_TABLE.iterkeys(): self.last_view_position[ii] = img.shape[VIEW_TABLE[ii][-1]] - 1 self.img = img self.img_aview = self.img.transpose(self.act_transposition) self.actual_slice = self.img_aview.shape[-1] - actualSlice - 1 self.last_view_position[self.actual_view] = self.actual_slice # set contours self.contours = contours if self.contours is None: self.contours_aview = None else: self.contours_aview = self.contours.transpose( self.act_transposition) self.voxel_size = np.array(voxelSize) self.voxel_scale = self.voxel_size / float(np.min(self.voxel_size)) self.voxel_volume = np.prod(voxelSize) # set seeds if seeds is None: self.seeds = np.zeros(self.img.shape, np.int8) else: self.seeds = seeds self.seeds_aview = self.seeds.transpose(self.act_transposition) self.seeds_modified = False self.initUI(self.img_aview.shape, self.voxel_scale[np.array(self.act_transposition)], 600, mode) if mode == 'draw': self.seeds_orig = self.seeds.copy() self.slice_box.setEraseFun(self.eraseVolume) # set view window values C/W lb = np.min(img) ub = np.max(img) dul = ub - lb self.cw_range = {'c': [lb, ub], 'w': [1, dul]} self.slider_cw['c'].setRange(lb, ub) self.slider_cw['w'].setRange(1, dul) self.changeC(lb + dul / 2) self.changeW(dul) self.offset = np.zeros((3, ), dtype=np.int16) def change_seed_class(self, id): self.current_class = id self.slice_box.seed_mark = self.current_class # print 'Current seed class changed to ', id, '.' def showStatus(self, msg): self.status_bar.showMessage(QString(msg)) QApplication.processEvents() def init_draw_mask(self, draw_mask, grid): mask_points = [] mask_iconlabel = [] for mask, label in draw_mask: w, h = mask.shape xx, yy = mask.nonzero() mask_points.append((xx - w / 2, yy - h / 2)) img = QImage(w, h, QImage.Format_ARGB32) img.fill(qRgba(255, 255, 255, 0)) for ii in range(xx.shape[0]): img.setPixel(xx[ii], yy[ii], qRgba(0, 0, 0, 255)) img = img.scaled(QSize(w * grid[0], h * grid[1])) icon = QIcon(QPixmap.fromImage(img)) mask_iconlabel.append((icon, label)) return mask_points, mask_iconlabel def saveSliceSeeds(self): aux = self.slice_box.getSliceSeeds() if aux is not None: self.seeds_aview[..., self.actual_slice] = aux self.seeds_modified = True else: self.seeds_modified = False def saveSeeds(self): print 'Saving seeds array ... ', # aux = np.swapaxes(np.swapaxes(self.seeds_aview, 1, 2), 0, 1) aux = np.swapaxes(self.seeds_aview, 0, 2) np.save(self.seeds_fname, aux) print 'done' def updateCropBounds(self): crp = self.getCropBounds() if crp is not None: _, cri = crp self.contours = np.zeros(self.img.shape, np.int8) self.contours[cri].fill(1) self.contours_aview = self.contours.transpose( self.act_transposition) def focusSliceSlider(self): self.slider.setFocus(True) def sliderSelectSlice(self, value): self.selectSlice(self.n_slices - value) def scrollSlices(self, inc): if abs(inc) > 0: new = self.actual_slice + inc self.selectSlice(new) def selectSlice(self, value, force=False): if not (self.allow_select_slice): return if (value < 0) or (value >= self.n_slices): return if (value != self.actual_slice) or force: self.saveSliceSeeds() if self.seeds_modified and (self.mode == 'crop'): self.updateCropBounds() if self.contours is None: contours = None else: contours = self.contours_aview[..., value] slider_val = self.n_slices - value self.slider.setValue(slider_val) self.slider.label.setText('Slice: %d / %d' % (slider_val, self.n_slices)) self.slice_box.setSlice(self.img_aview[..., value], self.seeds_aview[..., value], contours) self.actual_slice = value def getSeeds(self): return self.seeds def getImg(self): return self.img def getOffset(self): return self.offset * self.voxel_size def getSeedsVal(self, label): return self.img[self.seeds == label] def getContours(self): return self.contours def setContours(self, contours): self.contours = contours self.contours_aview = self.contours.transpose(self.act_transposition) self.selectSlice(self.actual_slice) def changeCW(self, value, key): rg = self.cw_range[key] if (value < rg[0]) or (value > rg[1]): return if (value != self.slice_box.getCW()[key]): self.slider_cw[key].setValue(value) self.slider_cw[key].label.setText('%s: %d' % (key.upper(), value)) self.slice_box.setCW(value, key) self.slice_box.updateSliceCW(self.img_aview[..., self.actual_slice]) def changeC(self, value): self.changeCW(value, 'c') def changeW(self, value): self.changeCW(value, 'w') def setView(self, value): self.last_view_position[self.actual_view] = self.actual_slice # save seeds self.saveSliceSeeds() if self.seeds_modified and (self.mode == 'crop'): self.updateCropBounds(self.seeds_aview[..., self.actual_slice]) key = str(value) self.actual_view = key self.actual_slice = self.last_view_position[key] self.act_transposition = VIEW_TABLE[key] self.img_aview = self.img.transpose(self.act_transposition) self.seeds_aview = self.seeds.transpose(self.act_transposition) if self.contours is not None: self.contours_aview = self.contours.transpose( self.act_transposition) contours = self.contours_aview[..., self.actual_slice] else: contours = None vscale = self.voxel_scale[np.array(self.act_transposition)] height = self.slice_box.height() grid = height / float(self.img_aview.shape[1] * vscale[1]) mgrid = (grid * vscale[0], grid * vscale[1]) self.slice_box.resizeSlice(new_slice_size=self.img_aview.shape[:-1], new_grid=mgrid) self.slice_box.setSlice(self.img_aview[..., self.actual_slice], self.seeds_aview[..., self.actual_slice], contours) self.allow_select_slice = False self.n_slices = self.img_aview.shape[2] slider_val = self.n_slices - self.actual_slice self.slider.setValue(slider_val) self.slider.setRange(1, self.n_slices) self.allow_select_slice = True self.slider.label.setText('Slice: %d / %d' % (slider_val, self.n_slices)) self.view_label.setText('View size: %d x %d' % self.img_aview.shape[:-1]) def changeMask(self, val): self.slice_box.setMaskPoints(self.mask_points_tab[val]) def changeContourMode(self, val): self.slice_box.contour_mode = str(val) self.slice_box.updateSlice() def changeEraseMode(self, val): self.slice_box.erase_mode = str(val) def eraseVolume(self, pos, mode): self.showStatus("Processing...") xyz = pos + (self.actual_slice, ) p = tuple(np.array(xyz)[np.array(self.act_transposition)]) if self.seeds[p] > 0: if mode == 'inside': erase_reg(self.seeds, p, val=0) elif mode == 'outside': erase_reg(self.seeds, p, val=-1) idxs = np.where(self.seeds < 0) self.seeds.fill(0) self.seeds[idxs] = 1 if self.contours is None: contours = None else: contours = self.contours_aview[..., self.actual_slice] self.slice_box.setSlice(self.img_aview[..., self.actual_slice], self.seeds_aview[..., self.actual_slice], contours) self.showStatus("Done") def cropUpdate(self, img): for ii in VIEW_TABLE.iterkeys(): self.last_view_position[ii] = 0 self.actual_slice = 0 self.img = img self.img_aview = self.img.transpose(self.act_transposition) self.contours = None self.contours_aview = None self.seeds = np.zeros(self.img.shape, np.int8) self.seeds_aview = self.seeds.transpose(self.act_transposition) self.seeds_modified = False vscale = self.voxel_scale[np.array(self.act_transposition)] height = self.slice_box.height() grid = height / float(self.img_aview.shape[1] * vscale[1]) mgrid = (grid * vscale[0], grid * vscale[1]) self.slice_box.resizeSlice(new_slice_size=self.img_aview.shape[:-1], new_grid=mgrid) self.slice_box.setSlice(self.img_aview[..., self.actual_slice], self.seeds_aview[..., self.actual_slice], None) self.allow_select_slice = False self.n_slices = self.img_aview.shape[2] self.slider.setValue(self.actual_slice + 1) self.slider.setRange(1, self.n_slices) self.allow_select_slice = True self.slider.label.setText('Slice: %d / %d' % (self.actual_slice + 1, self.n_slices)) self.view_label.setText('View size: %d x %d' % self.img_aview.shape[:-1]) def getCropBounds(self): nzs = self.seeds.nonzero() cri = [] flag = True for ii in range(3): if nzs[ii].shape[0] == 0: flag = False break smin, smax = np.min(nzs[ii]), np.max(nzs[ii]) if smin == smax: flag = False break cri.append((smin, smax)) if flag: cri = np.array(cri) out = [] offset = [] for jj, ii in enumerate(cri): out.append(slice(ii[0], ii[1] + 1)) offset.append(ii[0]) return np.array(offset), tuple(out) else: return None def crop(self): self.showStatus("Processing...") crp = self.getCropBounds() if crp is not None: offset, cri = crp crop = self.img[cri] self.img = np.ascontiguousarray(crop) self.offset += offset self.showStatus('Done') else: self.showStatus('Region not selected!') self.cropUpdate(self.img) def recalculate(self, event): self.saveSliceSeeds() if np.abs(np.min(self.seeds) - np.max(self.seeds)) < 2: self.showStatus('At least two regions must be marked!') return self.showStatus("Processing...") # idx = 3 # s = random_walker(self.img[idx,:,:], self.seeds[idx,:,:])#, mode='cg_mg') # plt.figure() # plt.imshow(mark_boundaries(self.img[idx,:,:], s)) # plt.show() # self.segmentation = np.zeros(self.img.shape) # self.segmentation[idx,:,:] = s self.segmentation = random_walker(self.img, self.seeds, mode='cg_mg') self.setContours(self.segmentation - 1) self.selectSlice(self.actual_slice) # self.updateVolume() self.showStatus("Done") def deleteSliceSeeds(self, event): self.seeds_aview[..., self.actual_slice] = 0 self.slice_box.setSlice(seeds=self.seeds_aview[..., self.actual_slice]) self.slice_box.updateSlice() def resetSliceDraw(self, event): seeds_orig_aview = self.seeds_orig.transpose(self.act_transposition) self.seeds_aview[..., self.actual_slice] = seeds_orig_aview[ ..., self.actual_slice] self.slice_box.setSlice(seeds=self.seeds_aview[..., self.actual_slice]) self.slice_box.updateSlice() def quit(self, event): self.close() # def save(self, event): # odp = os.path.expanduser("~/lisa_data") # if not op.exists(odp): # os.makedirs(odp) # # data = self.export() # # data['version'] = self.version # # data['experiment_caption'] = self.experiment_caption # # data['lisa_operator_identifier'] = self.lisa_operator_identifier # pth, filename = op.split(op.normpath(self.datapath)) # # filename += "-" + self.experiment_caption # filepath = 'org-' + filename + '.pklz' # filepath = op.join(odp, filepath) # filepath = misc.suggest_filename(filepath) # misc.obj_to_file(data, filepath, filetype='pklz') # # filepath = 'organ_last.pklz' # filepath = op.join(odp, filepath) # misc.obj_to_file(data, filepath, filetype='pklz') # def export(self): # slab = {} # slab['none'] = 0 # slab['liver'] = 1 # slab['lesions'] = 6 # slab.update(self.slab) # # data = {} # data['version'] = (1, 0, 1) # data['data3d'] = self.img # # data['crinfo'] = self.crinfo # data['segmentation'] = self.segmentation # data['slab'] = slab # # data['voxelsize_mm'] = self.voxelsize_mm # # data['orig_shape'] = self.orig_shape # # data['processing_time'] = self.processing_time # return data def updateVolume(self): text = 'Volume [mm3]:\n unknown' if self.voxel_volume is not None: if self.mode == 'draw': vd = self.seeds else: vd = self.contours if vd is not None: nzs = vd.nonzero() nn = nzs[0].shape[0] text = 'Volume [mm3]:\n %.2e' % (nn * self.voxel_volume) self.volume_label.setText(text) def getROI(self): crp = self.getCropBounds() if crp is not None: _, cri = crp else: cri = [] for jj, ii in enumerate(self.img.shape): off = self.offset[jj] cri.append(slice(off, off + ii)) return cri
def create_rows(self, layout): u"""Build the rows of the dialog box""" play_button_group = QButtonGroup(self) old_play_button_group = QButtonGroup(self) for num, entry in enumerate(self.entries_list, 3): tt_text = self.build_text_help_label(entry) ico_label = QLabel('', self) ico_label.setToolTip(tt_text) if entry.icon: ico_label.setPixmap(QPixmap.fromImage(entry.icon)) layout.addWidget(ico_label, num, 0) tt_label = QLabel(entry.display_word, self) tt_label.setToolTip(tt_text) layout.addWidget(tt_label, num, 1) if self.hide_text: tt_label.hide() # Play button. t_play_button = QPushButton(self) play_button_group.addButton(t_play_button, num - 3) t_play_button.setToolTip(self.play_help) t_play_button.setIcon(QIcon(os.path.join(icons_dir, 'play.png'))) layout.addWidget(t_play_button, num, self.play_column) if self.note[entry.audio_field_name]: t_play_old_button = QPushButton(self) old_play_button_group.addButton(t_play_old_button, num - 3) t_play_old_button.setIcon( QIcon(os.path.join(icons_dir, 'play.png'))) if not self.hide_text: t_play_old_button.setToolTip( self.note[entry.audio_field_name]) else: t_play_old_button.setToolTip(self.play_old_help_short) layout.addWidget(t_play_old_button, num, self.play_old_column) else: dummy_label = QLabel('', self) dummy_label.setToolTip(self.play_old_empty_line_help) layout.addWidget(dummy_label, num, self.play_old_column) # The group where we later look what to do: t_button_group = QButtonGroup(self) t_button_group.setExclusive(True) # Now the four buttons t_add_button = QPushButton(self) t_add_button.setCheckable(True) t_add_button.setFlat(True) t_add_button.setToolTip(self.add_help_text_short) t_add_button.setIcon(QIcon(os.path.join(icons_dir, 'add.png'))) layout.addWidget(t_add_button, num, self.add_column) t_button_group.addButton(t_add_button, Action.Add) t_keep_button = QPushButton(self) t_keep_button.setCheckable(True) t_keep_button.setFlat(True) t_keep_button.setToolTip(self.keep_help_text_short) t_keep_button.setIcon(QIcon(os.path.join(icons_dir, 'keep.png'))) layout.addWidget(t_keep_button, num, self.keep_column) t_button_group.addButton(t_keep_button, Action.Keep) t_delete_button = QPushButton(self) t_delete_button.setCheckable(True) t_delete_button.setFlat(True) t_delete_button.setToolTip(self.delete_help_text_short) t_delete_button.setIcon( QIcon(os.path.join(icons_dir, 'delete.png'))) layout.addWidget(t_delete_button, num, self.delete_column) t_button_group.addButton(t_delete_button, Action.Delete) t_blacklist_button = QPushButton(self) t_blacklist_button.setCheckable(True) t_blacklist_button.setFlat(True) t_blacklist_button.setToolTip(self.blacklist_help_text_short) t_blacklist_button.setIcon( QIcon(os.path.join(icons_dir, 'blacklist.png'))) if entry.entry_hash: layout.addWidget( t_blacklist_button, num, self.blacklist_column) else: t_blacklist_button.hide() dummy_label_bl = QLabel('', self) dummy_label_bl.setToolTip(self.blacklist_empty_line_help) layout.addWidget(dummy_label_bl, num, self.blacklist_column) t_button_group.button(entry.action).setChecked(True) # New: check a button based on how good the downloader is. t_button_group.addButton(t_blacklist_button, Action.Blacklist) self.buttons_groups.append(t_button_group) play_button_group.buttonClicked.connect( lambda button: play( self.entries_list[play_button_group.id(button)].file_path)) # N.B.: anki.sound.play() plays files from anywhere, not just # from the colection.media folder. We should be good, # here. (This behaviour may be a security risk, idk.) old_play_button_group.buttonClicked.connect( lambda button: playFromText( self.note[ self.entries_list[ old_play_button_group.id(button)].audio_field_name]))
class InterpolateConfirmDialog(QDialog): """ Dialog class to confirm the interpolation """ def __init__(self): """ Constructor """ QDialog.__init__(self) self.setWindowTitle(QCoreApplication.translate("VDLTools", "Edition Confirmation")) self.__layout = QGridLayout() self.__confirmLabel = QLabel( QCoreApplication.translate("VDLTools", "This LineString layer is not editable, what do you want to do ?")) self.__layout.addWidget(self.__confirmLabel, 0, 0, 1, 2) self.__radios = [] self.__radios.append(QRadioButton( QCoreApplication.translate("VDLTools", "Create point, and edit line with new vertex"))) self.__radios.append(QRadioButton(QCoreApplication.translate("VDLTools", "Create only the point"))) self.__radios.append(QRadioButton(QCoreApplication.translate("VDLTools", "Just edit line with new vertex"))) self.__scrollLayout = QGridLayout() self.__radios[0].setChecked(True) self.__radio_button_group = QButtonGroup() for i in range(len(self.__radios)): self.__scrollLayout.addWidget(self.__radios[i], i+1, 0, 1, 2) self.__radio_button_group.addButton(self.__radios[i], i) widget = QWidget() widget.setLayout(self.__scrollLayout) scroll = QScrollArea() scroll.setWidgetResizable(True) scroll.setWidget(widget) self.__layout.addWidget(scroll, 1, 0, 1, 2) self.__okButton = QPushButton(QCoreApplication.translate("VDLTools", "OK")) self.__okButton.setMinimumHeight(20) self.__okButton.setMinimumWidth(100) self.__layout.addWidget(self.__okButton, 4, 0) self.__cancelButton = QPushButton(QCoreApplication.translate("VDLTools", "Cancel")) self.__cancelButton.setMinimumHeight(20) self.__cancelButton.setMinimumWidth(100) self.__layout.addWidget(self.__cancelButton, 4, 1) self.setLayout(self.__layout) def setMainLabel(self, label): """ To set the title :param label: title """ self.__confirmLabel.setText(label) def setAllLabel(self, label): """ To set the all button title :param label: title """ self.__radios[0].setText(label) def setVtLabel(self, label): """ To set the vertex button title :param label: title """ self.__radios[2].setText(label) def getCheckedId(self): """ To get the radio button checked id 0 : all 1 : point 2 : vertex :return: id of radion button """ return self.__radio_button_group.checkedId() def okButton(self): """ To get the ok button instance :return: ok button instance """ return self.__okButton def cancelButton(self): """ To get the cancel button instance :return: cancel button instance """ return self.__cancelButton
class GroupSelectParameterWidget(GenericParameterWidget): """Widget class for Group Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A GroupSelectParameter object. :type parameter: GroupSelectParameter """ QWidget.__init__(self, parent) self._parameter = parameter # Store spin box self.spin_boxes = {} # Create elements # Label (name) self.label = QLabel(self._parameter.name) # Layouts self.main_layout = QVBoxLayout() self.input_layout = QVBoxLayout() # _inner_input_layout must be filled with widget in the child class self.inner_input_layout = QVBoxLayout() self.radio_button_layout = QGridLayout() # Create radio button group self.input_button_group = QButtonGroup() # List widget self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setDragDropMode(QAbstractItemView.DragDrop) self.list_widget.setDefaultDropAction(Qt.MoveAction) self.list_widget.setEnabled(False) self.list_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) for i, key in enumerate(self._parameter.options): value = self._parameter.options[key] radio_button = QRadioButton(value.get('label')) self.radio_button_layout.addWidget(radio_button, i, 0) if value.get('type') == SINGLE_DYNAMIC: double_spin_box = QDoubleSpinBox() self.radio_button_layout.addWidget(double_spin_box, i, 1) double_spin_box.setValue(value.get('value', 0)) double_spin_box.setMinimum( value.get('constraint', {}).get('min', 0)) double_spin_box.setMaximum( value.get('constraint', {}).get('max', 1)) double_spin_box.setSingleStep( value.get('constraint', {}).get('step', 0.01)) step = double_spin_box.singleStep() if step > 1: precision = 0 else: precision = len(str(step).split('.')[1]) if precision > 3: precision = 3 double_spin_box.setDecimals(precision) self.spin_boxes[key] = double_spin_box # Enable spin box depends on the selected option if self._parameter.selected == key: double_spin_box.setEnabled(True) else: double_spin_box.setEnabled(False) elif value.get('type') == STATIC: static_value = value.get('value', 0) if static_value is not None: self.radio_button_layout.addWidget( QLabel(str(static_value)), i, 1) elif value.get('type') == MULTIPLE_DYNAMIC: selected_fields = value.get('value', []) if self._parameter.selected == key: self.list_widget.setEnabled(True) else: self.list_widget.setEnabled(False) self.input_button_group.addButton(radio_button, i) if self._parameter.selected == key: radio_button.setChecked(True) # Help text self.help_label = QLabel(self._parameter.help_text) self.help_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) self.help_label.setWordWrap(True) self.help_label.setAlignment(Qt.AlignTop) self.inner_input_layout.addLayout(self.radio_button_layout) self.inner_input_layout.addWidget(self.list_widget) # Put elements into layouts self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.help_layout = QVBoxLayout() self.help_layout.addWidget(self.help_label) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # Update list widget self.update_list_widget() # Connect signal self.input_button_group.buttonClicked.connect( self.radio_buttons_clicked) def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ # Set value for each key for key, value in self._parameter.options.items(): if value.get('type') == STATIC: continue elif value.get('type') == SINGLE_DYNAMIC: new_value = self.spin_boxes.get(key).value() self._parameter.set_value_for_key(key, new_value) elif value.get('type') == MULTIPLE_DYNAMIC: # Need to iterate through all items items = [] for index in xrange(self.list_widget.count()): items.append(self.list_widget.item(index)) new_value = [i.text() for i in items] self._parameter.set_value_for_key(key, new_value) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.selected = None else: self._parameter.selected = self._parameter.options.keys( )[radio_button_checked_id] return self._parameter def update_list_widget(self): """Update list widget when radio button is clicked.""" # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id > -1: selected_dict = self._parameter.options.values( )[radio_button_checked_id] if selected_dict.get('type') == MULTIPLE_DYNAMIC: for field in selected_dict.get('value'): # Update list widget field_item = QListWidgetItem(self.list_widget) field_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field) field_item.setText(field) self.list_widget.addItem(field_item) def radio_buttons_clicked(self): """Handler when selected radio button changed.""" # Disable all spin boxes for spin_box in self.spin_boxes.values(): spin_box.setEnabled(False) # Disable list widget self.list_widget.setEnabled(False) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() if radio_button_checked_id > -1: selected_value = self._parameter.options.values( )[radio_button_checked_id] if selected_value.get('type') == MULTIPLE_DYNAMIC: # Enable list widget self.list_widget.setEnabled(True) elif selected_value.get('type') == SINGLE_DYNAMIC: selected_key = self._parameter.options.keys( )[radio_button_checked_id] self.spin_boxes[selected_key].setEnabled(True) def select_radio_button(self, key): """Helper to select a radio button with key. :param key: The key of the radio button. :type key: str """ key_index = self._parameter.options.keys().index(key) radio_button = self.input_button_group.button(key_index) radio_button.click()
def addWidgets(self): """ Add widgets """ nbArgument = 0 layoutUsed = self.mainLayout fontBold = QFont() fontBold.setBold(True) fontNormal = QFont() fontNormal.setBold(False) for i in xrange(len(self.actionData['data']['obj'])): # prevent to limit the display of all arguments # split all arguments in two tabulations if necessary nbArgument += 1 if nbArgument > MAX_ARGUMENT_TO_DISPLAY: layoutUsed = self.moreLayout # the second tab self.mainTab.setTabEnabled(1, True) if nbArgument > MAX_ARGUMENT_TO_DISPLAY2: layoutUsed = self.more2Layout # the second tab self.mainTab.setTabEnabled(2, True) # extract the name of the function varName = self.actionData['data']['obj'][i]['name'] #argNameLabel = QLabel( varName ) argNameLabel = QLabelEnhanced( varName, parent=self, data=self.actionData['data']['obj'][i]['descr']) argNameLabel.EnterLabel.connect(self.loadArgumentDescription) argNameLabel.LeaveLabel.connect(self.clearArgumentDescription) #argNameLabel.setToolTip(self.actionData['data']['obj'][i]['descr']) layoutUsed.addWidget(argNameLabel, i, 0) typeDetected = self.actionData['data']['obj'][i]['type'].split("/") opDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'operators': opDetected = True break if typeDetected[j].lower() == 'condition': opDetected = True break labDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'label': labDetected = True break constDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() in ['strconstant', 'intconstant']: constDetected = True break dictDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'dict': dictDetected = True break tplMDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'templatemessage': tplMDetected = True break if tplMDetected: typeDetected.pop(j) tplLDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'templatelayer': tplLDetected = True break if tplLDetected: typeDetected.pop(j) # exception for testcase parent in adapters or libraries if self.actionData['data']['obj'][i]['type'] != "testcase": if not self.adapterMode: if dictDetected or tplMDetected or tplLDetected: typeDetected.extend(['variables']) else: if not opDetected: if not labDetected: if not constDetected: typeDetected.extend( ['inputs', 'outputs', 'variables']) else: if not constDetected: typeDetected.extend(['inputs', 'outputs']) # second exception for agent mode if self.adapterMode and varName == "agent": if "none" in typeDetected or "None" in typeDetected: typeDetected = ['agents', "none"] else: typeDetected = ['agents'] # move none if exists on the list to the end noneDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'none': noneDetected = True break if noneDetected: typeDetected.pop(j) typeDetected.append("none") # remove image type imgDetected = False for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'image': imgDetected = True break if imgDetected: typeDetected.pop(j) # remove string type if operators exists strDetected = False if opDetected: for j in xrange(len(typeDetected)): if typeDetected[j].lower() == 'string': strDetected = True break if strDetected: typeDetected.pop(j) radioGroup = QButtonGroup(self) shiftWidget = 1 deltaWidget = 0 radioSelected = shiftWidget for j in xrange(len(typeDetected)): #if typeDetected[j].lower() == "list": # continue radioButton = QRadioButton(typeDetected[j].lower()) radioButton.setFont(fontNormal) radioGroup.addButton(radioButton) layoutUsed.addWidget(radioButton, i, j + shiftWidget + deltaWidget) if typeDetected[j].lower() == "testcase": pass elif typeDetected[j].lower() == "none": if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget else: if 'default-value' in self.actionData['data']['obj'][ i]: if not len( self.actionData['data']['obj'][i] ['selected-type']) and self.actionData['data'][ 'obj'][i]['default-value'] == 'None': radioSelected = j + shiftWidget + deltaWidget elif typeDetected[j].lower() in [ "inputs", "outputs", "agents", "variables" ]: paramCombo = QComboBox() layoutUsed.addWidget(paramCombo, i, j + shiftWidget + deltaWidget + 1) if typeDetected[j].lower() == 'inputs': for inpt in self.owner.getInputs(): paramCombo.addItem(inpt['name']) if typeDetected[j].lower() == 'outputs': for inpt in self.owner.getOutputs(): paramCombo.addItem(inpt['name']) if typeDetected[j].lower() == 'agents': for inpt in self.owner.getAgents(): paramCombo.addItem(inpt['name']) if typeDetected[j].lower() == 'variables': paramCombo.addItems(self.variables) # set as default value or not ? if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget for x in xrange(paramCombo.count()): if paramCombo.itemText(x) == self.actionData[ 'data']['obj'][i]['value']: paramCombo.setCurrentIndex(x) deltaWidget += 1 elif typeDetected[j].lower() == "string": textArea = QTextEdit() textArea.setMinimumHeight(HEIGHT_TEXT_AREA) textArea.setMinimumWidth(WIDTH_TEXT_AREA) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget try: if sys.version_info > (3, ): # python 3 support self.actionData['data']['obj'][i][ 'value'] = self.actionData['data']['obj'][ i]['value'] else: self.actionData['data']['obj'][i][ 'value'] = self.actionData['data']['obj'][ i]['value'].decode('utf8') textArea.setText( self.actionData['data']['obj'][i]['value']) except UnicodeDecodeError as e: textArea.setText( self.actionData['data']['obj'][i]['value']) except UnicodeEncodeError as e: textArea.setText( self.actionData['data']['obj'][i]['value']) else: if 'none' not in self.actionData['data']['obj'][i][ 'type'].lower(): if 'default-value' in self.actionData['data'][ 'obj'][i]: textArea.setText(self.actionData['data']['obj'] [i]['default-value']) layoutUsed.addWidget(textArea, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() in ["integer", "float"]: lineEdit = QLineEdit() if typeDetected[j].lower() == "integer": validator = QIntValidator(lineEdit) else: validator = QDoubleValidator(lineEdit) validator.setNotation( QDoubleValidator.StandardNotation) lineEdit.setValidator(validator) lineEdit.installEventFilter(self) if self.actionData['data']['obj'][i]['selected-type'] in [ 'integer', 'float' ]: radioSelected = j + shiftWidget + deltaWidget lineEdit.setText( "%s" % self.actionData['data']['obj'][i]['value']) else: if 'default-value' in self.actionData['data']['obj'][ i]: lineEdit.setText( str(self.actionData['data']['obj'][i] ['default-value'])) layoutUsed.addWidget(lineEdit, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() in ["strconstant", "intconstant"]: consCombo = QComboBox() # extract values tmpconstant = self.actionData['data']['obj'][i]['descr'] tmpvals = tmpconstant.split("|") # extract all constant and detect the default vals = [] defConstant = 0 defConstantVal = '' for zz in xrange(len(tmpvals)): if '(default)' in tmpvals[zz]: nameConstant = tmpvals[zz].split( '(default)')[0].strip() vals.append(nameConstant) defConstant = zz defConstantVal = nameConstant else: vals.append(tmpvals[zz].strip()) # append all constant to the combobox consCombo.addItems(vals) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget for x in xrange(len(vals)): if vals[x] == str(self.actionData['data']['obj'][i] ['value']): consCombo.setCurrentIndex(x) else: # set the current index for default value consCombo.setCurrentIndex(defConstant) layoutUsed.addWidget(consCombo, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "boolean": boolCombo = QComboBox() valBool = ["True", "False"] boolCombo.addItems(valBool) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget for x in xrange(len(valBool)): if valBool[x] == str(self.actionData['data']['obj'] [i]['value']): boolCombo.setCurrentIndex(x) else: # set the default value if 'default-value' in self.actionData['data']['obj'][ i]: for x in xrange(len(valBool)): if valBool[x] == str( self.actionData['data']['obj'][i] ['default-value']): boolCombo.setCurrentIndex(x) layoutUsed.addWidget(boolCombo, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "dict": dictWidget = DictWidget.DictWidget( parent=self, advancedMode=False, testParams=self.testParams, variables=self.variables) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget if not isinstance( self.actionData['data']['obj'][i]['value'], dict): self.actionData['data']['obj'][i]['value'] = { 'dict': [] } dictVal = self.actionData['data']['obj'][i]['value'][ 'dict'] dictWidget.setCurrentDict(dictVal=dictVal) layoutUsed.addWidget(dictWidget, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "dictadvanced": dictWidget = DictWidget.DictWidget( parent=self, advancedMode=True, testParams=self.testParams, variables=self.variables) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget if not isinstance( self.actionData['data']['obj'][i]['value'], dict): self.actionData['data']['obj'][i]['value'] = { 'dictadvanced': [] } dictVal = self.actionData['data']['obj'][i]['value'][ 'dictadvanced'] dictWidget.setCurrentDict(dictVal=dictVal) layoutUsed.addWidget(dictWidget, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "operators": opWidget = OperatorsWidget.OperatorsWidget( self, testParams=self.testParams, variables=self.variables) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget opWidget.setCurrentOperator( operatorVal=self.actionData['data']['obj'][i] ['value']) layoutUsed.addWidget(opWidget, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "condition": opWidget = OperatorsWidget.OperatorsWidget( self, testParams=self.testParams, variables=self.variables, liteMode=True) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget opWidget.setCurrentOperator( operatorVal=self.actionData['data']['obj'][i] ['value']) layoutUsed.addWidget(opWidget, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "templatelayer": textArea = QLineEdit() if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget textArea.setText( self.actionData['data']['obj'][i]['value']) else: if 'none' not in self.actionData['data']['obj'][i][ 'type'].lower(): if 'default-value' in self.actionData['data'][ 'obj'][i]: textArea.setText(self.actionData['data']['obj'] [i]['default-value']) layoutUsed.addWidget(textArea, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 elif typeDetected[j].lower() == "object": textArea = QTextEdit() textArea.setFixedHeight(HEIGHT_TEXT_AREA) textArea.setMinimumWidth(WIDTH_TEXT_AREA) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget textArea.setText( self.actionData['data']['obj'][i]['value']) else: # typeParam.setChecked(True) # fix bug if 'none' not in self.actionData['data']['obj'][i][ 'type'].lower(): if 'default-value' in self.actionData['data'][ 'obj'][i]: textArea.setText(self.actionData['data']['obj'] [i]['default-value']) layoutUsed.addWidget(textArea, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 else: textArea = QTextEdit() textArea.setFixedHeight(HEIGHT_TEXT_AREA) textArea.setMinimumWidth(WIDTH_TEXT_AREA) if self.actionData['data']['obj'][i][ 'selected-type'] == typeDetected[j].lower(): radioSelected = j + shiftWidget + deltaWidget textArea.setText( self.actionData['data']['obj'][i]['value']) else: if 'none' not in self.actionData['data']['obj'][i][ 'type'].lower(): if 'default-value' in self.actionData['data'][ 'obj'][i]: textArea.setText(self.actionData['data']['obj'] [i]['default-value']) layoutUsed.addWidget(textArea, i, j + shiftWidget + deltaWidget + 1) deltaWidget += 1 widgetRadio = layoutUsed.itemAtPosition(i, radioSelected).widget() widgetRadio.setChecked(True) widgetRadio.setFont(fontBold) if nbArgument < MAX_ARGUMENT_TO_DISPLAY: self.mainTab.setTabEnabled(1, False)
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 OptionsWidget(QWidget): progress = pyqtSignal(int) def __init__(self, conf, parent=None): QWidget.__init__(self, parent) self._conf = conf self._projects = [] for project in self._conf.projects: self._projects += [ProjectWidgets(project)] gLayout = QGridLayout() column = 0 for iproject in range(len(self._projects)): column += self._projects[iproject].addToLayout(column, gLayout) toolsGroup = QGroupBox('Projects && Tools') toolsGroup.setLayout(gLayout) scrollToolsGroup = QScrollArea() scrollToolsGroup.setMinimumHeight(350) #scrollToolsGroup.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOn ) scrollToolsGroup.setWidget(toolsGroup) self._buildMode = QComboBox() self._buildMode.addItems(('Release', 'Debug')) #self._svnUpdate = QCheckBox( 'SVN Update' ) #self._svnStatus = QCheckBox( 'SVN Status' ) self._make = QCheckBox('Build') self._enableDoc = QCheckBox('Build Documentation') self._devtoolset2 = QCheckBox('Build with devtoolset 2') self._qt5 = QCheckBox('Build with Qt 5 (Qt 4 default)') self._noCache = QCheckBox('Remove previous CMake cache') self._rmBuild = QCheckBox('Cleanup Build Directory') self._verbose = QCheckBox('Display Compiler Commands') self._threads = QComboBox() for j in range(16): self._threads.addItem('-j%d' % (j + 1), j + 1) self._commandGroup = QButtonGroup() self._commandGroup.setExclusive(True) #self._commandGroup.addButton( self._svnUpdate ) #self._commandGroup.addButton( self._svnStatus ) self._commandGroup.addButton(self._make) vLayout = QVBoxLayout() #vLayout.addWidget( self._svnUpdate ) #vLayout.addWidget( self._svnStatus ) vLayout.addWidget(self._make) vLayout.addStretch() commandGroup = QGroupBox('Command') commandGroup.setLayout(vLayout) vLayout = QVBoxLayout() vLayout.addWidget(self._buildMode) vLayout.addWidget(self._enableDoc) vLayout.addWidget(self._devtoolset2) vLayout.addWidget(self._qt5) vLayout.addWidget(self._noCache) vLayout.addWidget(self._rmBuild) vLayout.addStretch() optionsGroup = QGroupBox('Command Options') optionsGroup.setLayout(vLayout) vLayout = QVBoxLayout() vLayout.addWidget(self._threads) vLayout.addWidget(self._verbose) vLayout.addStretch() miscGroup = QGroupBox('Misc. Options') miscGroup.setLayout(vLayout) hLayout = QHBoxLayout() hLayout.addWidget(commandGroup) hLayout.addWidget(optionsGroup) hLayout.addWidget(miscGroup) commands = QWidget() commands.setLayout(hLayout) vLayout = QVBoxLayout() vLayout.addWidget(commands) vLayout.addWidget(scrollToolsGroup) vLayout.addStretch() self.setLayout(vLayout) self.readSettings() return def _getProjects(self): return self._projects def _getBuildMode(self): return self._buildMode.currentText() def _getThreads(self): return self._threads.currentText() #def _getSvnUpdate ( self ): return self._svnUpdate.isChecked() #def _getSvnStatus ( self ): return self._svnStatus.isChecked() def _getMake(self): return self._make.isChecked() def _getEnableDoc(self): return self._enableDoc.isChecked() def _getDevtoolset2(self): return self._devtoolset2.isChecked() def _getQt5(self): return self._qt5.isChecked() def _getNoCache(self): return self._noCache.isChecked() def _getRmBuild(self): return self._rmBuild.isChecked() def _getVerbose(self): return self._verbose.isChecked() projects = property(_getProjects) buildMode = property(_getBuildMode) threads = property(_getThreads) #svnUpdate = property( _getSvnUpdate ) #svnStatus = property( _getSvnStatus ) make = property(_getMake) enableDoc = property(_getEnableDoc) devtoolset2 = property(_getDevtoolset2) qt5 = property(_getQt5) noCache = property(_getNoCache) rmBuild = property(_getRmBuild) verbose = property(_getVerbose) def readSettings(self): settings = QSettings() #self._svnUpdate .setChecked( settings.value('builder/svnUpdate').toBool() ) #self._svnStatus .setChecked( settings.value('builder/svnStatus').toBool() ) self._make.setChecked(settings.value('builder/make').toBool()) self._enableDoc.setChecked( settings.value('builder/enableDoc').toBool()) self._devtoolset2.setChecked( settings.value('builder/devtoolset2').toBool()) self._qt5.setChecked(settings.value('builder/qt5').toBool()) self._noCache.setChecked(settings.value('builder/noCache').toBool()) self._rmBuild.setChecked(settings.value('builder/rmBuild').toBool()) self._verbose.setChecked(settings.value('builder/verbose').toBool()) buildModeName = settings.value('builder/buildMode').toString() index = self._buildMode.findText(buildModeName) if index >= 0: self._buildMode.setCurrentIndex(index) threads = settings.value('builder/threads').toString() index = self._threads.findText(threads) if index >= 0: self._threads.setCurrentIndex(index) for project in self._projects: project.readFromSettings() return def saveSettings(self): settings = QSettings() #settings.setValue('builder/svnUpdate' , self._svnUpdate .isChecked() ) #settings.setValue('builder/svnStatus' , self._svnStatus .isChecked() ) settings.setValue('builder/make', self._make.isChecked()) settings.setValue('builder/enableDoc', self._enableDoc.isChecked()) settings.setValue('builder/devtoolset2', self._devtoolset2.isChecked()) settings.setValue('builder/qt5', self._qt5.isChecked()) settings.setValue('builder/buildMode', self._buildMode.currentText()) settings.setValue('builder/noCache', self._noCache.isChecked()) settings.setValue('builder/rmBuild', self._rmBuild.isChecked()) settings.setValue('builder/verbose', self._verbose.isChecked()) settings.setValue('builder/threads', self._threads.currentText()) for project in self._projects: project.saveToSettings() return
class DateTimePickerWidget(datepicker_widget, QWidget): ok = pyqtSignal() cancel = pyqtSignal() """ A custom date picker with a time and date picker """ def __init__(self, parent=None, mode="DateTime"): super(DateTimePickerWidget, self).__init__(parent) self.setupUi(self) self.mode = mode self.group = QButtonGroup() self.group.setExclusive(True) self.group.addButton(self.ambutton) self.group.addButton(self.pmbutton) self.ambutton.toggled.connect(self.isDirty) self.pmbutton.toggled.connect(self.isDirty) self.datepicker.selectionChanged.connect(self.isDirty) self.hourpicker.itemSelectionChanged.connect(self.isDirty) self.minutepicker.itemSelectionChanged.connect(self.isDirty) self.setasnowbutton.pressed.connect(self.setAsNow) self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint) self.okButton.pressed.connect(self.ok.emit) self.closebutton.pressed.connect(self.cancel.emit) def setMinValue(self, mindate): self.datepicker.setMinimumDate(mindate) def setmode(self, mode): if mode == "Date": self.timesection.hide() self.setasnowbutton.setText("Set as current date") elif mode == "Time": self.datepicker.hide() self.setasnowbutton.setText("Set as current time") def isDirty(self, *args): date = self.getSelectedDate() time = self.getSelectedTime() datetime = QDateTime(date, time) if self.mode == "Date": value = datetime.toString("ddd d MMM yyyy") elif self.mode == "Time": value = datetime.toString("h:m ap") else: value = datetime.toString("ddd d MMM yyyy 'at' h:m ap") self.label.setText(value) def setDateTime(self, datetime): """ Set the picker to datatime datetime - The QDateTime with the value to set. """ self.setTime(datetime.time()) self.setDate(datetime.date()) def setAsNow(self): """ Set the current date and time on the picker as now. """ now = QDateTime.currentDateTime() self.setDateTime(now) def setTime(self, time): """ Set just the time part of the picker """ hour = time.hour() if hour > 12: hour = hour - 12 if hour == 0: hour = hour + 12 minute = time.minute() minute = int(round(minute / 5.0) * 5.0) amap = time.toString("AP") utils.log("Hour %s Minute %s" % (hour, minute)) try: houritems = self.hourpicker.findItems(str(hour), Qt.MatchFixedString) self.hourpicker.setCurrentItem(houritems[0]) except IndexError: utils.log("Can't find hour") try: minuteitems = self.minutepicker.findItems(str(minute), Qt.MatchFixedString) self.minutepicker.setCurrentItem(minuteitems[0]) except IndexError: utils.log("Can't find minute") if amap == "PM": self.pmbutton.toggle() def setDate(self, date): """ Set just the date part of the picker """ self.datepicker.setSelectedDate(date) def getSelectedTime(self): """ Returns the currently selected data and time """ try: hour = self.hourpicker.currentItem().text() except AttributeError: hour = "" try: minute = self.minutepicker.currentItem().text() except AttributeError: minute = "" zone = self.ambutton.isChecked() and "AM" or "PM" return QTime.fromString("%s%s%s" % (hour, minute, zone), "hmAP") def getSelectedDate(self): """ Returns just the date part of the picker """ return self.datepicker.selectedDate() @property def value(self): datetime = QDateTime() datetime.setDate(self.getSelectedDate()) datetime.setTime(self.getSelectedTime()) return datetime @value.setter def value(self, value): if value is None: self.setAsNow() return if isinstance(value, basestring): value = QDateTime.fromString(value, Qt.ISODate) self.setDate(value.date()) self.setTime(value.time())
class QgsComposerArrowWidget(Ui_QgsComposerArrowWidgetBase): def __init__(self, parent, arrow): Ui_QgsComposerArrowWidgetBase.__init__(self, parent) self.mArrow = arrow self.mRadioButtonGroup = QButtonGroup(self) self.mRadioButtonGroup.addButton(self.mDefaultMarkerRadioButton) self.mRadioButtonGroup.addButton(self.mNoMarkerRadioButton) self.mRadioButtonGroup.addButton(self.mSvgMarkerRadioButton) self.mRadioButtonGroup.setExclusive(True) # //disable the svg related gui elements by default self.on_mSvgMarkerRadioButton_toggled(False) # //add widget for general composer item properties itemPropertiesWidget = QgsComposerItemWidget(self, self.mArrow) self.mainLayout.addWidget(itemPropertiesWidget) self.mArrowHeadOutlineColorButton.setColorDialogTitle( QString("Select arrow head outline color")) self.mArrowHeadOutlineColorButton.setAllowAlpha(True) self.mArrowHeadOutlineColorButton.setContext("composer") self.mArrowHeadOutlineColorButton.setNoColorString( QString("Transparent outline")) self.mArrowHeadOutlineColorButton.setShowNoColor(True) self.mArrowHeadFillColorButton.setColorDialogTitle( QString("Select arrow head fill color")) self.mArrowHeadFillColorButton.setAllowAlpha(True) self.mArrowHeadFillColorButton.setContext("composer") self.mArrowHeadFillColorButton.setNoColorString( QString("Transparent fill")) self.mArrowHeadFillColorButton.setShowNoColor(True) self.setGuiElementValues() if (arrow): self.connect(arrow, SIGNAL("itemChanged()"), self.setGuiElementValues) self.connect(self.mArrowHeadWidthSpinBox, SIGNAL("valueChanged(double)"), self.on_mArrowHeadWidthSpinBox_valueChanged) self.timeEnd = 0 self.timeStart = 0 def on_mOutlineWidthSpinBox_valueChanged(self, d): if (not self.mArrow): return self.mArrow.beginCommand(QString("Arrow head outline width"), QgsComposerMergeCommand.ArrowOutlineWidth) self.mArrow.setArrowHeadOutlineWidth(self.mOutlineWidthSpinBox.value()) self.mArrow.update() self.mArrow.endCommand() def on_mArrowHeadWidthSpinBox_valueChanged(self, d): if (not self.mArrow): return self.mArrow.beginCommand(QString("Arrowhead width"), QgsComposerMergeCommand.ArrowHeadWidth) self.mArrow.setArrowHeadWidth(self.mArrowHeadWidthSpinBox.value()) self.mArrow.update() self.mArrow.endCommand() def on_mArrowHeadFillColorButton_colorChanged(self, newColor): if (not self.mArrow): return self.mArrow.beginCommand(QString("Arrow head fill color")) self.mArrow.setArrowHeadFillColor(newColor) self.mArrow.update() self.mArrow.endCommand() def on_mArrowHeadOutlineColorButton_colorChanged(self, newColor): if (not self.mArrow): return self.mArrow.beginCommand(QString("Arrow head outline color")) self.mArrow.setArrowHeadOutlineColor(newColor) self.mArrow.update() self.mArrow.endCommand() def blockAllSignals(self, block): self.mLineStyleButton.blockSignals(block) self.mArrowHeadFillColorButton.blockSignals(block) self.mArrowHeadOutlineColorButton.blockSignals(block) self.mOutlineWidthSpinBox.blockSignals(block) self.mArrowHeadWidthSpinBox.blockSignals(block) self.mDefaultMarkerRadioButton.blockSignals(block) self.mNoMarkerRadioButton.blockSignals(block) self.mSvgMarkerRadioButton.blockSignals(block) self.mStartMarkerLineEdit.blockSignals(block) self.mStartMarkerToolButton.blockSignals(block) self.mEndMarkerLineEdit.blockSignals(block) self.mEndMarkerToolButton.blockSignals(block) def setGuiElementValues(self): if (not self.mArrow): return self.blockAllSignals(True) self.mArrowHeadFillColorButton.setColor( self.mArrow.arrowHeadFillColor()) self.mArrowHeadOutlineColorButton.setColor( self.mArrow.arrowHeadOutlineColor()) self.mOutlineWidthSpinBox.setValue(self.mArrow.arrowHeadOutlineWidth()) self.mArrowHeadWidthSpinBox.setValue(self.mArrow.arrowHeadWidth()) mode = self.mArrow.markerMode() if (mode == QgsComposerArrow.DefaultMarker): self.mDefaultMarkerRadioButton.setChecked(True) elif (mode == QgsComposerArrow.NoMarker): self.mNoMarkerRadioButton.setChecked(True) else: # //svg marker: self.mSvgMarkerRadioButton.setChecked(True) self.enableSvgInputElements(True) self.mStartMarkerLineEdit.setText(self.mArrow.startMarker()) self.mEndMarkerLineEdit.setText(self.mArrow.endMarker()) self.updateLineSymbolMarker() self.blockAllSignals(False) def enableSvgInputElements(self, enable): self.mStartMarkerLineEdit.setEnabled(enable) self.mStartMarkerToolButton.setEnabled(enable) self.mEndMarkerLineEdit.setEnabled(enable) self.mEndMarkerToolButton.setEnabled(enable) def on_mDefaultMarkerRadioButton_toggled(self, toggled): if (self.mArrow and toggled): self.mArrow.beginCommand(QString("Arrow marker changed")) self.mArrow.setMarkerMode(QgsComposerArrow.DefaultMarker) self.mArrow.update() self.mArrow.endCommand() def on_mNoMarkerRadioButton_toggled(self, toggled): if (self.mArrow and toggled): self.mArrow.beginCommand(QString("Arrow marker changed")) self.mArrow.setMarkerMode(QgsComposerArrow.NoMarker) self.mArrow.update() self.mArrow.endCommand() def on_mSvgMarkerRadioButton_toggled(self, toggled): self.enableSvgInputElements(toggled) if (self.mArrow and toggled): self.mArrow.beginCommand(QString("Arrow marker changed")) self.mArrow.setMarkerMode(QgsComposerArrow.SVGMarker) self.mArrow.update() self.mArrow.endCommand() def on_mStartMarkerLineEdit_textChanged(self, text): if (self.mArrow): self.mArrow.beginCommand(QString("Arrow start marker")) fi = QFileInfo(text) if (fi.exists() and fi.isFile()): self.mArrow.setStartMarker(text) else: self.mArrow.setStartMarker("") self.mArrow.update() self.mArrow.endCommand() def on_mEndMarkerLineEdit_textChanged(self, text): if (self.mArrow): self.mArrow.beginCommand(QString("Arrow end marker")) fi = QFileInfo(text) if (fi.exists() and fi.isFile()): self.mArrow.setEndMarker(text) else: self.mArrow.setEndMarker("") self.mArrow.update() self.mArrow.endCommand() def on_mStartMarkerToolButton_clicked(self): if self.timeStart != 0: self.timeEnd = time.time() print self.timeEnd if self.timeEnd - self.timeStart <= 2: self.timeStart = 0 return s = QSettings() openDir = QString() if (not self.mStartMarkerLineEdit.text().isEmpty()): fi = QFileInfo(self.mStartMarkerLineEdit.text()) openDir = fi.dir().absolutePath() if (openDir.isEmpty()): openDir = s.value("/UI/lastComposerMarkerDir", QDir.homePath()).toString() svgFileName = QFileDialog.getOpenFileName( self, QString("Start marker svg file"), openDir) if (not svgFileName.isNull()): fileInfo = QFileInfo(svgFileName) s.setValue("/UI/lastComposerMarkerDir", fileInfo.absolutePath()) self.mArrow.beginCommand(QString("Arrow start marker")) self.mStartMarkerLineEdit.setText(svgFileName) self.mArrow.endCommand() self.timeStart = time.time() def on_mEndMarkerToolButton_clicked(self): if self.timeStart != 0: self.timeEnd = time.time() print self.timeEnd if self.timeEnd - self.timeStart <= 2: self.timeStart = 0 return s = QSettings() openDir = QString() if (not self.mEndMarkerLineEdit.text().isEmpty()): fi = QFileInfo(self.mEndMarkerLineEdit.text()) openDir = fi.dir().absolutePath() if (openDir.isEmpty()): openDir = s.value("/UI/lastComposerMarkerDir", QDir.homePath()).toString() svgFileName = QFileDialog.getOpenFileName( self, QString("End marker svg file"), openDir) if (not svgFileName.isNull()): fileInfo = QFileInfo(svgFileName) s.setValue("/UI/lastComposerMarkerDir", fileInfo.absolutePath()) self.mArrow.beginCommand(QString("Arrow end marker")) self.mEndMarkerLineEdit.setText(svgFileName) self.mArrow.endCommand() self.timeStart = time.time() def on_mLineStyleButton_clicked(self): if self.timeStart != 0: self.timeEnd = time.time() print self.timeEnd if self.timeEnd - self.timeStart <= 2: self.timeStart = 0 return if (not self.mArrow): return newSymbol = self.mArrow.lineSymbol().clone() d = QgsSymbolV2SelectorDialog(newSymbol, QgsStyleV2.defaultStyle(), None, self) d.setExpressionContext(self.mArrow.createExpressionContext()) if (d.exec_() == QDialog.Accepted): self.mArrow.beginCommand(QString("Arrow line style changed")) self.mArrow.setLineSymbol(newSymbol) self.updateLineSymbolMarker() self.mArrow.endCommand() self.mArrow.update() else: pass # delete newSymbol; self.timeStart = time.time() def updateLineSymbolMarker(self): if (not self.mArrow): return icon = QgsSymbolLayerV2Utils.symbolPreviewIcon( self.mArrow.lineSymbol(), self.mLineStyleButton.iconSize()) self.mLineStyleButton.setIcon(icon)
class TabBarWidget(QWidget): """ A tab bar widget using tool buttons as tabs. """ # TODO: A uniform size box layout. currentChanged = Signal(int) def __init__(self, parent=None, **kwargs): QWidget.__init__(self, parent, **kwargs) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.setLayout(layout) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__tabs = [] self.__currentIndex = -1 self.__changeOnHover = False self.__iconSize = QSize(26, 26) self.__group = QButtonGroup(self, exclusive=True) self.__group.buttonPressed[QAbstractButton].connect( self.__onButtonPressed ) self.setMouseTracking(True) self.__sloppyButton = None self.__sloppyRegion = QRegion() self.__sloppyTimer = QTimer(self, singleShot=True) self.__sloppyTimer.timeout.connect(self.__onSloppyTimeout) def setChangeOnHover(self, changeOnHover): """ If set to ``True`` the tab widget will change the current index when the mouse hovers over a tab button. """ if self.__changeOnHover != changeOnHover: self.__changeOnHover = changeOnHover def changeOnHover(self): """ Does the current tab index follow the mouse cursor. """ return self.__changeOnHover def count(self): """ Return the number of tabs in the widget. """ return len(self.__tabs) def addTab(self, text, icon=None, toolTip=None): """ Add a new tab and return it's index. """ return self.insertTab(self.count(), text, icon, toolTip) def insertTab(self, index, text, icon=None, toolTip=None): """ Insert a tab at `index` """ button = TabButton(self, objectName="tab-button") button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) button.setIconSize(self.__iconSize) button.setMouseTracking(True) self.__group.addButton(button) button.installEventFilter(self) tab = _Tab(text, icon, toolTip, button, None, None) self.layout().insertWidget(index, button) self.__tabs.insert(index, tab) self.__updateTab(index) if self.currentIndex() == -1: self.setCurrentIndex(0) return index def removeTab(self, index): """ Remove a tab at `index`. """ if index >= 0 and index < self.count(): self.layout().takeItem(index) tab = self.__tabs.pop(index) self.__group.removeButton(tab.button) tab.button.removeEventFilter(self) if tab.button is self.__sloppyButton: self.__sloppyButton = None self.__sloppyRegion = QRegion() tab.button.deleteLater() if self.currentIndex() == index: if self.count(): self.setCurrentIndex(max(index - 1, 0)) else: self.setCurrentIndex(-1) def setTabIcon(self, index, icon): """ Set the `icon` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(icon=icon) self.__updateTab(index) def setTabToolTip(self, index, toolTip): """ Set `toolTip` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(toolTip=toolTip) self.__updateTab(index) def setTabText(self, index, text): """ Set tab `text` for tab at `index` """ self.__tabs[index] = self.__tabs[index]._replace(text=text) self.__updateTab(index) def setTabPalette(self, index, palette): """ Set the tab button palette. """ self.__tabs[index] = self.__tabs[index]._replace(palette=palette) self.__updateTab(index) def setCurrentIndex(self, index): """ Set the current tab index. """ if self.__currentIndex != index: self.__currentIndex = index self.__sloppyRegion = QRegion() self.__sloppyButton = None if index != -1: self.__tabs[index].button.setChecked(True) self.currentChanged.emit(index) def currentIndex(self): """ Return the current index. """ return self.__currentIndex def button(self, index): """ Return the `TabButton` instance for index. """ return self.__tabs[index].button def setIconSize(self, size): if self.__iconSize != size: self.__iconSize = size for tab in self.__tabs: tab.button.setIconSize(self.__iconSize) def __updateTab(self, index): """ Update the tab button. """ tab = self.__tabs[index] b = tab.button if tab.text: b.setText(tab.text) if tab.icon is not None and not tab.icon.isNull(): b.setIcon(tab.icon) if tab.palette: b.setPalette(tab.palette) def __onButtonPressed(self, button): for i, tab in enumerate(self.__tabs): if tab.button is button: self.setCurrentIndex(i) break def __calcSloppyRegion(self, current): """ Given a current mouse cursor position return a region of the widget where hover/move events should change the current tab only on a timeout. """ p1 = current + QPoint(0, 2) p2 = current + QPoint(0, -2) p3 = self.pos() + QPoint(self.width()+10, 0) p4 = self.pos() + QPoint(self.width()+10, self.height()) return QRegion(QPolygon([p1, p2, p3, p4])) def __setSloppyButton(self, button): """ Set the current sloppy button (a tab button inside sloppy region) and reset the sloppy timeout. """ if not button.isChecked(): self.__sloppyButton = button delay = self.style().styleHint(QStyle.SH_Menu_SubMenuPopupDelay, None) # The delay timeout is the same as used by Qt in the QMenu. self.__sloppyTimer.start(delay) else: self.__sloppyTimer.stop() def __onSloppyTimeout(self): if self.__sloppyButton is not None: button = self.__sloppyButton self.__sloppyButton = None if not button.isChecked(): index = [tab.button for tab in self.__tabs].index(button) self.setCurrentIndex(index) def eventFilter(self, receiver, event): if event.type() == QEvent.MouseMove and \ isinstance(receiver, TabButton): pos = receiver.mapTo(self, event.pos()) if self.__sloppyRegion.contains(pos): self.__setSloppyButton(receiver) else: if not receiver.isChecked(): index = [tab.button for tab in self.__tabs].index(receiver) self.setCurrentIndex(index) #also update sloppy region if mouse is moved on the same icon self.__sloppyRegion = self.__calcSloppyRegion(pos) return QWidget.eventFilter(self, receiver, event) def leaveEvent(self, event): self.__sloppyButton = None self.__sloppyRegion = QRegion() return QWidget.leaveEvent(self, event)
class AddAccountDialog(base_class, ui_class): __metaclass__ = QSingleton implements(IObserver) def __init__(self, parent=None): super(AddAccountDialog, self).__init__(parent) with Resources.directory: self.setupUi(self) self.background_frame.setStyleSheet("") self.button_group = QButtonGroup(self) self.button_group.setObjectName("button_group") self.button_group.addButton(self.add_account_button, self.panel_view.indexOf(self.add_account_panel)) self.button_group.addButton(self.create_account_button, self.panel_view.indexOf(self.create_account_panel)) font = self.title_label.font() font.setPointSizeF(self.info_label.fontInfo().pointSizeF() + 3) font.setFamily("Sans Serif") self.title_label.setFont(font) font_metrics = self.create_status_label.fontMetrics() self.create_status_label.setMinimumHeight( font_metrics.height() + 2 * (font_metrics.height() + font_metrics.leading()) ) # reserve space for 3 lines font_metrics = self.email_note_label.fontMetrics() self.email_note_label.setMinimumWidth( font_metrics.width(u"The E-mail address is used when sending voicemail") ) # hack to make text justification look nice everywhere self.add_account_button.setChecked(True) self.panel_view.setCurrentWidget(self.add_account_panel) self.new_password_editor.textChanged.connect(self._SH_PasswordTextChanged) self.button_group.buttonClicked[int].connect(self._SH_PanelChangeRequest) self.accept_button.clicked.connect(self._SH_AcceptButtonClicked) self.display_name_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.name_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.username_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.sip_address_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.new_password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.verify_password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.email_address_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.display_name_editor.regexp = re.compile("^.*$") self.name_editor.regexp = re.compile("^.+$") self.username_editor.regexp = re.compile( "^\w(?<=[^0_])[\w.-]{4,31}(?<=[^_.-])$", re.IGNORECASE ) # in order to enable unicode characters add re.UNICODE to flags self.sip_address_editor.regexp = re.compile("^[^@\s]+@[^@\s]+$") self.password_editor.regexp = re.compile("^.*$") self.new_password_editor.regexp = re.compile("^.{8,}$") self.verify_password_editor.regexp = re.compile("^$") self.email_address_editor.regexp = re.compile("^[^@\s]+@[^@\s]+$") account_manager = AccountManager() notification_center = NotificationCenter() notification_center.add_observer(self, sender=account_manager) def _get_display_name(self): if self.panel_view.currentWidget() is self.add_account_panel: return unicode(self.display_name_editor.text()) else: return unicode(self.name_editor.text()) def _set_display_name(self, value): self.display_name_editor.setText(value) self.name_editor.setText(value) def _get_username(self): return unicode(self.username_editor.text()) def _set_username(self, value): self.username_editor.setText(value) def _get_sip_address(self): return unicode(self.sip_address_editor.text()) def _set_sip_address(self, value): self.sip_address_editor.setText(value) def _get_password(self): if self.panel_view.currentWidget() is self.add_account_panel: return unicode(self.password_editor.text()) else: return unicode(self.new_password_editor.text()) def _set_password(self, value): self.password_editor.setText(value) self.new_password_editor.setText(value) def _get_verify_password(self): return unicode(self.verify_password_editor.text()) def _set_verify_password(self, value): self.verify_password_editor.setText(value) def _get_email_address(self): return unicode(self.email_address_editor.text()) def _set_email_address(self, value): self.email_address_editor.setText(value) display_name = property(_get_display_name, _set_display_name) username = property(_get_username, _set_username) sip_address = property(_get_sip_address, _set_sip_address) password = property(_get_password, _set_password) verify_password = property(_get_verify_password, _set_verify_password) email_address = property(_get_email_address, _set_email_address) del _get_display_name, _set_display_name, _get_username, _set_username del _get_sip_address, _set_sip_address, _get_email_address, _set_email_address del _get_password, _set_password, _get_verify_password, _set_verify_password def _SH_AcceptButtonClicked(self): if self.panel_view.currentWidget() is self.add_account_panel: account = Account(self.sip_address) account.enabled = True account.display_name = self.display_name account.auth.password = self.password call_in_auxiliary_thread(account.save) account_manager = AccountManager() account_manager.default_account = account self.accept() else: self.setEnabled(False) self.create_status_label.value = Status("Creating account on server...") self._create_sip_account(self.username, self.password, self.email_address, self.display_name) def _SH_PanelChangeRequest(self, index): self.panel_view.setCurrentIndex(index) if self.panel_view.currentWidget() is self.add_account_panel: inputs = [self.display_name_editor, self.sip_address_editor, self.password_editor] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor, ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _SH_PasswordTextChanged(self, text): self.verify_password_editor.regexp = re.compile(u"^%s$" % re.escape(unicode(text))) def _SH_ValidityStatusChanged(self): red = "#cc0000" # validate the add panel if not self.display_name_editor.text_valid: self.add_status_label.value = Status("Display name cannot be empty", color=red) elif not self.sip_address_editor.text_correct: self.add_status_label.value = Status("SIP address should be specified as user@domain", color=red) elif not self.sip_address_editor.text_allowed: self.add_status_label.value = Status("An account with this SIP address was already added", color=red) elif not self.password_editor.text_valid: self.add_status_label.value = Status("Password cannot be empty", color=red) else: self.add_status_label.value = None # validate the create panel if not self.name_editor.text_valid: self.create_status_label.value = Status("Name cannot be empty", color=red) elif not self.username_editor.text_correct: self.create_status_label.value = Status( "Username should have 5 to 32 characters, start with a letter or non-zero digit, contain only letters, digits or .-_ and end with a letter or digit", color=red, ) elif not self.username_editor.text_allowed: self.create_status_label.value = Status( "The username you requested is already taken. Please choose another one and try again.", color=red ) elif not self.new_password_editor.text_valid: self.create_status_label.value = Status("Password should contain at least 8 characters", color=red) elif not self.verify_password_editor.text_valid: self.create_status_label.value = Status("Passwords do not match", color=red) elif not self.email_address_editor.text_valid: self.create_status_label.value = Status("E-mail address should be specified as user@domain", color=red) else: self.create_status_label.value = None # enable the accept button if everything is valid in the current panel if self.panel_view.currentWidget() is self.add_account_panel: inputs = [self.display_name_editor, self.sip_address_editor, self.password_editor] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor, ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _initialize(self): self.display_name = user_info.fullname self.username = user_info.username.lower().replace(" ", ".") self.sip_address = u"" self.password = u"" self.verify_password = u"" self.email_address = u"" @run_in_auxiliary_thread def _create_sip_account(self, username, password, email_address, display_name, timezone=None): red = "#cc0000" if timezone is None and sys.platform != "win32": try: timezone = open("/etc/timezone").read().strip() except (OSError, IOError): try: timezone = "/".join(os.readlink("/etc/localtime").split("/")[-2:]) except (OSError, IOError): pass enrollment_data = dict( username=username.lower().encode("utf-8"), password=password.encode("utf-8"), email=email_address.encode("utf-8"), display_name=display_name.encode("utf-8"), tzinfo=timezone, ) try: settings = SIPSimpleSettings() response = urllib2.urlopen(settings.server.enrollment_url, urllib.urlencode(dict(enrollment_data))) response_data = cjson.decode(response.read().replace(r"\/", "/")) response_data = defaultdict(lambda: None, response_data) if response_data["success"]: from blink import Blink try: certificate_path = None passport = response_data["passport"] if passport is not None: certificate_path = Blink().save_certificates( response_data["sip_address"], passport["crt"], passport["key"], passport["ca"] ) except (GNUTLSError, IOError, OSError): pass account_manager = AccountManager() try: account = Account(response_data["sip_address"]) except AccountExists: account = account_manager.get_account(response_data["sip_address"]) account.enabled = True account.display_name = display_name account.auth.password = password account.sip.outbound_proxy = response_data["outbound_proxy"] account.nat_traversal.msrp_relay = response_data["msrp_relay"] account.xcap.xcap_root = response_data["xcap_root"] account.tls.certificate = certificate_path account.server.settings_url = response_data["settings_url"] account.save() account_manager.default_account = account call_in_gui_thread(self.accept) elif response_data["error"] == "user_exists": call_in_gui_thread(self.username_editor.addException, username) else: call_in_gui_thread( setattr, self.create_status_label, "value", Status(response_data["error_message"], color=red) ) except (cjson.DecodeError, KeyError): call_in_gui_thread(setattr, self.create_status_label, "value", Status("Illegal server response", color=red)) except urllib2.URLError, e: call_in_gui_thread( setattr, self.create_status_label, "value", Status("Failed to contact server: %s" % e.reason, color=red) ) finally:
class QuestionDlg(QDialog): def __init__(self,parent=None): super(QuestionDlg,self).__init__(parent) # self.setStyleSheet("background-image:url('image/panelbg.jpg'); border: 2px; border-radius 2px;") self.setWindowFlags(Qt.CustomizeWindowHint) # self.setStyleSheet("border: 2px; border-radius 2px;") # self.setWindowFlags(Qt.FramelessWindowHint) tabWidget=QTabWidget(self) tabWidget.currentChanged.connect(self.changeTab) # tabWidget.setTabShape(QTabWidget.Triangular) tabWidget.setStyleSheet("QTabWidget::pane{border:0px;}\ QTabBar::tab { height: 60px; width: 260px; color:rgb(0, 0, 255); font-size:20px; font-weight:bold;} \ QTabBar::tab:hover{background:rgb(255,255, 255, 100);} \ QTabBar::tab:selected{border-color:green;background-color:white;color:green;}") # tabWidget.setStyleSheet("QTabBar::tab:hover{background:rgb(255,255, 255, 100);}") self.btngroup = QButtonGroup() w1=QWidget() w1.setAccessibleName("w1tab") self.w1title = QComboBox() self.btn_start = QPushButton("开始") self.choicenum_text = QComboBox() self.choicenum_text.setObjectName('w1combonums') # self.w1title.setStyleSheet("background-image:url('image/panelbg.jpg');") titleLayout, btnlayout, bottomlayout = self.genOneTab(tabtitle = self.w1title, tabbtn=self.btn_start, tabnums=self.choicenum_text) tab1layout = QVBoxLayout() tab1layout.addLayout(titleLayout) tab1layout.addLayout(btnlayout) tab1layout.addLayout(bottomlayout) w1.setLayout(tab1layout) # w1.setStyleSheet("background-image: url(image/bg.gif);") w1.setStyleSheet("background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #228888);") # w1.setStyleSheet("border-image: url(image/bg2.gif);") # firstUi.setupUi(w1) w2=QWidget() w2.setAccessibleName("w2tab") self.w2title = QComboBox() self.btn_start2 = QPushButton("开始") self.choicenum_text2 = QComboBox() self.choicenum_text2.setObjectName('w2combonums') titleLayout2, btnlayout2, bottomlayout2 = self.genOneTab(tabtitle = self.w2title, tabbtn=self.btn_start2, tabnums=self.choicenum_text2, strwhere = "where studentsn like '04%' ") tab2layout = QVBoxLayout() tab2layout.addLayout(titleLayout2) tab2layout.addLayout(btnlayout2) tab2layout.addLayout(bottomlayout2) w2.setLayout(tab2layout) # w2.setStyleSheet("background-image: url(image/bg.gif);") w2.setStyleSheet("background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #228888);") tabWidget.addTab(w1,"三(3)班") tabWidget.addTab(w2,"三(4)班") tabWidget.resize(760,700) # print(tabWidget.parentWidget()) btnclose = QPushButton(self) btnclose.setText("╳") btnclose.setGeometry(735, 5, 20, 20) btnclose.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255)") btnclose.clicked.connect(self.close) btnMinimized = QPushButton(self) btnMinimized.setText("▁") btnMinimized.setGeometry(710, 5, 20, 20) btnMinimized.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255)") btnMinimized.clicked.connect(lambda: self.showMinimized()) btnSysMenu = QPushButton(self) btnSysMenu.setText("▼") btnSysMenu.setGeometry(685, 5, 20, 20) btnSysMenu.setStyleSheet("background-color:rgb(0,100,0); color:rgb(255,255,255)") btnSysMenu.clicked.connect(lambda: self.showMinimized()) popMenu = QMenu(self) entry1 = popMenu.addAction("初始化") self.connect(entry1,SIGNAL('triggered()'), self.initStudent) entry2 = popMenu.addAction("清除提问人员") self.connect(entry2,SIGNAL('triggered()'), self.deleteTmpdata) btnSysMenu.setMenu(popMenu) btnSysMenu.setStyleSheet("QPushButton::menu-indicator {image: url('image/sysmenu.png');subcontrol-position: right center;}") self.lstchoices = [] self.threadcounter = 0 # self.createDb() cur = conn.cursor() # today = datetime.date.today() # cur.execute("delete from tmprecord where datequestion= '" +str(today) + "'") #delete tmp date no today cur.execute("delete from tmprecord where 1=1" ) # cur.execute("delete from tmprecord where datequestion!= '" +str(today) + "'") #delete tmp date no today conn.commit() cur.execute("select studentsn from student ") self.studentSnlst = cur.fetchall() cur.close() # self.btncolor = self.btngroup.buttons()[0].palette().color(1).getRgb() # for i in list(range(0, self.studentNums)): # for isn in self.studentSnlst: # self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png);") # print(isn) # for i in list(range(0, self.studentNums)): # self.btngroup.buttons()[i].setStyleSheet("background-color: rgb(120,220,220);") # self.btngroup.buttons()[i].setStyleSheet("border-image: url(image/ex_stu.png);") # self.btngroup.buttons()[i].setStyleSheet("background-image: url(image/ex_stu.png);background-size:20px 20px;") # print("background-color: rgb(120,220,220);", "background-color: rgb" + str(self.btncolor) + ";") self.setWindowTitle("课堂随机提问") self.setWindowIcon(QIcon("image/start.ico")) self.setGeometry(100, 20, 760, 700) self.connect(self.btn_start, SIGNAL("clicked()"), self.startChoice) self.connect(self.w1title, SIGNAL("currentIndexChanged(int)"), self.changeTitle) self.connect(self.btn_start2, SIGNAL("clicked()"), self.startChoice) self.connect(self.w2title, SIGNAL("currentIndexChanged(int)"), self.changeTitle) def initStudent(self): cur = conn.cursor() cur.execute("update student set wrongquestions=0") conn.commit() cur.execute("update student set rightquestions=0") conn.commit() # cur.execute("select * from student") # print(cur.fetchall()) cur.close() def deleteTmpdata(self): cur = conn.cursor() cur.execute("delete from tmprecord where 1=1" ) conn.commit() cur.close() def changeTab(self, curtab): if curtab == 0: strwhere = " and studentsn like '03%' " elif curtab == 1: strwhere = " and studentsn like '04%' " self.lstchoices = [] self.threadcounter = 0 cur = conn.cursor() cur.execute("select studentsn from student where 1=1 " + strwhere) self.studentSnlst = cur.fetchall() for isn in self.studentSnlst: self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png); color:dark;") self.btngroup.button(int(isn[0])).setIcon(QIcon()) # self.btngroup.buttons()[i].setStyleSheet("background-color: rgb(120,220,220);") # self.btngroup.buttons()[i].setStyleSheet("border-image: url(image/ex_stu.png);") curmenu = self.btngroup.button(int(isn[0])).menu() curmenu.actions()[0].setEnabled(True) curmenu.actions()[1].setEnabled(True) cur.close() def mousePressEvent(self, event): self.offset = event.pos() # print(self.offset) def mouseMoveEvent(self, event): x=event.globalX() y=event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x-x_w, y-y_w) def genOneTab(self, tabtitle="", tabbtn="", tabnums="", strwhere = "where studentsn like '03%' "): # tabtitle.setFixedHeight(40) # tabtitle.setFixedWidth(160) tabtitle.setFont(QFont('Courier New', 20)) tabtitle.setStyleSheet("border: 3px solid blue;\ border-radius: 6px; \ padding: 1px 18px 1px 20px;\ min-width: 8em;") model = tabtitle.model() for row in ["随堂演板", "随堂提问"]: item = QStandardItem(str(row)) item.setForeground(QColor('blue')) item.setBackground(QColor(0,200,50, 130)) font = item.font() font.setPointSize(20) item.setFont(font) model.appendRow(item) tabtitle.setCurrentIndex(0) titleLayout = QHBoxLayout() tabtitle.setMinimumHeight(50); titleLayout.addWidget(tabtitle) titleLayout.setAlignment(tabtitle, Qt.AlignCenter) btnlayout = QGridLayout() cur = conn.cursor() strsql = "select studentsn, studentname from student " + strwhere cur.execute(strsql) tmpnum = 0 for item in cur.fetchall(): irow = tmpnum // 7 icol = tmpnum % 7 tmpnum += 1 btnlayout.setRowMinimumHeight(irow, 80) tmpbtn = QPushButton(item[1]) tmpbtn.setFont(QFont('宋体', 16)) tmpbtn.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)) popMenu = QMenu(self) entry1 = popMenu.addAction("正确") self.connect(entry1,SIGNAL('triggered()'), lambda item=item[0]: self.answerRight(item)) entry2 = popMenu.addAction("错误") self.connect(entry2,SIGNAL('triggered()'), lambda item=item[0]: self.answerWrong(item)) entry3 = popMenu.addAction("替换") self.connect(entry3,SIGNAL('triggered()'), lambda item=item[0]: self.resetStudent(item)) tmpbtn.setMenu(popMenu) tmpbtn.setAutoDefault(False) self.btngroup.addButton(tmpbtn, int(item[0])) btnlayout.addWidget(tmpbtn, irow, icol) tabbtn.setIcon(QIcon("image/start.png")) tabbtn.setStyleSheet("border: 5px solid yellow;") tabbtn.setFixedHeight(45) tabbtn.setFixedWidth(100) tabbtn.setFont(QFont('宋体', 20)) # tabnums.setFixedHeight(40) # tabnums.setFixedWidth(60) tabnums.setFont(QFont('Courier New', 20)) tabnums.setStyleSheet("border: 5px solid blue; color:red;font-weight:bold;font-size:26px;\ border-radius: 6px; \ padding: 1px 1px 1px 1px;\ min-width: 2em; ") # tabnums.VerticalContentAlignment="Center" # tabnums.addItems(["1", "2", "3", "4", "5", "6"]) model = tabnums.model() for row in list(range(1, 7)): item = QStandardItem(str(row)) # item.setStyleSheet("background-color:rgb(0,0,255)") item.setForeground(QColor('red')) item.setBackground(QColor(0,200,50, 130)) # font = item.font() # font.setPointSize(16) # item.setFont(font) model.appendRow(item) tabnums.setCurrentIndex(2) bottomlayout = QHBoxLayout() bottomlayout.setSizeConstraint(QLayout.SetFixedSize) bottomlayout.addStretch(10) bottomlayout.addWidget(tabbtn) bottomlayout.setSpacing(5) bottomlayout.addWidget(tabnums) cur.close() return(titleLayout, btnlayout, bottomlayout) def changeTitle(self, curindex): # whichtabpage = self.sender().parentWidget().parentWidget().parentWidget() # print(whichtabpage.tabText(0), whichtabpage1) for isn in self.studentSnlst: self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png);") self.btngroup.button(int(isn[0])).setIcon(QIcon()) # self.btngroup.buttons()[i].setStyleSheet("background-color: rgb(120,220,220);") # self.btngroup.buttons()[i].setStyleSheet("border-image: url(image/ex_stu.png);") curmenu = self.btngroup.button(int(isn[0])).menu() curmenu.actions()[0].setEnabled(True) curmenu.actions()[1].setEnabled(True) whichtabpage = self.sender().parentWidget().accessibleName() if whichtabpage == "w1tab": if curindex == 1: self.choicenum_text.setCurrentIndex(0) self.choicenum_text.setEnabled(False) else: self.choicenum_text.setEnabled(True) self.choicenum_text.setCurrentIndex(2) else: if curindex == 1: self.choicenum_text2.setCurrentIndex(0) self.choicenum_text2.setEnabled(False) else: self.choicenum_text2.setEnabled(True) self.choicenum_text2.setCurrentIndex(2) def startChoice(self): self.lstchoices = [] self.threadcounter = 0 whichtabpage = self.sender().parentWidget().accessibleName() if whichtabpage == "w1tab": strwhere = " and studentsn like '03%' " tabCombonums = self.findChild(QComboBox, 'w1combonums') else: strwhere = " and studentsn like '04%' " tabCombonums = self.findChild(QComboBox, 'w2combonums') # for i in list(range(0, self.studentNums)): cur = conn.cursor() # cur.execute("select studentsn from student where 1=1 " + strwhere) # self.studentSnlst = cur.fetchall() # for isn in self.studentSnlst: # self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png);") # self.btngroup.button(int(isn[0])).setIcon(QIcon()) # # self.btngroup.buttons()[i].setStyleSheet("background-color: rgb(120,220,220);") # # self.btngroup.buttons()[i].setStyleSheet("border-image: url(image/ex_stu.png);") # curmenu = self.btngroup.button(int(isn[0])).menu() # curmenu.actions()[0].setEnabled(True) # curmenu.actions()[1].setEnabled(True) allstudent = [] lstrecord = ['0000', '1111'] if tabCombonums.isEnabled(): cur.execute("select studentsn from tmprecord where 1=1 " + strwhere) for item in cur.fetchall(): lstrecord.append(item[0]) # print(lstrecord, 'record', "select studentsn from student where studentsn like '03%' and studentsn not in " + str(tuple(lstrecord))) cur.execute("select studentsn from student where studentsn not in " + str(tuple(lstrecord)) + strwhere) for item in cur.fetchall(): allstudent.append(item[0]) nums = int(tabCombonums.currentText()) if nums >= len(allstudent): cur.execute("delete from tmprecord where datequestion like '%%' ") #delete tmp date no today conn.commit() allstudent = [] cur.execute("select studentsn from student where 1=1 " + strwhere) for item in cur.fetchall(): allstudent.append(item[0]) # print(tabCombonums.currentText()) cur.close() for i in range(10): thread = MyThread(self) thread.trigger.connect(self.choicestudent) thread.setup(allstudent, nums) # just setting up a parameter thread.start() def choicestudent(self, allstudent, num): for isn in self.studentSnlst: self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png);") # self.btngroup.buttons()[i].setStyleSheet("background-color: rgb(120,220,220);") random.seed() self.lstchoices = random.sample(allstudent, num) for ibtn in self.lstchoices: self.btngroup.button(int(ibtn)).setStyleSheet("border: 6px solid rgb(255,0,0); color:black; font-size:26px;") # self.btngroup.button(int(ibtn)).setStyleSheet("border-image: url(image/ex_stu_ok.png); color:dark;") # self.btngroup.button(int(ibtn)).setStyleSheet("background-color: red; color:white;") # self.btngroup.buttons()[ibtn].setStyleSheet("background-color: red; color:white;") self.threadcounter += 1 if self.threadcounter == 10: for isn in self.studentSnlst: self.btngroup.button(int(isn[0])).setStyleSheet("border-image: url(image/ex_stu.png);") for ibtn in self.lstchoices: self.btngroup.button(int(ibtn)).setStyleSheet("border: 6px solid rgb(255,0,0); color:black; font-size:26px;") cur = conn.cursor() if self.choicenum_text.isEnabled(): for ibtn in self.lstchoices: today = datetime.date.today() strsql = "insert into tmprecord values (?, ?, ?)" cur.execute(strsql, (None, ibtn, today)) conn.commit() # cur.execute("select * from tmprecord") # tmpaa = [] # for item in cur.fetchall(): # tmpaa.append(item[1]) # # print(item[1], sep="|", end="--") # tmpaa.sort() # print(tmpaa) cur.close() # print(self.btngroup.buttons()[ibtn].text()) self.threadcounter = 0 def choiceOneStudent(self, curbtn, num=1): # print(self.findChildren(QComboBox)) if curbtn[:2] == "03": strwhere = " and studentsn like '03%' " tabCombonums = self.findChild(QComboBox, 'w1combonums') elif curbtn[:2] == "04": strwhere = " and studentsn like '04%' " tabCombonums = self.findChild(QComboBox, 'w2combonums') allstudent = [] cur = conn.cursor() lstrecord = ['0000', '1111'] if tabCombonums.isEnabled(): cur.execute("select studentsn from tmprecord where 1=1 " + strwhere) for item in cur.fetchall(): lstrecord.append(item[0]) cur.execute("select studentsn from student where studentsn not in " + str(tuple(lstrecord)) + strwhere) for item in cur.fetchall(): allstudent.append(item[0]) # cur.execute("select * from tmprecord") # print(cur.fetchall(), '111111111111111111') random.seed() otherbtn = random.sample(allstudent, num)[0] # self.btngroup.button(int(otherbtn)).setStyleSheet("background-color: red; color:white;") # self.btngroup.button(int(otherbtn)).setStyleSheet("border-image: url(image/ex_stu_ok.png);") self.btngroup.button(int(otherbtn)).setStyleSheet("border: 6px solid rgb(255,0,0); color:black; font-size:26px;") self.btngroup.button(int(otherbtn)).setFocus() # print(self.lstchoices, 'choice one another00000000000000001') self.lstchoices.remove(curbtn) self.lstchoices.append(otherbtn) # print(self.lstchoices, 'choice one another000000000000000002') # cur.execute("delete from tmprecord where studentsn='" + curbtn + "'") # can not delete ,because this student is ill. # conn.commit() if tabCombonums.isEnabled(): today = datetime.date.today() cur.execute("insert into tmprecord values (?, ?, ?)", (None, otherbtn, today)) conn.commit() # cur.execute("select * from tmprecord") # print(cur.fetchall(), '2222222222222') cur.close() def answerRight(self, value): if value not in self.lstchoices: return self.btngroup.button(int(value)).setIcon(QIcon("image/smile.png")) self.btngroup.button(int(value)).setIconSize(QSize(20,20)) cur = conn.cursor() cur.execute("select rightquestions from student where studentsn='" + value + "'") studentRightQuestions = cur.fetchall()[0][0] + 1 cur.execute("update student set rightquestions=" + str(studentRightQuestions) + " where studentsn='" + value + "'") conn.commit() curmenu = self.btngroup.button(int(value)).menu() if not curmenu.actions()[1].isEnabled (): # must delete wrongquestionnums cur.execute("select wrongquestions from student where studentsn='" + value + "'") studentWrongQuestions = cur.fetchall()[0][0] - 1 cur.execute("update student set wrongquestions=" + str(studentWrongQuestions) + " where studentsn='" + value + "'") conn.commit() curmenu.actions()[0].setEnabled(False) curmenu.actions()[1].setEnabled(True) # curmenu.actions()[2].setEnabled(False) # cur.execute("select * from student where studentsn='" + value + "'") # print(cur.fetchall(), 'right-------') cur.close() def answerWrong(self, value): if value not in self.lstchoices: return self.btngroup.button(int(value)).setIcon(QIcon("image/cry.png")) self.btngroup.button(int(value)).setIconSize(QSize(20,20)) # self.btngroup.button(int(value)).setStyleSheet("border-image: url(image/ex_stu.png);") cur = conn.cursor() cur.execute("select wrongquestions from student where studentsn='" + value + "'") studentWrongQuestions = cur.fetchall()[0][0] + 1 cur.execute("update student set wrongquestions=" + str(studentWrongQuestions) + " where studentsn='" + value + "'") conn.commit() curmenu = self.btngroup.button(int(value)).menu() if not curmenu.actions()[0].isEnabled (): # must delete wrongquestionnums cur.execute("select rightquestions from student where studentsn='" + value + "'") studentRightQuestions = cur.fetchall()[0][0] - 1 cur.execute("update student set rightquestions=" + str(studentRightQuestions) + " where studentsn='" + value + "'") conn.commit() curmenu.actions()[0].setEnabled(True) curmenu.actions()[1].setEnabled(False) # cur.execute("select * from student where studentsn='" + value + "'") # print(cur.fetchall(), 'wrong--') cur.close() def resetStudent(self, value): if value not in self.lstchoices: return # self.btngroup.button(int(value)).setStyleSheet("background-color: rgb(120,220,220);") self.btngroup.button(int(value)).setIcon(QIcon()) self.btngroup.button(int(value)).setStyleSheet("border-image: url(image/ex_stu.png);") self.btngroup.button(int(value)).setAutoDefault(False) cur = conn.cursor() curmenu = self.btngroup.button(int(value)).menu() if not curmenu.actions()[0].isEnabled(): cur.execute("select rightquestions from student where studentsn='" + value + "'") studentRightQuestions = cur.fetchall()[0][0] - 1 cur.execute("update student set rightquestions=" + str(studentRightQuestions) + " where studentsn='" + value + "'") conn.commit() if not curmenu.actions()[1].isEnabled(): cur.execute("select wrongquestions from student where studentsn='" + value + "'") studentWrongQuestions = cur.fetchall()[0][0] - 1 cur.execute("update student set wrongquestions=" + str(studentWrongQuestions) + " where studentsn='" + value + "'") conn.commit() cur.close() curmenu.actions()[0].setEnabled(True) curmenu.actions()[1].setEnabled(True) self.choiceOneStudent(value) def createDb(self): cur = conn.cursor() sqlstr = 'create table student (id integer primary key, \ studentsn varchar(20), \ studentname varchar(20), \ rightquestions integer, \ wrongquestions integer)' # print(sqlstr) sqlstr2 = 'create table tmprecord (id integer primary key, \ studentsn varchar(20), \ datequestion date)' strdelete = "delete from student where 1=1" cur.execute(strdelete) conn.commit() strdelete = "delete from tmprecord where 1=1" cur.execute(strdelete) conn.commit() # print(sqlstr2) # cur.execute(sqlstr) # conn.commit() # cur.execute(sqlstr2) # conn.commit() # insert example data a03lst = ["曾忆谊","赵佳泉","翁文秀","林珑","郑铭洁","林泽思","吴崇霖","陈思嘉","欧阳月孜","郭展羽","詹伟哲","黄佳仪","杨秋霞","周奕子","林楚杰","欧伊涵","许腾誉","陈唯凯","陈树凯","林彦君","张钰佳","高锴","杨博凯","林妙菲","林楚鸿","陈展烯","姚静茵","吴欣桐","范思杰","肖佳","马思广","许一帆","姚奕帆","陈海珣","吴黛莹","吴育桐","肖凯帆","林欣阳","叶茂霖","姚楷臻","陈嘉豪","陈琦","杨子楷","陈炎宏","陈幸仪","杨景畅","罗暖婷","郑馨"] a04lst = ["罗恩琪","王可","曾祥威","谢濡婷","温嘉凯","许洁仪","肖欣淇","陈凯佳","林天倩","李乐海","吴文慧","黄文婷","万誉","陈进盛","张裕涵","陈振嘉","王巧玲","林珮琪","陈炜楷","杨健","赵泽锴","张凤临","蔡子丹","陈烨杰","廖妍希","林树超","夏培轩","陈锦森","李星","蔡依婷","姚容创","姚凯扬","沈嘉克","周凡","张玉川","邱金迅","陈菲敏","陈星翰","朱煜楷","郑泽洪","钱剑非","罗奕丰","陈杜炜","林知钦"] strsql = "insert into student values (?, ?, ?,?,?)" for i in list(range(0,len(a03lst))): cur.execute(strsql, (None, "03"+str(i+1).zfill(2), a03lst[i], 0, 0)) conn.commit() strsql = "insert into student values (?, ?, ?,?,?)" for i in list(range(0,len(a04lst))): cur.execute(strsql, (None, "04"+str(i+1).zfill(2), a04lst[i], 0, 0)) conn.commit() cur.close()
def create_rows(self, layout): u"""Build one row of the dialog box""" play_button_group = QButtonGroup(self) old_play_button_group = QButtonGroup(self) for num, (source, dest, text, dl_fname, dl_hash, extras, icon)\ in enumerate(self.list, 3): tt_text = self.build_text_help_label(text, source, extras) ico_label = QLabel('', self) ico_label.setToolTip(tt_text) if icon: ico_label.setPixmap(QPixmap.fromImage(icon)) layout.addWidget(ico_label, num, 0) tt_label = QLabel(text, self) tt_label.setToolTip(tt_text) layout.addWidget(tt_label, num, 1) if self.hide_text: tt_label.hide() # Play button. t_play_button = QPushButton(self) play_button_group.addButton(t_play_button, num - 3) t_play_button.setToolTip(self.play_help) t_play_button.setIcon(QIcon(os.path.join(icons_dir, 'play.png'))) layout.addWidget(t_play_button, num, self.play_column) if self.note[dest]: t_play_old_button = QPushButton(self) old_play_button_group.addButton(t_play_old_button, num - 3) t_play_old_button.setIcon( QIcon(os.path.join(icons_dir, 'play.png'))) if not self.hide_text: t_play_old_button.setToolTip(self.note[dest]) else: t_play_old_button.setToolTip(self.play_old_help_short) layout.addWidget(t_play_old_button, num, self.play_old_column) else: dummy_label = QLabel('', self) dummy_label.setToolTip(self.play_old_empty_line_help) layout.addWidget(dummy_label, num, self.play_old_column) # The group where we later look what to do: t_button_group = QButtonGroup(self) t_button_group.setExclusive(True) # Now the four buttons t_add_button = QPushButton(self) t_add_button.setCheckable(True) t_add_button.setChecked(True) t_add_button.setFlat(True) t_add_button.setToolTip(self.add_help_text_short) t_add_button.setIcon(QIcon(os.path.join(icons_dir, 'add.png'))) layout.addWidget(t_add_button, num, self.add_column) t_button_group.addButton(t_add_button, action['add']) t_keep_button = QPushButton(self) t_keep_button.setCheckable(True) t_keep_button.setFlat(True) t_keep_button.setToolTip(self.keep_help_text_short) t_keep_button.setIcon(QIcon(os.path.join(icons_dir, 'keep.png'))) layout.addWidget(t_keep_button, num, self.keep_column) t_button_group.addButton(t_keep_button, action['keep']) t_delete_button = QPushButton(self) t_delete_button.setCheckable(True) t_delete_button.setFlat(True) t_delete_button.setToolTip(self.delete_help_text_short) t_delete_button.setIcon( QIcon(os.path.join(icons_dir, 'delete.png'))) layout.addWidget(t_delete_button, num, self.delete_column) t_button_group.addButton(t_delete_button, action['delete']) t_blacklist_button = QPushButton(self) t_blacklist_button.setCheckable(True) t_blacklist_button.setFlat(True) t_blacklist_button.setToolTip(self.blacklist_help_text_short) t_blacklist_button.setIcon( QIcon(os.path.join(icons_dir, 'blacklist.png'))) if self.show_skull_and_bones: layout.addWidget(t_blacklist_button, num, self.blacklist_column) else: t_blacklist_button.hide() t_button_group.addButton(t_blacklist_button, action['blacklist']) self.buttons_groups.append(t_button_group) play_button_group.buttonClicked.connect( lambda button: play(self.list[play_button_group.id(button)][3])) old_play_button_group.buttonClicked.connect( lambda button: playFromText(self.note[self.list[ old_play_button_group.id(button)][1]]))