コード例 #1
0
ファイル: montagedialog.py プロジェクト: stralu/mnelab
class MontageDialog(QDialog):
    def __init__(self, parent, montages, selected=None):
        super().__init__(parent)
        self.setWindowTitle("Set montage")
        vbox = QVBoxLayout(self)
        self.montages = QListWidget()
        self.montages.insertItems(0, montages)
        self.montages.setSelectionMode(QListWidget.SingleSelection)
        if selected is not None:
            for i in range(self.montages.count()):
                if self.montages.item(i).data(0) == selected:
                    self.montages.item(i).setSelected(True)
        vbox.addWidget(self.montages)
        hbox = QHBoxLayout()
        self.view_button = QPushButton("View")
        self.view_button.clicked.connect(self.view_montage)
        hbox.addWidget(self.view_button)
        hbox.addStretch()
        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        hbox.addWidget(self.buttonbox)
        vbox.addLayout(hbox)
        self.buttonbox.accepted.connect(self.accept)
        self.buttonbox.rejected.connect(self.reject)
        self.montages.itemSelectionChanged.connect(self.toggle_buttons)
        self.toggle_buttons()  # initialize OK and View buttons state

    @Slot()
    def toggle_buttons(self):
        """Toggle OK and View buttons.
        """
        if self.montages.selectedItems():
            self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(True)
            self.view_button.setEnabled(True)
        else:
            self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(False)
            self.view_button.setEnabled(False)

    def view_montage(self):
        name = self.montages.selectedItems()[0].data(0)
        montage = make_standard_montage(name)
        fig = montage.plot(show_names=True, show=False)
        win = fig.canvas.manager.window
        win.setWindowModality(Qt.WindowModal)
        win.setWindowTitle("Montage")
        win.findChild(QStatusBar).hide()
        win.findChild(QToolBar).hide()
        fig.show()
コード例 #2
0
ファイル: configdialog.py プロジェクト: Joydeep75/spyder
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.main = parent

        # Widgets
        self.pages_widget = QStackedWidget()
        self.pages_widget.setMinimumWidth(600)
        self.contents_widget = QListWidget()
        self.button_reset = QPushButton(_('Reset to defaults'))

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply
                                | QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)

        # Widgets setup
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
        self.setWindowTitle(_('Preferences'))
        self.setWindowIcon(ima.icon('configure'))
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setSpacing(1)
        self.contents_widget.setCurrentRow(0)
        self.contents_widget.setMinimumWidth(220)
        self.contents_widget.setMinimumHeight(400)

        # Layout
        hsplitter = QSplitter()
        hsplitter.addWidget(self.contents_widget)
        hsplitter.addWidget(self.pages_widget)
        hsplitter.setStretchFactor(0, 1)
        hsplitter.setStretchFactor(1, 2)

        btnlayout = QHBoxLayout()
        btnlayout.addWidget(self.button_reset)
        btnlayout.addStretch(1)
        btnlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(hsplitter)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

        # Signals and slots
        if self.main:
            self.button_reset.clicked.connect(self.main.reset_spyder)
        self.pages_widget.currentChanged.connect(self.current_page_changed)
        self.contents_widget.currentRowChanged.connect(
            self.pages_widget.setCurrentIndex)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        bbox.clicked.connect(self.button_clicked)

        # Ensures that the config is present on spyder first run
        CONF.set('main', 'interface_language', load_lang_conf())
コード例 #3
0
ファイル: personalbests.py プロジェクト: keziah55/cycleTracks
class NewPBDialog(TimerDialog):
    """ Dialog showing a message congratulating the user on a new PB.
    
        The dialog has an 'Ok' button, but will also timeout after a few milliseconds.
        
        Parameters
        ----------
        timeout : int
            Number of milliseconds for the dialog to be shown. Default is 3000.
    """
    def __init__(self, timeout=3000):
        super().__init__(timeout=timeout)

        self.label = QLabel()
        font = self.label.font()
        font.setPointSize(14)
        self.label.setFont(font)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
        self.okButton = self.buttonBox.button(QDialogButtonBox.Ok)
        self.okButton.clicked.connect(self.accept)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.buttonBox)
        self.setLayout(self.layout)
        self.setWindowTitle("New personal best")

    def setMessage(self, text):
        self.label.setText(text)
コード例 #4
0
ファイル: configdialog.py プロジェクト: impact27/spyder
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.main = parent

        # Widgets
        self.pages_widget = QStackedWidget()
        self.pages_widget.setMinimumWidth(600)
        self.contents_widget = QListWidget()
        self.button_reset = QPushButton(_('Reset to defaults'))

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply |
                                QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)

        # Widgets setup
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle(_('Preferences'))
        self.setWindowIcon(ima.icon('configure'))
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setSpacing(1)
        self.contents_widget.setCurrentRow(0)
        self.contents_widget.setMinimumWidth(220)
        self.contents_widget.setMinimumHeight(400)

        # Layout
        hsplitter = QSplitter()
        hsplitter.addWidget(self.contents_widget)
        hsplitter.addWidget(self.pages_widget)
        hsplitter.setStretchFactor(0, 1)
        hsplitter.setStretchFactor(1, 2)

        btnlayout = QHBoxLayout()
        btnlayout.addWidget(self.button_reset)
        btnlayout.addStretch(1)
        btnlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(hsplitter)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

        # Signals and slots
        if self.main:
            self.button_reset.clicked.connect(self.main.reset_spyder)
        self.pages_widget.currentChanged.connect(self.current_page_changed)
        self.contents_widget.currentRowChanged.connect(
                                             self.pages_widget.setCurrentIndex)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        bbox.clicked.connect(self.button_clicked)

        # Ensures that the config is present on spyder first run
        CONF.set('main', 'interface_language', load_lang_conf())
コード例 #5
0
ファイル: entities.py プロジェクト: s40723103/Pyslvs-UI
    def __init__(self, parent: MainWindowBase):
        super(_ScaleDialog, self).__init__(parent)
        self.setWindowTitle("Scale Mechanism")
        self.main_layout = QVBoxLayout(self)
        self.enlarge = QDoubleSpinBox(self)
        self.shrink = QDoubleSpinBox(self)
        self.__add_option("Enlarge", self.enlarge)
        self.__add_option("Shrink", self.shrink)

        button_box = QDialogButtonBox(self)
        button_box.setStandardButtons(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        button_box.button(QDialogButtonBox.Ok).setEnabled(
            bool(parent.vpoint_list))
        self.main_layout.addWidget(button_box)
コード例 #6
0
ファイル: dialogs.py プロジェクト: ezcad-dev/ezcad
    def __init__(self, parent=None, objname=None):
        QDialog.__init__(self, parent)

        # If used for data object in tree, the main is the tree widget.
        self.parent = parent
        self.objname = objname

        # Widgets
        self.pages_widget = QStackedWidget()
        self.contents_widget = QListWidget()
        self.button_reset = QPushButton(_('Reset to defaults'))

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply |
                                QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)

        # Widgets setup
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Ezcad), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        if self.objname is None:
            self.setWindowTitle(_('Preferences'))
        else:
            self.setWindowTitle(_('Preferences of ') + self.objname)
        self.setWindowIcon(ima.icon('configure'))
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setSpacing(1)
        self.contents_widget.setCurrentRow(0)

        # Layout
        hsplitter = QSplitter()
        hsplitter.addWidget(self.contents_widget)
        hsplitter.addWidget(self.pages_widget)
        hsplitter.setSizes([150,500])

        btnlayout = QHBoxLayout()
        btnlayout.addWidget(self.button_reset)
        btnlayout.addStretch(1)
        btnlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(hsplitter)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

        # Signals and slots
        self.pages_widget.currentChanged.connect(self.current_page_changed)
        self.contents_widget.currentRowChanged.connect(
            self.pages_widget.setCurrentIndex)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        bbox.clicked.connect(self.button_clicked)

        # Ensures that the config is present on ezcad first run
        CONF.set('main', 'interface_language', load_lang_conf())
コード例 #7
0
    def __init__(
        self,
        title="Title",
        description="Description",
        unique_names=None,
        choose_from_list=False,
    ):
        QDialog.__init__(self)
        self.setModal(True)
        self.setWindowTitle(title)
        # self.setMinimumWidth(250)
        # self.setMinimumHeight(150)

        if unique_names is None:
            unique_names = []

        self.unique_names = unique_names
        self.choose_from_list = choose_from_list

        self.layout = QFormLayout()
        self.layout.setSizeConstraint(QLayout.SetFixedSize)

        label = QLabel(description)
        label.setAlignment(Qt.AlignHCenter)

        self.layout.addRow(self.createSpace(5))
        self.layout.addRow(label)
        self.layout.addRow(self.createSpace(10))

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.ok_button = buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)

        if choose_from_list:
            self.param_name_combo = QComboBox()
            self.param_name.currentIndexChanged.connect(self.validateChoice)
            for item in unique_names:
                self.param_name_combo.addItem(item)
            self.layout.addRow("Job:", self.param_name_combo)
        else:
            self.param_name = QLineEdit(self)
            self.param_name.setFocus()
            self.param_name.textChanged.connect(self.validateName)
            self.validColor = self.param_name.palette().color(
                self.param_name.backgroundRole())

            self.layout.addRow("Name:", self.param_name)

        self.layout.addRow(self.createSpace(10))

        self.layout.addRow(buttons)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        self.setLayout(self.layout)
コード例 #8
0
ファイル: layoutdialog.py プロジェクト: 0xBADCA7/spyder
class LayoutSaveDialog(QDialog):
    """ """
    def __init__(self, parent, order):
        super(LayoutSaveDialog, self).__init__(parent)

        # variables
        self._parent = parent

        # widgets
        self.combo_box = QComboBox(self)
        self.combo_box.addItems(order)
        self.combo_box.setEditable(True)
        self.combo_box.clearEditText()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
                                           QDialogButtonBox.Cancel,
                                           Qt.Horizontal, self)
        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
        self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel)

        # widget setup
        self.button_ok.setEnabled(False)
        self.dialog_size = QSize(300, 100)
        self.setWindowTitle('Save layout as')
        self.setModal(True)
        self.setMinimumSize(self.dialog_size)
        self.setFixedSize(self.dialog_size)

        # layouts
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.combo_box)
        self.layout.addWidget(self.button_box)
        self.setLayout(self.layout)

        # signals and slots
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.close)
        self.combo_box.editTextChanged.connect(self.check_text)

    def check_text(self, text):
        """Disable empty layout name possibility"""
        if to_text_string(text) == u'':
            self.button_ok.setEnabled(False)
        else:
            self.button_ok.setEnabled(True)
コード例 #9
0
class LayoutSaveDialog(QDialog):
    """ """
    def __init__(self, parent, order):
        super(LayoutSaveDialog, self).__init__(parent)

        # variables
        self._parent = parent

        # widgets
        self.combo_box = QComboBox(self)
        self.combo_box.addItems(order)
        self.combo_box.setEditable(True)
        self.combo_box.clearEditText()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
                                           QDialogButtonBox.Cancel,
                                           Qt.Horizontal, self)
        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
        self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel)

        # widget setup
        self.button_ok.setEnabled(False)
        self.dialog_size = QSize(300, 100)
        self.setWindowTitle('Save layout as')
        self.setModal(True)
        self.setMinimumSize(self.dialog_size)
        self.setFixedSize(self.dialog_size)

        # layouts
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.combo_box)
        self.layout.addWidget(self.button_box)
        self.setLayout(self.layout)

        # signals and slots
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.close)
        self.combo_box.editTextChanged.connect(self.check_text)

    def check_text(self, text):
        """Disable empty layout name possibility"""
        if to_text_string(text) == u'':
            self.button_ok.setEnabled(False)
        else:
            self.button_ok.setEnabled(True)
コード例 #10
0
ファイル: newconfig.py プロジェクト: tayloris/ert
    def __init__(self, configuration_path, parent=None):
        QDialog.__init__(self, parent)

        self.setModal(True)
        self.setWindowTitle("New configuration file")
        self.setMinimumWidth(250)
        self.setMinimumHeight(150)

        layout = QFormLayout()

        directory, filename = os.path.split(configuration_path)

        if directory.strip() == "":
            directory = os.path.abspath(os.curdir)
            self.configuration_path = "%s/%s" % (directory, filename)
        else:
            self.configuration_path = configuration_path

        configuration_location = QLabel()
        configuration_location.setText(directory)

        configuration_name = QLabel()
        configuration_name.setText(filename)

        self.db_type = QComboBox()
        self.db_type.addItem("BLOCK_FS")
        self.db_type.addItem("PLAIN")

        self.num_realizations = QSpinBox()
        self.num_realizations.setMinimum(1)
        self.num_realizations.setMaximum(1000)
        self.num_realizations.setValue(10)

        self.storage_path = QLineEdit()
        self.storage_path.setText("Storage")
        self.storage_path.textChanged.connect(self._validateName)

        layout.addRow(createSpace(10))
        layout.addRow("Configuration name:", configuration_name)
        layout.addRow("Configuration location:", configuration_location)
        layout.addRow("Path to store DBase:", self.storage_path)
        layout.addRow("DBase type:", self.db_type)
        layout.addRow("Number of realizations", self.num_realizations)
        layout.addRow(createSpace(10))

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.ok_button = buttons.button(QDialogButtonBox.Ok)

        layout.addRow(buttons)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        self.setLayout(layout)
コード例 #11
0
    def __init__(self, editor):
        QDialog.__init__(self, editor, Qt.WindowTitleHint
                         | Qt.WindowCloseButtonHint)

        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.lineno = None
        self.editor = editor

        self.setWindowTitle(_("Editor"))
        self.setModal(True)

        label = QLabel(_("Go to line:"))
        self.lineedit = QLineEdit()
        validator = QIntValidator(self.lineedit)
        validator.setRange(1, editor.get_line_count())
        self.lineedit.setValidator(validator)
        self.lineedit.textChanged.connect(self.text_has_changed)
        cl_label = QLabel(_("Current line:"))
        cl_label_v = QLabel("<b>%d</b>" % editor.get_cursor_line_number())
        last_label = QLabel(_("Line count:"))
        last_label_v = QLabel("%d" % editor.get_line_count())

        glayout = QGridLayout()
        glayout.addWidget(label, 0, 0, Qt.AlignVCenter | Qt.AlignRight)
        glayout.addWidget(self.lineedit, 0, 1, Qt.AlignVCenter)
        glayout.addWidget(cl_label, 1, 0, Qt.AlignVCenter | Qt.AlignRight)
        glayout.addWidget(cl_label_v, 1, 1, Qt.AlignVCenter)
        glayout.addWidget(last_label, 2, 0, Qt.AlignVCenter | Qt.AlignRight)
        glayout.addWidget(last_label_v, 2, 1, Qt.AlignVCenter)

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
                                Qt.Vertical, self)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        btnlayout = QVBoxLayout()
        btnlayout.addWidget(bbox)
        btnlayout.addStretch(1)

        ok_button = bbox.button(QDialogButtonBox.Ok)
        ok_button.setEnabled(False)
        self.lineedit.textChanged.connect(
            lambda text: ok_button.setEnabled(len(text) > 0))

        layout = QHBoxLayout()
        layout.addLayout(glayout)
        layout.addLayout(btnlayout)
        self.setLayout(layout)

        self.lineedit.setFocus()
コード例 #12
0
ファイル: customdialog.py プロジェクト: tayloris/ert
    def addButtons(self):
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.ok_button = buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)

        self.layout.addRow(self.createSpace(10))
        self.layout.addRow(buttons)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
コード例 #13
0
    def install_button_layout(self):
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.button_list += [bbox.button(QDialogButtonBox.Ok)]

        self.button_layout = QHBoxLayout()
        self.button_layout.addStretch()
        self.button_layout.addWidget(bbox)

        vlayout = self.layout()
        vlayout.addSpacing(10)
        vlayout.addLayout(self.button_layout)
コード例 #14
0
    def __init__(
        self,
        title="Title",
        description="Description",
        unique_names=None,
    ):
        QDialog.__init__(self)
        self.setModal(True)
        self.setWindowTitle(title)

        if unique_names is None:
            unique_names = []

        self.unique_names = unique_names

        self.layout = QFormLayout()
        self.layout.setSizeConstraint(QLayout.SetFixedSize)

        label = QLabel(description)
        label.setAlignment(Qt.AlignHCenter)

        self.layout.addRow(self.createSpace(5))
        self.layout.addRow(label)
        self.layout.addRow(self.createSpace(10))

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self
        )
        self.ok_button = buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)

        self.param_name = QLineEdit(self)
        self.param_name.setFocus()
        self.param_name.textChanged.connect(self.validateName)
        self.validColor = self.param_name.palette().color(
            self.param_name.backgroundRole()
        )

        self.layout.addRow("Name:", self.param_name)

        self.layout.addRow(self.createSpace(10))

        self.layout.addRow(buttons)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        self.setLayout(self.layout)
