예제 #1
0
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
예제 #2
0
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)
        }
예제 #3
0
    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
예제 #4
0
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
            )
        }
예제 #5
0
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()
예제 #6
0
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
예제 #7
0
    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)
        )
예제 #8
0
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
예제 #9
0
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()
예제 #10
0
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
예제 #11
0
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)}
예제 #12
0
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)
        }
예제 #13
0
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()))
예제 #14
0
    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))
예제 #16
0
    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
예제 #17
0
 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)
예제 #18
0
 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)
예제 #19
0
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)
예제 #20
0
    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)
예제 #21
0
    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)
예제 #22
0
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)
예제 #23
0
    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)
예제 #24
0
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]
예제 #25
0
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)
예제 #26
0
파일: preferences.py 프로젝트: urkh/Turpial
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}
예제 #27
0
    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)
예제 #28
0
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()
예제 #29
0
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 )
예제 #30
0
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)
예제 #31
0
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)
예제 #32
0
    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")
예제 #33
0
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
예제 #34
0
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
예제 #35
0
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()
예제 #36
0
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
예제 #37
0
    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")
예제 #38
0
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()
예제 #39
0
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)
예제 #40
0
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())
예제 #41
0
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)
예제 #42
0
    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()
예제 #44
0
    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_()
예제 #45
0
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
예제 #46
0
 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]))
예제 #47
0
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
예제 #48
0
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)
예제 #50
0
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)
예제 #51
0
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
예제 #52
0
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)
예제 #55
0
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:
예제 #56
0
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()
예제 #57
0
 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]]))