コード例 #15
0
ファイル: confpage.py プロジェクト: asdlei99/spyder
class LSPServerEditor(QDialog):
    DEFAULT_HOST = '127.0.0.1'
    DEFAULT_PORT = 2084
    DEFAULT_CMD = ''
    DEFAULT_ARGS = ''
    DEFAULT_CONFIGURATION = '{}'
    DEFAULT_EXTERNAL = False
    DEFAULT_STDIO = False
    HOST_REGEX = re.compile(r'^\w+([.]\w+)*$')
    NON_EMPTY_REGEX = re.compile(r'^\S+$')
    JSON_VALID = _('Valid JSON')
    JSON_INVALID = _('Invalid JSON')
    MIN_SIZE = QSize(850, 600)
    INVALID_CSS = "QLineEdit {border: 1px solid red;}"
    VALID_CSS = "QLineEdit {border: 1px solid green;}"

    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, stdio=False,
                 configurations={}, **kwargs):
        super(LSPServerEditor, self).__init__(parent)

        description = _(
            "To create a new server configuration, you need to select a "
            "programming language, set the command to start its associated "
            "server and enter any arguments that should be passed to it on "
            "startup. Additionally, you can set the server's hostname and "
            "port if connecting to an external server, "
            "or to a local one using TCP instead of stdio pipes."
            "<br><br>"
            "<i>Note</i>: You can use the placeholders <tt>{host}</tt> and "
            "<tt>{port}</tt> in the server arguments field to automatically "
            "fill in the respective values.<br>"
        )
        self.parent = parent
        self.external = external

        # Widgets
        self.server_settings_description = QLabel(description)
        self.lang_cb = QComboBox(self)
        self.external_cb = QCheckBox(_('External server'), self)
        self.host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.cmd_label = QLabel(_('Command:'))
        self.cmd_input = QLineEdit(self)
        self.args_label = QLabel(_('Arguments:'))
        self.args_input = QLineEdit(self)
        self.json_label = QLabel(self.JSON_VALID, self)
        self.conf_label = QLabel(_('<b>Server Configuration:</b>'))
        self.conf_input = CodeEditor(None)

        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                     QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setMinimumSize(self.MIN_SIZE)
        self.setWindowTitle(_('LSP server editor'))

        self.server_settings_description.setWordWrap(True)

        self.lang_cb.setToolTip(
            _('Programming language provided by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        self.button_ok.setEnabled(False)
        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        self.host_input.setPlaceholderText('127.0.0.1')
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        self.cmd_input.setText(cmd)
        self.cmd_input.setPlaceholderText('/absolute/path/to/command')

        self.args_input.setToolTip(
            _('Additional arguments required to start the server'))
        self.args_input.setText(args)
        self.args_input.setPlaceholderText(r'--host {host} --port {port}')

        self.conf_input.setup_editor(
            language='json',
            color_scheme=CONF.get('appearance', 'selected'),
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json',
            folding=False
        )
        self.conf_input.set_language('json', 'config.json')
        self.conf_input.setToolTip(_('Additional LSP server configuration '
                                     'set at runtime. JSON required'))
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            conf_text = '{}'
        self.conf_input.set_text(conf_text)

        self.external_cb.setToolTip(
            _('Check if the server runs on a remote location'))
        self.external_cb.setChecked(external)

        self.stdio_cb = QCheckBox(_('Use stdio pipes for communication'), self)
        self.stdio_cb.setToolTip(_('Check if the server communicates '
                                   'using stdin/out pipes'))
        self.stdio_cb.setChecked(stdio)

        # Layout setup
        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(self.server_settings_description)

        vlayout = QVBoxLayout()

        lang_group = QGroupBox(_('Language'))
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(self.lang_cb)
        lang_group.setLayout(lang_layout)
        vlayout.addWidget(lang_group)

        server_group = QGroupBox(_('Language server'))
        server_layout = QGridLayout()
        server_layout.addWidget(self.cmd_label, 0, 0)
        server_layout.addWidget(self.cmd_input, 0, 1)
        server_layout.addWidget(self.args_label, 1, 0)
        server_layout.addWidget(self.args_input, 1, 1)
        server_group.setLayout(server_layout)
        vlayout.addWidget(server_group)

        address_group = QGroupBox(_('Server address'))
        host_layout = QVBoxLayout()
        host_layout.addWidget(self.host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(self.port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        address_group.setLayout(conn_info_layout)
        vlayout.addWidget(address_group)

        advanced_group = QGroupBox(_('Advanced'))
        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(self.external_cb)
        advanced_layout.addWidget(self.stdio_cb)
        advanced_group.setLayout(advanced_layout)
        vlayout.addWidget(advanced_group)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(self.conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        vlayout.addStretch()
        hlayout.addLayout(vlayout, 2)
        hlayout.addLayout(conf_layout, 3)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(self.bbox)
        self.setLayout(general_vlayout)
        self.form_status(False)

        # Signals
        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())
        self.external_cb.stateChanged.connect(self.set_local_options)
        self.stdio_cb.stateChanged.connect(self.set_stdio_options)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.conf_input.textChanged.connect(self.validate)
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Final setup
        if language is not None:
            self.form_status(True)
            self.validate()
            if stdio:
                self.set_stdio_options(True)
            if external:
                self.set_local_options(True)

    @Slot()
    def validate(self):
        host_text = self.host_input.text()
        cmd_text = self.cmd_input.text()

        if not self.HOST_REGEX.match(host_text):
            self.button_ok.setEnabled(False)
            self.host_input.setStyleSheet(self.INVALID_CSS)
            if bool(host_text):
                self.host_input.setToolTip(_('Hostname must be valid'))
            else:
                self.host_input.setToolTip(
                    _('Hostname or IP address of the host on which the server '
                      'is running. Must be non empty.'))
        else:
            self.host_input.setStyleSheet(self.VALID_CSS)
            self.host_input.setToolTip(_('Hostname is valid'))
            self.button_ok.setEnabled(True)

        if not self.external:
            if not self.NON_EMPTY_REGEX.match(cmd_text):
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(self.INVALID_CSS)
                self.cmd_input.setToolTip(
                    _('Command used to start the LSP server locally. Must be '
                      'non empty'))
                return

            if find_program(cmd_text) is None:
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(self.INVALID_CSS)
                self.cmd_input.setToolTip(_('Program was not found '
                                            'on your system'))
            else:
                self.cmd_input.setStyleSheet(self.VALID_CSS)
                self.cmd_input.setToolTip(_('Program was found on your '
                                            'system'))
                self.button_ok.setEnabled(True)

        try:
            json.loads(self.conf_input.toPlainText())
            try:
                self.json_label.setText(self.JSON_VALID)
            except Exception:
                pass
        except ValueError:
            try:
                self.json_label.setText(self.JSON_INVALID)
                self.button_ok.setEnabled(False)
            except Exception:
                pass

    def form_status(self, status):
        self.host_input.setEnabled(status)
        self.port_spinner.setEnabled(status)
        self.external_cb.setEnabled(status)
        self.stdio_cb.setEnabled(status)
        self.cmd_input.setEnabled(status)
        self.args_input.setEnabled(status)
        self.conf_input.setEnabled(status)
        self.json_label.setVisible(status)

    @Slot()
    def lang_selection_changed(self):
        idx = self.lang_cb.currentIndex()
        if idx == 0:
            self.set_defaults()
            self.form_status(False)
            self.button_ok.setEnabled(False)
        else:
            server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1])
            self.form_status(True)
            if server is not None:
                self.host_input.setText(server.host)
                self.port_spinner.setValue(server.port)
                self.external_cb.setChecked(server.external)
                self.stdio_cb.setChecked(server.stdio)
                self.cmd_input.setText(server.cmd)
                self.args_input.setText(server.args)
                self.conf_input.set_text(json.dumps(server.configurations))
                self.json_label.setText(self.JSON_VALID)
                self.button_ok.setEnabled(True)
            else:
                self.set_defaults()

    def set_defaults(self):
        self.cmd_input.setStyleSheet('')
        self.host_input.setStyleSheet('')
        self.host_input.setText(self.DEFAULT_HOST)
        self.port_spinner.setValue(self.DEFAULT_PORT)
        self.external_cb.setChecked(self.DEFAULT_EXTERNAL)
        self.stdio_cb.setChecked(self.DEFAULT_STDIO)
        self.cmd_input.setText(self.DEFAULT_CMD)
        self.args_input.setText(self.DEFAULT_ARGS)
        self.conf_input.set_text(self.DEFAULT_CONFIGURATION)
        self.json_label.setText(self.JSON_VALID)

    @Slot(bool)
    @Slot(int)
    def set_local_options(self, enabled):
        self.external = enabled
        self.cmd_input.setEnabled(True)
        self.args_input.setEnabled(True)
        if enabled:
            self.cmd_input.setEnabled(False)
            self.cmd_input.setStyleSheet('')
            self.args_input.setEnabled(False)
            self.stdio_cb.stateChanged.disconnect()
            self.stdio_cb.setChecked(False)
            self.stdio_cb.setEnabled(False)
        else:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.stdio_cb.setEnabled(True)
            self.stdio_cb.setChecked(False)
            self.stdio_cb.stateChanged.connect(self.set_stdio_options)
        try:
            self.validate()
        except Exception:
            pass

    @Slot(bool)
    @Slot(int)
    def set_stdio_options(self, enabled):
        self.stdio = enabled
        if enabled:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.external_cb.stateChanged.disconnect()
            self.external_cb.setChecked(False)
            self.external_cb.setEnabled(False)
            self.host_input.setStyleSheet('')
            self.host_input.setEnabled(False)
            self.port_spinner.setEnabled(False)
        else:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.external_cb.setChecked(False)
            self.external_cb.setEnabled(True)
            self.external_cb.stateChanged.connect(self.set_local_options)
            self.host_input.setEnabled(True)
            self.port_spinner.setEnabled(True)
        try:
            self.validate()
        except Exception:
            pass

    def get_options(self):
        language_idx = self.lang_cb.currentIndex()
        language = LSP_LANGUAGES[language_idx - 1]
        host = self.host_input.text()
        port = int(self.port_spinner.value())
        external = self.external_cb.isChecked()
        stdio = self.stdio_cb.isChecked()
        args = self.args_input.text()
        cmd = self.cmd_input.text()
        configurations = json.loads(self.conf_input.toPlainText())
        server = LSPServer(language=language.lower(), cmd=cmd, args=args,
                           host=host, port=port, external=external,
                           stdio=stdio, configurations=configurations)
        return server
コード例 #16
0
ファイル: shortcuts.py プロジェクト: ChunHungLiu/spyder
    def __init__(self, parent, context, name, sequence, shortcuts):
        super(ShortcutEditor, self).__init__(parent)
        self._parent = parent

        self.context = context
        self.npressed = 0
        self.keys = set()
        self.key_modifiers = set()
        self.key_non_modifiers = list()
        self.key_text = list()
        self.sequence = sequence
        self.new_sequence = None
        self.edit_state = True
        self.shortcuts = shortcuts

        # Widgets
        self.label_info = QLabel()
        self.label_info.setText(_("Press the new shortcut and select 'Ok': \n"
             "(Press 'Tab' once to switch focus between the shortcut entry \n"
             "and the buttons below it)"))
        self.label_current_sequence = QLabel(_("Current shortcut:"))
        self.text_current_sequence = QLabel(sequence)
        self.label_new_sequence = QLabel(_("New shortcut:"))
        self.text_new_sequence = CustomLineEdit(self)
        self.text_new_sequence.setPlaceholderText(sequence)
        self.helper_button = HelperToolButton()
        self.helper_button.hide()
        self.label_warning = QLabel()
        self.label_warning.hide()

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)

        # Setup widgets
        self.setWindowTitle(_('Shortcut: {0}').format(name))
        self.button_ok.setFocusPolicy(Qt.NoFocus)
        self.button_ok.setEnabled(False)
        self.button_cancel.setFocusPolicy(Qt.NoFocus)
        self.helper_button.setToolTip('')
        self.helper_button.setFocusPolicy(Qt.NoFocus)
        style = """
            QToolButton {
              margin:1px;
              border: 0px solid grey;
              padding:0px;
              border-radius: 0px;
            }"""
        self.helper_button.setStyleSheet(style)
        self.text_new_sequence.setFocusPolicy(Qt.NoFocus)
        self.label_warning.setFocusPolicy(Qt.NoFocus)

        # Layout
        spacing = 5
        layout_sequence = QGridLayout()
        layout_sequence.addWidget(self.label_info, 0, 0, 1, 3)
        layout_sequence.addItem(QSpacerItem(spacing, spacing), 1, 0, 1, 2)
        layout_sequence.addWidget(self.label_current_sequence, 2, 0)
        layout_sequence.addWidget(self.text_current_sequence, 2, 2)
        layout_sequence.addWidget(self.label_new_sequence, 3, 0)
        layout_sequence.addWidget(self.helper_button, 3, 1)
        layout_sequence.addWidget(self.text_new_sequence, 3, 2)
        layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2)

        layout = QVBoxLayout()
        layout.addLayout(layout_sequence)
        layout.addSpacing(spacing)
        layout.addWidget(bbox)
        self.setLayout(layout)

        # Signals
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
コード例 #17
0
ファイル: fileassociations.py プロジェクト: nixjdm/spyder
class InputTextDialog(QDialog):
    """Input text dialog with regex validation."""
    def __init__(self, parent=None, title='', label=''):
        """Input text dialog with regex validation."""
        super(InputTextDialog, self).__init__(parent=parent)
        self._reg = None
        self._regex = None

        # Widgets
        self.label = QLabel()
        self.lineedit = QLineEdit()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
        self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setWindowTitle(title)
        self.setMinimumWidth(500)  # FIXME: use metrics
        self.label.setText(label)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.lineedit)
        layout.addSpacing(24)  # FIXME: use metrics
        layout.addWidget(self.button_box)
        self.setLayout(layout)

        # Signals
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)
        self.lineedit.textChanged.connect(self.validate)

        self.validate()

    def validate(self):
        """Validate content."""
        text = self.text().strip()
        is_valid = bool(text)
        if self._reg:
            res = self._reg.match(text)
            if res:
                text_matched = res.group(0)
                is_valid = is_valid and text_matched == text
            else:
                is_valid = False
        self.button_ok.setEnabled(is_valid)

    def set_regex_validation(self, regex):
        """Set the regular expression to validate content."""
        self._regex = regex
        self._reg = re.compile(regex, re.IGNORECASE)
        validator = QRegExpValidator(QRegExp(regex))
        self.lineedit.setValidator(validator)

    def text(self):
        """Return the text of the lineedit."""
        return self.lineedit.text()

    def set_text(self, text):
        """Set the text of the lineedit."""
        self.lineedit.setText(text)
        self.validate()
コード例 #18
0
ファイル: lspmanager.py プロジェクト: vasulakkaraju/spyder
    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>%(host)s</tt> and '
                        '<tt>%(port)s</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(_('Programming language provided '
                                  'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(_('Name of the host that will provide '
                                     'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(_('Command used to start the '
                                    'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(_('Additional arguments required to '
                                     'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('color_schemes', 'selected')
        self.conf_input.setup_editor(
            language='JSON',
            color_scheme=color_scheme,
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json')
        self.conf_input.setToolTip(_('Additional LSP server configurations '
                                     'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(_('Check if the server runs '
                                      'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(
            self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()
コード例 #19
0
ファイル: merge_dialog.py プロジェクト: yangrq1018/cutelog
class MergeDialog(QDialog):

    # name of src tab, names of dst tabs, whether to keep connections alive or not
    merge_tabs_signal = Signal(str, list, bool)

    def __init__(self, parent, loggers):
        super().__init__(parent)

        self.loggers = loggers
        self.merge_list = []   # all tabs to be merged
        self.merge_dst = None  # tab to merge the rest of merge_list into

        self.setupUi()

    def setupUi(self):
        self.resize(340, 320)
        self.gridLayout = QGridLayout(self)
        self.dstComboBox = QComboBox(self)
        self.gridLayout.addWidget(self.dstComboBox, 1, 2, 1, 2)
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Cancel | QDialogButtonBox.Ok, self)
        self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 4)
        self.loggerList = QListWidget(self)
        self.loggerList.setDefaultDropAction(Qt.IgnoreAction)
        self.loggerList.setSelectionMode(QAbstractItemView.MultiSelection)
        self.gridLayout.addWidget(self.loggerList, 1, 0, 4, 2)
        self.keepAliveCheckBox = QCheckBox("Keep connections alive", self)
        self.keepAliveCheckBox.setChecked(True)
        self.gridLayout.addWidget(self.keepAliveCheckBox, 2, 2, 1, 2)
        self.srcsLabel = QLabel("All loggers:", self)
        self.gridLayout.addWidget(self.srcsLabel, 0, 0, 1, 2)
        self.dstLabel = QLabel("Merge all into:", self)
        self.gridLayout.addWidget(self.dstLabel, 0, 2, 1, 2)
        spacerItem = QSpacerItem(20, 169, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem, 4, 2, 1, 2)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.loggerList.selectionModel().selectionChanged.connect(self.merge_list_changed)
        self.dstComboBox.currentTextChanged.connect(self.merge_dst_changed)
        self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)
        self.keepAliveCheckBox.setToolTip("If disabled then only the destination connection "
                                          "will still be alive after merging.")

        self.fill_logger_list()

    def fill_logger_list(self):
        for logger_name in self.loggers.keys():
            LoggerListItem(self.loggerList, logger_name)

    def merge_list_changed(self, sel, desel):
        sel = sel.indexes()
        desel = desel.indexes()
        for index in sel:
            sel_item = self.loggerList.itemFromIndex(index)
            self.merge_list.append(sel_item)
            self.dstComboBox.addItem(sel_item.name)
            self.ok_button.setEnabled(True)

        for index in desel:
            desel_item = self.loggerList.itemFromIndex(index)
            self.merge_list.remove(desel_item)
            row = self.dstComboBox.findText(desel_item.name)
            self.dstComboBox.removeItem(row)
            if self.dstComboBox.count() == 0:
                self.ok_button.setEnabled(False)

    def merge_dst_changed(self, text):
        self.merge_dst = text

    def accept(self):
        name_list = [item.name for item in self.merge_list]
        name_list.remove(self.merge_dst)
        self.merge_tabs_signal.emit(self.merge_dst, name_list, self.keepAliveCheckBox.isChecked())
        self.done(0)

    def reject(self):
        self.done(0)
コード例 #20
0
ファイル: settings.py プロジェクト: mrakitin/Xi-cam.gui
class ConfigDialog(QDialog):
    def __init__(self):
        super(ConfigDialog, self).__init__()

        # Set size and position
        self.setGeometry(0, 0, 900, 550)
        frameGm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

        self.contentsWidget = QListView()
        self.contentsWidget.setViewMode(QListView.IconMode)
        # self.contentsWidget.setIconSize(QSize(96, 84))
        self.contentsWidget.setMovement(QListView.Static)
        self.contentsWidget.setMaximumWidth(174)
        self.contentsWidget.setSpacing(12)
        self.contentsWidget.setSelectionMode(QAbstractItemView.SingleSelection)

        self.contentsModel = QStandardItemModel()
        self.contentsWidget.setModel(self.contentsModel)
        self.contentsWidget.selectionModel().currentChanged.connect(self.changePage)

        self.buttonboxWidget = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Apply# | QDialogButtonBox.Help
        )
        self.buttonboxWidget.button(QDialogButtonBox.Ok).clicked.connect(self.ok)
        self.buttonboxWidget.button(QDialogButtonBox.Apply).clicked.connect(self.apply)
        self.buttonboxWidget.button(QDialogButtonBox.Cancel).clicked.connect(self.close)

        self.pagesWidget = QStackedWidget()

        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.contentsWidget)
        horizontalLayout.addWidget(self.pagesWidget, 1)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(horizontalLayout)
        # mainLayout.addStretch(1)
        mainLayout.addSpacing(12)
        mainLayout.addWidget(self.buttonboxWidget)

        self.setLayout(mainLayout)
        self.setWindowTitle("Config Dialog")

        # Set modality
        self.setModal(True)

        self.lastwidget = None

        self.createIcons()
        self.restore()

        pluginmanager.attach(self.pluginsChanged)

    def createIcons(self):
        self.contentsModel.clear()
        for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"):
            item = QStandardItem(pluginInfo.plugin_object.icon, pluginInfo.plugin_object.name())
            item.widget = pluginInfo.plugin_object.widget
            item.setTextAlignment(Qt.AlignHCenter)
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            item.setSizeHint(QSize(136, 80))
            self.contentsModel.appendRow(item)

    def show(self):
        if self.lastwidget:
            self.pagesWidget.addWidget(self.lastwidget)
            self.pagesWidget.setCurrentWidget(self.lastwidget)
        self.restore()
        super(ConfigDialog, self).show()

    def changePage(self, current, previous):
        if not current:
            current = previous
        current = self.contentsModel.itemFromIndex(current)
        self.pagesWidget.addWidget(current.widget)
        self.pagesWidget.setCurrentWidget(current.widget)
        self.lastwidget = current.widget

    def pluginsChanged(self):
        self.createIcons()

    def restore(self):
        for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"):
            pluginInfo.plugin_object.restore()

        self.apply()

    def ok(self):
        self._empty()
        self.apply()
        self.accept()

    def apply(self):
        for pluginInfo in pluginmanager.getPluginsOfCategory("SettingsPlugin"):
            pluginInfo.plugin_object.save()

    def close(self):
        self._empty()
        self.restore()
        self.reject()

    def _empty(self):
        """
        Disown all widget children (otherwise their c++ objects are force deleted when the dialog closes).
        Must be run in reverse to avoid index update errors
        """
        for i in reversed(range(self.pagesWidget.count())):
            self.pagesWidget.widget(i).setParent(None)

    def closeEvent(self, event):
        self.close()
        event.accept()

    def keyPressEvent(self, e: QKeyEvent):
        if e.key() != Qt.Key_Escape:
            super(ConfigDialog, self).keyPressEvent(e)
        else:
            self.close()
コード例 #21
0
ファイル: lspmanager.py プロジェクト: cfanpc/spyder
    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>%(host)s</tt> and '
                        '<tt>%(port)s</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(_('Programming language provided '
                                  'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(_('Name of the host that will provide '
                                     'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(_('Command used to start the '
                                    'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(_('Additional arguments required to '
                                     'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('appearance', 'selected')
        self.conf_input.setup_editor(
            language='JSON',
            color_scheme=color_scheme,
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json')
        self.conf_input.setToolTip(_('Additional LSP server configurations '
                                     'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(_('Check if the server runs '
                                      'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(
            self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()
コード例 #22
0
class ConfigDialog(QDialog):
    """
    Dialog window for specifying test configuration.

    The window contains two radio buttons (for 'py,test' and 'nose'),
    a line edit box for specifying the working directory, a button to
    use a file browser for selecting the directory, and OK and Cancel
    buttons. Initially, neither radio button is selected and the OK
    button is disabled. Selecting a radio button enabled the OK
    button.
    """
    def __init__(self, config, parent=None):
        """
        Construct a dialog window.

        Parameters
        ----------
        config : Config
            Initial configuration
        parent : QWidget
        """
        super(ConfigDialog, self).__init__(parent)
        self.setWindowTitle(_('Configure tests'))
        layout = QVBoxLayout(self)

        framework_groupbox = QGroupBox(_('Test framework'), self)
        framework_layout = QVBoxLayout(framework_groupbox)
        self.pytest_button = QRadioButton('py.test', framework_groupbox)
        framework_layout.addWidget(self.pytest_button)
        self.nose_button = QRadioButton('nose', framework_groupbox)
        framework_layout.addWidget(self.nose_button)
        layout.addWidget(framework_groupbox)

        layout.addSpacing(10)

        wdir_label = QLabel(_('Directory from which to run tests'))
        layout.addWidget(wdir_label)
        wdir_layout = QHBoxLayout()
        self.wdir_lineedit = QLineEdit(self)
        wdir_layout.addWidget(self.wdir_lineedit)
        self.wdir_button = QPushButton(ima.icon('DirOpenIcon'), '', self)
        self.wdir_button.setToolTip(_("Select directory"))
        self.wdir_button.clicked.connect(lambda: self.select_directory())
        wdir_layout.addWidget(self.wdir_button)
        layout.addLayout(wdir_layout)

        layout.addSpacing(20)

        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel)
        layout.addWidget(self.buttons)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

        ok_button = self.buttons.button(QDialogButtonBox.Ok)
        ok_button.setEnabled(False)
        self.pytest_button.toggled.connect(lambda: ok_button.setEnabled(True))
        self.nose_button.toggled.connect(lambda: ok_button.setEnabled(True))

        if config.framework == 'py.test':
            self.pytest_button.setChecked(True)
        elif config.framework == 'nose':
            self.nose_button.setChecked(True)
        self.wdir_lineedit.setText(config.wdir)

    def select_directory(self):
        """Display dialog for user to select working directory."""
        basedir = to_text_string(self.wdir_lineedit.text())
        if not osp.isdir(basedir):
            basedir = getcwd()
        title = _("Select directory")
        directory = getexistingdirectory(self, title, basedir)
        if directory:
            self.wdir_lineedit.setText(directory)

    def get_config(self):
        """
        Return the test configuration specified by the user.

        Returns
        -------
        Config
            Test configuration
        """
        if self.pytest_button.isChecked():
            framework = 'py.test'
        elif self.nose_button.isChecked():
            framework = 'nose'
        else:
            framework = None
        return Config(framework=framework, wdir=self.wdir_lineedit.text())
コード例 #23
0
ファイル: actions.py プロジェクト: lzfernandes/conda-manager
class CondaPackageActionDialog(QDialog):
    """ """
    def __init__(self, parent, env, name, action, version, versions):
        super(CondaPackageActionDialog, self).__init__(parent)
        self._parent = parent
        self._env = env
        self._version_text = None
        self._name = name
        self._dependencies_dic = {}
        self._conda_process = \
            conda_api_q.CondaProcess(self, self._on_process_finished)

        # widgets
        self.label = QLabel(self)
        self.combobox_version = QComboBox()
        self.label_version = QLabel(self)
        self.widget_version = None
        self.table_dependencies = None

        self.checkbox = QCheckBox(_('Install dependencies (recommended)'))
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                     QDialogButtonBox.Cancel, Qt.Horizontal,
                                     self)

        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)

        dialog_size = QSize(300, 90)

        # helper variable values
        action_title = {const.UPGRADE: _("Upgrade package"),
                        const.DOWNGRADE: _("Downgrade package"),
                        const.REMOVE: _("Remove package"),
                        const.INSTALL: _("Install package")}

        # Versions might have duplicates from different builds
        versions = sort_versions(list(set(versions)), reverse=True)

        # FIXME: There is a bug, a package installed by anaconda has version
        # astropy 0.4 and the linked list 0.4 but the available versions
        # in the json file do not include 0.4 but 0.4rc1... so...
        # temporal fix is to check if inside list otherwise show full list
        if action == const.UPGRADE:
            if version in versions:
                index = versions.index(version)
                versions = versions[:index]
            else:
                versions = versions
        elif action == const.DOWNGRADE:
            if version in versions:
                index = versions.index(version)
                versions = versions[index+1:]
            else:
                versions = versions
        elif action == const.REMOVE:
            versions = [version]
            self.combobox_version.setEnabled(False)

        if len(versions) == 1:
            if action == const.REMOVE:
                labeltext = _('Package version to remove:')
            else:
                labeltext = _('Package version available:')
            self.label_version.setText(versions[0])
            self.widget_version = self.label_version
        else:
            labeltext = _("Select package version:")
            self.combobox_version.addItems(versions)
            self.widget_version = self.combobox_version

        self.label.setText(labeltext)
        self.label_version.setAlignment(Qt.AlignLeft)
        self.table_dependencies = QWidget(self)

        self._layout = QGridLayout()
        self._layout.addWidget(self.label, 0, 0, Qt.AlignVCenter |
                               Qt.AlignLeft)
        self._layout.addWidget(self.widget_version, 0, 1, Qt.AlignVCenter |
                               Qt.AlignRight)

        self.widgets = [self.checkbox, self.button_ok, self.widget_version,
                        self.table_dependencies]
        row_index = 1

        # Create a Table
        if action in [const.INSTALL, const.UPGRADE, const.DOWNGRADE]:
            table = QTableView(self)
            dialog_size = QSize(dialog_size.width() + 40, 300)
            self.table_dependencies = table
            row_index = 1
            self._layout.addItem(QSpacerItem(10, 5), row_index, 0)
            self._layout.addWidget(self.checkbox, row_index + 1, 0, 1, 2)
            self.checkbox.setChecked(True)
            self._changed_version(versions[0])

            table.setSelectionBehavior(QAbstractItemView.SelectRows)
            table.verticalHeader().hide()
            table.horizontalHeader().hide()
            table.setAlternatingRowColors(True)
            table.setShowGrid(False)
            table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            table.horizontalHeader().setStretchLastSection(True)

        self._layout.addWidget(self.table_dependencies, row_index + 2, 0, 1, 2,
                               Qt.AlignHCenter)
        self._layout.addItem(QSpacerItem(10, 5), row_index + 3, 0)
        self._layout.addWidget(self.bbox, row_index + 6, 0, 1, 2,
                               Qt.AlignHCenter)

        title = "{0}: {1}".format(action_title[action], name)
        self.setLayout(self._layout)
        self.setMinimumSize(dialog_size)
        self.setFixedSize(dialog_size)
        self.setWindowTitle(title)
        self.setModal(True)

        # signals and slots
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.close)
        self.combobox_version.currentIndexChanged.connect(
            self._changed_version)
        self.checkbox.stateChanged.connect(self._changed_checkbox)

    def _changed_version(self, version, dependencies=True):
        """ """
        self._set_gui_disabled(True)
        install_dependencies = (self.checkbox.checkState() == 2)
        self._version_text = to_text_string(version)
        self._get_dependencies(install_dependencies)

    def _get_dependencies(self, dependencies=True):
        """ """
        name = [self._name + '=' + self._version_text]

        # Temporal fix
        env_name = self._env
        if env_name != 'root':
            env_name = osp.basename(env_name)
        self._conda_process.dependencies(name=env_name, pkgs=name,
                                         dep=dependencies)

    def _changed_checkbox(self, state):
        """ """
        if state:
            self._changed_version(self._version_text)
        else:
            self._changed_version(self._version_text, dependencies=False)

    def _on_process_finished(self, boo):
        """ """
        if self.isVisible():
            dic = self._conda_process.output
            self.dependencies_dic = dic
            self._set_dependencies_table()
            self._set_gui_disabled(False)

    def _set_dependencies_table(self):
        """ """
        table = self.table_dependencies
        dic = self.dependencies_dic
        table.setModel(CondaDependenciesModel(self, dic))
        table.resizeColumnsToContents()
        table.resizeColumnToContents(1)

    def _set_gui_disabled(self, value):
        """ """
        if value:
            table = self.table_dependencies
            table.setModel(CondaDependenciesModel(self, {}))
            table.resizeColumnsToContents()
            table.setDisabled(True)
        else:
            table = self.table_dependencies
            table.setDisabled(False)

        for widget in self.widgets:
            widget.setDisabled(value)
コード例 #24
0
ファイル: FramesWidget.py プロジェクト: desty2k/QtPyBotnet
class FramesWidget(BaseFrame):
    rejected = Signal()
    accepted = Signal()
    back = Signal()

    def __init__(self, parent=None):
        super(FramesWidget, self).__init__(parent)
        self.config_frames = []
        self.frames_instances = []
        self.current_frame = 0

        self.widget_layout = QVBoxLayout(self)
        self.setLayout(self.widget_layout)

        self.frames_widget = QWidget(self)
        self.frames_widget.setContentsMargins(0, 0, 0, 0)
        self.frames_widget_layout = QGridLayout(self.frames_widget)
        self.frames_widget_layout.setContentsMargins(0, 0, 0, 0)
        self.widget_layout.addWidget(self.frames_widget)

        self.btn_box = QDialogButtonBox(self)
        self.btn_box.setObjectName("btn_box")
        self.btn_box.setStandardButtons(QDialogButtonBox.Reset
                                        | QDialogButtonBox.Cancel
                                        | QDialogButtonBox.Ok)
        self.btn_box.button(QDialogButtonBox.Reset).setText("Back")
        self.btn_box.button(QDialogButtonBox.Ok).setText("Next")
        self.widget_layout.addWidget(self.btn_box)

        self.btn_box.button(QDialogButtonBox.Reset).clicked.connect(
            self.on_btn_box_resetted)
        QMetaObject.connectSlotsByName(self)

    def add_frames(self, frames):
        for frame in frames:
            self.add_frame(frame)

    def add_frame(self, frame):
        f = frame(self.frames_widget)
        f.setVisible(False)
        f.set_next_enabled.connect(
            self.btn_box.button(QDialogButtonBox.Ok).setEnabled)
        self.frames_widget_layout.addWidget(f, 0, 0, 1, 1)
        self.frames_instances.append(f)

        if len(self.frames_instances) > 0:
            self.frames_instances[0].setVisible(True)
            if self.frames_instances[0].disable_next_on_enter:
                self.btn_box.button(QDialogButtonBox.Ok).setEnabled(False)

    @Slot(dict)
    def set_options(self, options):
        for frame in self.frames_instances:
            frame.set_options(options)

    @Slot()
    def collect_info(self) -> dict:
        """Get info from every page"""
        settings = {}
        for frame in self.frames_instances:
            settings = settings | frame.collect_info()
        return settings

    @Slot()
    def on_btn_box_rejected(self):
        """When user clicks cancel button"""
        self.rejected.emit()

    @Slot()
    def on_btn_box_accepted(self):
        """On Next button clicked"""
        if self.current_frame + 1 < len(self.frames_instances):
            # if not last
            self.frames_instances[self.current_frame].setVisible(False)
            self.current_frame = self.current_frame + 1
            self.frames_instances[self.current_frame].setVisible(True)

            # if disable on enter page
            self.btn_box.button(
                QDialogButtonBox.Ok).setEnabled(not self.frames_instances[
                    self.current_frame].disable_next_on_enter)

            # if next page is last
            self._change_next_finish()

        # if last page
        elif self.current_frame + 1 == len(self.frames_instances):
            self.accepted.emit()

    @Slot()
    def on_btn_box_resetted(self):
        """On Back button clicked."""
        if self.current_frame > 0:
            self.frames_instances[self.current_frame].setVisible(False)
            self.current_frame = self.current_frame - 1
            self.frames_instances[self.current_frame].setVisible(True)
            self._change_next_finish()

            self.btn_box.button(
                QDialogButtonBox.Ok).setEnabled(not self.frames_instances[
                    self.current_frame].disable_next_on_enter)
        else:
            self.back.emit()

    def _change_next_finish(self):
        if self.current_frame + 1 == len(self.frames_instances):
            self.btn_box.button(QDialogButtonBox.Ok).setText("Finish")
        else:
            self.btn_box.button(QDialogButtonBox.Ok).setText("Next")
コード例 #25
0
class LevelEditDialog(QDialog):

    level_changed = Signal(LogLevel)

    def __init__(self,
                 parent,
                 level=None,
                 creating_new_level=False,
                 level_names=set()):
        super().__init__(parent)

        if level:
            self.level = level
        else:
            self.level = deepcopy(NO_LEVEL)

        self.creating_new_level = creating_new_level
        self.level_names = level_names

        self.setupUi()
        self.load_level(self.level)
        self.update_output()

    def setupUi(self):
        self.resize(350, 280)
        self.gridLayout = QGridLayout(self)
        self.levelNameLabel = QLabel("Level name", self)
        self.gridLayout.addWidget(self.levelNameLabel, 0, 0)

        self.levelNameLine = QLineEdit(self)
        self.gridLayout.addWidget(self.levelNameLine, 1, 0, 1, 0)

        self.groupBox = QGroupBox("Light mode", self)
        self.gridLayout.addWidget(self.groupBox, 2, 0)
        self.groupBoxDark = QGroupBox("Dark mode", self)
        self.gridLayout.addWidget(self.groupBoxDark, 2, 1)

        self.formLayout = QFormLayout(self.groupBox)
        self.groupBox.setLayout(self.formLayout)
        self.fgColorPreview = QLineEdit(self)
        self.formLayout.addRow("Foreground", self.fgColorPreview)
        self.bgColorPreview = QLineEdit(self)
        self.formLayout.addRow("Background", self.bgColorPreview)
        self.boldCheckBox = QCheckBox(self.groupBox)
        self.formLayout.addRow("Bold", self.boldCheckBox)
        self.italicCheckBox = QCheckBox(self.groupBox)
        self.formLayout.addRow("Italic", self.italicCheckBox)
        self.underlineCheckBox = QCheckBox(self.groupBox)
        self.formLayout.addRow("Underline", self.underlineCheckBox)

        self.formLayoutDark = QFormLayout(self.groupBoxDark)
        self.groupBoxDark.setLayout(self.formLayoutDark)
        self.fgColorPreviewDark = QLineEdit(self)
        self.formLayoutDark.addRow("Foreground", self.fgColorPreviewDark)
        self.bgColorPreviewDark = QLineEdit(self)
        self.formLayoutDark.addRow("Background", self.bgColorPreviewDark)
        self.boldCheckBoxDark = QCheckBox(self.groupBoxDark)
        self.formLayoutDark.addRow("Bold", self.boldCheckBoxDark)
        self.italicCheckBoxDark = QCheckBox(self.groupBox)
        self.formLayoutDark.addRow("Italic", self.italicCheckBoxDark)
        self.underlineCheckBoxDark = QCheckBox(self.groupBox)
        self.formLayoutDark.addRow("Underline", self.underlineCheckBoxDark)

        self.spacer = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.gridLayout.addItem(self.spacer, 3, 0, 1, 2)

        self.previewLabel = QLabel("Preview", self)
        self.gridLayout.addWidget(self.previewLabel, 4, 0, 1, 2)
        self.previewLine = QLineEdit(self)
        self.gridLayout.addWidget(self.previewLine, 5, 0)
        self.previewLineDark = QLineEdit(self)
        self.gridLayout.addWidget(self.previewLineDark, 5, 1)

        buttons = QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Cancel
        self.buttonBox = QDialogButtonBox(buttons, self)
        self.resetButton = self.buttonBox.button(QDialogButtonBox.Reset)
        self.gridLayout.addWidget(self.buttonBox, 6, 0, 1, 2)

        self.setup_widget_attributes()
        self.setup_widget_connections()

    def setup_widget_attributes(self):

        self.fgColorPreview.setReadOnly(True)
        self.bgColorPreview.setReadOnly(True)
        self.fgColorPreviewDark.setReadOnly(True)
        self.bgColorPreviewDark.setReadOnly(True)

        self.previewLine.setText("Log message")
        self.previewLineDark.setText("Log message")

        self.resetButton.setMaximumWidth(60)
        self.resetButton.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)

        self.levelNameLine.setText(self.level.levelname)
        if self.creating_new_level:
            self.name_validator = LevelNameValidator(self, self.level_names)
            self.levelNameLine.setValidator(self.name_validator)
            self.levelNameLine.textChanged.connect(self.level_name_valid)
        else:
            self.levelNameLine.setReadOnly(True)

    def setup_widget_connections(self):
        self.boldCheckBox.toggled.connect(self.toggle_bold)
        self.italicCheckBox.toggled.connect(self.toggle_italic)
        self.underlineCheckBox.toggled.connect(self.toggle_underline)

        self.boldCheckBoxDark.toggled.connect(
            partial(self.toggle_bold, dark=True))
        self.italicCheckBoxDark.toggled.connect(
            partial(self.toggle_italic, dark=True))
        self.underlineCheckBoxDark.toggled.connect(
            partial(self.toggle_underline, dark=True))

        # couldn't find a way to make this any better
        self.fgColorPreview.mouseReleaseEvent = partial(
            self.open_color_dialog, 'fg')
        self.bgColorPreview.mouseReleaseEvent = partial(
            self.open_color_dialog, 'bg')
        self.fgColorPreviewDark.mouseReleaseEvent = partial(
            self.open_color_dialog, 'fgDark')
        self.bgColorPreviewDark.mouseReleaseEvent = partial(
            self.open_color_dialog, 'bgDark')

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.resetButton.clicked.connect(self.reset_level)

    def set_checkboxes_state(self):
        self.boldCheckBox.setChecked(self.bold)
        self.italicCheckBox.setChecked(self.italic)
        self.underlineCheckBox.setChecked(self.underline)

        self.boldCheckBoxDark.setChecked(self.boldDark)
        self.italicCheckBoxDark.setChecked(self.italicDark)
        self.underlineCheckBoxDark.setChecked(self.underlineDark)

    def load_level(self, level):
        self.bg = level.bg
        self.fg = level.fg
        self.bgDark = level.bgDark
        self.fgDark = level.fgDark

        self.bold = 'bold' in level.styles
        self.italic = 'italic' in level.styles
        self.underline = 'underline' in level.styles

        self.boldDark = 'bold' in level.stylesDark
        self.italicDark = 'italic' in level.stylesDark
        self.underlineDark = 'underline' in level.stylesDark

    def reset_level(self):
        replacement = DEFAULT_LEVELS.get(self.level.levelname)
        if not replacement:
            replacement = NO_LEVEL

        self.load_level(replacement)
        self.update_output()

    def toggle_bold(self, enabled, dark=False):
        if not dark:
            self.bold = enabled
        else:
            self.boldDark = enabled
        self.update_output()

    def toggle_italic(self, enabled, dark=False):
        if not dark:
            self.italic = enabled
        else:
            self.italicDark = enabled
        self.update_output()

    def toggle_underline(self, enabled, dark=False):
        if not dark:
            self.underline = enabled
        else:
            self.underlineDark = enabled
        self.update_output()

    def open_color_dialog(self, attr_name, mouse_event):
        d = QColorDialog(self)
        d.setCurrentColor(getattr(self, attr_name))
        f = partial(self.set_color, attr_name)
        d.colorSelected.connect(
            f)  # d.open(f) doesn't pass color for some reason
        d.open()

    def set_color(self, attr_name, color):
        setattr(self, attr_name, color)
        self.update_output()

    def accept(self):
        self.level.styles = set()
        if self.bold:
            self.level.styles.add('bold')
        if self.italic:
            self.level.styles.add('italic')
        if self.underline:
            self.level.styles.add('underline')

        self.level.stylesDark = set()
        if self.boldDark:
            self.level.stylesDark.add('bold')
        if self.italicDark:
            self.level.stylesDark.add('italic')
        if self.underlineDark:
            self.level.stylesDark.add('underline')

        self.level.bg = self.bg
        self.level.fg = self.fg
        self.level.bgDark = self.bgDark
        self.level.fgDark = self.fgDark

        self.level.levelname = self.levelNameLine.text().upper()

        self.level_changed.emit(self.level)
        self.done(0)

    def reject(self):
        self.done(0)

    def update_output(self):
        # Setting the pallette doesn't override the global stylesheet,
        # which is why I can't just set pallete with needed colors here.

        self.previewLine.setStyleSheet("""QLineEdit {{
                                               color: {};
                                               background: {}
                                          }}""".format(self.fg.name(),
                                                       self.bg.name()))

        self.previewLineDark.setStyleSheet("""QLineEdit {{
                                                   color: {};
                                                   background: {}
                                              }}""".format(
            self.fgDark.name(), self.bgDark.name()))

        self.bgColorPreview.setStyleSheet(
            'QLineEdit {{background: {} }}'.format(self.bg.name()))
        self.fgColorPreview.setStyleSheet(
            'QLineEdit {{background: {} }}'.format(self.fg.name()))

        self.bgColorPreviewDark.setStyleSheet(
            'QLineEdit {{ background: {} }}'.format(self.bgDark.name()))
        self.fgColorPreviewDark.setStyleSheet(
            'QLineEdit {{ background: {} }}'.format(self.fgDark.name()))

        font = self.previewLine.font()
        font.setBold(self.bold)
        font.setItalic(self.italic)
        font.setUnderline(self.underline)
        self.previewLine.setFont(font)

        fontDark = self.previewLineDark.font()
        fontDark.setBold(self.boldDark)
        fontDark.setItalic(self.italicDark)
        fontDark.setUnderline(self.underlineDark)
        self.previewLineDark.setFont(fontDark)

        self.set_checkboxes_state()

    def level_name_valid(self):
        if self.levelNameLine.hasAcceptableInput():
            self.buttonBox.button(QDialogButtonBox.Save).setEnabled(True)
        else:
            self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False)
コード例 #26
0
class SnippetEditor(QDialog):
    SNIPPET_VALID = _('Valid snippet')
    SNIPPET_INVALID = _('Invalid snippet')
    INVALID_CB_CSS = "QComboBox {border: 1px solid red;}"
    VALID_CB_CSS = "QComboBox {border: 1px solid green;}"
    INVALID_LINE_CSS = "QLineEdit {border: 1px solid red;}"
    VALID_LINE_CSS = "QLineEdit {border: 1px solid green;}"
    MIN_SIZE = QSize(850, 600)

    def __init__(self,
                 parent,
                 language=None,
                 trigger_text='',
                 description='',
                 snippet_text='',
                 remove_trigger=False,
                 trigger_texts=[],
                 descriptions=[],
                 get_option=None,
                 set_option=None):
        super(SnippetEditor, self).__init__(parent)

        snippet_description = _(
            "To add a new text snippet, you need to define the text "
            "that triggers it, a short description (two words maximum) "
            "of the snippet and if it should delete the trigger text when "
            "inserted. Finally, you need to define the snippet body to insert."
        )

        self.parent = parent
        self.trigger_text = trigger_text
        self.description = description
        self.remove_trigger = remove_trigger
        self.snippet_text = snippet_text
        self.descriptions = descriptions
        self.base_snippet = Snippet(language=language,
                                    trigger_text=trigger_text,
                                    snippet_text=snippet_text,
                                    description=description,
                                    remove_trigger=remove_trigger,
                                    get_option=get_option,
                                    set_option=set_option)

        # Widgets
        self.snippet_settings_description = QLabel(snippet_description)
        self.snippet_settings_description.setFixedWidth(450)

        # Trigger text
        self.trigger_text_label = QLabel(_('Trigger text:'))
        self.trigger_text_cb = QComboBox(self)
        self.trigger_text_cb.setEditable(True)

        # Description
        self.description_label = QLabel(_('Description:'))
        self.description_input = QLineEdit(self)

        # Remove trigger
        self.remove_trigger_cb = QCheckBox(
            _('Remove trigger text on insertion'), self)
        self.remove_trigger_cb.setToolTip(
            _('Check if the text that triggers '
              'this snippet should be removed '
              'when inserting it'))
        self.remove_trigger_cb.setChecked(self.remove_trigger)

        # Snippet body input
        self.snippet_label = QLabel(_('<b>Snippet text:</b>'))
        self.snippet_valid_label = QLabel(self.SNIPPET_INVALID, self)
        self.snippet_input = SimpleCodeEditor(None)

        # Dialog buttons
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setWindowTitle(_('Snippet editor'))

        self.snippet_settings_description.setWordWrap(True)
        self.trigger_text_cb.setToolTip(
            _('Trigger text for the current snippet'))
        self.trigger_text_cb.addItems(trigger_texts)

        if self.trigger_text != '':
            idx = trigger_texts.index(self.trigger_text)
            self.trigger_text_cb.setCurrentIndex(idx)

        self.description_input.setText(self.description)
        self.description_input.textChanged.connect(lambda _x: self.validate())

        text_inputs = (self.trigger_text, self.description, self.snippet_text)
        non_empty_text = all([x != '' for x in text_inputs])
        if non_empty_text:
            self.button_ok.setEnabled(True)

        self.snippet_input.setup_editor(language=language,
                                        color_scheme=get_option(
                                            'selected', section='appearance'),
                                        wrap=False,
                                        highlight_current_line=True,
                                        font=get_font())
        self.snippet_input.set_language(language)
        self.snippet_input.setToolTip(_('Snippet text completion to insert'))
        self.snippet_input.set_text(snippet_text)

        # Layout setup
        general_layout = QVBoxLayout()
        general_layout.addWidget(self.snippet_settings_description)

        snippet_settings_group = QGroupBox(_('Trigger information'))
        settings_layout = QGridLayout()
        settings_layout.addWidget(self.trigger_text_label, 0, 0)
        settings_layout.addWidget(self.trigger_text_cb, 0, 1)
        settings_layout.addWidget(self.description_label, 1, 0)
        settings_layout.addWidget(self.description_input, 1, 1)

        all_settings_layout = QVBoxLayout()
        all_settings_layout.addLayout(settings_layout)
        all_settings_layout.addWidget(self.remove_trigger_cb)
        snippet_settings_group.setLayout(all_settings_layout)
        general_layout.addWidget(snippet_settings_group)

        text_layout = QVBoxLayout()
        text_layout.addWidget(self.snippet_label)
        text_layout.addWidget(self.snippet_input)
        text_layout.addWidget(self.snippet_valid_label)
        general_layout.addLayout(text_layout)

        general_layout.addWidget(self.bbox)
        self.setLayout(general_layout)

        # Signals
        self.trigger_text_cb.editTextChanged.connect(self.validate)
        self.description_input.textChanged.connect(self.validate)
        self.snippet_input.textChanged.connect(self.validate)
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Final setup
        if trigger_text != '' or snippet_text != '':
            self.validate()

    @Slot()
    def validate(self):
        trigger_text = self.trigger_text_cb.currentText()
        description_text = self.description_input.text()
        snippet_text = self.snippet_input.toPlainText()

        invalid = False
        try:
            build_snippet_ast(snippet_text)
            self.snippet_valid_label.setText(self.SNIPPET_VALID)
        except SyntaxError:
            invalid = True
            self.snippet_valid_label.setText(self.SNIPPET_INVALID)

        if trigger_text == '':
            invalid = True
            self.trigger_text_cb.setStyleSheet(self.INVALID_CB_CSS)
        else:
            self.trigger_text_cb.setStyleSheet(self.VALID_CB_CSS)

        if trigger_text in self.descriptions:
            if self.trigger_text != trigger_text:
                if description_text in self.descriptions[trigger_text]:
                    invalid = True
                    self.description_input.setStyleSheet(self.INVALID_LINE_CSS)
                else:
                    self.description_input.setStyleSheet(self.VALID_LINE_CSS)
            else:
                if description_text != self.description:
                    if description_text in self.descriptions[trigger_text]:
                        invalid = True
                        self.description_input.setStyleSheet(
                            self.INVALID_LINE_CSS)
                    else:
                        self.description_input.setStyleSheet(
                            self.VALID_LINE_CSS)
                else:
                    self.description_input.setStyleSheet(self.VALID_LINE_CSS)

        self.button_ok.setEnabled(not invalid)

    def get_options(self):
        trigger_text = self.trigger_text_cb.currentText()
        description_text = self.description_input.text()
        snippet_text = self.snippet_input.toPlainText()
        remove_trigger = self.remove_trigger_cb.isChecked()
        self.base_snippet.update(trigger_text, description_text, snippet_text,
                                 remove_trigger)
        return self.base_snippet
コード例 #27
0
class ConfigDialog(QDialog):
    """
    Dialog window for specifying test configuration.

    The window contains a combobox with all the frameworks, a line edit box for
    specifying the working directory, a button to use a file browser for
    selecting the directory, and OK and Cancel buttons. Initially, no framework
    is selected and the OK button is disabled. Selecting a framework enables
    the OK button.
    """
    def __init__(self, frameworks, config, parent=None):
        """
        Construct a dialog window.

        Parameters
        ----------
        frameworks : dict of (str, type)
            Names of all supported frameworks with their associated class
            (assumed to be a subclass of RunnerBase)
        config : Config
            Initial configuration
        parent : QWidget
        """
        super(ConfigDialog, self).__init__(parent)
        self.setWindowTitle(_('Configure tests'))
        layout = QVBoxLayout(self)

        framework_layout = QHBoxLayout()
        framework_label = QLabel(_('Test framework'))
        framework_layout.addWidget(framework_label)

        self.framework_combobox = QComboBox(self)
        for ix, (name, runner) in enumerate(sorted(frameworks.items())):
            installed = runner.is_installed()
            if installed:
                label = name
            else:
                label = '{} ({})'.format(name, _('not available'))
            self.framework_combobox.addItem(label)
            self.framework_combobox.model().item(ix).setEnabled(installed)

        framework_layout.addWidget(self.framework_combobox)
        layout.addLayout(framework_layout)

        layout.addSpacing(10)

        wdir_label = QLabel(_('Directory from which to run tests'))
        layout.addWidget(wdir_label)
        wdir_layout = QHBoxLayout()
        self.wdir_lineedit = QLineEdit(self)
        wdir_layout.addWidget(self.wdir_lineedit)
        self.wdir_button = QPushButton(ima.icon('DirOpenIcon'), '', self)
        self.wdir_button.setToolTip(_("Select directory"))
        self.wdir_button.clicked.connect(lambda: self.select_directory())
        wdir_layout.addWidget(self.wdir_button)
        layout.addLayout(wdir_layout)

        layout.addSpacing(20)

        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel)
        layout.addWidget(self.buttons)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

        self.ok_button = self.buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)
        self.framework_combobox.currentIndexChanged.connect(
            self.framework_changed)

        self.framework_combobox.setCurrentIndex(-1)
        if config.framework:
            index = self.framework_combobox.findText(config.framework)
            if index != -1:
                self.framework_combobox.setCurrentIndex(index)
        self.wdir_lineedit.setText(config.wdir)

    @Slot(int)
    def framework_changed(self, index):
        """Called when selected framework changes."""
        if index != -1:
            self.ok_button.setEnabled(True)

    def select_directory(self):
        """Display dialog for user to select working directory."""
        basedir = to_text_string(self.wdir_lineedit.text())
        if not osp.isdir(basedir):
            basedir = getcwd()
        title = _("Select directory")
        directory = getexistingdirectory(self, title, basedir)
        if directory:
            self.wdir_lineedit.setText(directory)

    def get_config(self):
        """
        Return the test configuration specified by the user.

        Returns
        -------
        Config
            Test configuration
        """
        framework = self.framework_combobox.currentText()
        if framework == '':
            framework = None
        return Config(framework=framework, wdir=self.wdir_lineedit.text())
コード例 #28
0
    def __init__(self, parent, context, name, sequence, shortcuts):
        super(ShortcutEditor, self).__init__(parent)
        self._parent = parent

        self.context = context
        self.npressed = 0
        self.keys = set()
        self.key_modifiers = set()
        self.key_non_modifiers = list()
        self.key_text = list()
        self.sequence = sequence
        self.new_sequence = None
        self.edit_state = True
        self.shortcuts = shortcuts

        # Widgets
        self.label_info = QLabel()
        self.label_info.setText(
            _("Press the new shortcut and select 'Ok': \n"
              "(Press 'Tab' once to switch focus between the shortcut entry \n"
              "and the buttons below it)"))
        self.label_current_sequence = QLabel(_("Current shortcut:"))
        self.text_current_sequence = QLabel(sequence)
        self.label_new_sequence = QLabel(_("New shortcut:"))
        self.text_new_sequence = CustomLineEdit(self)
        self.text_new_sequence.setPlaceholderText(sequence)
        self.helper_button = HelperToolButton()
        self.helper_button.hide()
        self.label_warning = QLabel()
        self.label_warning.hide()

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)

        # Setup widgets
        self.setWindowTitle(_('Shortcut: {0}').format(name))
        self.button_ok.setFocusPolicy(Qt.NoFocus)
        self.button_ok.setEnabled(False)
        self.button_cancel.setFocusPolicy(Qt.NoFocus)
        self.helper_button.setToolTip('')
        self.helper_button.setFocusPolicy(Qt.NoFocus)
        style = """
            QToolButton {
              margin:1px;
              border: 0px solid grey;
              padding:0px;
              border-radius: 0px;
            }"""
        self.helper_button.setStyleSheet(style)
        self.text_new_sequence.setFocusPolicy(Qt.NoFocus)
        self.label_warning.setFocusPolicy(Qt.NoFocus)

        # Layout
        spacing = 5
        layout_sequence = QGridLayout()
        layout_sequence.addWidget(self.label_info, 0, 0, 1, 3)
        layout_sequence.addItem(QSpacerItem(spacing, spacing), 1, 0, 1, 2)
        layout_sequence.addWidget(self.label_current_sequence, 2, 0)
        layout_sequence.addWidget(self.text_current_sequence, 2, 2)
        layout_sequence.addWidget(self.label_new_sequence, 3, 0)
        layout_sequence.addWidget(self.helper_button, 3, 1)
        layout_sequence.addWidget(self.text_new_sequence, 3, 2)
        layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2)

        layout = QVBoxLayout()
        layout.addLayout(layout_sequence)
        layout.addSpacing(spacing)
        layout.addWidget(bbox)
        self.setLayout(layout)

        # Signals
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
コード例 #29
0
class LayoutSettingsDialog(QDialog):
    """Layout settings dialog"""
    def __init__(self, parent, names, order, active):
        super(LayoutSettingsDialog, self).__init__(parent)

        # variables
        self._parent = parent
        self._selection_model = None
        self.names = names
        self.order = order
        self.active = active

        # widgets
        self.button_move_up = QPushButton(_('Move Up'))
        self.button_move_down = QPushButton(_('Move Down'))
        self.button_delete = QPushButton(_('Delete Layout'))
        self.button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.group_box = QGroupBox(_("Layout Display and Order"))
        self.table = QTableView(self)
        self.ok_button = self.button_box.button(QDialogButtonBox.Ok)
        self.cancel_button = self.button_box.button(QDialogButtonBox.Cancel)
        self.cancel_button.setDefault(True)
        self.cancel_button.setAutoDefault(True)

        # widget setup
        self.dialog_size = QSize(300, 200)
        self.setMinimumSize(self.dialog_size)
        self.setFixedSize(self.dialog_size)
        self.setWindowTitle('Layout Settings')

        self.table.setModel(LayoutModel(self.table, order, active))
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.verticalHeader().hide()
        self.table.horizontalHeader().hide()
        self.table.setAlternatingRowColors(True)
        self.table.setShowGrid(False)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.setColumnHidden(1, True)

        # need to keep a reference for pyside not to segfault!
        self._selection_model = self.table.selectionModel()

        # layout
        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(self.button_move_up)
        buttons_layout.addWidget(self.button_move_down)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self.button_delete)

        group_layout = QHBoxLayout()
        group_layout.addWidget(self.table)
        group_layout.addLayout(buttons_layout)
        self.group_box.setLayout(group_layout)

        layout = QVBoxLayout()
        layout.addWidget(self.group_box)
        layout.addWidget(self.button_box)

        self.setLayout(layout)

        # signals and slots
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.close)
        self.button_delete.clicked.connect(self.delete_layout)
        self.button_move_up.clicked.connect(lambda: self.move_layout(True))
        self.button_move_down.clicked.connect(lambda: self.move_layout(False))
        self.table.model().dataChanged.connect(
            lambda: self.selection_changed(None, None))
        self._selection_model.selectionChanged.connect(
            lambda: self.selection_changed(None, None))

        # focus table
        index = self.table.model().index(0, 0)
        self.table.setCurrentIndex(index)
        self.table.setFocus()

    def delete_layout(self):
        """ """
        names, order, active = self.names, self.order, self.order
        name = from_qvariant(self.table.selectionModel().currentIndex().data(),
                             to_text_string)

        if name in names:
            index = names.index(name)
            # In case nothing has focus in the table
        if index != -1:
            order.remove(name)
            names[index] = None
            if name in active:
                active.remove(name)
            self.names, self.order, self.active = names, order, active
            self.table.model().set_data(order, active)
            index = self.table.model().index(0, 0)
            self.table.setCurrentIndex(index)
            self.table.setFocus()
            self.selection_changed(None, None)
            if len(order) == 0:
                self.button_move_up.setDisabled(True)
                self.button_move_down.setDisabled(True)
                self.button_delete.setDisabled(True)

    def move_layout(self, up=True):
        """ """
        names, order, active = self.names, self.order, self.active
        row = self.table.selectionModel().currentIndex().row()
        row_new = row

        if up:
            row_new -= 1
        else:
            row_new += 1

        order[row], order[row_new] = order[row_new], order[row]

        self.order = order
        self.table.model().set_data(order, active)
        index = self.table.model().index(row_new, 0)
        self.table.setCurrentIndex(index)
        self.table.setFocus()
        self.selection_changed(None, None)

    def selection_changed(self, selection, deselection):
        """ """
        model = self.table.model()
        index = self.table.currentIndex()
        row = index.row()
        order, names, active = self.order, self.names, self.active

        state = model.row(row)[1]
        name = model.row(row)[0]

        # Check if name changed
        if name not in names:  # Did changed
            if row != -1:  # row == -1, means no items left to delete
                old_name = order[row]
                order[row] = name
                names[names.index(old_name)] = name
                if old_name in active:
                    active[active.index(old_name)] = name

        # Check if checbox clicked
        if state:
            if name not in active:
                active.append(name)
        else:
            if name in active:
                active.remove(name)

        self.active = active
        self.button_move_up.setDisabled(False)
        self.button_move_down.setDisabled(False)

        if row == 0:
            self.button_move_up.setDisabled(True)
        if row == len(names) - 1:
            self.button_move_down.setDisabled(True)
        if len(names) == 0:
            self.button_move_up.setDisabled(True)
            self.button_move_down.setDisabled(True)
コード例 #30
0
class ConfigDialog(QDialog):
    """
    Dialog window for specifying test configuration.

    The window contains a combobox with all the frameworks, a line edit box for
    specifying the working directory, a button to use a file browser for
    selecting the directory, and OK and Cancel buttons. Initially, no framework
    is selected and the OK button is disabled. Selecting a framework enables
    the OK button.
    """

    def __init__(self, frameworks, config, parent=None):
        """
        Construct a dialog window.

        Parameters
        ----------
        frameworks : dict of (str, type)
            Names of all supported frameworks with their associated class
            (assumed to be a subclass of RunnerBase)
        config : Config
            Initial configuration
        parent : QWidget
        """
        super(ConfigDialog, self).__init__(parent)
        self.setWindowTitle(_('Configure tests'))
        layout = QVBoxLayout(self)

        framework_layout = QHBoxLayout()
        framework_label = QLabel(_('Test framework'))
        framework_layout.addWidget(framework_label)

        self.framework_combobox = QComboBox(self)
        for ix, (name, runner) in enumerate(sorted(frameworks.items())):
            installed = runner.is_installed()
            if installed:
                label = name
            else:
                label = '{} ({})'.format(name, _('not available'))
            self.framework_combobox.addItem(label)
            self.framework_combobox.model().item(ix).setEnabled(installed)

        framework_layout.addWidget(self.framework_combobox)
        layout.addLayout(framework_layout)

        layout.addSpacing(10)

        wdir_label = QLabel(_('Directory from which to run tests'))
        layout.addWidget(wdir_label)
        wdir_layout = QHBoxLayout()
        self.wdir_lineedit = QLineEdit(self)
        wdir_layout.addWidget(self.wdir_lineedit)
        self.wdir_button = QPushButton(ima.icon('DirOpenIcon'), '', self)
        self.wdir_button.setToolTip(_("Select directory"))
        self.wdir_button.clicked.connect(lambda: self.select_directory())
        wdir_layout.addWidget(self.wdir_button)
        layout.addLayout(wdir_layout)

        layout.addSpacing(20)

        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok |
                                        QDialogButtonBox.Cancel)
        layout.addWidget(self.buttons)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

        self.ok_button = self.buttons.button(QDialogButtonBox.Ok)
        self.ok_button.setEnabled(False)
        self.framework_combobox.currentIndexChanged.connect(
            self.framework_changed)

        self.framework_combobox.setCurrentIndex(-1)
        if config.framework:
            index = self.framework_combobox.findText(config.framework)
            if index != -1:
                self.framework_combobox.setCurrentIndex(index)
        self.wdir_lineedit.setText(config.wdir)

    @Slot(int)
    def framework_changed(self, index):
        """Called when selected framework changes."""
        if index != -1:
            self.ok_button.setEnabled(True)

    def select_directory(self):
        """Display dialog for user to select working directory."""
        basedir = to_text_string(self.wdir_lineedit.text())
        if not osp.isdir(basedir):
            basedir = getcwd()
        title = _("Select directory")
        directory = getexistingdirectory(self, title, basedir)
        if directory:
            self.wdir_lineedit.setText(directory)

    def get_config(self):
        """
        Return the test configuration specified by the user.

        Returns
        -------
        Config
            Test configuration
        """
        framework = self.framework_combobox.currentText()
        if framework == '':
            framework = None
        return Config(framework=framework, wdir=self.wdir_lineedit.text())
コード例 #31
0
ファイル: actions.py プロジェクト: Discalced51/conda-manager
class CondaPackageActionDialog(QDialog):
    """ """

    def __init__(self, parent, prefix, name, action, version, versions, packages_sizes, active_channels):
        super(CondaPackageActionDialog, self).__init__(parent)
        self._parent = parent
        self._prefix = prefix
        self._version_text = None
        self._name = name
        self._dependencies_dic = {}
        self._active_channels = active_channels
        self._packages_sizes = packages_sizes
        self.api = ManagerAPI()

        # Widgets
        self.label = QLabel(self)
        self.combobox_version = QComboBox()
        self.label_version = QLabel(self)
        self.widget_version = None
        self.table_dependencies = None

        self.checkbox = QCheckBox(_("Install dependencies (recommended)"))
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)

        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)

        dialog_size = QSize(300, 90)

        # Helper variable values
        action_title = {
            C.ACTION_UPGRADE: _("Upgrade package"),
            C.ACTION_DOWNGRADE: _("Downgrade package"),
            C.ACTION_REMOVE: _("Remove package"),
            C.ACTION_INSTALL: _("Install package"),
        }

        # FIXME: There is a bug, a package installed by anaconda has version
        # astropy 0.4 and the linked list 0.4 but the available versions
        # in the json file do not include 0.4 but 0.4rc1... so...
        # temporal fix is to check if inside list otherwise show full list
        if action == C.ACTION_UPGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[index + 1 :]
            else:
                versions = versions
        elif action == C.ACTION_DOWNGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[:index]
            else:
                versions = versions
        elif action == C.ACTION_REMOVE:
            combo_versions = [version]
            self.combobox_version.setEnabled(False)
        elif action == C.ACTION_INSTALL:
            combo_versions = versions

        # Reverse order for combobox
        combo_versions = list(reversed(combo_versions))

        if len(versions) == 1:
            if action == C.ACTION_REMOVE:
                labeltext = _("Package version to remove:")
            else:
                labeltext = _("Package version available:")
            self.label_version.setText(combo_versions[0])
            self.widget_version = self.label_version
        else:
            labeltext = _("Select package version:")
            self.combobox_version.addItems(combo_versions)
            self.widget_version = self.combobox_version

        self.label.setText(labeltext)
        self.label_version.setAlignment(Qt.AlignLeft)
        self.table_dependencies = QWidget(self)

        layout = QVBoxLayout()
        version_layout = QHBoxLayout()
        version_layout.addWidget(self.label)
        version_layout.addStretch()
        version_layout.addWidget(self.widget_version)
        layout.addLayout(version_layout)

        self.widgets = [self.checkbox, self.button_ok, self.widget_version, self.table_dependencies]

        # Create a Table
        if action in [C.ACTION_INSTALL, C.ACTION_UPGRADE, C.ACTION_DOWNGRADE]:
            table = QTableView(self)
            dialog_size = QSize(dialog_size.width() + 40, 300)
            self.table_dependencies = table
            layout.addWidget(self.checkbox)
            self.checkbox.setChecked(True)
            self._changed_version(versions[0])

            table.setSelectionBehavior(QAbstractItemView.SelectRows)
            table.verticalHeader().hide()
            table.horizontalHeader().hide()
            table.setAlternatingRowColors(True)
            table.setShowGrid(False)
            table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            table.horizontalHeader().setStretchLastSection(True)

        layout.addWidget(self.table_dependencies)
        layout.addWidget(self.bbox)

        title = "{0}: {1}".format(action_title[action], name)
        self.setLayout(layout)
        self.setMinimumSize(dialog_size)
        self.setFixedSize(dialog_size)
        self.setWindowTitle(title)
        self.setModal(True)

        # Signals and slots
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.close)
        self.combobox_version.currentIndexChanged.connect(self._changed_version)
        self.checkbox.stateChanged.connect(self._changed_checkbox)

    def _changed_version(self, version, dependencies=True):
        """ """
        self._set_gui_disabled(True)
        version = self.combobox_version.currentText()
        install_dependencies = self.checkbox.checkState() == Qt.Checked
        self._version_text = to_text_string(version)
        self._get_dependencies(install_dependencies)

    def _get_dependencies(self, dependencies=True):
        """ """
        package_name = [self._name + "=" + self._version_text]

        worker = self.api.conda_dependencies(
            prefix=self._prefix, pkgs=package_name, dep=dependencies, channels=self._active_channels
        )
        worker.sig_finished.connect(self._on_process_finished)

    def _changed_checkbox(self, state):
        """ """
        if state:
            self._changed_version(self._version_text)
        else:
            self._changed_version(self._version_text, dependencies=False)

    def _on_process_finished(self, worker, output, error):
        """ """
        if self.isVisible():
            dic = output
            self.dependencies_dic = dic
            self._set_dependencies_table()
            self._set_gui_disabled(False)

    def _set_dependencies_table(self):
        """ """
        table = self.table_dependencies
        dic = self.dependencies_dic
        table.setModel(CondaDependenciesModel(self, dic, self._packages_sizes))
        table.resizeColumnsToContents()
        table.resizeRowsToContents()

    def _set_gui_disabled(self, value):
        """ """
        if value:
            table = self.table_dependencies
            table.setModel(CondaDependenciesModel(self, {}))
            table.resizeColumnsToContents()
            table.setDisabled(True)
        else:
            table = self.table_dependencies
            table.setDisabled(False)

        for widget in self.widgets:
            widget.setDisabled(value)

    def reject(self):
        self.api.conda_terminate()
        super(CondaPackageActionDialog, self).reject()
コード例 #32
0
ファイル: layoutdialog.py プロジェクト: 0xBADCA7/spyder
class LayoutSettingsDialog(QDialog):
    """Layout settings dialog"""
    def __init__(self, parent, names, order, active):
        super(LayoutSettingsDialog, self).__init__(parent)

        # variables
        self._parent = parent
        self._selection_model = None
        self.names = names
        self.order = order
        self.active = active

        # widgets
        self.button_move_up = QPushButton(_('Move Up'))
        self.button_move_down = QPushButton(_('Move Down'))
        self.button_delete = QPushButton(_('Delete Layout'))
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
                                           QDialogButtonBox.Cancel,
                                           Qt.Horizontal, self)
        self.group_box = QGroupBox(_("Layout Display and Order"))
        self.table = QTableView(self)
        self.ok_button = self.button_box.button(QDialogButtonBox.Ok)
        self.cancel_button = self.button_box.button(QDialogButtonBox.Cancel)
        self.cancel_button.setDefault(True)
        self.cancel_button.setAutoDefault(True)

        # widget setup
        self.dialog_size = QSize(300, 200)
        self.setMinimumSize(self.dialog_size)
        self.setFixedSize(self.dialog_size)
        self.setWindowTitle('Layout Settings')

        self.table.setModel(LayoutModel(self.table, order, active))
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.verticalHeader().hide()
        self.table.horizontalHeader().hide()
        self.table.setAlternatingRowColors(True)
        self.table.setShowGrid(False)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.setColumnHidden(1, True)
        
        # need to keep a reference for pyside not to segfault!
        self._selection_model = self.table.selectionModel()

        # layout
        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(self.button_move_up)
        buttons_layout.addWidget(self.button_move_down)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self.button_delete)

        group_layout = QHBoxLayout()
        group_layout.addWidget(self.table)
        group_layout.addLayout(buttons_layout)
        self.group_box.setLayout(group_layout)

        layout = QVBoxLayout()
        layout.addWidget(self.group_box)
        layout.addWidget(self.button_box)

        self.setLayout(layout)

        # signals and slots
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.close)
        self.button_delete.clicked.connect(self.delete_layout)
        self.button_move_up.clicked.connect(lambda: self.move_layout(True))
        self.button_move_down.clicked.connect(lambda: self.move_layout(False))
        self.table.model().dataChanged.connect(
           lambda: self.selection_changed(None, None))
        self._selection_model.selectionChanged.connect(
           lambda: self.selection_changed(None, None))

        # focus table
        index = self.table.model().index(0, 0)
        self.table.setCurrentIndex(index)
        self.table.setFocus()

    def delete_layout(self):
        """ """
        names, order, active = self.names, self.order, self.order
        name = from_qvariant(self.table.selectionModel().currentIndex().data(),
                             to_text_string)

        if name in names:
            index = names.index(name)
            # In case nothing has focus in the table
        if index != -1:
            order.remove(name)
            names[index] = None
            if name in active:
                active.remove(name)
            self.names, self.order, self.active = names, order, active
            self.table.model().set_data(order, active)
            index = self.table.model().index(0, 0)
            self.table.setCurrentIndex(index)
            self.table.setFocus()
            self.selection_changed(None, None)
            if len(order) == 0:
                self.button_move_up.setDisabled(True)
                self.button_move_down.setDisabled(True)
                self.button_delete.setDisabled(True)

    def move_layout(self, up=True):
        """ """
        names, order, active = self.names, self.order, self.active
        row = self.table.selectionModel().currentIndex().row()
        row_new = row

        if up:
            row_new -= 1
        else:
            row_new += 1

        order[row], order[row_new] = order[row_new], order[row]

        self.order = order
        self.table.model().set_data(order, active)
        index = self.table.model().index(row_new, 0)
        self.table.setCurrentIndex(index)
        self.table.setFocus()
        self.selection_changed(None, None)

    def selection_changed(self, selection, deselection):
        """ """
        model = self.table.model()
        index = self.table.currentIndex()
        row = index.row()
        order, names, active = self.order, self.names, self.active

        state = model.row(row)[1]
        name = model.row(row)[0]

        # Check if name changed
        if name not in names:  # Did changed
            if row != -1:  # row == -1, means no items left to delete
                old_name = order[row]
                order[row] = name
                names[names.index(old_name)] = name
                if old_name in active:
                    active[active.index(old_name)] = name

        # Check if checbox clicked
        if state:
            if name not in active:
                active.append(name)
        else:
            if name in active:
                active.remove(name)

        self.active = active
        self.button_move_up.setDisabled(False)
        self.button_move_down.setDisabled(False)

        if row == 0:
            self.button_move_up.setDisabled(True)
        if row == len(names) - 1:
            self.button_move_down.setDisabled(True)
        if len(names) == 0:
            self.button_move_up.setDisabled(True)
            self.button_move_down.setDisabled(True)
コード例 #33
0
ファイル: fileassociations.py プロジェクト: nixjdm/spyder
class ApplicationsDialog(QDialog):
    """Dialog for selection of installed system/user applications."""
    def __init__(self, parent=None):
        """Dialog for selection of installed system/user applications."""
        super(ApplicationsDialog, self).__init__(parent=parent)

        # Widgets
        self.label = QLabel()
        self.label_browse = QLabel()
        self.edit_filter = QLineEdit()
        self.list = QListWidget()
        self.button_browse = QPushButton(_('Browse...'))
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
        self.button_cancel = self.button_box.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setWindowTitle(_('Applications'))
        self.edit_filter.setPlaceholderText(_('Type to filter by name'))
        self.list.setIconSize(QSize(16, 16))  # FIXME: Use metrics

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.edit_filter)
        layout.addWidget(self.list)
        layout_browse = QHBoxLayout()
        layout_browse.addWidget(self.button_browse)
        layout_browse.addWidget(self.label_browse)
        layout.addLayout(layout_browse)
        layout.addSpacing(12)  # FIXME: Use metrics
        layout.addWidget(self.button_box)
        self.setLayout(layout)

        # Signals
        self.edit_filter.textChanged.connect(self.filter)
        self.button_browse.clicked.connect(lambda x: self.browse())
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)
        self.list.currentItemChanged.connect(self._refresh)

        self._refresh()
        self.setup()

    def setup(self, applications=None):
        """Load installed applications."""
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.list.clear()
        if applications is None:
            apps = get_installed_applications()
        else:
            apps = applications

        for app in sorted(apps, key=lambda x: x.lower()):
            fpath = apps[app]
            icon = get_application_icon(fpath)
            item = QListWidgetItem(icon, app)
            item.setToolTip(fpath)
            item.fpath = fpath
            self.list.addItem(item)

        # FIXME: Use metrics
        self.list.setMinimumWidth(self.list.sizeHintForColumn(0) + 24)
        QApplication.restoreOverrideCursor()
        self._refresh()

    def _refresh(self):
        """Refresh the status of buttons on widget."""
        self.button_ok.setEnabled(self.list.currentRow() != -1)

    def browse(self, fpath=None):
        """Prompt user to select an application not found on the list."""
        app = None
        item = None

        if sys.platform == 'darwin':
            if fpath is None:
                basedir = '/Applications/'
                filters = _('Applications (*.app)')
                title = _('Select application')
                fpath, __ = getopenfilename(self, title, basedir, filters)

            if fpath and fpath.endswith('.app') and os.path.isdir(fpath):
                app = os.path.basename(fpath).split('.app')[0]
                for row in range(self.list.count()):
                    item = self.list.item(row)
                    if app == item.text() and fpath == item.fpath:
                        break
                else:
                    item = None
        elif os.name == 'nt':
            if fpath is None:
                basedir = 'C:\\'
                filters = _('Applications (*.exe *.bat *.com)')
                title = _('Select application')
                fpath, __ = getopenfilename(self, title, basedir, filters)

            if fpath:
                check_1 = fpath.endswith('.bat') and is_text_file(fpath)
                check_2 = (fpath.endswith(('.exe', '.com'))
                           and not is_text_file(fpath))
                if check_1 or check_2:
                    app = os.path.basename(fpath).capitalize().rsplit('.')[0]
                    for row in range(self.list.count()):
                        item = self.list.item(row)
                        if app == item.text() and fpath == item.fpath:
                            break
                    else:
                        item = None
        else:
            if fpath is None:
                basedir = '/'
                filters = _('Applications (*.desktop)')
                title = _('Select application')
                fpath, __ = getopenfilename(self, title, basedir, filters)

            if fpath and fpath.endswith(('.desktop')) and is_text_file(fpath):
                entry_data = parse_linux_desktop_entry(fpath)
                app = entry_data['name']
                for row in range(self.list.count()):
                    item = self.list.item(row)
                    if app == item.text() and fpath == item.fpath:
                        break
                else:
                    item = None

        if fpath:
            if item:
                self.list.setCurrentItem(item)
            elif app:
                icon = get_application_icon(fpath)
                item = QListWidgetItem(icon, app)
                item.fpath = fpath
                self.list.addItem(item)
                self.list.setCurrentItem(item)

        self.list.setFocus()
        self._refresh()

    def filter(self, text):
        """Filter the list of applications based on text."""
        text = self.edit_filter.text().lower().strip()
        for row in range(self.list.count()):
            item = self.list.item(row)
            item.setHidden(text not in item.text().lower())
        self._refresh()

    def set_extension(self, extension):
        """Set the extension on the label of the dialog."""
        self.label.setText(
            _('Choose the application for files of type ') + extension)

    @property
    def application_path(self):
        """Return the selected application path to executable."""
        item = self.list.currentItem()
        path = item.fpath if item else ''
        return path

    @property
    def application_name(self):
        """Return the selected application name."""
        item = self.list.currentItem()
        text = item.text() if item else ''
        return text
コード例 #34
0
    def __init__(self):

        super().__init__()

        self.resize(400, 200)
        self.setWindowTitle("Load Run From Database")

        self._id_uid = None
        self._mode_id_uid = "id"

        label = QLabel("Enter run ID or UID:")
        self.le_id_uid = LineEditExtended()
        self.le_id_uid.textChanged.connect(self.le_id_uid_text_changed)
        self.le_id_uid.editingFinished.connect(self.le_id_uid_editing_finished)
        set_tooltip(self.le_id_uid, "Enter <b>Run ID</b> or <b>Run UID</b>.")

        self._validator_id = IntValidatorStrict()
        # Short UID example: "04c9afa7"
        self._validator_uid_short = QRegExpValidator(QRegExp(r"[0-9a-f]{8}"))
        # Full UID example: "04c9afa7-a43a-4af1-8e55-2034384d4a77"
        self._validator_uid_full = QRegExpValidator(
            QRegExp(
                r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
            ))

        self.rb_id = QRadioButton("Run ID")
        set_tooltip(
            self.rb_id,
            "The value in the line edit box is <b>Run ID</b> (e.g. <b>34235</b> or <b>-1</b>)"
        )
        self.rb_id.setChecked(self._mode_id_uid == "id")
        self.rb_uid = QRadioButton("Run UID")
        self.rb_uid.setChecked(self._mode_id_uid == "uid")
        set_tooltip(
            self.rb_uid,
            "The value in the line edit box is <b>Run UID</b> "
            "(e.g. <b>04c9afb7-a43a-4af1-8e55-2034384d4a77</b> or <b>04c9afb7</b>)",
        )

        self.btn_group = QButtonGroup()
        self.btn_group.addButton(self.rb_id)
        self.btn_group.addButton(self.rb_uid)
        self.btn_group.buttonToggled.connect(self.btn_group_button_toggled)

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        self.pb_ok = button_box.button(QDialogButtonBox.Ok)

        vbox = QVBoxLayout()

        vbox.addStretch(1)

        hbox = QHBoxLayout()
        hbox.addWidget(label)
        hbox.addStretch(1)
        vbox.addLayout(hbox)
        vbox.addWidget(self.le_id_uid)

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.rb_id)
        hbox.addStretch(1)
        hbox.addWidget(self.rb_uid)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        vbox.addStretch(1)
        vbox.addWidget(button_box)
        self.setLayout(vbox)

        # This is how the button from QDialogButtonBox can be disabled
        # button_box.button(QDialogButtonBox.Ok).setEnabled(False)

        self.le_id_uid.setText("")
        self._validate_id_uid()
コード例 #35
0
ファイル: epochdialog.py プロジェクト: ECGKit/mnelab
class EpochDialog(QDialog):
    def __init__(self, parent, events):
        super().__init__(parent)
        self.setWindowTitle("Create Epochs")

        grid = QGridLayout(self)
        label = QLabel("Events:")
        label.setAlignment(Qt.AlignTop)
        grid.addWidget(label, 0, 0, 1, 1)

        self.events = QListWidget()
        self.events.insertItems(0, unique(events[:, 2]).astype(str))
        self.events.setSelectionMode(QListWidget.ExtendedSelection)
        grid.addWidget(self.events, 0, 1, 1, 2)

        grid.addWidget(QLabel("Interval around events:"), 1, 0, 1, 1)
        self.tmin = QDoubleSpinBox()
        self.tmin.setMinimum(-10000)
        self.tmin.setValue(-0.2)
        self.tmin.setSingleStep(0.1)
        self.tmin.setAlignment(Qt.AlignRight)
        self.tmax = QDoubleSpinBox()
        self.tmax.setMinimum(-10000)
        self.tmax.setValue(0.5)
        self.tmax.setSingleStep(0.1)
        self.tmax.setAlignment(Qt.AlignRight)
        grid.addWidget(self.tmin, 1, 1, 1, 1)
        grid.addWidget(self.tmax, 1, 2, 1, 1)

        self.baseline = QCheckBox("Baseline Correction:")
        self.baseline.setChecked(True)
        self.baseline.stateChanged.connect(self.toggle_baseline)
        grid.addWidget(self.baseline, 2, 0, 1, 1)
        self.a = QDoubleSpinBox()
        self.a.setMinimum(-10000)
        self.a.setValue(-0.2)
        self.a.setSingleStep(0.1)
        self.a.setAlignment(Qt.AlignRight)
        self.b = QDoubleSpinBox()
        self.b.setMinimum(-10000)
        self.b.setValue(0)
        self.b.setSingleStep(0.1)
        self.b.setAlignment(Qt.AlignRight)
        grid.addWidget(self.a, 2, 1, 1, 1)
        grid.addWidget(self.b, 2, 2, 1, 1)
        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonbox.accepted.connect(self.accept)
        self.buttonbox.rejected.connect(self.reject)
        grid.addWidget(self.buttonbox, 3, 0, 1, -1)
        self.events.itemSelectionChanged.connect(self.toggle_ok)
        self.toggle_ok()
        grid.setSizeConstraint(QGridLayout.SetFixedSize)

    @Slot()
    def toggle_ok(self):
        if self.events.selectedItems():
            self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(True)
        else:
            self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(False)

    @Slot()
    def toggle_baseline(self):
        if self.baseline.isChecked():
            self.a.setEnabled(True)
            self.b.setEnabled(True)
        else:
            self.a.setEnabled(False)
            self.b.setEnabled(False)
コード例 #36
0
ファイル: pathmanager.py プロジェクト: ubuntu11/spyder
class PathManager(QDialog):
    """Path manager dialog."""
    redirect_stdio = Signal(bool)
    sig_path_changed = Signal(object)

    def __init__(self,
                 parent,
                 path=None,
                 read_only_path=None,
                 not_active_path=None,
                 sync=True):
        """Path manager dialog."""
        super(PathManager, self).__init__(parent)
        assert isinstance(path, (tuple, None))

        self.path = path or ()
        self.read_only_path = read_only_path or ()
        self.not_active_path = not_active_path or ()
        self.last_path = getcwd_or_home()
        self.original_path_dict = None

        # Widgets
        self.add_button = None
        self.remove_button = None
        self.movetop_button = None
        self.moveup_button = None
        self.movedown_button = None
        self.movebottom_button = None
        self.sync_button = None
        self.selection_widgets = []
        self.top_toolbar_widgets = self._setup_top_toolbar()
        self.bottom_toolbar_widgets = self._setup_bottom_toolbar()
        self.listwidget = QListWidget(self)
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)

        # Widget setup
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle(_("PYTHONPATH manager"))
        self.setWindowIcon(ima.icon('pythonpath'))
        self.resize(500, 300)
        self.sync_button.setVisible(os.name == 'nt' and sync)

        # Layouts
        top_layout = QHBoxLayout()
        self._add_widgets_to_layout(self.top_toolbar_widgets, top_layout)

        bottom_layout = QHBoxLayout()
        self._add_widgets_to_layout(self.bottom_toolbar_widgets, bottom_layout)
        bottom_layout.addWidget(self.bbox)

        layout = QVBoxLayout()
        layout.addLayout(top_layout)
        layout.addWidget(self.listwidget)
        layout.addLayout(bottom_layout)
        self.setLayout(layout)

        # Signals
        self.listwidget.currentRowChanged.connect(lambda x: self.refresh())
        self.listwidget.itemChanged.connect(lambda x: self.refresh())
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Setup
        self.setup()

    def _add_widgets_to_layout(self, widgets, layout):
        """Helper to add toolbar widgets to top and bottom layout."""
        layout.setAlignment(Qt.AlignLeft)
        for widget in widgets:
            if widget is None:
                layout.addStretch(1)
            else:
                layout.addWidget(widget)

    def _setup_top_toolbar(self):
        """Create top toolbar and actions."""
        self.movetop_button = create_toolbutton(
            self,
            text=_("Move to top"),
            icon=ima.icon('2uparrow'),
            triggered=lambda: self.move_to(absolute=0),
            text_beside_icon=True)
        self.moveup_button = create_toolbutton(
            self,
            text=_("Move up"),
            icon=ima.icon('1uparrow'),
            triggered=lambda: self.move_to(relative=-1),
            text_beside_icon=True)
        self.movedown_button = create_toolbutton(
            self,
            text=_("Move down"),
            icon=ima.icon('1downarrow'),
            triggered=lambda: self.move_to(relative=1),
            text_beside_icon=True)
        self.movebottom_button = create_toolbutton(
            self,
            text=_("Move to bottom"),
            icon=ima.icon('2downarrow'),
            triggered=lambda: self.move_to(absolute=1),
            text_beside_icon=True)

        toolbar = [
            self.movetop_button, self.moveup_button, self.movedown_button,
            self.movebottom_button
        ]
        self.selection_widgets.extend(toolbar)
        return toolbar

    def _setup_bottom_toolbar(self):
        """Create bottom toolbar and actions."""
        self.add_button = create_toolbutton(
            self,
            text=_('Add path'),
            icon=ima.icon('edit_add'),
            triggered=lambda x: self.add_path(),
            text_beside_icon=True)
        self.remove_button = create_toolbutton(
            self,
            text=_('Remove path'),
            icon=ima.icon('edit_remove'),
            triggered=lambda x: self.remove_path(),
            text_beside_icon=True)
        self.sync_button = create_toolbutton(
            self,
            text=_("Synchronize..."),
            icon=ima.icon('fileimport'),
            triggered=self.synchronize,
            tip=_("Synchronize Spyder's path list with PYTHONPATH "
                  "environment variable"),
            text_beside_icon=True)

        self.selection_widgets.append(self.remove_button)
        return [self.add_button, self.remove_button, None, self.sync_button]

    def _create_item(self, path):
        """Helper to create a new list item."""
        item = QListWidgetItem(path)
        item.setIcon(ima.icon('DirClosedIcon'))

        if path in self.read_only_path:
            item.setFlags(Qt.NoItemFlags | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Checked)
        elif path in self.not_active_path:
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
        else:
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Checked)

        return item

    @property
    def editable_bottom_row(self):
        """Maximum bottom row count that is editable."""
        read_only_count = len(self.read_only_path)
        if read_only_count == 0:
            max_row = self.listwidget.count() - 1
        else:
            max_row = self.listwidget.count() - read_only_count - 1
        return max_row

    def setup(self):
        """Populate list widget."""
        self.listwidget.clear()
        for path in self.path + self.read_only_path:
            item = self._create_item(path)
            self.listwidget.addItem(item)
        self.listwidget.setCurrentRow(0)
        self.original_path_dict = self.get_path_dict()
        self.refresh()

    @Slot()
    def synchronize(self):
        """
        Synchronize Spyder's path list with PYTHONPATH environment variable
        Only apply to: current user, on Windows platforms.
        """
        answer = QMessageBox.question(
            self, _("Synchronize"),
            _("This will synchronize Spyder's path list with "
              "<b>PYTHONPATH</b> environment variable for the current user, "
              "allowing you to run your Python modules outside Spyder "
              "without having to configure sys.path. "
              "<br>"
              "Do you want to clear contents of PYTHONPATH before "
              "adding Spyder's path list?"),
            QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)

        if answer == QMessageBox.Cancel:
            return
        elif answer == QMessageBox.Yes:
            remove = True
        else:
            remove = False

        from spyder.utils.environ import (get_user_env, listdict2envdict,
                                          set_user_env)
        env = get_user_env()

        # Includes read only paths
        active_path = tuple(k for k, v in self.get_path_dict(True).items()
                            if v)

        if remove:
            ppath = active_path
        else:
            ppath = env.get('PYTHONPATH', [])
            if not isinstance(ppath, list):
                ppath = [ppath]

            ppath = tuple(p for p in ppath if p not in active_path)
            ppath = ppath + active_path

        env['PYTHONPATH'] = list(ppath)
        set_user_env(listdict2envdict(env), parent=self)

    def get_path_dict(self, read_only=False):
        """
        Return an ordered dict with the path entries as keys and the active
        state as the value.

        If `read_only` is True, the read_only entries are also included.
        `read_only` entry refers to the project path entry.
        """
        odict = OrderedDict()
        for row in range(self.listwidget.count()):
            item = self.listwidget.item(row)
            path = item.text()
            if path in self.read_only_path and not read_only:
                continue
            odict[path] = item.checkState() == Qt.Checked
        return odict

    def refresh(self):
        """Refresh toolbar widgets."""
        enabled = self.listwidget.currentItem() is not None
        for widget in self.selection_widgets:
            widget.setEnabled(enabled)

        # Disable buttons based on row
        row = self.listwidget.currentRow()
        disable_widgets = []

        # Move up/top disabled for top item
        if row == 0:
            disable_widgets.extend([self.movetop_button, self.moveup_button])

        # Move down/bottom disabled for bottom item
        if row == self.editable_bottom_row:
            disable_widgets.extend(
                [self.movebottom_button, self.movedown_button])
        for widget in disable_widgets:
            widget.setEnabled(False)

        self.sync_button.setEnabled(self.listwidget.count() > 0)

        # Ok button only enabled if actual changes occur
        self.button_ok.setEnabled(
            self.original_path_dict != self.get_path_dict())

    def check_path(self, path):
        """Check that the path is not a [site|dist]-packages folder."""
        if os.name == 'nt':
            pat = re.compile(r'.*lib/(?:site|dist)-packages.*')
        else:
            pat = re.compile(r'.*lib/python.../(?:site|dist)-packages.*')

        path_norm = path.replace('\\', '/')
        return pat.match(path_norm) is None

    @Slot()
    def add_path(self, directory=None):
        """
        Add path to list widget.

        If `directory` is provided, the folder dialog is overridden.
        """
        if directory is None:
            self.redirect_stdio.emit(False)
            directory = getexistingdirectory(self, _("Select directory"),
                                             self.last_path)
            self.redirect_stdio.emit(True)

        if PY2:
            is_unicode = False
            try:
                directory.decode('ascii')
            except (UnicodeEncodeError, UnicodeDecodeError):
                is_unicode = True

            if is_unicode:
                QMessageBox.warning(
                    self, _("Add path"),
                    _("You are using Python 2 and the selected path has "
                      "Unicode characters."
                      "<br> "
                      "Therefore, this path will not be added."),
                    QMessageBox.Ok)
                return

        directory = osp.abspath(directory)
        self.last_path = directory

        if directory in self.get_path_dict():
            item = self.listwidget.findItems(directory, Qt.MatchExactly)[0]
            item.setCheckState(Qt.Checked)
            answer = QMessageBox.question(
                self, _("Add path"),
                _("This directory is already included in the list."
                  "<br> "
                  "Do you want to move it to the top of it?"),
                QMessageBox.Yes | QMessageBox.No)

            if answer == QMessageBox.Yes:
                item = self.listwidget.takeItem(self.listwidget.row(item))
                self.listwidget.insertItem(0, item)
                self.listwidget.setCurrentRow(0)
        else:
            if self.check_path(directory):
                item = self._create_item(directory)
                self.listwidget.insertItem(0, item)
                self.listwidget.setCurrentRow(0)
            else:
                answer = QMessageBox.warning(
                    self, _("Add path"),
                    _("This directory cannot be added to the path!"
                      "<br><br>"
                      "If you want to set a different Python interpreter, "
                      "please go to <tt>Preferences > Main interpreter</tt>"
                      "."), QMessageBox.Ok)

        self.refresh()

    @Slot()
    def remove_path(self, force=False):
        """
        Remove path from list widget.

        If `force` is True, the message box is overridden.
        """
        if self.listwidget.currentItem():
            if not force:
                answer = QMessageBox.warning(
                    self, _("Remove path"),
                    _("Do you really want to remove the selected path?"),
                    QMessageBox.Yes | QMessageBox.No)

            if force or answer == QMessageBox.Yes:
                self.listwidget.takeItem(self.listwidget.currentRow())
                self.refresh()

    def move_to(self, absolute=None, relative=None):
        """Move items of list widget."""
        index = self.listwidget.currentRow()
        if absolute is not None:
            if absolute:
                new_index = self.listwidget.count() - 1
            else:
                new_index = 0
        else:
            new_index = index + relative

        new_index = max(0, min(self.editable_bottom_row, new_index))
        item = self.listwidget.takeItem(index)
        self.listwidget.insertItem(new_index, item)
        self.listwidget.setCurrentRow(new_index)
        self.refresh()

    def current_row(self):
        """Returns the current row of the list."""
        return self.listwidget.currentRow()

    def set_current_row(self, row):
        """Set the current row of the list."""
        self.listwidget.setCurrentRow(row)

    def row_check_state(self, row):
        """Return the checked state for item in row."""
        item = self.listwidget.item(row)
        return item.checkState()

    def set_row_check_state(self, row, value):
        """Set the current checked state for item in row."""
        item = self.listwidget.item(row)
        item.setCheckState(value)

    def count(self):
        """Return the number of items."""
        return self.listwidget.count()

    def accept(self):
        """Override Qt method."""
        path_dict = self.get_path_dict()
        if self.original_path_dict != path_dict:
            self.sig_path_changed.emit(path_dict)
        super(PathManager, self).accept()
コード例 #37
0
ファイル: dlg_load_mask.py プロジェクト: mrakitin/PyXRF
class DialogLoadMask(QDialog):
    """
    Dialog box for selecting spatial ROI and mask.

    Typical use:

    default_dir = "/home/user/data"
    n_rows, n_columns = 15, 20  # Some values

    # Values that are changed by the dialog box
    roi = (2, 3, 11, 9)
    use_roi = True
    mask_f_path = ""
    use_mask = False

    dlg = DialogLoadMask()
    dlg.set_image_size(n_rows=n_rows, n_columns=n_columns)
    dlg.set_roi(row_start=roi[0], column_start=roi[1], row_end=roi[2], column_end=roi[3])
    dlg.set_roi_active(use_roi)

    dlg.set_default_directory(default_dir)
    dlg.set_mask_file_path(mask_f_path)
    dlg.set_mask_file_active(use_mask)

    if dlg.exec() == QDialog.Accepted:
        # If success, then read the values back. Discard changes if rejected.
        roi = dlg.get_roi()
        use_roi = dlg.get_roi_active()
        mask_f_path = dlg.get_mask_file_path()
        use_mask = dlg.get_mask_file_active()
    """
    def __init__(self):

        super().__init__()

        self._validation_enabled = False

        self.resize(500, 300)
        self.setWindowTitle("Load Mask or Select ROI")

        # Initialize variables used with ROI selection group
        self._n_rows = 0
        self._n_columns = 0
        self._roi_active = False
        self._row_start = -1
        self._column_start = -1
        self._row_end = -1
        self._column_end = -1
        # ... with Mask group
        self._mask_active = False
        self._mask_file_path = ""
        self._default_directory = ""

        # Fields for entering spatial ROI coordinates
        self.validator_rows = QIntValidator()
        self.validator_rows.setBottom(1)
        self.validator_cols = QIntValidator()
        self.validator_cols.setBottom(1)

        self.le_roi_start_row = LineEditExtended()
        self.le_roi_start_row.setValidator(self.validator_rows)
        self.le_roi_start_row.editingFinished.connect(
            self.le_roi_start_row_editing_finished)
        self.le_roi_start_row.textChanged.connect(
            self.le_roi_start_row_text_changed)
        self.le_roi_start_col = LineEditExtended()
        self.le_roi_start_col.setValidator(self.validator_cols)
        self.le_roi_start_col.editingFinished.connect(
            self.le_roi_start_col_editing_finished)
        self.le_roi_start_col.textChanged.connect(
            self.le_roi_start_col_text_changed)
        self.le_roi_end_row = LineEditExtended()
        self.le_roi_end_row.setValidator(self.validator_rows)
        self.le_roi_end_row.editingFinished.connect(
            self.le_roi_end_row_editing_finished)
        self.le_roi_end_row.textChanged.connect(
            self.le_roi_end_row_text_changed)
        self.le_roi_end_col = LineEditExtended()
        self.le_roi_end_col.setValidator(self.validator_cols)
        self.le_roi_end_col.editingFinished.connect(
            self.le_roi_end_col_editing_finished)
        self.le_roi_end_col.textChanged.connect(
            self.le_roi_end_col_text_changed)
        self._text_map_size_base = "   * Map size: "
        self.label_map_size = QLabel(self._text_map_size_base + "not set")

        # Group box for spatial ROI selection
        self.gb_roi = QGroupBox("Select ROI (in pixels)")
        set_tooltip(
            self.gb_roi,
            "Select rectangular <b>spatial ROI</b>. If <b>mask</b> is "
            "loaded, then ROI is applied to the masked data.",
        )
        self.gb_roi.setCheckable(True)
        self.gb_roi.toggled.connect(self.gb_roi_toggled)
        self.gb_roi.setChecked(self._roi_active)
        vbox = QVBoxLayout()
        grid = QGridLayout()
        grid.addWidget(QLabel("Start position(*):"), 0, 0)
        grid.addWidget(QLabel("row"), 0, 1)
        grid.addWidget(self.le_roi_start_row, 0, 2)
        grid.addWidget(QLabel("column"), 0, 3)
        grid.addWidget(self.le_roi_start_col, 0, 4)
        grid.addWidget(QLabel("End position(*):"), 1, 0)
        grid.addWidget(QLabel("row"), 1, 1)
        grid.addWidget(self.le_roi_end_row, 1, 2)
        grid.addWidget(QLabel("column"), 1, 3)
        grid.addWidget(self.le_roi_end_col, 1, 4)
        vbox.addLayout(grid)
        vbox.addWidget(self.label_map_size)
        self.gb_roi.setLayout(vbox)

        # Widgets for loading mask
        self.pb_load_mask = QPushButton("Load Mask ...")
        self.pb_load_mask.clicked.connect(self.pb_load_mask_clicked)
        self._le_load_mask_default_text = "select 'mask' file"
        self.le_load_mask = LineEditReadOnly(self._le_load_mask_default_text)

        # Group box for setting mask
        self.gb_mask = QGroupBox("Set mask")
        set_tooltip(
            self.gb_mask,
            "Load <b>mask</b> from file. Active pixels in the mask are "
            "represented by positive integers. If <b>spatial ROI</b> is "
            "selected, then it is applied to the masked data.",
        )
        self.gb_mask.setCheckable(True)
        self.gb_mask.toggled.connect(self.gb_mask_toggled)
        self.gb_mask.setChecked(self._mask_active)
        hbox = QHBoxLayout()
        hbox.addWidget(self.pb_load_mask)
        hbox.addWidget(self.le_load_mask)
        self.gb_mask.setLayout(hbox)

        # Yes/No button box
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_ok = self.button_box.button(QDialogButtonBox.Ok)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        vbox = QVBoxLayout()
        vbox.addWidget(self.gb_roi)
        vbox.addStretch(1)
        vbox.addWidget(self.gb_mask)
        vbox.addStretch(2)
        vbox.addWidget(self.button_box)
        self.setLayout(vbox)

        self._validation_enabled = True
        self._validate_all_widgets()

    def _compute_home_directory(self):
        dir_name = "."
        if self._default_directory:
            dir_name = self._default_directory
        if self._mask_file_path:
            d, _ = os.path.split(self._mask_file_path)
            dir_name = d if d else dir_name
        return dir_name

    def pb_load_mask_clicked(self):
        dir_name = self._compute_home_directory()
        file_name = QFileDialog.getOpenFileName(self, "Load Mask From File",
                                                dir_name, "All (*)")
        file_name = file_name[0]
        if file_name:
            self._mask_file_path = file_name
            self._show_mask_file_path()
            logger.debug(f"Mask file is selected: '{file_name}'")

    def gb_roi_toggled(self, state):
        self._roi_activate(state)

    def _read_le_roi_value(self, line_edit, v_default):
        """
        Attempt to read value from line edit box as int, return `v_default` if not successful.

        Parameters
        ----------
        line_edit: QLineEdit
            reference to QLineEdit object
        v_default: int
            default value returned if the value read from edit box is incorrect
        """
        try:
            val = int(line_edit.text())
            if val < 1:
                raise Exception()
        except Exception:
            val = v_default
        return val

    def le_roi_start_row_editing_finished(self):
        self._row_start = self._read_le_roi_value(self.le_roi_start_row,
                                                  self._row_start + 1) - 1

    def le_roi_end_row_editing_finished(self):
        self._row_end = self._read_le_roi_value(self.le_roi_end_row,
                                                self._row_end)

    def le_roi_start_col_editing_finished(self):
        self._column_start = self._read_le_roi_value(
            self.le_roi_start_col, self._column_start + 1) - 1

    def le_roi_end_col_editing_finished(self):
        self._column_end = self._read_le_roi_value(self.le_roi_end_col,
                                                   self._column_end)

    def le_roi_start_row_text_changed(self):
        self._validate_all_widgets()

    def le_roi_end_row_text_changed(self):
        self._validate_all_widgets()

    def le_roi_start_col_text_changed(self):
        self._validate_all_widgets()

    def le_roi_end_col_text_changed(self):
        self._validate_all_widgets()

    def gb_mask_toggled(self, state):
        self._mask_file_activate(state)

    def _validate_all_widgets(self):
        """
        Validate the values and state of all widgets, update the 'valid' state
        of the widgets and enable/disable Ok button.
        """

        if not self._validation_enabled:
            return

        # Check if all fields have valid input values
        def _check_valid_input(line_edit, flag_valid):
            val = self._read_le_roi_value(line_edit, -1)
            state = val > 0
            line_edit.setValid(state)
            flag_valid = flag_valid if state else False
            return val, flag_valid

        # Set all line edits to 'valid' state
        self.le_roi_start_row.setValid(True)
        self.le_roi_end_row.setValid(True)
        self.le_roi_start_col.setValid(True)
        self.le_roi_end_col.setValid(True)
        self.le_load_mask.setValid(True)

        flag_valid = True

        if self._roi_active:
            # Perform the following checks only if ROI group is active
            rs, flag_valid = _check_valid_input(self.le_roi_start_row,
                                                flag_valid)
            re, flag_valid = _check_valid_input(self.le_roi_end_row,
                                                flag_valid)
            cs, flag_valid = _check_valid_input(self.le_roi_start_col,
                                                flag_valid)
            ce, flag_valid = _check_valid_input(self.le_roi_end_col,
                                                flag_valid)

            # Check if start
            if (rs > 0) and (re > 0) and (rs > re):
                self.le_roi_start_row.setValid(False)
                self.le_roi_end_row.setValid(False)
                flag_valid = False
            if (cs > 0) and (ce > 0) and (cs > ce):
                self.le_roi_start_col.setValid(False)
                self.le_roi_end_col.setValid(False)
                flag_valid = False

        if self._mask_active:
            if not self._mask_file_path:
                self.le_load_mask.setValid(False)
                flag_valid = False

        self.button_ok.setEnabled(flag_valid)

    def set_image_size(self, *, n_rows, n_columns):
        """
        Set the image size. Image size is used to for input validation. When image
        size is set, the selection is reset to cover the whole image.

        Parameters
        ----------
        n_rows: int
            The number of rows in the image: (1..)
        n_columns: int
            The number of columns in the image: (1..)
        """
        if n_rows < 1 or n_columns < 1:
            raise ValueError(
                "DialogLoadMask: image size have zero rows or zero columns: "
                f"n_rows={n_rows} n_columns={n_columns}. "
                "Report the error to the development team.")

        self._n_rows = n_rows
        self._n_columns = n_columns

        self._row_start = 0
        self._row_end = n_rows
        self._column_start = 0
        self._column_end = n_columns

        self._show_selection(True)
        self._validate_all_widgets()

        self.validator_rows.setTop(n_rows)
        self.validator_cols.setTop(n_columns)
        # Set label
        self.label_map_size.setText(
            f"{self._text_map_size_base}{self._n_rows} rows, {self._n_columns} columns."
        )

    def _show_selection(self, visible):
        """visible: True - show values, False - hide values"""
        def _show_number(l_edit, value):
            if value > 0:
                l_edit.setText(f"{value}")
            else:
                # This would typically mean incorrect initialization of the dialog box
                l_edit.setText("")

        _show_number(self.le_roi_start_row, self._row_start + 1)
        _show_number(self.le_roi_start_col, self._column_start + 1)
        _show_number(self.le_roi_end_row, self._row_end)
        _show_number(self.le_roi_end_col, self._column_end)

    def set_roi(self, *, row_start, column_start, row_end, column_end):
        """
        Set the values of fields that define selection of the image region. First set
        the image size (`set_image_size()`) and then set the selection.

        Parameters
        ----------
        row_start: int
            The row number of the first pixel in the selection (0..n_rows-1).
            Negative (-1) - resets value to 0.
        column_start: int
            The column number of the first pixel in the selection (0..n_columns-1).
            Negative (-1) - resets value to 0.
        row_end: int
            The row number following the last pixel in the selection (1..n_rows).
            This row is not included in the selection. Negative (-1) - resets value to n_rows.
        column_end: int
            The column number following the last pixel in the selection (1..n_columns).
            This column is not included in the selection. Negative (-1) - resets value to n_columns.
        """
        # The variables holding the selected region are following Python conventions for the
        #   selections: row_start, column_start are in the range 0..n_rows-1, 0..n_columns-1
        #   and row_end, column_end are in the range 1..n_rows, 1..n_columns.
        #   The values displayed in the dialog box are just pixels numbers in the range
        #   1..n_rows, 1..n_columns that define the rectangle in the way intuitive to the user.
        self._row_start = int(
            np.clip(row_start, a_min=0, a_max=self._n_rows - 1))
        self._column_start = int(
            np.clip(column_start, a_min=0, a_max=self._n_columns - 1))

        def _adjust_last_index(index, n_elements):
            if index < 0:
                index = n_elements
            index = int(np.clip(index, 1, n_elements))
            return index

        self._row_end = _adjust_last_index(row_end, self._n_rows)
        self._column_end = _adjust_last_index(column_end, self._n_columns)
        self._show_selection(self._roi_active)
        self._validate_all_widgets()

    def _roi_activate(self, state):
        self._roi_active = state
        self._show_selection(state)
        self._validate_all_widgets()

    def set_roi_active(self, state):
        self._roi_activate(state)
        self.gb_roi.setChecked(self._roi_active)

    def get_roi(self):
        return self._row_start, self._column_start, self._row_end, self._column_end

    def get_roi_active(self):
        return self._roi_active

    def _show_mask_file_path(self):
        fpath = self._mask_file_path if self._mask_file_path else self._le_load_mask_default_text
        self.le_load_mask.setText(fpath)
        self._validate_all_widgets()

    def _mask_file_activate(self, state):
        self._mask_active = state
        self._show_mask_file_path()
        self._validate_all_widgets()

    def set_mask_file_active(self, state):
        self._mask_file_activate(state)
        self.gb_mask.setChecked(self._mask_active)

    def get_mask_file_active(self):
        return self._mask_active

    def set_mask_file_path(self, fpath):
        self._mask_file_path = fpath
        self._show_mask_file_path()

    def get_mask_file_path(self):
        return self._mask_file_path

    def set_default_directory(self, dir_name):
        self._default_directory = dir_name

    def get_default_directory(self):
        return self._default_directory
コード例 #38
0
class HeaderEditDialog(QDialog):

    # name of the current preset; whether to set this preset as default; list of Columns
    header_changed = Signal(str, bool, list)

    def __init__(self, parent, table_header):
        super().__init__(parent)

        self.table_header = table_header
        self.default_preset_name = None
        self.preset_name = table_header.preset_name
        self.columns = deepcopy(table_header.columns)
        self.setupUi()
        self.update_output()

    def setupUi(self):
        self.resize(240, 400)
        self.vbox = QVBoxLayout(self)
        self.presetLabel = QLabel(self)
        self.columnList = QListWidget(self)
        self.setAsDefaultCheckbox = QCheckBox("Set as default preset", self)
        self.vbox.addWidget(self.presetLabel)
        self.vbox.addWidget(self.columnList)
        self.vbox.addWidget(self.setAsDefaultCheckbox)

        self.columnList.setDragDropMode(QListWidget.InternalMove)
        self.columnList.setDefaultDropAction(Qt.MoveAction)
        self.columnList.setSelectionMode(QListWidget.ExtendedSelection)
        self.columnList.setAlternatingRowColors(True)
        self.columnList.installEventFilter(self)
        self.columnList.setContextMenuPolicy(Qt.CustomContextMenu)
        self.columnList.customContextMenuRequested.connect(self.open_menu)
        self.columnList.model().rowsMoved.connect(self.read_columns_from_list)

        # for a dumb qss hack to make selected checkboxes not white on a light theme
        self.columnList.setObjectName("ColumnList")

        buttons = QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Cancel
        self.buttonBox = QDialogButtonBox(buttons, self)
        self.vbox.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.resetButton = self.buttonBox.button(QDialogButtonBox.Reset)
        self.resetButton.clicked.connect(self.reset_to_stock)

    def eventFilter(self, object, event):
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Space or event.key() == Qt.Key_Return:
                self.toggle_selected_columns()
                return True
            if event.key() == Qt.Key_Delete:
                self.delete_selected()
                return True
        return False

    def update_output(self):
        self.presetLabel.setText("Preset: {}".format(self.preset_name))
        self.setAsDefaultCheckbox.setChecked(
            CONFIG['default_header_preset'] == self.preset_name)
        self.columnList.clear()
        for column in self.columns:
            ColumnListItem(self.columnList, column)

    def accept(self):
        self.read_columns_from_list()
        self.header_changed.emit(self.preset_name,
                                 self.setAsDefaultCheckbox.isChecked(),
                                 self.columns)
        self.done(0)

    def reject(self):
        self.done(0)

    def reset_to_stock(self):
        self.columns = deepcopy(DEFAULT_COLUMNS)
        self.update_output()

    def read_columns_from_list(self):
        new_columns = []
        for i in range(self.columnList.count()):
            item = self.columnList.item(i)
            new_columns.append(item.column)
        self.columns = new_columns

    def toggle_selected_columns(self):
        selected = self.columnList.selectedItems()
        for item in selected:
            value_now = item.data(Qt.CheckStateRole)
            item.setData(Qt.CheckStateRole, not value_now)
        self.columnList.reset(
        )  # @Improvement: is there a better way to update QListWidget?

    def open_menu(self, position):
        menu = QMenu(self)

        preset_menu = menu.addMenu('Presets')
        preset_menu.addAction('New preset', self.new_preset_dialog)
        preset_menu.addSeparator()

        preset_names = CONFIG.get_header_presets()

        if len(preset_names) == 0:
            action = preset_menu.addAction('No presets')
            action.setEnabled(False)
        else:
            delete_menu = menu.addMenu('Delete preset')
            for name in preset_names:
                preset_menu.addAction(name, partial(self.load_preset, name))
                delete_menu.addAction(name, partial(self.delete_preset, name))

        menu.addSeparator()
        menu.addAction('New column...', self.create_new_column_dialog)

        if len(self.columnList.selectedIndexes()) > 0:
            menu.addAction('Delete selected', self.delete_selected)

        menu.popup(self.columnList.viewport().mapToGlobal(position))

    def load_preset(self, name):
        new_columns = CONFIG.load_header_preset(name)
        if not new_columns:
            return

        self.columns = new_columns
        self.preset_name = name
        self.update_output()

    def new_preset_dialog(self):
        d = QInputDialog(self)
        d.setLabelText('Enter the new name for the new preset:')
        d.setWindowTitle('Create new preset')
        d.textValueSelected.connect(self.create_new_preset)
        d.open()

    def create_new_preset(self, name):
        if name in CONFIG.get_header_presets():
            show_warning_dialog(
                self, "Preset creation error",
                'Preset named "{}" already exists.'.format(name))
            return
        if len(name.strip()) == 0:
            show_warning_dialog(
                self, "Preset creation error",
                'This preset name is not allowed.'.format(name))
            return

        self.preset_name = name
        self.update_output()
        CONFIG.save_header_preset(name, self.columns)

    def delete_preset(self, name):
        CONFIG.delete_header_preset(name)
        if name == self.preset_name:
            self.columns = deepcopy(DEFAULT_COLUMNS)
            self.update_output()

    def create_new_column_dialog(self):
        d = CreateNewColumnDialog(self)
        d.add_new_column.connect(self.add_new_column)
        d.setWindowTitle('Create new column')
        d.open()

    def add_new_column(self, name, title):
        new_column = Column(name, title)
        # if the last column is message, insert this column before it (I think that makes sense?)
        if len(self.columns) == 0:
            self.columns.append(new_column)
        elif self.columns[-1].name in ('message', 'msg'):
            self.columns.insert(-1, new_column)
        else:
            self.columns.append(new_column)
        self.update_output()

    def delete_selected(self):
        selected = self.columnList.selectedItems()
        for item in selected:
            self.columnList.takeItem(self.columnList.row(item))
        self.read_columns_from_list()
        self.update_output()