def setup_page(self):
        settings_group = QGroupBox(_("Settings"))
        use_color_box = self.create_checkbox(
            _("Use deterministic colors to differentiate functions"),
            'use_colors', default=True)

        results_group = QGroupBox(_("Results"))
        results_label1 = QLabel(_("Memory profiler plugin results "
                                  "(the output of memory_profiler)\n"
                                  "is stored here:"))
        results_label1.setWordWrap(True)

        # Warning: do not try to regroup the following QLabel contents with
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863 of Profiler plugon
        results_label2 = QLabel(MemoryProfilerWidget.DATAPATH)

        results_label2.setTextInteractionFlags(Qt.TextSelectableByMouse)
        results_label2.setWordWrap(True)

        settings_layout = QVBoxLayout()
        settings_layout.addWidget(use_color_box)
        settings_group.setLayout(settings_layout)

        results_layout = QVBoxLayout()
        results_layout.addWidget(results_label1)
        results_layout.addWidget(results_label2)
        results_group.setLayout(results_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(settings_group)
        vlayout.addWidget(results_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #2
0
    def setup_page(self):
        settings_group = QGroupBox(_("Settings"))
        hist_spin = self.create_spinbox(
            _("History depth: "),
            _(" entries"),
            "max_entries",
            min_=10,
            max_=10000,
            step=10,
            tip=_("Set maximum line count"),
        )

        sourcecode_group = QGroupBox(_("Source code"))
        wrap_mode_box = self.create_checkbox(_("Wrap lines"), "wrap")
        go_to_eof_box = self.create_checkbox(_("Scroll automatically to last entry"), "go_to_eof")

        settings_layout = QVBoxLayout()
        settings_layout.addWidget(hist_spin)
        settings_group.setLayout(settings_layout)

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(wrap_mode_box)
        sourcecode_layout.addWidget(go_to_eof_box)
        sourcecode_group.setLayout(sourcecode_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(settings_group)
        vlayout.addWidget(sourcecode_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #3
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Workspace
        interface_group = QGroupBox(_("Interface"))
        restore_data_box = newcb(_("Restore data on startup"),
                                 'restore_data_on_startup')
        save_data_box = newcb(_("Save data on exit"),
                              'save_data_on_exit')
        save_history_box = newcb(_("Save history"),
                                 'save_history')
        save_non_project_box = newcb(_("Save non project files opened"),
                                     'save_non_project_files')

        interface_layout = QVBoxLayout()
        interface_layout.addWidget(restore_data_box)
        interface_layout.addWidget(save_data_box)
        interface_layout.addWidget(save_history_box)
        interface_layout.addWidget(save_non_project_box)
        interface_group.setLayout(interface_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(interface_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #4
0
    def setup_page(self):
        filter_group = QGroupBox(_("Filter"))
        filter_data = [
            ('exclude_private', _("Exclude private references")),
            ('exclude_capitalized', _("Exclude capitalized references")),
            ('exclude_uppercase', _("Exclude all-uppercase references")),
            ('exclude_unsupported', _("Exclude unsupported data types")),
                ]
        filter_boxes = [self.create_checkbox(text, option)
                        for option, text in filter_data]

        display_group = QGroupBox(_("Display"))
        display_data = [('minmax', _("Show arrays min/max"), '')]
        display_boxes = [self.create_checkbox(text, option, tip=tip)
                         for option, text, tip in display_data]

        filter_layout = QVBoxLayout()
        for box in filter_boxes:
            filter_layout.addWidget(box)
        filter_group.setLayout(filter_layout)

        display_layout = QVBoxLayout()
        for box in display_boxes:
            display_layout.addWidget(box)
        display_group.setLayout(display_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(filter_group)
        vlayout.addWidget(display_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #5
0
    def setup_page(self):
        """Setup config page widgets and options."""
        settings_group = QGroupBox(_("Settings"))
        hist_spin = self.create_spinbox(
                            _("History depth: "), _(" entries"),
                            'max_entries', min_=10, max_=10000, step=10,
                            tip=_("Set maximum line count"))

        sourcecode_group = QGroupBox(_("Source code"))
        wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap')
        linenumbers_mode_box = self.create_checkbox(_("Show line numbers"),
                                                    'line_numbers')
        go_to_eof_box = self.create_checkbox(
                        _("Scroll automatically to last entry"), 'go_to_eof')

        settings_layout = QVBoxLayout()
        settings_layout.addWidget(hist_spin)
        settings_group.setLayout(settings_layout)

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(wrap_mode_box)
        sourcecode_layout.addWidget(linenumbers_mode_box)
        sourcecode_layout.addWidget(go_to_eof_box)
        sourcecode_group.setLayout(sourcecode_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(settings_group)
        vlayout.addWidget(sourcecode_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #6
0
    def setup_page(self):
        about_label = QLabel(_("The <b>current working directory</b> is "
                    "the working directory for IPython consoles "
                    "and the current directory for the File Explorer."))
        about_label.setWordWrap(True)

        console_group = QGroupBox(_("Console directory"))
        console_label = QLabel(_("The working directory for new consoles is:"))
        console_label.setWordWrap(True)
        console_bg = QButtonGroup(console_group)
        console_project_radio = self.create_radiobutton(
                                _("The current project directory "
                                  "or user home directory "
                                  "(if no project is active)"),
                                'console/use_project_or_home_directory',
                                True,
                                button_group=console_bg)
        console_cwd_radio = self.create_radiobutton(
                                _("The current working directory"),
                                'console/use_cwd',
                                False,
                                button_group=console_bg)

        console_dir_radio = self.create_radiobutton(
                                _("the following directory:"),
                                'console/use_fixed_directory', False,
                                _("The directory when a new console "
                                  "is open will be the specified path"),
                                button_group=console_bg)
        console_dir_bd = self.create_browsedir("", 'console/fixed_directory',
                                               getcwd())
        console_dir_radio.toggled.connect(console_dir_bd.setEnabled)
        console_project_radio.toggled.connect(console_dir_bd.setDisabled)
        console_cwd_radio.toggled.connect(console_dir_bd.setDisabled)
        console_dir_layout = QHBoxLayout()
        console_dir_layout.addWidget(console_dir_radio)
        console_dir_layout.addWidget(console_dir_bd)

        console_layout = QVBoxLayout()
        console_layout.addWidget(console_label)
        console_layout.addWidget(console_project_radio)
        console_layout.addWidget(console_cwd_radio)
        console_layout.addLayout(console_dir_layout)
        console_group.setLayout(console_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(console_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #7
0
    def create_fontgroup(self, option=None, text=None, title=None,
                         tip=None, fontfilters=None, without_group=False):
        """Option=None -> setting plugin font"""

        if title:
            fontlabel = QLabel(title)
        else:
            fontlabel = QLabel(_("Font"))
        fontbox = QFontComboBox()

        if fontfilters is not None:
            fontbox.setFontFilters(fontfilters)

        sizelabel = QLabel("  "+_("Size"))
        sizebox = QSpinBox()
        sizebox.setRange(7, 100)
        self.fontboxes[(fontbox, sizebox)] = option
        layout = QHBoxLayout()

        for subwidget in (fontlabel, fontbox, sizelabel, sizebox):
            layout.addWidget(subwidget)
        layout.addStretch(1)

        widget = QWidget(self)
        widget.fontlabel = fontlabel
        widget.sizelabel = sizelabel        
        widget.fontbox = fontbox
        widget.sizebox = sizebox
        widget.setLayout(layout)

        if not without_group:
            if text is None:
                text = _("Font style")

            group = QGroupBox(text)
            group.setLayout(layout)

            if tip is not None:
                group.setToolTip(tip)

            return group
        else:
            return widget
Beispiel #8
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Workspace
        vcs_group = QGroupBox(_("Version control"))
        use_version_control = newcb(_("Use version control"), "use_version_control")

        styles = ["git", "hg"]
        choices = list(zip(styles, [style.lower() for style in styles]))
        vcs_combo = self.create_combobox(_("Version control system"), choices, "version_control_system", default="git")

        vcs_layout = QVBoxLayout()
        vcs_layout.addWidget(use_version_control)
        vcs_layout.addWidget(vcs_combo)
        vcs_group.setLayout(vcs_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(vcs_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #9
0
    def setup_ui(self):
        self.setWindowTitle("Add New Grain")
        self.setWindowIcon(QIcon(RESOURCE_PATH + "icons/nakka-finocyl.gif"))

        self.resize(400, 400)

        controls = QGridLayout()
        gb_frame = QGroupBox(self.tr("Grain Design"))
        gb_frame.setLayout(controls)
        
        self.cb_grain_type = QComboBox()

        # TODO: make grain types auto propagate combobox
        self.cb_grain_type.addItems([self.tr("Cylindrical (BATES)")])
        controls.addWidget(QLabel(self.tr("Core Shape")), 0, 0)
        controls.addWidget(self.cb_grain_type, 0, 1)

        self.cb_propellant_type = QComboBox()
        self.cb_propellant_type.addItems(app_context.propellant_db.propellant_names())
        controls.addWidget(QLabel(self.tr("Propellant Type")), 1, 0)
        controls.addWidget(self.cb_propellant_type, 1, 1)

        # ok and cancel buttons
        btn_ok = QPushButton(self.tr("Apply"))
        btn_ok.clicked.connect(self.confirm_grain)
        btn_cancel = QPushButton(self.tr("Close"))
        btn_cancel.clicked.connect(self.close)

        lay_btns = QHBoxLayout()
        lay_btns.addWidget(btn_ok)
        lay_btns.addWidget(btn_cancel)
        frame_btns = QFrame()
        frame_btns.setLayout(lay_btns)

        # master layout
        master = QVBoxLayout()
        master.addWidget(gb_frame)
        master.addSpacing(10)
        master.addWidget(frame_btns)
        self.setLayout(master)
Beispiel #10
0
        def setup_chamber_design():
            # master layout
            master = QVBoxLayout()
            # master group box
            self.gb_chamber = QGroupBox(self.tr("Chamber Design"))

            # nozzle settings button
            self.btn_nozzle_settings = QPushButton(self.tr("Edit Nozzle"))
            self.btn_nozzle_settings.setMinimumHeight(50)
            master.addWidget(self.btn_nozzle_settings)

            # nozzle info pane
            fl_nozzle_info = QFormLayout()
            gb_nozzle = QGroupBox(self.tr("Nozzle Info"))
            gb_nozzle.setLayout(fl_nozzle_info)

            self.lbl_nozzle_throat = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Throat Diameter:")), self.lbl_nozzle_throat)
            self.lbl_nozzle_exit = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Exit Diameter:")), self.lbl_nozzle_exit)
            self.lbl_nozzle_expansion_ratio = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Expansion Ratio:")), self.lbl_nozzle_expansion_ratio)
            # add group box to master
            master.addWidget(gb_nozzle)
            master.addStretch()

            # overall motor info pane
            fl_motor_info = QFormLayout()
            gb_motor = QGroupBox(self.tr("Motor Info"))
            gb_motor.setLayout(fl_motor_info)

            self.lbl_kn = QLabel()
            fl_motor_info.addRow(QLabel(self.tr("Kn:")), self.lbl_kn)
            self.lbl_port_throat = QLabel()
            fl_motor_info.addRow(QLabel(self.tr("Port/Throat Ratio:")), self.lbl_port_throat)

            master.addWidget(gb_motor)
            self.gb_chamber.setLayout(master)
Beispiel #11
0
    def setup_page(self):
        # Connections group
        connections_group = QGroupBox(_("Automatic connections"))
        connections_label = QLabel(_("This pane can automatically "
                                     "show an object's help information after "
                                     "a left parenthesis is written next to it. "
                                     "Below you can decide to which plugin "
                                     "you want to connect it to turn on this "
                                     "feature."))
        connections_label.setWordWrap(True)
        editor_box = self.create_checkbox(_("Editor"), 'connect/editor')
        rope_installed = programs.is_module_installed('rope')
        jedi_installed = programs.is_module_installed('jedi', '>=0.8.1')
        editor_box.setEnabled(rope_installed or jedi_installed)
        if not rope_installed and not jedi_installed:
            editor_tip = _("This feature requires the Rope or Jedi libraries.\n"
                           "It seems you don't have either installed.")
            editor_box.setToolTip(editor_tip)
        ipython_box = self.create_checkbox(_("IPython Console"),
                                           'connect/ipython_console')

        connections_layout = QVBoxLayout()
        connections_layout.addWidget(connections_label)
        connections_layout.addWidget(editor_box)
        connections_layout.addWidget(ipython_box)
        connections_group.setLayout(connections_layout)

        # Features group
        features_group = QGroupBox(_("Additional features"))
        math_box = self.create_checkbox(_("Render mathematical equations"),
                                        'math')
        req_sphinx = programs.is_module_installed('sphinx', '>=1.1')
        math_box.setEnabled(req_sphinx)
        if not req_sphinx:
            sphinx_ver = programs.get_module_version('sphinx')
            sphinx_tip = _("This feature requires Sphinx 1.1 or superior.")
            sphinx_tip += "\n" + _("Sphinx %s is currently installed.") % sphinx_ver
            math_box.setToolTip(sphinx_tip)

        features_layout = QVBoxLayout()
        features_layout.addWidget(math_box)
        features_group.setLayout(features_layout)

        # Source code group
        sourcecode_group = QGroupBox(_("Source code"))
        wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap')

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(wrap_mode_box)
        sourcecode_group.setLayout(sourcecode_layout)

        # Final layout
        vlayout = QVBoxLayout()
        vlayout.addWidget(connections_group)
        vlayout.addWidget(features_group)
        vlayout.addWidget(sourcecode_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
    def setup_page(self):
        network_group = QGroupBox(_("Network settings"))
        self.checkbox_proxy = self.create_checkbox(_("Use network proxy"),
                                                   'use_proxy_flag',
                                                   default=False)
        server = self.create_lineedit(_('Server'), 'server', default='',
                                      alignment=Qt.Horizontal)
        port = self.create_lineedit(_('Port'), 'port', default='',
                                    alignment=Qt.Horizontal)
        user = self.create_lineedit(_('User'), 'user', default='',
                                    alignment=Qt.Horizontal)
        password = self.create_lineedit(_('Password'), 'password', default='',
                                        alignment=Qt.Horizontal)

        self.widgets = [server, port, user, password]

        # Layouts
        network_layout = QGridLayout()
        network_layout.addWidget(self.checkbox_proxy, 0, 0)
        network_layout.addWidget(server.label, 1, 0)
        network_layout.addWidget(server.textbox, 1, 1)
        network_layout.addWidget(port.label, 1, 2)
        network_layout.addWidget(port.textbox, 1, 3)
        network_layout.addWidget(user.label, 2, 0)
        network_layout.addWidget(user.textbox, 2, 1)
        network_layout.addWidget(password.label, 2, 2)
        network_layout.addWidget(password.textbox, 2, 3)
        network_group.setLayout(network_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(network_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)

        # Signals
        self.checkbox_proxy.clicked.connect(self.proxy_settings)
        self.proxy_settings()
Beispiel #13
0
    def setup_page(self):
        results_group = QGroupBox(_("Results"))
        results_label1 = QLabel(
            _("Profiler plugin results " "(the output of python's profile/cProfile)\n" "are stored here:")
        )
        results_label1.setWordWrap(True)

        # Warning: do not try to regroup the following QLabel contents with
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863
        results_label2 = QLabel(ProfilerWidget.DATAPATH)

        results_label2.setTextInteractionFlags(Qt.TextSelectableByMouse)
        results_label2.setWordWrap(True)

        results_layout = QVBoxLayout()
        results_layout.addWidget(results_label1)
        results_layout.addWidget(results_label2)
        results_group.setLayout(results_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(results_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #14
0
    def setup_page(self):
        ar_group = QGroupBox(_("Autorefresh"))
        ar_box = self.create_checkbox(_("Enable autorefresh"),
                                      'autorefresh')
        ar_spin = self.create_spinbox(_("Refresh interval: "),
                                      _(" ms"), 'autorefresh/timeout',
                                      min_=100, max_=1000000, step=100)
        
        filter_group = QGroupBox(_("Filter"))
        filter_data = [
            ('exclude_private', _("Exclude private references")),
            ('exclude_capitalized', _("Exclude capitalized references")),
            ('exclude_uppercase', _("Exclude all-uppercase references")),
            ('exclude_unsupported', _("Exclude unsupported data types")),
                ]
        filter_boxes = [self.create_checkbox(text, option)
                        for option, text in filter_data]

        display_group = QGroupBox(_("Display"))
        display_data = [('truncate', _("Truncate values"), '')]
        if programs.is_module_installed('numpy'):
            display_data.append(('minmax', _("Show arrays min/max"), ''))
        display_data.append(
            ('remote_editing', _("Edit data in the remote process"),
             _("Editors are opened in the remote process for NumPy "
               "arrays, PIL images, lists, tuples and dictionaries.\n"
               "This avoids transfering large amount of data between "
               "the remote process and Spyder (through the socket)."))
                            )
        display_boxes = [self.create_checkbox(text, option, tip=tip)
                         for option, text, tip in display_data]
        
        ar_layout = QVBoxLayout()
        ar_layout.addWidget(ar_box)
        ar_layout.addWidget(ar_spin)
        ar_group.setLayout(ar_layout)
        
        filter_layout = QVBoxLayout()
        for box in filter_boxes:
            filter_layout.addWidget(box)
        filter_group.setLayout(filter_layout)

        display_layout = QVBoxLayout()
        for box in display_boxes:
            display_layout.addWidget(box)
        display_group.setLayout(display_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(ar_group)
        vlayout.addWidget(filter_group)
        vlayout.addWidget(display_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #15
0
    def setup_page(self):
        settings_group = QGroupBox(_("Settings"))
        save_box = self.create_checkbox(_("Save file before analyzing it"),
                                        'save_before', default=True)
        
        hist_group = QGroupBox(_("History"))
        hist_label1 = QLabel(_("The following option will be applied at next "
                               "startup."))
        hist_label1.setWordWrap(True)
        hist_spin = self.create_spinbox(_("History: "),
                            _(" results"), 'max_entries', default=50,
                            min_=10, max_=1000000, step=10)

        results_group = QGroupBox(_("Results"))
        results_label1 = QLabel(_("Results are stored here:"))
        results_label1.setWordWrap(True)

        # Warning: do not try to regroup the following QLabel contents with 
        # widgets above -- this string was isolated here in a single QLabel
        # on purpose: to fix Issue 863
        results_label2 = QLabel(PylintWidget.DATAPATH)

        results_label2.setTextInteractionFlags(Qt.TextSelectableByMouse)
        results_label2.setWordWrap(True)

        settings_layout = QVBoxLayout()
        settings_layout.addWidget(save_box)
        settings_group.setLayout(settings_layout)

        hist_layout = QVBoxLayout()
        hist_layout.addWidget(hist_label1)
        hist_layout.addWidget(hist_spin)
        hist_group.setLayout(hist_layout)

        results_layout = QVBoxLayout()
        results_layout.addWidget(results_label1)
        results_layout.addWidget(results_label2)
        results_group.setLayout(results_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(settings_group)
        vlayout.addWidget(hist_group)
        vlayout.addWidget(results_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #16
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.dir = None
        self.runconf = RunConfiguration()
        firstrun_o = CONF.get('run', ALWAYS_OPEN_FIRST_RUN_OPTION, False)

        # --- Interpreter ---
        interpreter_group = QGroupBox(_("Console"))
        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)

        self.current_radio = QRadioButton(CURRENT_INTERPRETER)
        interpreter_layout.addWidget(self.current_radio)

        self.dedicated_radio = QRadioButton(DEDICATED_INTERPRETER)
        interpreter_layout.addWidget(self.dedicated_radio)

        self.systerm_radio = QRadioButton(SYSTERM_INTERPRETER)
        interpreter_layout.addWidget(self.systerm_radio)

        # --- General settings ----
        common_group = QGroupBox(_("General settings"))
        common_layout = QGridLayout()
        common_group.setLayout(common_layout)

        self.clear_var_cb = QCheckBox(CLEAR_ALL_VARIABLES)
        common_layout.addWidget(self.clear_var_cb, 0, 0)

        self.console_ns_cb = QCheckBox(CONSOLE_NAMESPACE)
        common_layout.addWidget(self.console_ns_cb, 1, 0)

        self.post_mortem_cb = QCheckBox(POST_MORTEM)
        common_layout.addWidget(self.post_mortem_cb, 2, 0)

        self.clo_cb = QCheckBox(_("Command line options:"))
        common_layout.addWidget(self.clo_cb, 3, 0)
        self.clo_edit = QLineEdit()
        self.clo_cb.toggled.connect(self.clo_edit.setEnabled)
        self.clo_edit.setEnabled(False)
        common_layout.addWidget(self.clo_edit, 3, 1)

        # --- Working directory ---
        wdir_group = QGroupBox(_("Working directory settings"))
        wdir_layout = QVBoxLayout()
        wdir_group.setLayout(wdir_layout)

        self.file_dir_radio = QRadioButton(FILE_DIR)
        wdir_layout.addWidget(self.file_dir_radio)

        self.cwd_radio = QRadioButton(CW_DIR)
        wdir_layout.addWidget(self.cwd_radio)

        fixed_dir_layout = QHBoxLayout()
        self.fixed_dir_radio = QRadioButton(FIXED_DIR)
        fixed_dir_layout.addWidget(self.fixed_dir_radio)
        self.wd_edit = QLineEdit()
        self.fixed_dir_radio.toggled.connect(self.wd_edit.setEnabled)
        self.wd_edit.setEnabled(False)
        fixed_dir_layout.addWidget(self.wd_edit)
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select directory"))
        browse_btn.clicked.connect(self.select_directory)
        fixed_dir_layout.addWidget(browse_btn)
        wdir_layout.addLayout(fixed_dir_layout)

        # --- System terminal ---
        external_group = QGroupBox(_("External system terminal"))
        external_group.setDisabled(True)

        self.systerm_radio.toggled.connect(external_group.setEnabled)

        external_layout = QGridLayout()
        external_group.setLayout(external_layout)
        self.interact_cb = QCheckBox(INTERACT)
        external_layout.addWidget(self.interact_cb, 1, 0, 1, -1)

        self.pclo_cb = QCheckBox(_("Command line options:"))
        external_layout.addWidget(self.pclo_cb, 3, 0)
        self.pclo_edit = QLineEdit()
        self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled)
        self.pclo_edit.setEnabled(False)
        self.pclo_edit.setToolTip(
            _("<b>-u</b> is added to the "
              "other options you set here"))
        external_layout.addWidget(self.pclo_edit, 3, 1)

        # Checkbox to preserve the old behavior, i.e. always open the dialog
        # on first run
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog"))
        self.firstrun_cb.clicked.connect(self.set_firstrun_o)
        self.firstrun_cb.setChecked(firstrun_o)

        layout = QVBoxLayout()
        layout.addWidget(interpreter_group)
        layout.addWidget(common_group)
        layout.addWidget(wdir_group)
        layout.addWidget(external_group)
        layout.addWidget(hline)
        layout.addWidget(self.firstrun_cb)
        self.setLayout(layout)
Beispiel #17
0
    def setup_page(self):
        newcb = self.create_checkbox

        # Interface Group
        interface_group = QGroupBox(_("Interface"))
        banner_box = newcb(_("Display initial banner"),
                           'show_banner',
                           tip=_("This option lets you hide the message "
                                 "shown at\nthe top of the console when "
                                 "it's opened."))
        calltips_box = newcb(_("Show calltips"), 'show_calltips')
        ask_box = newcb(_("Ask for confirmation before closing"),
                        'ask_before_closing')
        reset_namespace_box = newcb(
            _("Ask for confirmation before removing all user-defined "
              "variables"),
            'show_reset_namespace_warning',
            tip=_("This option lets you hide the warning message shown\n"
                  "when resetting the namespace from Spyder."))
        show_time_box = newcb(_("Show elapsed time"), 'show_elapsed_time')
        ask_restart_box = newcb(
            _("Ask for confirmation before restarting"),
            'ask_before_restart',
            tip=_("This option lets you hide the warning message shown\n"
                  "when restarting the kernel."))

        interface_layout = QVBoxLayout()
        interface_layout.addWidget(banner_box)
        interface_layout.addWidget(calltips_box)
        interface_layout.addWidget(ask_box)
        interface_layout.addWidget(reset_namespace_box)
        interface_layout.addWidget(show_time_box)
        interface_layout.addWidget(ask_restart_box)
        interface_group.setLayout(interface_layout)

        comp_group = QGroupBox(_("Completion type"))
        comp_label = QLabel(_("Decide what type of completion to use"))
        comp_label.setWordWrap(True)
        completers = [(_("Graphical"), 0), (_("Terminal"), 1), (_("Plain"), 2)]
        comp_box = self.create_combobox(
            _("Completion:") + "   ", completers, 'completion_type')
        comp_layout = QVBoxLayout()
        comp_layout.addWidget(comp_label)
        comp_layout.addWidget(comp_box)
        comp_group.setLayout(comp_layout)

        # Source Code Group
        source_code_group = QGroupBox(_("Source code"))
        buffer_spin = self.create_spinbox(
            _("Buffer:  "),
            _(" lines"),
            'buffer_size',
            min_=-1,
            max_=1000000,
            step=100,
            tip=_("Set the maximum number of lines of text shown in the\n"
                  "console before truncation. Specifying -1 disables it\n"
                  "(not recommended!)"))
        source_code_layout = QVBoxLayout()
        source_code_layout.addWidget(buffer_spin)
        source_code_group.setLayout(source_code_layout)

        # --- Graphics ---
        # Pylab Group
        pylab_group = QGroupBox(_("Support for graphics (Matplotlib)"))
        pylab_box = newcb(_("Activate support"), 'pylab')
        autoload_pylab_box = newcb(
            _("Automatically load Pylab and NumPy modules"),
            'pylab/autoload',
            tip=_("This lets you load graphics support without importing\n"
                  "the commands to do plots. Useful to work with other\n"
                  "plotting libraries different to Matplotlib or to develop\n"
                  "GUIs with Spyder."))
        autoload_pylab_box.setEnabled(self.get_option('pylab'))
        pylab_box.toggled.connect(autoload_pylab_box.setEnabled)

        pylab_layout = QVBoxLayout()
        pylab_layout.addWidget(pylab_box)
        pylab_layout.addWidget(autoload_pylab_box)
        pylab_group.setLayout(pylab_layout)

        # Pylab backend Group
        inline = _("Inline")
        automatic = _("Automatic")
        backend_group = QGroupBox(_("Graphics backend"))
        bend_label = QLabel(
            _("Decide how graphics are going to be displayed "
              "in the console. If unsure, please select "
              "<b>%s</b> to put graphics inside the "
              "console or <b>%s</b> to interact with "
              "them (through zooming and panning) in a "
              "separate window.") % (inline, automatic))
        bend_label.setWordWrap(True)

        backends = [(inline, 0), (automatic, 1), ("Qt5", 2), ("Qt4", 3)]

        if sys.platform == 'darwin':
            backends.append(("OS X", 4))
        if sys.platform.startswith('linux'):
            backends.append(("Gtk3", 5))
            backends.append(("Gtk", 6))
        if PY2:
            backends.append(("Wx", 7))
        backends.append(("Tkinter", 8))
        backends = tuple(backends)

        backend_box = self.create_combobox(
            _("Backend:") + "   ",
            backends,
            'pylab/backend',
            default=0,
            tip=_("This option will be applied the next time a console is "
                  "opened."))

        backend_layout = QVBoxLayout()
        backend_layout.addWidget(bend_label)
        backend_layout.addWidget(backend_box)
        backend_group.setLayout(backend_layout)
        backend_group.setEnabled(self.get_option('pylab'))
        pylab_box.toggled.connect(backend_group.setEnabled)

        # Inline backend Group
        inline_group = QGroupBox(_("Inline backend"))
        inline_label = QLabel(
            _("Decide how to render the figures created by "
              "this backend"))
        inline_label.setWordWrap(True)
        formats = (("PNG", 0), ("SVG", 1))
        format_box = self.create_combobox(_("Format:") + "   ",
                                          formats,
                                          'pylab/inline/figure_format',
                                          default=0)
        resolution_spin = self.create_spinbox(
            _("Resolution:") + "  ",
            " " + _("dpi"),
            'pylab/inline/resolution',
            min_=50,
            max_=999,
            step=0.1,
            tip=_("Only used when the format is PNG. Default is "
                  "72"))
        width_spin = self.create_spinbox(_("Width:") + "  ",
                                         " " + _("inches"),
                                         'pylab/inline/width',
                                         min_=2,
                                         max_=20,
                                         step=1,
                                         tip=_("Default is 6"))
        height_spin = self.create_spinbox(_("Height:") + "  ",
                                          " " + _("inches"),
                                          'pylab/inline/height',
                                          min_=1,
                                          max_=20,
                                          step=1,
                                          tip=_("Default is 4"))
        bbox_inches_box = newcb(_("Use a tight layout for inline plots"),
                                'pylab/inline/bbox_inches',
                                tip=_(
                                    "Sets bbox_inches to \"tight\" when\n"
                                    "plotting inline with matplotlib.\n"
                                    "When enabled, can cause discrepancies\n"
                                    "between the image displayed inline and\n"
                                    "that created using savefig."))

        inline_v_layout = QVBoxLayout()
        inline_v_layout.addWidget(inline_label)
        inline_layout = QGridLayout()
        inline_layout.addWidget(format_box.label, 1, 0)
        inline_layout.addWidget(format_box.combobox, 1, 1)
        inline_layout.addWidget(resolution_spin.plabel, 2, 0)
        inline_layout.addWidget(resolution_spin.spinbox, 2, 1)
        inline_layout.addWidget(resolution_spin.slabel, 2, 2)
        inline_layout.addWidget(width_spin.plabel, 3, 0)
        inline_layout.addWidget(width_spin.spinbox, 3, 1)
        inline_layout.addWidget(width_spin.slabel, 3, 2)
        inline_layout.addWidget(height_spin.plabel, 4, 0)
        inline_layout.addWidget(height_spin.spinbox, 4, 1)
        inline_layout.addWidget(height_spin.slabel, 4, 2)
        inline_layout.addWidget(bbox_inches_box, 5, 0, 1, 4)

        inline_h_layout = QHBoxLayout()
        inline_h_layout.addLayout(inline_layout)
        inline_h_layout.addStretch(1)
        inline_v_layout.addLayout(inline_h_layout)
        inline_group.setLayout(inline_v_layout)
        inline_group.setEnabled(self.get_option('pylab'))
        pylab_box.toggled.connect(inline_group.setEnabled)

        # --- Startup ---
        # Run lines Group
        run_lines_group = QGroupBox(_("Run code"))
        run_lines_label = QLabel(
            _("You can run several lines of code when "
              "a console is started. Please introduce "
              "each one separated by semicolons and a "
              "space, for example:<br>"
              "<i>import os; import sys</i>"))
        run_lines_label.setWordWrap(True)
        run_lines_edit = self.create_lineedit(_("Lines:"),
                                              'startup/run_lines',
                                              '',
                                              alignment=Qt.Horizontal)

        run_lines_layout = QVBoxLayout()
        run_lines_layout.addWidget(run_lines_label)
        run_lines_layout.addWidget(run_lines_edit)
        run_lines_group.setLayout(run_lines_layout)

        # Run file Group
        run_file_group = QGroupBox(_("Run a file"))
        run_file_label = QLabel(
            _("You can also run a whole file at startup "
              "instead of just some lines (This is "
              "similar to have a PYTHONSTARTUP file)."))
        run_file_label.setWordWrap(True)
        file_radio = newcb(_("Use the following file:"),
                           'startup/use_run_file', False)
        run_file_browser = self.create_browsefile('', 'startup/run_file', '')
        run_file_browser.setEnabled(False)
        file_radio.toggled.connect(run_file_browser.setEnabled)

        run_file_layout = QVBoxLayout()
        run_file_layout.addWidget(run_file_label)
        run_file_layout.addWidget(file_radio)
        run_file_layout.addWidget(run_file_browser)
        run_file_group.setLayout(run_file_layout)

        # ---- Debug ----
        # Pdb run lines Group
        pdb_run_lines_group = QGroupBox(_("Run code while debugging"))
        pdb_run_lines_label = QLabel(
            _("You can run several lines of code on each "
              "new prompt while debugging. Please "
              "introduce each one separated by semicolons "
              "and a space, for example:<br>"
              "<i>import matplotlib.pyplot as plt</i>"))
        pdb_run_lines_label.setWordWrap(True)
        pdb_run_lines_edit = self.create_lineedit(_("Lines:"),
                                                  'startup/pdb_run_lines',
                                                  '',
                                                  alignment=Qt.Horizontal)

        pdb_run_lines_layout = QVBoxLayout()
        pdb_run_lines_layout.addWidget(pdb_run_lines_label)
        pdb_run_lines_layout.addWidget(pdb_run_lines_edit)
        pdb_run_lines_group.setLayout(pdb_run_lines_layout)

        # Debug Group
        debug_group = QGroupBox(_("Debug"))
        debug_layout = QVBoxLayout()

        prevent_closing_box = newcb(
            _("Prevent editor from closing files while debugging"),
            'pdb_prevent_closing',
            tip=_("This option prevents the user from closing a file while"
                  " it is debugged."))
        debug_layout.addWidget(prevent_closing_box)

        continue_box = newcb(
            _("Stop debugging on first line of files without breakpoints"),
            'pdb_stop_first_line',
            tip=_("This option lets you decide if the debugger should"
                  " stop on the first line while debugging if no breakpoints"
                  " are present."))
        debug_layout.addWidget(continue_box)

        libraries_box = newcb(
            _("Ignore Python libraries while debugging"),
            'pdb_ignore_lib',
            tip=_("This option lets you decide if the debugger should "
                  "ignore the system libraries while debugging."))
        debug_layout.addWidget(libraries_box)

        execute_events_box = newcb(
            _("Process execute events while debugging"),
            'pdb_execute_events',
            tip=_("This option lets you decide if the debugger should "
                  "process the 'execute events' after each prompt, such as "
                  "matplotlib 'show' command."))
        debug_layout.addWidget(execute_events_box)

        exclamation_mark_box = newcb(
            _("Use exclamation mark prefix for Pdb commands"),
            'pdb_use_exclamation_mark',
            tip=_("This option lets you decide if the Pdb commands should "
                  "be prefixed by an exclamation mark. This helps in "
                  "separating Pdb commands from Python code."))
        debug_layout.addWidget(exclamation_mark_box)

        debug_group.setLayout(debug_layout)

        # ---- Advanced settings ----
        # Enable Jedi completion
        jedi_group = QGroupBox(_("Jedi completion"))
        jedi_label = QLabel(
            _("Enable Jedi-based <tt>Tab</tt> completion "
              "in the IPython console; similar to the "
              "greedy completer, but without evaluating "
              "the code.<br>"
              "<b>Warning:</b> Slows down your console "
              "when working with large dataframes!"))
        jedi_label.setWordWrap(True)
        jedi_box = newcb(_("Use Jedi completion in the IPython console"),
                         "jedi_completer",
                         tip=_("<b>Warning</b>: "
                               "Slows down your console when working with "
                               "large dataframes!<br>"
                               "Allows completion of nested lists etc."))

        jedi_layout = QVBoxLayout()
        jedi_layout.addWidget(jedi_label)
        jedi_layout.addWidget(jedi_box)
        jedi_group.setLayout(jedi_layout)

        # Greedy completer group
        greedy_group = QGroupBox(_("Greedy completion"))
        greedy_label = QLabel(
            _("Enable <tt>Tab</tt> completion on elements "
              "of lists, results of function calls, etc, "
              "<i>without</i> assigning them to a variable, "
              "like <tt>li[0].&lt;Tab&gt;</tt> or "
              "<tt>ins.meth().&lt;Tab&gt;</tt> <br>"
              "<b>Warning:</b> Due to a bug, IPython's "
              "greedy completer requires a leading "
              "<tt>&lt;Space&gt;</tt> for some completions; "
              "e.g.  <tt>np.sin(&lt;Space&gt;np.&lt;Tab&gt;"
              "</tt> works while <tt>np.sin(np.&lt;Tab&gt; "
              "</tt> doesn't."))
        greedy_label.setWordWrap(True)
        greedy_box = newcb(_("Use greedy completion in the IPython console"),
                           "greedy_completer",
                           tip="<b>Warning</b>: It can be unsafe because the "
                           "code is actually evaluated when you press "
                           "<tt>Tab</tt>.")

        greedy_layout = QVBoxLayout()
        greedy_layout.addWidget(greedy_label)
        greedy_layout.addWidget(greedy_box)
        greedy_group.setLayout(greedy_layout)

        # Autocall group
        autocall_group = QGroupBox(_("Autocall"))
        autocall_label = QLabel(
            _("Autocall makes IPython automatically call "
              "any callable object even if you didn't "
              "type explicit parentheses.<br>"
              "For example, if you type <i>str 43</i> it "
              "becomes <i>str(43)</i> automatically."))
        autocall_label.setWordWrap(True)

        smart = _('Smart')
        full = _('Full')
        autocall_opts = ((_('Off'), 0), (smart, 1), (full, 2))
        autocall_box = self.create_combobox(
            _("Autocall:  "),
            autocall_opts,
            'autocall',
            default=0,
            tip=_("On <b>%s</b> mode, Autocall is not applied if "
                  "there are no arguments after the callable. On "
                  "<b>%s</b> mode, all callable objects are "
                  "automatically called (even if no arguments are "
                  "present).") % (smart, full))

        autocall_layout = QVBoxLayout()
        autocall_layout.addWidget(autocall_label)
        autocall_layout.addWidget(autocall_box)
        autocall_group.setLayout(autocall_layout)

        # Sympy group
        sympy_group = QGroupBox(_("Symbolic mathematics"))
        sympy_label = QLabel(
            _("Perfom symbolic operations in the console "
              "(e.g. integrals, derivatives, vector "
              "calculus, etc) and get the outputs in a "
              "beautifully printed style (it requires the "
              "Sympy module)."))
        sympy_label.setWordWrap(True)
        sympy_box = newcb(_("Use symbolic math"),
                          "symbolic_math",
                          tip=_("This option loads the Sympy library to work "
                                "with.<br>Please refer to its documentation "
                                "to learn how to use it."))

        sympy_layout = QVBoxLayout()
        sympy_layout.addWidget(sympy_label)
        sympy_layout.addWidget(sympy_box)
        sympy_group.setLayout(sympy_layout)

        # Prompts group
        prompts_group = QGroupBox(_("Prompts"))
        prompts_label = QLabel(
            _("Modify how Input and Output prompts are "
              "shown in the console."))
        prompts_label.setWordWrap(True)
        in_prompt_edit = self.create_lineedit(
            _("Input prompt:"),
            'in_prompt',
            '',
            _('Default is<br>'
              'In [&lt;span class="in-prompt-number"&gt;'
              '%i&lt;/span&gt;]:'),
            alignment=Qt.Horizontal)
        out_prompt_edit = self.create_lineedit(
            _("Output prompt:"),
            'out_prompt',
            '',
            _('Default is<br>'
              'Out[&lt;span class="out-prompt-number"&gt;'
              '%i&lt;/span&gt;]:'),
            alignment=Qt.Horizontal)

        prompts_layout = QVBoxLayout()
        prompts_layout.addWidget(prompts_label)
        prompts_g_layout = QGridLayout()
        prompts_g_layout.addWidget(in_prompt_edit.label, 0, 0)
        prompts_g_layout.addWidget(in_prompt_edit.textbox, 0, 1)
        prompts_g_layout.addWidget(out_prompt_edit.label, 1, 0)
        prompts_g_layout.addWidget(out_prompt_edit.textbox, 1, 1)
        prompts_layout.addLayout(prompts_g_layout)
        prompts_group.setLayout(prompts_layout)

        # Windows adjustments
        windows_group = QGroupBox(_("Windows adjustments"))
        hide_cmd_windows = newcb(
            _("Hide command line output windows "
              "generated by the subprocess module."), 'hide_cmd_windows')
        windows_layout = QVBoxLayout()
        windows_layout.addWidget(hide_cmd_windows)
        windows_group.setLayout(windows_layout)

        # --- Tabs organization ---
        self.tabs = QTabWidget()
        self.tabs.addTab(
            self.create_tab(interface_group, comp_group, source_code_group),
            _("Display"))
        self.tabs.addTab(
            self.create_tab(pylab_group, backend_group, inline_group),
            _("Graphics"))
        self.tabs.addTab(self.create_tab(run_lines_group, run_file_group),
                         _("Startup"))
        self.tabs.addTab(self.create_tab(debug_group, pdb_run_lines_group),
                         _("Debugger"))
        self.tabs.addTab(
            self.create_tab(jedi_group, greedy_group, autocall_group,
                            sympy_group, prompts_group, windows_group),
            _("Advanced settings"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.tabs)
        self.setLayout(vlayout)
Beispiel #18
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Display tab ---
        showtabbar_box = newcb(_("Show tab bar"), 'show_tab_bar')
        showclassfuncdropdown_box = newcb(
            _("Show selector for classes and functions"),
            'show_class_func_dropdown')
        showindentguides_box = newcb(_("Show indent guides"), 'indent_guides')
        linenumbers_box = newcb(_("Show line numbers"), 'line_numbers')
        blanks_box = newcb(_("Show blank spaces"), 'blank_spaces')
        currentline_box = newcb(_("Highlight current line"),
                                'highlight_current_line')
        currentcell_box = newcb(_("Highlight current cell"),
                                'highlight_current_cell')
        wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
        scroll_past_end_box = newcb(_("Scroll past the end"),
                                    'scroll_past_end')

        edgeline_box = newcb(_("Show vertical lines at"), 'edge_line')
        edgeline_edit = self.create_lineedit(
            "",
            'edge_line_columns',
            tip=("Enter values separated by commas"),
            alignment=Qt.Horizontal,
            regex="[0-9]+(,[0-9]+)*")
        edgeline_edit_label = QLabel(_("characters"))
        edgeline_box.toggled.connect(edgeline_edit.setEnabled)
        edgeline_box.toggled.connect(edgeline_edit_label.setEnabled)
        edgeline_edit.setEnabled(self.get_option('edge_line'))
        edgeline_edit_label.setEnabled(self.get_option('edge_line'))

        occurrence_box = newcb(_("Highlight occurrences after"),
                               'occurrence_highlighting')
        occurrence_spin = self.create_spinbox(
            "",
            _(" ms"),
            'occurrence_highlighting/timeout',
            min_=100,
            max_=1000000,
            step=100)
        occurrence_box.toggled.connect(occurrence_spin.spinbox.setEnabled)
        occurrence_box.toggled.connect(occurrence_spin.slabel.setEnabled)
        occurrence_spin.spinbox.setEnabled(
            self.get_option('occurrence_highlighting'))
        occurrence_spin.slabel.setEnabled(
            self.get_option('occurrence_highlighting'))

        display_g_layout = QGridLayout()
        display_g_layout.addWidget(edgeline_box, 0, 0)
        display_g_layout.addWidget(edgeline_edit.textbox, 0, 1)
        display_g_layout.addWidget(edgeline_edit_label, 0, 2)
        display_g_layout.addWidget(occurrence_box, 1, 0)
        display_g_layout.addWidget(occurrence_spin.spinbox, 1, 1)
        display_g_layout.addWidget(occurrence_spin.slabel, 1, 2)

        display_h_layout = QHBoxLayout()
        display_h_layout.addLayout(display_g_layout)
        display_h_layout.addStretch(1)

        display_layout = QVBoxLayout()
        display_layout.addWidget(showtabbar_box)
        display_layout.addWidget(showclassfuncdropdown_box)
        display_layout.addWidget(showindentguides_box)
        display_layout.addWidget(linenumbers_box)
        display_layout.addWidget(blanks_box)
        display_layout.addWidget(currentline_box)
        display_layout.addWidget(currentcell_box)
        display_layout.addWidget(wrap_mode_box)
        display_layout.addWidget(scroll_past_end_box)
        display_layout.addLayout(display_h_layout)

        display_widget = QWidget()
        display_widget.setLayout(display_layout)

        # --- Source code tab ---
        closepar_box = newcb(
            _("Automatic insertion of parentheses, braces and brackets"),
            'close_parentheses')
        close_quotes_box = newcb(_("Automatic insertion of closing quotes"),
                                 'close_quotes')
        add_colons_box = newcb(
            _("Automatic insertion of colons after 'for', 'if', 'def', etc"),
            'add_colons')
        autounindent_box = newcb(
            _("Automatic indentation after 'else', 'elif', etc."),
            'auto_unindent')
        tab_mode_box = newcb(
            _("Tab always indent"),
            'tab_always_indent',
            default=False,
            tip=_("If enabled, pressing Tab will always indent,\n"
                  "even when the cursor is not at the beginning\n"
                  "of a line (when this option is enabled, code\n"
                  "completion may be triggered using the alternate\n"
                  "shortcut: Ctrl+Space)"))
        ibackspace_box = newcb(_("Intelligent backspace"),
                               'intelligent_backspace',
                               default=True)
        removetrail_box = newcb(
            _("Automatically remove trailing spaces when saving files"),
            'always_remove_trailing_spaces',
            default=False)

        indent_chars_box = self.create_combobox(
            _("Indentation characters: "),
            ((_("2 spaces"), '*  *'), (_("3 spaces"), '*   *'),
             (_("4 spaces"), '*    *'), (_("5 spaces"), '*     *'),
             (_("6 spaces"), '*      *'), (_("7 spaces"), '*       *'),
             (_("8 spaces"), '*        *'), (_("Tabulations"), '*\t*')),
            'indent_chars')
        tabwidth_spin = self.create_spinbox(_("Tab stop width:"), _("spaces"),
                                            'tab_stop_width_spaces', 4, 1, 8,
                                            1)

        def enable_tabwidth_spin(index):
            if index == 7:  # Tabulations
                tabwidth_spin.plabel.setEnabled(True)
                tabwidth_spin.spinbox.setEnabled(True)
            else:
                tabwidth_spin.plabel.setEnabled(False)
                tabwidth_spin.spinbox.setEnabled(False)

        indent_chars_box.combobox.currentIndexChanged.connect(
            enable_tabwidth_spin)

        indent_tab_grid_layout = QGridLayout()
        indent_tab_grid_layout.addWidget(indent_chars_box.label, 0, 0)
        indent_tab_grid_layout.addWidget(indent_chars_box.combobox, 0, 1)
        indent_tab_grid_layout.addWidget(tabwidth_spin.plabel, 1, 0)
        indent_tab_grid_layout.addWidget(tabwidth_spin.spinbox, 1, 1)
        indent_tab_grid_layout.addWidget(tabwidth_spin.slabel, 1, 2)

        indent_tab_layout = QHBoxLayout()
        indent_tab_layout.addLayout(indent_tab_grid_layout)
        indent_tab_layout.addStretch(1)

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(closepar_box)
        sourcecode_layout.addWidget(autounindent_box)
        sourcecode_layout.addWidget(add_colons_box)
        sourcecode_layout.addWidget(close_quotes_box)
        sourcecode_layout.addWidget(tab_mode_box)
        sourcecode_layout.addWidget(ibackspace_box)
        sourcecode_layout.addWidget(removetrail_box)
        sourcecode_layout.addLayout(indent_tab_layout)

        sourcecode_widget = QWidget()
        sourcecode_widget.setLayout(sourcecode_layout)

        # --- Run code tab ---
        saveall_box = newcb(_("Save all files before running script"),
                            'save_all_before_run')
        focus_box = newcb(
            _("Maintain focus in the Editor after running cells "
              "or selections"), 'focus_to_editor')
        run_cell_box = newcb(
            _("Copy full cell contents to the console when "
              "running code cells"), 'run_cell_copy')

        run_layout = QVBoxLayout()
        run_layout.addWidget(saveall_box)
        run_layout.addWidget(focus_box)
        run_layout.addWidget(run_cell_box)

        run_widget = QWidget()
        run_widget.setLayout(run_layout)

        # --- Advanced tab ---
        # -- Templates
        template_btn = self.create_button(_("Edit template for new files"),
                                          self.plugin.edit_template)

        # -- Autosave
        autosave_group = QGroupBox(_('Autosave'))
        autosave_checkbox = newcb(
            _('Automatically save a copy of files with unsaved changes'),
            'autosave_enabled')
        autosave_spinbox = self.create_spinbox(_('Autosave interval: '),
                                               _('seconds'),
                                               'autosave_interval',
                                               min_=1,
                                               max_=3600)
        autosave_checkbox.toggled.connect(autosave_spinbox.setEnabled)

        autosave_layout = QVBoxLayout()
        autosave_layout.addWidget(autosave_checkbox)
        autosave_layout.addWidget(autosave_spinbox)
        autosave_group.setLayout(autosave_layout)

        # -- Docstring
        docstring_group = QGroupBox(_('Docstring type'))

        numpy_url = "<a href='{}'>Numpy</a>".format(NUMPYDOC)
        googledoc_url = "<a href='{}'>Google</a>".format(GOOGLEDOC)
        docstring_label = QLabel(
            _("Here you can select the type of docstrings ({} or {}) you "
              "want the editor to automatically introduce when pressing "
              "<tt>{}</tt> after a function/method/class "
              "declaration.").format(numpy_url, googledoc_url,
                                     DOCSTRING_SHORTCUT))
        docstring_label.setOpenExternalLinks(True)
        docstring_label.setWordWrap(True)

        docstring_combo_choices = (
            (_("Numpy"), 'Numpydoc'),
            (_("Google"), 'Googledoc'),
        )
        docstring_combo = self.create_combobox("Type:",
                                               docstring_combo_choices,
                                               'docstring_type')

        docstring_layout = QVBoxLayout()
        docstring_layout.addWidget(docstring_label)
        docstring_layout.addWidget(docstring_combo)
        docstring_group.setLayout(docstring_layout)

        # -- Annotations
        annotations_group = QGroupBox(_("Annotations"))
        annotations_label = QLabel(
            _("Display a marker to the left of line numbers when the "
              "following annotations appear at the beginning of a comment: "
              "<tt>TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, "
              "!!!, ???</tt>"))
        annotations_label.setWordWrap(True)
        todolist_box = newcb(_("Display code annotations"), 'todo_list')

        annotations_layout = QVBoxLayout()
        annotations_layout.addWidget(annotations_label)
        annotations_layout.addWidget(todolist_box)
        annotations_group.setLayout(annotations_layout)

        # -- EOL
        eol_group = QGroupBox(_("End-of-line characters"))
        eol_label = QLabel(
            _("When opening a text file containing "
              "mixed end-of-line characters (this may "
              "raise syntax errors in the consoles "
              "on Windows platforms), Spyder may fix the "
              "file automatically."))
        eol_label.setWordWrap(True)
        check_eol_box = newcb(_("Fix automatically and show warning "
                                "message box"),
                              'check_eol_chars',
                              default=True)
        convert_eol_on_save_box = newcb(_("On Save: convert EOL characters"
                                          " to"),
                                        'convert_eol_on_save',
                                        default=False)
        eol_combo_choices = (
            (_("LF (UNIX)"), 'LF'),
            (_("CRLF (Windows)"), 'CRLF'),
            (_("CR (Mac)"), 'CR'),
        )
        convert_eol_on_save_combo = self.create_combobox(
            "",
            eol_combo_choices,
            ('convert_eol_on_'
             'save_to'),
        )
        convert_eol_on_save_box.toggled.connect(
            convert_eol_on_save_combo.setEnabled)
        convert_eol_on_save_combo.setEnabled(
            self.get_option('convert_eol_on_save'))

        eol_on_save_layout = QHBoxLayout()
        eol_on_save_layout.addWidget(convert_eol_on_save_box)
        eol_on_save_layout.addWidget(convert_eol_on_save_combo)

        eol_layout = QVBoxLayout()
        eol_layout.addWidget(eol_label)
        eol_layout.addWidget(check_eol_box)
        eol_layout.addLayout(eol_on_save_layout)
        eol_group.setLayout(eol_layout)

        # --- Tabs ---
        tabs = QTabWidget()
        tabs.addTab(self.create_tab(display_widget), _("Display"))
        tabs.addTab(self.create_tab(sourcecode_widget), _("Source code"))
        tabs.addTab(self.create_tab(run_widget), _('Run Code'))
        tabs.addTab(
            self.create_tab(template_btn, autosave_group, docstring_group,
                            annotations_group, eol_group),
            _("Advanced settings"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
Beispiel #19
0
    def __init__(self, parent, text):
        QWidget.__init__(self, parent)

        self.text_editor = QTextEdit(self)
        self.text_editor.setText(text)
        self.text_editor.setReadOnly(True)

        # Type frame
        type_layout = QHBoxLayout()
        type_label = QLabel(_("Import as"))
        type_layout.addWidget(type_label)
        data_btn = QRadioButton(_("data"))
        data_btn.setChecked(True)
        self._as_data= True
        type_layout.addWidget(data_btn)
        code_btn = QRadioButton(_("code"))
        self._as_code = False
        type_layout.addWidget(code_btn)
        txt_btn = QRadioButton(_("text"))
        type_layout.addWidget(txt_btn)

        h_spacer = QSpacerItem(40, 20,
                               QSizePolicy.Expanding, QSizePolicy.Minimum)
        type_layout.addItem(h_spacer)
        type_frame = QFrame()
        type_frame.setLayout(type_layout)

        # Opts frame
        grid_layout = QGridLayout()
        grid_layout.setSpacing(0)

        col_label = QLabel(_("Column separator:"))
        grid_layout.addWidget(col_label, 0, 0)
        col_w = QWidget()
        col_btn_layout = QHBoxLayout()
        self.tab_btn = QRadioButton(_("Tab"))
        self.tab_btn.setChecked(False)
        col_btn_layout.addWidget(self.tab_btn)
        self.ws_btn = QRadioButton(_("Whitespace"))
        self.ws_btn.setChecked(False)
        col_btn_layout.addWidget(self.ws_btn)
        other_btn_col = QRadioButton(_("other"))
        other_btn_col.setChecked(True)
        col_btn_layout.addWidget(other_btn_col)
        col_w.setLayout(col_btn_layout)
        grid_layout.addWidget(col_w, 0, 1)
        self.line_edt = QLineEdit(",")
        self.line_edt.setMaximumWidth(30)
        self.line_edt.setEnabled(True)
        other_btn_col.toggled.connect(self.line_edt.setEnabled)
        grid_layout.addWidget(self.line_edt, 0, 2)

        row_label = QLabel(_("Row separator:"))
        grid_layout.addWidget(row_label, 1, 0)
        row_w = QWidget()
        row_btn_layout = QHBoxLayout()
        self.eol_btn = QRadioButton(_("EOL"))
        self.eol_btn.setChecked(True)
        row_btn_layout.addWidget(self.eol_btn)
        other_btn_row = QRadioButton(_("other"))
        row_btn_layout.addWidget(other_btn_row)
        row_w.setLayout(row_btn_layout)
        grid_layout.addWidget(row_w, 1, 1)
        self.line_edt_row = QLineEdit(";")
        self.line_edt_row.setMaximumWidth(30)
        self.line_edt_row.setEnabled(False)
        other_btn_row.toggled.connect(self.line_edt_row.setEnabled)
        grid_layout.addWidget(self.line_edt_row, 1, 2)

        grid_layout.setRowMinimumHeight(2, 15)

        other_group = QGroupBox(_("Additional options"))
        other_layout = QGridLayout()
        other_group.setLayout(other_layout)

        skiprows_label = QLabel(_("Skip rows:"))
        other_layout.addWidget(skiprows_label, 0, 0)
        self.skiprows_edt = QLineEdit('0')
        self.skiprows_edt.setMaximumWidth(30)
        intvalid = QIntValidator(0, len(to_text_string(text).splitlines()),
                                 self.skiprows_edt)
        self.skiprows_edt.setValidator(intvalid)
        other_layout.addWidget(self.skiprows_edt, 0, 1)

        other_layout.setColumnMinimumWidth(2, 5)

        comments_label = QLabel(_("Comments:"))
        other_layout.addWidget(comments_label, 0, 3)
        self.comments_edt = QLineEdit('#')
        self.comments_edt.setMaximumWidth(30)
        other_layout.addWidget(self.comments_edt, 0, 4)

        self.trnsp_box = QCheckBox(_("Transpose"))
        #self.trnsp_box.setEnabled(False)
        other_layout.addWidget(self.trnsp_box, 1, 0, 2, 0)

        grid_layout.addWidget(other_group, 3, 0, 2, 0)

        opts_frame = QFrame()
        opts_frame.setLayout(grid_layout)

        data_btn.toggled.connect(opts_frame.setEnabled)
        data_btn.toggled.connect(self.set_as_data)
        code_btn.toggled.connect(self.set_as_code)
#        self.connect(txt_btn, SIGNAL("toggled(bool)"),
#                     self, SLOT("is_text(bool)"))

        # Final layout
        layout = QVBoxLayout()
        layout.addWidget(type_frame)
        layout.addWidget(self.text_editor)
        layout.addWidget(opts_frame)
        self.setLayout(layout)
Beispiel #20
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Display tab ---
        showtabbar_box = newcb(_("Show tab bar"), 'show_tab_bar')
        showclassfuncdropdown_box = newcb(
                _("Show selector for classes and functions"),
                'show_class_func_dropdown')
        showindentguides_box = newcb(_("Show Indent Guides"),
                                     'indent_guides')
        linenumbers_box = newcb(_("Show line numbers"), 'line_numbers')
        blanks_box = newcb(_("Show blank spaces"), 'blank_spaces')
        currentline_box = newcb(_("Highlight current line"),
                                'highlight_current_line')
        currentcell_box = newcb(_("Highlight current cell"),
                                'highlight_current_cell')
        wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
        scroll_past_end_box = newcb(_("Scroll past the end"),
                                    'scroll_past_end')

        edgeline_box = newcb(_("Show vertical lines at"), 'edge_line')
        edgeline_edit = self.create_lineedit(
            "",
            'edge_line_columns',
            tip=("Enter values separated by commas"),
            alignment=Qt.Horizontal,
            regex="[0-9]+(,[0-9]+)*")
        edgeline_edit_label = QLabel(_("characters"))
        edgeline_box.toggled.connect(edgeline_edit.setEnabled)
        edgeline_box.toggled.connect(edgeline_edit_label.setEnabled)
        edgeline_edit.setEnabled(self.get_option('edge_line'))
        edgeline_edit_label.setEnabled(self.get_option('edge_line'))

        occurrence_box = newcb(_("Highlight occurrences after"),
                               'occurrence_highlighting')
        occurrence_spin = self.create_spinbox(
            "", _(" ms"),
            'occurrence_highlighting/timeout',
            min_=100, max_=1000000, step=100)
        occurrence_box.toggled.connect(occurrence_spin.spinbox.setEnabled)
        occurrence_box.toggled.connect(occurrence_spin.slabel.setEnabled)
        occurrence_spin.spinbox.setEnabled(
                self.get_option('occurrence_highlighting'))
        occurrence_spin.slabel.setEnabled(
                self.get_option('occurrence_highlighting'))

        display_g_layout = QGridLayout()
        display_g_layout.addWidget(edgeline_box, 0, 0)
        display_g_layout.addWidget(edgeline_edit.textbox, 0, 1)
        display_g_layout.addWidget(edgeline_edit_label, 0, 2)
        display_g_layout.addWidget(occurrence_box, 1, 0)
        display_g_layout.addWidget(occurrence_spin.spinbox, 1, 1)
        display_g_layout.addWidget(occurrence_spin.slabel, 1, 2)

        display_h_layout = QHBoxLayout()
        display_h_layout.addLayout(display_g_layout)
        display_h_layout.addStretch(1)

        display_layout = QVBoxLayout()
        display_layout.addWidget(showtabbar_box)
        display_layout.addWidget(showclassfuncdropdown_box)
        display_layout.addWidget(showindentguides_box)
        display_layout.addWidget(linenumbers_box)
        display_layout.addWidget(blanks_box)
        display_layout.addWidget(currentline_box)
        display_layout.addWidget(currentcell_box)
        display_layout.addWidget(wrap_mode_box)
        display_layout.addWidget(scroll_past_end_box)
        display_layout.addLayout(display_h_layout)

        display_widget = QWidget()
        display_widget.setLayout(display_layout)

        # --- Source code tab ---
        closepar_box = newcb(
            _("Automatic insertion of parentheses, braces and brackets"),
            'close_parentheses')
        close_quotes_box = newcb(
            _("Automatic insertion of closing quotes"),
            'close_quotes')
        add_colons_box = newcb(
            _("Automatic insertion of colons after 'for', 'if', 'def', etc"),
            'add_colons')
        autounindent_box = newcb(
            _("Automatic indentation after 'else', 'elif', etc."),
            'auto_unindent')
        tab_mode_box = newcb(
            _("Tab always indent"),
            'tab_always_indent', default=False,
            tip=_("If enabled, pressing Tab will always indent,\n"
                  "even when the cursor is not at the beginning\n"
                  "of a line (when this option is enabled, code\n"
                  "completion may be triggered using the alternate\n"
                  "shortcut: Ctrl+Space)"))
        ibackspace_box = newcb(
            _("Intelligent backspace"),
            'intelligent_backspace',
            default=True)
        removetrail_box = newcb(
            _("Automatically remove trailing spaces when saving files"),
            'always_remove_trailing_spaces',
            default=False)

        indent_chars_box = self.create_combobox(
            _("Indentation characters: "),
            ((_("2 spaces"), '*  *'),
             (_("3 spaces"), '*   *'),
             (_("4 spaces"), '*    *'),
             (_("5 spaces"), '*     *'),
             (_("6 spaces"), '*      *'),
             (_("7 spaces"), '*       *'),
             (_("8 spaces"), '*        *'),
             (_("Tabulations"), '*\t*')),
            'indent_chars')
        tabwidth_spin = self.create_spinbox(
            _("Tab stop width:"),
            _("spaces"),
            'tab_stop_width_spaces',
            4, 1, 8, 1)

        def enable_tabwidth_spin(index):
            if index == 7:  # Tabulations
                tabwidth_spin.plabel.setEnabled(True)
                tabwidth_spin.spinbox.setEnabled(True)
            else:
                tabwidth_spin.plabel.setEnabled(False)
                tabwidth_spin.spinbox.setEnabled(False)

        indent_chars_box.combobox.currentIndexChanged.connect(
            enable_tabwidth_spin)

        indent_tab_grid_layout = QGridLayout()
        indent_tab_grid_layout.addWidget(indent_chars_box.label, 0, 0)
        indent_tab_grid_layout.addWidget(indent_chars_box.combobox, 0, 1)
        indent_tab_grid_layout.addWidget(tabwidth_spin.plabel, 1, 0)
        indent_tab_grid_layout.addWidget(tabwidth_spin.spinbox, 1, 1)
        indent_tab_grid_layout.addWidget(tabwidth_spin.slabel, 1, 2)

        indent_tab_layout = QHBoxLayout()
        indent_tab_layout.addLayout(indent_tab_grid_layout)
        indent_tab_layout.addStretch(1)

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(closepar_box)
        sourcecode_layout.addWidget(autounindent_box)
        sourcecode_layout.addWidget(add_colons_box)
        sourcecode_layout.addWidget(close_quotes_box)
        sourcecode_layout.addWidget(tab_mode_box)
        sourcecode_layout.addWidget(ibackspace_box)
        sourcecode_layout.addWidget(removetrail_box)
        sourcecode_layout.addLayout(indent_tab_layout)

        sourcecode_widget = QWidget()
        sourcecode_widget.setLayout(sourcecode_layout)

        # --- Run code tab ---
        saveall_box = newcb(_("Save all files before running script"),
                            'save_all_before_run')
        focus_box = newcb(_("Maintain focus in the Editor after running cells "
                            "or selections"), 'focus_to_editor')
        run_cell_box = newcb(_("Copy full cell contents to the console when "
                               "running code cells"), 'run_cell_copy')

        run_layout = QVBoxLayout()
        run_layout.addWidget(saveall_box)
        run_layout.addWidget(focus_box)
        run_layout.addWidget(run_cell_box)

        run_widget = QWidget()
        run_widget.setLayout(run_layout)

        # --- Advanced tab ---
        # -- Templates
        template_btn = self.create_button(_("Edit template for new files"),
                                          self.plugin.edit_template)

        # -- Autosave
        autosave_group = QGroupBox(_('Autosave'))
        autosave_checkbox = newcb(
            _('Automatically save a copy of files with unsaved changes'),
            'autosave_enabled')
        autosave_spinbox = self.create_spinbox(
            _('Autosave interval: '),
            _('seconds'),
            'autosave_interval',
            min_=1, max_=3600)
        autosave_checkbox.toggled.connect(autosave_spinbox.setEnabled)

        autosave_layout = QVBoxLayout()
        autosave_layout.addWidget(autosave_checkbox)
        autosave_layout.addWidget(autosave_spinbox)
        autosave_group.setLayout(autosave_layout)

        # -- Docstring
        docstring_group = QGroupBox(_('Docstring type'))

        numpy_url = "<a href='{}'>Numpy</a>".format(NUMPYDOC)
        googledoc_url = "<a href='{}'>Google</a>".format(GOOGLEDOC)
        docstring_label = QLabel(
            _("Here you can select the type of docstrings ({} or {}) you "
              "want the editor to automatically introduce when pressing "
              "<tt>{}</tt> after a function/method/class "
              "declaration.").format(
                  numpy_url, googledoc_url, DOCSTRING_SHORTCUT))
        docstring_label.setOpenExternalLinks(True)
        docstring_label.setWordWrap(True)

        docstring_combo_choices = ((_("Numpy"), 'Numpydoc'),
                                   (_("Google"), 'Googledoc'),)
        docstring_combo = self.create_combobox(
            "Type:",
            docstring_combo_choices,
            'docstring_type')

        docstring_layout = QVBoxLayout()
        docstring_layout.addWidget(docstring_label)
        docstring_layout.addWidget(docstring_combo)
        docstring_group.setLayout(docstring_layout)

        # -- Annotations
        annotations_group = QGroupBox(_("Annotations"))
        annotations_label = QLabel(
            _("Display a marker to the left of line numbers when the "
              "following annotations appear at the beginning of a comment: "
              "<tt>TODO, FIXME, XXX, HINT, TIP, @todo, HACK, BUG, OPTIMIZE, "
              "!!!, ???</tt>"))
        annotations_label.setWordWrap(True)
        todolist_box = newcb(
            _("Display code annotations"),
            'todo_list')

        annotations_layout = QVBoxLayout()
        annotations_layout.addWidget(annotations_label)
        annotations_layout.addWidget(todolist_box)
        annotations_group.setLayout(annotations_layout)

        # -- EOL
        eol_group = QGroupBox(_("End-of-line characters"))
        eol_label = QLabel(_("When opening a text file containing "
                             "mixed end-of-line characters (this may "
                             "raise syntax errors in the consoles "
                             "on Windows platforms), Spyder may fix the "
                             "file automatically."))
        eol_label.setWordWrap(True)
        check_eol_box = newcb(_("Fix automatically and show warning "
                                "message box"),
                              'check_eol_chars', default=True)
        convert_eol_on_save_box = newcb(_("On Save: convert EOL characters"
                                          " to"),
                                        'convert_eol_on_save', default=False)
        eol_combo_choices = ((_("LF (UNIX)"), 'LF'),
                             (_("CRLF (Windows)"), 'CRLF'),
                             (_("CR (Mac)"), 'CR'),
                             )
        convert_eol_on_save_combo = self.create_combobox("",
                                                         eol_combo_choices,
                                                         ('convert_eol_on_'
                                                          'save_to'),
                                                         )
        convert_eol_on_save_box.toggled.connect(
                convert_eol_on_save_combo.setEnabled)
        convert_eol_on_save_combo.setEnabled(
                self.get_option('convert_eol_on_save'))

        eol_on_save_layout = QHBoxLayout()
        eol_on_save_layout.addWidget(convert_eol_on_save_box)
        eol_on_save_layout.addWidget(convert_eol_on_save_combo)

        eol_layout = QVBoxLayout()
        eol_layout.addWidget(eol_label)
        eol_layout.addWidget(check_eol_box)
        eol_layout.addLayout(eol_on_save_layout)
        eol_group.setLayout(eol_layout)

        # --- Tabs ---
        tabs = QTabWidget()
        tabs.addTab(self.create_tab(display_widget), _("Display"))
        tabs.addTab(self.create_tab(sourcecode_widget), _("Source code"))
        tabs.addTab(self.create_tab(run_widget), _('Run Code'))
        tabs.addTab(self.create_tab(template_btn, autosave_group,
                                    docstring_group, annotations_group,
                                    eol_group),
                    _("Advanced settings"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
Beispiel #21
0
    def setup_page(self):
        about_label = QLabel(
            _("The <b>global working directory</b> is "
              "the working directory for newly opened <i>consoles</i> "
              "(Python/IPython consoles and terminals), for the "
              "<i>file explorer</i>, for the <i>find in files</i> "
              "plugin and for new files created in the <i>editor</i>."))
        about_label.setWordWrap(True)

        startup_group = QGroupBox(_("Startup"))
        startup_bg = QButtonGroup(startup_group)
        startup_label = QLabel(
            _("At startup, the global working "
              "directory is:"))
        startup_label.setWordWrap(True)
        lastdir_radio = self.create_radiobutton(
            _("the same as in last session"),
            'startup/use_last_directory',
            True,
            _("At startup, Spyder will restore the "
              "global directory from last session"),
            button_group=startup_bg)
        thisdir_radio = self.create_radiobutton(
            _("the following directory:"),
            'startup/use_fixed_directory',
            False,
            _("At startup, the global working "
              "directory will be the specified path"),
            button_group=startup_bg)
        thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
                                           getcwd())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        lastdir_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        editor_o_group = QGroupBox(_("Open file"))
        editor_o_label = QLabel(_("Files are opened from:"))
        editor_o_label.setWordWrap(True)
        editor_o_bg = QButtonGroup(editor_o_group)
        editor_o_radio1 = self.create_radiobutton(
            _("the current file directory"),
            'editor/open/browse_scriptdir',
            button_group=editor_o_bg)
        editor_o_radio2 = self.create_radiobutton(
            _("the global working directory"),
            'editor/open/browse_workdir',
            button_group=editor_o_bg)

        editor_n_group = QGroupBox(_("New file"))
        editor_n_label = QLabel(_("Files are created in:"))
        editor_n_label.setWordWrap(True)
        editor_n_bg = QButtonGroup(editor_n_group)
        editor_n_radio1 = self.create_radiobutton(
            _("the current file directory"),
            'editor/new/browse_scriptdir',
            button_group=editor_n_bg)
        editor_n_radio2 = self.create_radiobutton(
            _("the global working directory"),
            'editor/new/browse_workdir',
            button_group=editor_n_bg)
        # Note: default values for the options above are set in plugin's
        #       constructor (see below)

        other_group = QGroupBox(_("Change to file base directory"))
        newcb = self.create_checkbox
        open_box = newcb(_("When opening a file"),
                         'editor/open/auto_set_to_basedir')
        save_box = newcb(_("When saving a file"),
                         'editor/save/auto_set_to_basedir')

        startup_layout = QVBoxLayout()
        startup_layout.addWidget(startup_label)
        startup_layout.addWidget(lastdir_radio)
        startup_layout.addLayout(thisdir_layout)
        startup_group.setLayout(startup_layout)

        editor_o_layout = QVBoxLayout()
        editor_o_layout.addWidget(editor_o_label)
        editor_o_layout.addWidget(editor_o_radio1)
        editor_o_layout.addWidget(editor_o_radio2)
        editor_o_group.setLayout(editor_o_layout)

        editor_n_layout = QVBoxLayout()
        editor_n_layout.addWidget(editor_n_label)
        editor_n_layout.addWidget(editor_n_radio1)
        editor_n_layout.addWidget(editor_n_radio2)
        editor_n_group.setLayout(editor_n_layout)

        other_layout = QVBoxLayout()
        other_layout.addWidget(open_box)
        other_layout.addWidget(save_box)
        other_group.setLayout(other_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(startup_group)
        vlayout.addWidget(editor_o_group)
        vlayout.addWidget(editor_n_group)
        vlayout.addWidget(other_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #22
0
    def setup_page(self):
        run_dlg = _("Run Settings")
        run_menu = _("Run")
        about_label = QLabel(_("The following are the default <i>%s</i>. "\
                               "These options may be overriden using the "\
                               "<b>%s</b> dialog box (see the <b>%s</b> menu)"\
                               ) % (run_dlg, run_dlg, run_menu))
        about_label.setWordWrap(True)

        interpreter_group = QGroupBox(_("Console"))
        interpreter_bg = QButtonGroup(interpreter_group)
        self.current_radio = self.create_radiobutton(
            CURRENT_INTERPRETER,
            CURRENT_INTERPRETER_OPTION,
            True,
            button_group=interpreter_bg)
        self.dedicated_radio = self.create_radiobutton(
            DEDICATED_INTERPRETER,
            DEDICATED_INTERPRETER_OPTION,
            False,
            button_group=interpreter_bg)
        self.systerm_radio = self.create_radiobutton(
            SYSTERM_INTERPRETER,
            SYSTERM_INTERPRETER_OPTION,
            False,
            button_group=interpreter_bg)

        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)
        interpreter_layout.addWidget(self.current_radio)
        interpreter_layout.addWidget(self.dedicated_radio)
        interpreter_layout.addWidget(self.systerm_radio)

        general_group = QGroupBox(_("General settings"))
        wdir_bg = QButtonGroup(general_group)
        wdir_label = QLabel(_("Default working directory is:"))
        wdir_label.setWordWrap(True)
        dirname_radio = self.create_radiobutton(_("the script directory"),
                                                WDIR_USE_SCRIPT_DIR_OPTION,
                                                True,
                                                button_group=wdir_bg)
        thisdir_radio = self.create_radiobutton(_("the following directory:"),
                                                WDIR_USE_FIXED_DIR_OPTION,
                                                False,
                                                button_group=wdir_bg)
        thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        dirname_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        post_mortem = self.create_checkbox(
            _("Enter debugging mode when errors appear during execution"),
            'post_mortem', False)

        general_layout = QVBoxLayout()
        general_layout.addWidget(wdir_label)
        general_layout.addWidget(dirname_radio)
        general_layout.addLayout(thisdir_layout)
        general_layout.addWidget(post_mortem)
        general_group.setLayout(general_layout)

        dedicated_group = QGroupBox(_("Dedicated Python console"))
        interact_after = self.create_checkbox(
            _("Interact with the Python console after execution"), 'interact',
            False)
        show_warning = self.create_checkbox(
            _("Show warning when killing running processes"),
            'show_kill_warning', True)

        dedicated_layout = QVBoxLayout()
        dedicated_layout.addWidget(interact_after)
        dedicated_layout.addWidget(show_warning)
        dedicated_group.setLayout(dedicated_layout)

        firstrun_cb = self.create_checkbox(
            ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"),
            ALWAYS_OPEN_FIRST_RUN_OPTION, False)

        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(interpreter_group)
        vlayout.addWidget(general_group)
        vlayout.addWidget(dedicated_group)
        vlayout.addWidget(firstrun_cb)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #23
0
class SiriusScrnView(QWidget):
    """
    Class to read Sirius screen cameras image data.

    To allow saving a grid correctly, control calibrationgrid_flag, which
    indicates if the screen is in calibration grid position.
    You can control it by using the method/Slot updateCalibrationGridFlag.
    """

    save_files = Signal()

    def __init__(self, parent=None, prefix=_VACA_PREFIX, device=None):
        """Initialize object."""
        QWidget.__init__(self, parent=parent)
        self.prefix = prefix
        self.device = SiriusPVName(device)
        self.scrn_prefix = self.device.substitute(prefix=prefix)
        self._receivedData = False
        self.setObjectName(self.scrn_prefix.sec + 'App')

        self.screen_type_conn = SiriusConnectionSignal(
            self.scrn_prefix.substitute(propty='ScrnType-Sts'))
        self.screen_type_conn.new_value_signal.connect(
            self.updateCalibrationGridFlag)
        self._calibrationgrid_flag = self.screen_type_conn.getvalue()
        self.save_files.connect(self._saveGridLocalFiles)
        self.ch_ImgROIHeight = SiriusConnectionSignal(
            self.scrn_prefix.substitute(propty='ImgROIHeight-RB'))
        self.ch_ImgROIWidth = SiriusConnectionSignal(
            self.scrn_prefix.substitute(propty='ImgROIWidth-RB'))
        self.ch_ImgROIOffsetX = SiriusConnectionSignal(
            self.scrn_prefix.substitute(propty='ImgROIOffsetX-RB'))
        self.ch_ImgROIOffsetY = SiriusConnectionSignal(
            self.scrn_prefix.substitute(propty='ImgROIOffsetY-RB'))

        self._setupUi()
        self.setFocus(True)
        self.setFocusPolicy(Qt.StrongFocus)
        self._loadCalibrationGrid(default=True)

    @property
    def calibrationgrid_flag(self):
        """Indicate if the screen device is in calibration grid position."""
        return self._calibrationgrid_flag

    @Slot(int)
    def updateCalibrationGridFlag(self, new_state):
        """Update calibrationgrid_flag property."""
        self._calibrationgrid_flag = new_state
        if new_state == 1:
            self.pushbutton_savegrid.setEnabled(True)
        else:
            self.pushbutton_savegrid.setEnabled(False)

    def _setupUi(self):
        self.cameraview_widget = QWidget()
        self.cameraview_widget.setLayout(self._cameraviewLayout())

        self.settings_widget = QWidget(self)
        self.settings_widget.setLayout(self._settingsLayout())
        self.settings_widget.setStyleSheet("""
            .QLabel{
                min-width: 5em;}
            QLabel{
                qproperty-alignment: AlignCenter;}""")

        self.calibrationgrid_widget = QWidget(self)
        self.calibrationgrid_widget.setLayout(self._calibrationgridLayout())
        self.calibrationgrid_widget.setSizePolicy(QSzPlcy.Expanding,
                                                  QSzPlcy.Expanding)
        self.calibrationgrid_widget.layout().setAlignment(Qt.AlignHCenter)
        self.tab = QTabWidget(self)
        self.tab.setStyleSheet("""
            QTabWidget::pane {
                border-left: 2px solid gray;
                border-bottom: 2px solid gray;
                border-right: 2px solid gray;
            }""")
        self.tab.addTab(self.settings_widget, 'Camera Settings')
        self.tab.addTab(self.calibrationgrid_widget, 'Calibration')

        self.statistics_groupBox = QGroupBox('Statistics', self)
        self.statistics_groupBox.setLayout(self._statisticsLayout())
        self.statistics_groupBox.setSizePolicy(QSzPlcy.Expanding,
                                               QSzPlcy.Expanding)
        self.statistics_groupBox.setStyleSheet("""
            .QLabel{
                min-width:0.28em; max-width:0.28em;
                min-height:1.29em; max-height:1.29em;}
            QLabel{
                qproperty-alignment: AlignCenter;}
            PyDMWidget{
                min-width:4.84em; max-width:4.84em;
                min-height:1.29em; max-height:1.29em;}""")

        self.trigger_groupBox = QGroupBox('Trigger', self)
        if 'TB' in self.device or 'BO' in self.device:
            trg_prefix = 'AS-Fam:TI-Scrn-TBBO'
        elif 'TS' in self.device:
            trg_prefix = 'TS-Fam:TI-Scrn'
        hbl = QHBoxLayout(self.trigger_groupBox)
        hbl.addWidget(
            HLTriggerSimple(parent=self.trigger_groupBox,
                            device=trg_prefix,
                            prefix=self.prefix))
        self.trigger_groupBox.setLayout(hbl)
        self.trigger_groupBox.setStyleSheet("""
            PyDMWidget{
                min-width:4.84em; max-width:4.84em;
                min-height:1.29em; max-height:1.29em;}""")

        vlay = QVBoxLayout()
        vlay.addWidget(self.statistics_groupBox)
        vlay.addWidget(self.trigger_groupBox)
        vlay.setSpacing(10)

        lay = QGridLayout(self)
        lay.setHorizontalSpacing(10)
        lay.setVerticalSpacing(10)
        lay.addWidget(self.cameraview_widget, 0, 0, 1, 2)
        lay.addWidget(self.tab, 1, 0)
        lay.addLayout(vlay, 1, 1)
        lay.setRowStretch(0, 15)
        lay.setRowStretch(1, 7)

    def _cameraviewLayout(self):
        label = QLabel(self.device, self)
        label.setStyleSheet("""font-weight: bold;max-height:1.29em;""")
        label.setAlignment(Qt.AlignCenter)
        self.image_view = _SiriusImageView(
            parent=self,
            image_channel=self.scrn_prefix.substitute(propty='ImgData-Mon'),
            width_channel=self.scrn_prefix.substitute(propty='ImgROIWidth-RB'),
            offsetx_channel=self.scrn_prefix.substitute(
                propty='ImgROIOffsetX-RB'),
            offsety_channel=self.scrn_prefix.substitute(
                propty='ImgROIOffsetY-RB'),
            maxwidth_channel=self.scrn_prefix.substitute(
                propty='ImgMaxWidth-Cte'),
            maxheight_channel=self.scrn_prefix.substitute(
                propty='ImgMaxHeight-Cte'))
        self.image_view.setObjectName('ScrnView')
        self.image_view.normalizeData = True
        self.image_view.readingOrder = self.image_view.Clike
        self.image_view.maxRedrawRate = 15
        self.image_view.setStyleSheet("""
            #ScrnView{min-width:30em; min-height:24em;}""")
        self.image_view.failToSaveGrid.connect(self._showFailToSaveGridMsg)
        self.image_view.receivedData.connect(self._setReceivedDataFlag)

        lay = QGridLayout()
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(label, 0, 1)
        lay.addItem(QSpacerItem(40, 2, QSzPlcy.Preferred, QSzPlcy.Fixed), 1, 1)
        lay.addWidget(self.image_view, 2, 1)
        return lay

    def _calibrationgridLayout(self):
        self.checkBox_showgrid = QCheckBox('Show', self)
        self.checkBox_showgrid.setEnabled(False)
        self.checkBox_showgrid.setStyleSheet("""
            min-width:4em; max-width:4em;
            min-height:1.29em; max-height:1.29em;""")
        self.checkBox_showgrid.toggled.connect(
            self.image_view.showCalibrationGrid)
        self.pushbutton_savegrid = QPushButton('Save', self)
        self.pushbutton_savegrid.setEnabled(False)
        self.pushbutton_savegrid.setStyleSheet("""
            min-width:4em; max-width:4em;
            min-height:1.29em; max-height:1.29em;""")
        self.pushbutton_savegrid.clicked.connect(self._saveCalibrationGrid)
        self.pushbutton_loadgrid = QPushButton('Load', self)
        self.pushbutton_loadgrid.setStyleSheet("""
            min-width:4em; max-width:4em;
            min-height:1.29em; max-height:1.29em;""")
        self.pushbutton_loadgrid.clicked.connect(self._loadCalibrationGrid)
        hbox_grid = QHBoxLayout()
        hbox_grid.addWidget(self.checkBox_showgrid)
        hbox_grid.addWidget(self.pushbutton_savegrid)
        hbox_grid.addWidget(self.pushbutton_loadgrid)

        lb = QLabel('Show levels <')
        lb.setStyleSheet("min-width:7em;max-width:7em;")
        self.spinbox_gridfilterfactor = QSpinBoxPlus()
        self.spinbox_gridfilterfactor.setMaximum(100)
        self.spinbox_gridfilterfactor.setMinimum(0)
        self.spinbox_gridfilterfactor.setValue(
            self.image_view.calibration_grid_filterfactor)
        self.spinbox_gridfilterfactor.editingFinished.connect(
            self._setCalibrationGridFilterFactor)
        self.spinbox_gridfilterfactor.setStyleSheet("""
            min-width:4em; max-width:4em;""")
        hbox_filter = QHBoxLayout()
        hbox_filter.setSpacing(0)
        hbox_filter.addWidget(lb)
        hbox_filter.addWidget(self.spinbox_gridfilterfactor)
        hbox_filter.addWidget(QLabel(' %'))

        lb = QLabel('Remove border: ')
        lb.setStyleSheet("min-width:7em;max-width:7em;")
        self.spinbox_removeborder = QSpinBoxPlus()
        self.spinbox_removeborder.setMaximum(512)
        self.spinbox_removeborder.setMinimum(0)
        self.spinbox_removeborder.setValue(
            self.image_view.calibration_grid_removeborder)
        self.spinbox_removeborder.editingFinished.connect(
            self._setCalibrationGridBorder2Remove)
        self.spinbox_removeborder.setStyleSheet("""
            min-width:4em; max-width:4em;""")
        hbox_remove = QHBoxLayout()
        hbox_remove.setSpacing(0)
        hbox_remove.addWidget(lb)
        hbox_remove.addWidget(self.spinbox_removeborder)
        hbox_remove.addWidget(QLabel(' px'))

        hbox_EnblLED = _create_propty_layout(parent=self,
                                             prefix=self.scrn_prefix,
                                             propty='EnblLED',
                                             propty_type='enbldisabl',
                                             width=4.68)

        lay = QFormLayout()
        lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred))
        lay.addRow('  Grid: ', hbox_grid)
        lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred))
        lay.addRow('  ', hbox_filter)
        lay.addRow('  ', hbox_remove)
        lay.addItem(QSpacerItem(1, 20, QSzPlcy.Ignored, QSzPlcy.Preferred))
        lay.addRow('  LED: ', hbox_EnblLED)
        lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred))
        lay.setLabelAlignment(Qt.AlignRight)
        lay.setFormAlignment(Qt.AlignCenter)
        return lay

    def _settingsLayout(self):
        label_CamEnbl = QLabel('Enable: ', self)
        hbox_CamEnbl = _create_propty_layout(parent=self,
                                             prefix=self.scrn_prefix,
                                             propty='CamEnbl',
                                             propty_type='enbldisabl')

        label_CamAcqPeriod = QLabel('Acquire\nPeriod [s]:', self)
        hbox_CamAcqPeriod = _create_propty_layout(parent=self,
                                                  prefix=self.scrn_prefix,
                                                  propty='CamAcqPeriod',
                                                  propty_type='sprb',
                                                  width=5.0)

        label_CamExposureTime = QLabel('Exposure\nTime [us]:', self)
        hbox_CamExposureTime = _create_propty_layout(parent=self,
                                                     prefix=self.scrn_prefix,
                                                     propty='CamExposureTime',
                                                     propty_type='sprb',
                                                     width=5.0)

        label_CamGain = QLabel('Gain[dB]:', self)
        hbox_CamGain = _create_propty_layout(parent=self,
                                             prefix=self.scrn_prefix,
                                             propty='CamGain',
                                             width=5.0,
                                             propty_type='sprb')

        label_AutoGain = QLabel('Auto Gain: ', self)
        self.pb_autogain = PyDMPushButton(
            label='',
            icon=qta.icon('mdi.auto-fix'),
            parent=self,
            pressValue=1,
            init_channel=self.scrn_prefix.substitute(propty='CamAutoGain-Cmd'))
        self.pb_autogain.setObjectName('autog')
        self.pb_autogain.setStyleSheet(
            "#autog{min-width:25px; max-width:25px; icon-size:20px;}")

        cam_prefix = SiriusPVName(self.scrn_prefix).substitute(dev='ScrnCam')
        label_Reset = QLabel('Reset: ', self)
        self.pb_dtl = PyDMPushButton(
            label='',
            icon=qta.icon('fa5s.sync'),
            parent=self,
            pressValue=1,
            init_channel=cam_prefix.substitute(propty='Rst-Cmd'))
        self.pb_dtl.setObjectName('reset')
        self.pb_dtl.setStyleSheet(
            "#reset{min-width:25px; max-width:25px; icon-size:20px;}")

        self.pb_details = QPushButton(qta.icon('fa5s.ellipsis-h'), '', self)
        self.pb_details.setToolTip('More settings')
        self.pb_details.setObjectName('detail')
        self.pb_details.setStyleSheet(
            "#detail{min-width:25px; max-width:25px; icon-size:20px;}")
        self.pb_details.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Preferred)
        util.connect_window(self.pb_details,
                            _ScrnSettingsDetails,
                            parent=self,
                            prefix=self.prefix,
                            device=self.device)

        hbox_aux = QHBoxLayout()
        hbox_aux.addWidget(self.pb_dtl, alignment=Qt.AlignLeft)
        hbox_aux.addWidget(self.pb_details, alignment=Qt.AlignRight)

        lay = QFormLayout()
        lay.setFormAlignment(Qt.AlignCenter)
        lay.addRow(label_CamEnbl, hbox_CamEnbl)
        lay.addRow(label_CamAcqPeriod, hbox_CamAcqPeriod)
        lay.addRow(label_CamExposureTime, hbox_CamExposureTime)
        lay.addRow(label_CamGain, hbox_CamGain)
        lay.addRow(label_AutoGain, self.pb_autogain)
        lay.addRow(label_Reset, hbox_aux)
        return lay

    def _statisticsLayout(self):
        # - Method
        label_Method = QLabel('CalcMethod:', self)
        label_Method.setStyleSheet("min-width:7em;")

        self.comboBox_Method = QComboBox(self)
        self.comboBox_Method.addItem('DimFei', 0)
        self.comboBox_Method.addItem('NDStats', 1)
        self.comboBox_Method.setCurrentIndex(0)
        self.comboBox_Method.setStyleSheet("""
            QComboBox::item {height: 1em;}
            QComboBox{min-width:6em;}""")
        self.comboBox_Method.currentIndexChanged.connect(
            self._handleShowStatistics)

        # - Centroid
        label_Centroid = QLabel('Centroid [mm]: ', self)
        label_Centroid.setStyleSheet("min-width:7em;")
        label_i_Center = QLabel('(', self)
        self.PyDMLabel_CenterXDimFei = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='CenterXDimFei-Mon'))
        self.PyDMLabel_CenterXDimFei.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_CenterXNDStats = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='CenterXNDStats-Mon'))
        self.PyDMLabel_CenterXNDStats.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_CenterXNDStats.setVisible(False)
        label_m_Center = QLabel(',', self)
        self.PyDMLabel_CenterYDimFei = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='CenterYDimFei-Mon'))
        self.PyDMLabel_CenterYDimFei.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_CenterYNDStats = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='CenterYNDStats-Mon'))
        self.PyDMLabel_CenterYNDStats.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_CenterYNDStats.setVisible(False)
        label_f_Center = QLabel(')', self)

        # - Sigma
        label_Sigma = QLabel('Sigma [mm]: ', self)
        label_Sigma.setStyleSheet("min-width:7em;")
        label_i_Sigma = QLabel('(', self)
        self.PyDMLabel_SigmaXDimFei = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='SigmaXDimFei-Mon'))
        self.PyDMLabel_SigmaXDimFei.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_SigmaXNDStats = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='SigmaXNDStats-Mon'))
        self.PyDMLabel_SigmaXNDStats.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_SigmaXNDStats.setVisible(False)
        label_m_Sigma = QLabel(',', self)
        self.PyDMLabel_SigmaYDimFei = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='SigmaYDimFei-Mon'))
        self.PyDMLabel_SigmaYDimFei.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_SigmaYNDStats = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='SigmaYNDStats-Mon'))
        self.PyDMLabel_SigmaYNDStats.setStyleSheet(
            'min-width:4em; max-width:4em;')
        self.PyDMLabel_SigmaYNDStats.setVisible(False)
        label_f_Sigma = QLabel(')', self)

        # - Theta
        label_Theta = QLabel('Theta [rad]: ')
        label_Theta.setStyleSheet("min-width:7em;")
        label_i_Theta = QLabel('(', self)
        self.PyDMLabel_ThetaDimFei = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(propty='ThetaDimFei-Mon'))
        self.PyDMLabel_ThetaDimFei.setStyleSheet("max-width:12em;")
        self.PyDMLabel_ThetaNDStats = PyDMLabel(
            parent=self,
            init_channel=self.scrn_prefix.substitute(
                propty='ThetaNDStats-Mon'))
        self.PyDMLabel_ThetaNDStats.setStyleSheet("max-width:12em;")
        self.PyDMLabel_ThetaNDStats.setVisible(False)
        label_f_Theta = QLabel(')', self)

        lay = QGridLayout()
        lay.addWidget(label_Method, 1, 1, 1, 3)
        lay.addWidget(self.comboBox_Method, 1, 3, 1, 3)
        lay.addWidget(label_Centroid, 3, 1, alignment=Qt.AlignCenter)
        lay.addWidget(label_i_Center, 3, 2)
        lay.addWidget(self.PyDMLabel_CenterXDimFei, 3, 3)
        lay.addWidget(self.PyDMLabel_CenterXNDStats, 3, 3)
        lay.addWidget(label_m_Center, 3, 4)
        lay.addWidget(self.PyDMLabel_CenterYDimFei, 3, 5)
        lay.addWidget(self.PyDMLabel_CenterYNDStats, 3, 5)
        lay.addWidget(label_f_Center, 3, 6)
        lay.addWidget(label_Sigma, 5, 1, alignment=Qt.AlignCenter)
        lay.addWidget(label_i_Sigma, 5, 2)
        lay.addWidget(self.PyDMLabel_SigmaXDimFei, 5, 3)
        lay.addWidget(self.PyDMLabel_SigmaXNDStats, 5, 3)
        lay.addWidget(label_m_Sigma, 5, 4)
        lay.addWidget(self.PyDMLabel_SigmaYDimFei, 5, 5)
        lay.addWidget(self.PyDMLabel_SigmaYNDStats, 5, 5)
        lay.addWidget(label_f_Sigma, 5, 6)
        lay.addWidget(label_Theta, 7, 1, alignment=Qt.AlignCenter)
        lay.addWidget(label_i_Theta, 7, 2)
        lay.addWidget(self.PyDMLabel_ThetaDimFei, 7, 3, 1, 3)
        lay.addWidget(self.PyDMLabel_ThetaNDStats, 7, 3, 1, 3)
        lay.addWidget(label_f_Theta, 7, 6)
        return lay

    def _handleShowStatistics(self, visible):
        self.PyDMLabel_CenterXDimFei.setVisible(not visible)
        self.PyDMLabel_CenterXNDStats.setVisible(visible)
        self.PyDMLabel_CenterYDimFei.setVisible(not visible)
        self.PyDMLabel_CenterYNDStats.setVisible(visible)
        self.PyDMLabel_ThetaDimFei.setVisible(not visible)
        self.PyDMLabel_ThetaNDStats.setVisible(visible)
        self.PyDMLabel_SigmaXDimFei.setVisible(not visible)
        self.PyDMLabel_SigmaXNDStats.setVisible(visible)
        self.PyDMLabel_SigmaYDimFei.setVisible(not visible)
        self.PyDMLabel_SigmaYNDStats.setVisible(visible)

    def _saveCalibrationGrid(self):
        t = Thread(target=self._saveCalibrationGrid_thread, daemon=True)
        t.start()

    def _saveCalibrationGrid_thread(self):
        roi_h = float(self.ch_ImgROIHeight.value)
        roi_w = float(self.ch_ImgROIWidth.value)
        roi_offsetx = float(self.ch_ImgROIOffsetX.value)
        roi_offsety = float(self.ch_ImgROIOffsetY.value)

        cond = roi_h != float(self.image_view.image_maxheight) or \
            roi_w != float(self.image_view.image_maxwidth) or \
            roi_offsetx != 0 or roi_offsety != 0
        if cond:
            # Disable camera acquisition and wait for disabling
            self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(0)
            state = self.SiriusLedState_CamEnbl.state
            while state == 1:
                time.sleep(0.1)
                state = self.SiriusLedState_CamEnbl.state

            # Change ROI to get entire image
            self.ch_ImgROIHeight.send_value_signal[float].emit(
                float(self.image_view.image_maxheight))
            self.ch_ImgROIWidth.send_value_signal[float].emit(
                float(self.image_view.image_maxwidth))
            self.ch_ImgROIOffsetX.send_value_signal[float].emit(0)
            self.ch_ImgROIOffsetY.send_value_signal[float].emit(0)

        # Enable led and wait for status
        self.PyDMStateButton_EnblLED.send_value_signal[int].emit(1)
        while not self.SiriusLedState_EnblLED.state:
            time.sleep(0.1)

        # Enable camera acquisition and wait for receiveing first frame
        self._receivedData = False
        self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(1)
        while not self._receivedData:
            time.sleep(0.1)

        # Save grid
        self.image_view.saveCalibrationGrid()

        if cond:
            # Disable camera acquisition and wait for disabling
            self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(0)
            state = self.SiriusLedState_CamEnbl.state
            while state == 1:
                time.sleep(0.1)
                state = self.SiriusLedState_CamEnbl.state

            # Change ROI to original size
            self.ch_ImgROIHeight.send_value_signal[float].emit(roi_h)
            self.ch_ImgROIWidth.send_value_signal[float].emit(roi_w)
            self.ch_ImgROIOffsetX.send_value_signal[float].emit(roi_offsetx)
            self.ch_ImgROIOffsetY.send_value_signal[float].emit(roi_offsety)

            # Enable camera acquisition
            self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(1)

        # Enable showing saved grid
        time.sleep(0.1)
        self.checkBox_showgrid.setEnabled(True)
        self.save_files.emit()

    def _saveGridLocalFiles(self):
        home = os.path.expanduser('~')
        folder_month = datetime.now().strftime('%Y-%m')
        folder_day = datetime.now().strftime('%Y-%m-%d')
        path = os.path.join(home, 'mounts', 'screens-iocs', folder_month,
                            folder_day)
        if not os.path.exists(path):
            os.makedirs(path)
        fn, _ = QFileDialog.getSaveFileName(
            self, 'Save Grid As...', path + '/' + self.device +
            datetime.now().strftime('_%Y-%m-%d_%Hh%Mmin'), '*.npy')
        if not fn:
            return False

        path_default = os.path.join(home, 'mounts', 'screens-iocs', 'default')
        if not os.path.exists(path_default):
            os.makedirs(path_default)
        fn_default = path_default + '/' + self.device

        grid = self.image_view.calibrationGrid
        width = self.image_view.imageWidth
        data = np.append(width, grid)
        np.save(fn, data)
        np.save(fn_default, data)

    def _loadCalibrationGrid(self, default=False):
        home = os.path.expanduser('~')
        if not default:
            folder_month = datetime.now().strftime('%Y-%m')
            path = os.path.join(home, 'mounts', 'screens-iocs', folder_month)
            fn, _ = QFileDialog.getOpenFileName(self, 'Load Grid...', path,
                                                '*.npy')
            if not fn:
                return
            if self.device not in fn:
                ans = QMessageBox.question(
                    self, 'Warning',
                    'The name of the selected file does not contain the name' +
                    ' of this screen. Are you sure you\'re loading this grid?',
                    QMessageBox.Yes, QMessageBox.Cancel)
                if ans == QMessageBox.Cancel:
                    return
        else:
            path = os.path.join(home, 'mounts', 'screens-iocs', 'default')
            fn = path + '/' + self.device + '.npy'

        try:
            data = np.load(fn)
            self.image_view.calibrationGrid = data
        except Exception as e:
            if not default:
                QMessageBox.critical(
                    self, 'Error',
                    'Could not load calibration grid from file ' + fn + '. ' +
                    '\nError message: ' + str(e), QMessageBox.Ok)
            return

        # Enable showing saved grid
        self.checkBox_showgrid.setEnabled(True)

    def _setReceivedDataFlag(self):
        self._receivedData = True

    def _setCalibrationGridFilterFactor(self):
        self.image_view.set_calibration_grid_filterfactor(
            self.spinbox_gridfilterfactor.value())

    def _setCalibrationGridBorder2Remove(self):
        self.image_view.set_calibration_grid_border2remove(
            self.spinbox_removeborder.value())

    @Slot()
    def _showFailToSaveGridMsg(self):
        QMessageBox.warning(self, 'Warning',
                            'Could not save calibration grid!', QMessageBox.Ok)
Beispiel #24
0
class DesignTab(QWidget):
    def __init__(self):
        super(DesignTab, self).__init__()
        self.setup_ui()
        self.grain_dialog = None

        self.btn_new_grain.clicked.connect(self.create_grain_dialog)

    def create_grain_dialog(self):
        self.grain_dialog = NewGrainDialog()
        self.grain_dialog.show()
        self.grain_dialog.activateWindow()
        self.grain_dialog.raise_()

    def setup_ui(self):
        sp = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setSizePolicy(sp)

        def setup_grain_design():
            # grain table view
            master = QHBoxLayout(self)
            master.addWidget(QTableView())

            # grain design controls
            controls = QVBoxLayout(self)
            # add a push button
            self.btn_new_grain = QPushButton(self.tr("New Grain"))
            self.btn_new_grain.setMinimumHeight(50)
            controls.addWidget(self.btn_new_grain)

            # add a dividing line
            line = QFrame()
            line.setFrameShape(QFrame.HLine)
            line.setFrameShadow(QFrame.Sunken)
            controls.addSpacing(5)
            controls.addWidget(line)

            # rest of the controls buttons
            self.btn_edit_grain = QPushButton(self.tr("Edit"))
            self.btn_edit_grain.setMinimumHeight(30)
            controls.addWidget(self.btn_edit_grain)
            self.btn_delete_Grain = QPushButton(self.tr("Delete"))
            self.btn_delete_Grain.setMinimumHeight(30)
            controls.addWidget(self.btn_delete_Grain)

            # move grain up and down
            moveup = QHBoxLayout()
            self.btn_move_up = QToolButton()
            self.btn_move_up.setArrowType(Qt.UpArrow)
            moveup.addWidget(self.btn_move_up)
            moveup.addWidget(QLabel(self.tr("Move Up")))
            controls.addLayout(moveup)

            movedown = QHBoxLayout()
            self.btn_move_down = QToolButton()
            self.btn_move_down.setArrowType(Qt.DownArrow)
            movedown.addWidget(self.btn_move_down)
            movedown.addWidget(QLabel(self.tr("Move Down")))
            controls.addLayout(movedown)
            controls.addStretch()

            # add info for motor design
            fl_propellant_info = QFormLayout()
            gb_motor_info = QGroupBox(self.tr("Propellant Info"))
            gb_motor_info.setLayout(fl_propellant_info)

            self.lbl_num_grains = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Number of Segments:")), self.lbl_num_grains)
            self.lbl_motor_dia = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Motor Diameter:")), self.lbl_motor_dia)
            self.lbl_motor_len = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Propellant Length:")), self.lbl_motor_len)
            self.lbl_prop_mass = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Propellant Mass:")), self.lbl_prop_mass)
            self.lbl_volume_loading = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Volume Loading:")), self.lbl_volume_loading)

            # set group box's layout
            controls.addWidget(gb_motor_info)

            # setup master layout
            master.addLayout(controls)
            self.gb_design = QGroupBox(self.tr("Grain Design"))
            self.gb_design.setLayout(master)

        def setup_chamber_design():
            # master layout
            master = QVBoxLayout()
            # master group box
            self.gb_chamber = QGroupBox(self.tr("Chamber Design"))

            # nozzle settings button
            self.btn_nozzle_settings = QPushButton(self.tr("Edit Nozzle"))
            self.btn_nozzle_settings.setMinimumHeight(50)
            master.addWidget(self.btn_nozzle_settings)

            # nozzle info pane
            fl_nozzle_info = QFormLayout()
            gb_nozzle = QGroupBox(self.tr("Nozzle Info"))
            gb_nozzle.setLayout(fl_nozzle_info)

            self.lbl_nozzle_throat = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Throat Diameter:")), self.lbl_nozzle_throat)
            self.lbl_nozzle_exit = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Exit Diameter:")), self.lbl_nozzle_exit)
            self.lbl_nozzle_expansion_ratio = QLabel()
            fl_nozzle_info.addRow(QLabel(self.tr("Expansion Ratio:")), self.lbl_nozzle_expansion_ratio)
            # add group box to master
            master.addWidget(gb_nozzle)
            master.addStretch()

            # overall motor info pane
            fl_motor_info = QFormLayout()
            gb_motor = QGroupBox(self.tr("Motor Info"))
            gb_motor.setLayout(fl_motor_info)

            self.lbl_kn = QLabel()
            fl_motor_info.addRow(QLabel(self.tr("Kn:")), self.lbl_kn)
            self.lbl_port_throat = QLabel()
            fl_motor_info.addRow(QLabel(self.tr("Port/Throat Ratio:")), self.lbl_port_throat)

            master.addWidget(gb_motor)
            self.gb_chamber.setLayout(master)

        def setup_gfx_ui():
            # design overview
            self.motor_display_view = QGraphicsView()
            self.motor_display_scene = QGraphicsScene()
            self.motor_display_view.setScene(self.motor_display_scene)
            self.motor_display_view.show()

            # sliced cross section
            self.grain_slice_view = QGraphicsView()
            self.grain_slice_scene = QGraphicsScene()
            self.grain_slice_view.setScene(self.grain_slice_scene)
            self.grain_slice_view.show()

            # splitter
            self.splt_gfx = QSplitter(Qt.Horizontal)
            self.splt_gfx.addWidget(self.motor_display_view)
            self.splt_gfx.addWidget(self.grain_slice_view)
            self.splt_gfx.setStretchFactor(0, 10)
            self.splt_gfx.setStretchFactor(1, 3)
            self.splt_gfx.setMinimumHeight(50)

        setup_grain_design()
        setup_chamber_design()
        setup_gfx_ui()

        self.splt_grain_design = QSplitter(Qt.Horizontal)
        self.splt_grain_design.addWidget(self.gb_design)
        self.splt_grain_design.addWidget(self.gb_chamber)
        self.splt_grain_design.setStretchFactor(0, 10)
        self.splt_grain_design.setStretchFactor(1, 3)

        self.splt_main = QSplitter(Qt.Vertical)
        self.splt_main.addWidget(self.splt_grain_design)
        self.splt_main.addWidget(self.splt_gfx)
        self.splt_main.setSizes([300, 150])

        layout = QVBoxLayout()
        layout.addWidget(self.splt_main)
        self.setLayout(layout)
Beispiel #25
0
        def setup_grain_design():
            # grain table view
            master = QHBoxLayout(self)
            master.addWidget(QTableView())

            # grain design controls
            controls = QVBoxLayout(self)
            # add a push button
            self.btn_new_grain = QPushButton(self.tr("New Grain"))
            self.btn_new_grain.setMinimumHeight(50)
            controls.addWidget(self.btn_new_grain)

            # add a dividing line
            line = QFrame()
            line.setFrameShape(QFrame.HLine)
            line.setFrameShadow(QFrame.Sunken)
            controls.addSpacing(5)
            controls.addWidget(line)

            # rest of the controls buttons
            self.btn_edit_grain = QPushButton(self.tr("Edit"))
            self.btn_edit_grain.setMinimumHeight(30)
            controls.addWidget(self.btn_edit_grain)
            self.btn_delete_Grain = QPushButton(self.tr("Delete"))
            self.btn_delete_Grain.setMinimumHeight(30)
            controls.addWidget(self.btn_delete_Grain)

            # move grain up and down
            moveup = QHBoxLayout()
            self.btn_move_up = QToolButton()
            self.btn_move_up.setArrowType(Qt.UpArrow)
            moveup.addWidget(self.btn_move_up)
            moveup.addWidget(QLabel(self.tr("Move Up")))
            controls.addLayout(moveup)

            movedown = QHBoxLayout()
            self.btn_move_down = QToolButton()
            self.btn_move_down.setArrowType(Qt.DownArrow)
            movedown.addWidget(self.btn_move_down)
            movedown.addWidget(QLabel(self.tr("Move Down")))
            controls.addLayout(movedown)
            controls.addStretch()

            # add info for motor design
            fl_propellant_info = QFormLayout()
            gb_motor_info = QGroupBox(self.tr("Propellant Info"))
            gb_motor_info.setLayout(fl_propellant_info)

            self.lbl_num_grains = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Number of Segments:")), self.lbl_num_grains)
            self.lbl_motor_dia = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Motor Diameter:")), self.lbl_motor_dia)
            self.lbl_motor_len = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Propellant Length:")), self.lbl_motor_len)
            self.lbl_prop_mass = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Propellant Mass:")), self.lbl_prop_mass)
            self.lbl_volume_loading = QLabel()
            fl_propellant_info.addRow(QLabel(self.tr("Volume Loading:")), self.lbl_volume_loading)

            # set group box's layout
            controls.addWidget(gb_motor_info)

            # setup master layout
            master.addLayout(controls)
            self.gb_design = QGroupBox(self.tr("Grain Design"))
            self.gb_design.setLayout(master)
Beispiel #26
0
def _get_scenes(path: "PathLike", img: AICSImage, in_memory: bool) -> None:
    # Get napari viewer from current process
    viewer = napari.current_viewer()

    # Add a checkbox widget if not present
    if AICSIMAGEIO_CHOICES not in viewer.window._dock_widgets:
        # Create a checkbox widget to set "Clear On Scene Select" or not
        scene_clear_checkbox = QCheckBox(CLEAR_LAYERS_ON_SELECT)
        scene_clear_checkbox.setChecked(False)

        # Create a checkbox widget to set "Unpack Channels" or not
        channel_unpack_checkbox = QCheckBox(UNPACK_CHANNELS_TO_LAYERS)
        channel_unpack_checkbox.setChecked(False)

        # Add all scene management state to a single box
        scene_manager_group = QGroupBox()
        scene_manager_group_layout = QVBoxLayout()
        scene_manager_group_layout.addWidget(scene_clear_checkbox)
        scene_manager_group_layout.addWidget(channel_unpack_checkbox)
        scene_manager_group.setLayout(scene_manager_group_layout)
        scene_manager_group.setFixedHeight(100)

        viewer.window.add_dock_widget(
            scene_manager_group,
            area="right",
            name=AICSIMAGEIO_CHOICES,
        )

    # Create the list widget and populate with the ids & scenes in the file
    list_widget = QListWidget()
    for i, scene in enumerate(img.scenes):
        list_widget.addItem(f"{i}{SCENE_LABEL_DELIMITER}{scene}")

    # Add this files scenes widget to viewer
    viewer.window.add_dock_widget(
        list_widget,
        area="right",
        name=f"{Path(path).name}{SCENE_LABEL_DELIMITER}Scenes",
    )

    # Function to create image layer from a scene selected in the list widget
    def open_scene(item: QListWidgetItem) -> None:
        scene_text = item.text()

        # Use scene indexes to cover for duplicate names
        scene_index = int(scene_text.split(SCENE_LABEL_DELIMITER)[0])

        # Update scene on image and get data
        img.set_scene(scene_index)
        data = _get_full_image_data(img=img, in_memory=in_memory)

        # Get metadata and add to image
        meta = _get_meta(data, img)

        # Optionally clear layers
        if _widget_is_checked(CLEAR_LAYERS_ON_SELECT):
            viewer.layers.clear()

        # Optionally remove channel axis
        if not _widget_is_checked(UNPACK_CHANNELS_TO_LAYERS):
            meta["name"] = scene_text
            meta.pop("channel_axis", None)

        viewer.add_image(data, **meta)

    list_widget.currentItemChanged.connect(open_scene)  # type: ignore
Beispiel #27
0
class PluginsConfigPage(PluginConfigPage):
    def setup_page(self):
        newcb = self.create_checkbox
        self.plugins_checkboxes = {}

        header_label = QLabel(
            _("Here you can turn on/off any internal or external Spyder plugin "
              "to disable functionality that is not desired or to have a lighter "
              "experience. Unchecked plugins in this page will be unloaded "
              "immediately and will not be loaded the next time Spyder starts."
              ))
        header_label.setWordWrap(True)

        # ------------------ Internal plugin status group ---------------------
        internal_layout = QGridLayout()
        self.internal_plugins_group = QGroupBox(_("Internal plugins"))

        i = 0
        for plugin_name in self.plugin.all_internal_plugins:
            (conf_section_name,
             PluginClass) = self.plugin.all_internal_plugins[plugin_name]

            if not getattr(PluginClass, 'CAN_BE_DISABLED', True):
                # Do not list core plugins that can not be disabled
                continue

            plugin_loc_name = None
            if hasattr(PluginClass, 'get_name'):
                plugin_loc_name = PluginClass.get_name()
            elif hasattr(PluginClass, 'get_plugin_title'):
                plugin_loc_name = PluginClass.get_plugin_title()

            plugin_state = CONF.get(conf_section_name, 'enable', True)
            cb = newcb(plugin_loc_name,
                       'enable',
                       default=True,
                       section=conf_section_name,
                       restart=True)
            internal_layout.addWidget(cb, i // 2, i % 2)
            self.plugins_checkboxes[plugin_name] = (cb, plugin_state)
            i += 1

        self.internal_plugins_group.setLayout(internal_layout)

        # ------------------ External plugin status group ---------------------
        external_layout = QGridLayout()
        self.external_plugins_group = QGroupBox(_("External plugins"))

        i = 0
        for i, plugin_name in enumerate(self.plugin.all_external_plugins):
            (conf_section_name,
             PluginClass) = self.plugin.all_external_plugins[plugin_name]

            plugin_loc_name = None
            if hasattr(PluginClass, 'get_name'):
                plugin_loc_name = PluginClass.get_name()
            elif hasattr(PluginClass, 'get_plugin_title'):
                plugin_loc_name = PluginClass.get_plugin_title()

            cb = newcb(plugin_loc_name,
                       'enable',
                       default=True,
                       section=conf_section_name,
                       restart=True)
            external_layout.addWidget(cb, i // 2, i % 2)
            self.plugins_checkboxes[plugin_name] = cb
            i += 1

        self.external_plugins_group.setLayout(external_layout)

        layout = QVBoxLayout()
        layout.addWidget(header_label)
        layout.addWidget(self.internal_plugins_group)
        if self.plugin.all_external_plugins:
            layout.addWidget(self.external_plugins_group)
        layout.addStretch(1)
        self.setLayout(layout)

    def apply_settings(self):
        for plugin_name in self.plugins_checkboxes:
            cb, previous_state = self.plugins_checkboxes[plugin_name]
            if cb.isChecked() and not previous_state:
                self.plugin.set_plugin_enabled(plugin_name)
                PluginClass = None
                external = False
                if plugin_name in self.plugin.all_internal_plugins:
                    (__, PluginClass
                     ) = self.plugin.all_internal_plugins[plugin_name]
                elif plugin_name in self.plugin.all_external_plugins:
                    (__, PluginClass
                     ) = self.plugin.all_external_plugins[plugin_name]
                    external = True

                # TODO: Once we can test that all plugins can be restarted
                # without problems during runtime, we can enable the
                # autorestart feature provided by the plugin registry:
                # self.plugin.register_plugin(self.main, PluginClass,
                #                             external=external)
            elif not cb.isChecked() and previous_state:
                # TODO: Once we can test that all plugins can be restarted
                # without problems during runtime, we can enable the
                # autorestart feature provided by the plugin registry:
                # self.plugin.delete_plugin(plugin_name)
                pass
        return set({})
Beispiel #28
0
    def __init__(self, parent, text):
        QWidget.__init__(self, parent)

        self.text_editor = QTextEdit(self)
        self.text_editor.setText(text)
        self.text_editor.setReadOnly(True)

        # Type frame
        type_layout = QHBoxLayout()
        type_label = QLabel(_("Import as"))
        type_layout.addWidget(type_label)
        data_btn = QRadioButton(_("data"))
        data_btn.setChecked(True)
        self._as_data= True
        type_layout.addWidget(data_btn)
        code_btn = QRadioButton(_("code"))
        self._as_code = False
        type_layout.addWidget(code_btn)
        txt_btn = QRadioButton(_("text"))
        type_layout.addWidget(txt_btn)

        h_spacer = QSpacerItem(40, 20,
                               QSizePolicy.Expanding, QSizePolicy.Minimum)
        type_layout.addItem(h_spacer)
        type_frame = QFrame()
        type_frame.setLayout(type_layout)

        # Opts frame
        grid_layout = QGridLayout()
        grid_layout.setSpacing(0)

        col_label = QLabel(_("Column separator:"))
        grid_layout.addWidget(col_label, 0, 0)
        col_w = QWidget()
        col_btn_layout = QHBoxLayout()
        self.tab_btn = QRadioButton(_("Tab"))
        self.tab_btn.setChecked(False)
        col_btn_layout.addWidget(self.tab_btn)
        other_btn_col = QRadioButton(_("other"))
        other_btn_col.setChecked(True)
        col_btn_layout.addWidget(other_btn_col)
        col_w.setLayout(col_btn_layout)
        grid_layout.addWidget(col_w, 0, 1)
        self.line_edt = QLineEdit(",")
        self.line_edt.setMaximumWidth(30)
        self.line_edt.setEnabled(True)
        other_btn_col.toggled.connect(self.line_edt.setEnabled)
        grid_layout.addWidget(self.line_edt, 0, 2)

        row_label = QLabel(_("Row separator:"))
        grid_layout.addWidget(row_label, 1, 0)
        row_w = QWidget()
        row_btn_layout = QHBoxLayout()
        self.eol_btn = QRadioButton(_("EOL"))
        self.eol_btn.setChecked(True)
        row_btn_layout.addWidget(self.eol_btn)
        other_btn_row = QRadioButton(_("other"))
        row_btn_layout.addWidget(other_btn_row)
        row_w.setLayout(row_btn_layout)
        grid_layout.addWidget(row_w, 1, 1)
        self.line_edt_row = QLineEdit(";")
        self.line_edt_row.setMaximumWidth(30)
        self.line_edt_row.setEnabled(False)
        other_btn_row.toggled.connect(self.line_edt_row.setEnabled)
        grid_layout.addWidget(self.line_edt_row, 1, 2)

        grid_layout.setRowMinimumHeight(2, 15)

        other_group = QGroupBox(_("Additional options"))
        other_layout = QGridLayout()
        other_group.setLayout(other_layout)

        skiprows_label = QLabel(_("Skip rows:"))
        other_layout.addWidget(skiprows_label, 0, 0)
        self.skiprows_edt = QLineEdit('0')
        self.skiprows_edt.setMaximumWidth(30)
        intvalid = QIntValidator(0, len(to_text_string(text).splitlines()),
                                 self.skiprows_edt)
        self.skiprows_edt.setValidator(intvalid)
        other_layout.addWidget(self.skiprows_edt, 0, 1)

        other_layout.setColumnMinimumWidth(2, 5)

        comments_label = QLabel(_("Comments:"))
        other_layout.addWidget(comments_label, 0, 3)
        self.comments_edt = QLineEdit('#')
        self.comments_edt.setMaximumWidth(30)
        other_layout.addWidget(self.comments_edt, 0, 4)

        self.trnsp_box = QCheckBox(_("Transpose"))
        #self.trnsp_box.setEnabled(False)
        other_layout.addWidget(self.trnsp_box, 1, 0, 2, 0)

        grid_layout.addWidget(other_group, 3, 0, 2, 0)

        opts_frame = QFrame()
        opts_frame.setLayout(grid_layout)

        data_btn.toggled.connect(opts_frame.setEnabled)
        data_btn.toggled.connect(self.set_as_data)
        code_btn.toggled.connect(self.set_as_code)
#        self.connect(txt_btn, SIGNAL("toggled(bool)"),
#                     self, SLOT("is_text(bool)"))

        # Final layout
        layout = QVBoxLayout()
        layout.addWidget(type_frame)
        layout.addWidget(self.text_editor)
        layout.addWidget(opts_frame)
        self.setLayout(layout)
Beispiel #29
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Introspection ---
        # Basic features group
        basic_features_group = QGroupBox(_("Basic features"))
        completion_box = newcb(_("Enable code completion"), 'code_completion')
        enable_hover_hints_box = newcb(
            _("Enable hover hints"),
            'enable_hover_hints',
            tip=_("If enabled, hovering the mouse pointer over an object\n"
                  "name will display that object's signature and/or\n"
                  "docstring (if present)."))
        goto_definition_box = newcb(
            _("Enable Go to definition"),
            'jedi_definition',
            tip=_("If enabled, left-clicking on an object name while \n"
                  "pressing the {} key will go to that object's definition\n"
                  "(if resolved).".format(self.CTRL)))
        follow_imports_box = newcb(_("Follow imports when going to a "
                                     "definition"),
                                   'jedi_definition/follow_imports')
        show_signature_box = newcb(_("Show calltips"), 'jedi_signature_help')

        basic_features_layout = QVBoxLayout()
        basic_features_layout.addWidget(completion_box)
        basic_features_layout.addWidget(enable_hover_hints_box)
        basic_features_layout.addWidget(goto_definition_box)
        basic_features_layout.addWidget(follow_imports_box)
        basic_features_layout.addWidget(show_signature_box)
        basic_features_group.setLayout(basic_features_layout)

        # Advanced group
        advanced_group = QGroupBox(_("Advanced"))
        modules_textedit = self.create_textedit(
            _("Preload the following modules to make completion faster "
              "and more accurate:"),
            'preload_modules'
        )
        if is_dark_interface():
            modules_textedit.textbox.setStyleSheet(
                "border: 1px solid #32414B;"
            )

        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(modules_textedit)
        advanced_group.setLayout(advanced_layout)

        # --- Linting ---
        # Linting options
        linting_label = QLabel(_("Spyder can optionally highlight syntax "
                                 "errors and possible problems with your "
                                 "code in the editor."))
        linting_label.setOpenExternalLinks(True)
        linting_label.setWordWrap(True)
        linting_check = self.create_checkbox(
            _("Enable basic linting"),
            'pyflakes')

        linting_complexity_box = self.create_checkbox(
            _("Enable complexity linting with "
              "the Mccabe package"), 'mccabe')

        # Linting layout
        linting_layout = QVBoxLayout()
        linting_layout.addWidget(linting_label)
        linting_layout.addWidget(linting_check)
        linting_layout.addWidget(linting_complexity_box)
        linting_widget = QWidget()
        linting_widget.setLayout(linting_layout)

        # --- Code style tab ---
        # Code style label
        pep_url = (
            '<a href="https://www.python.org/dev/peps/pep-0008">PEP 8</a>')
        code_style_codes_url = _(
            "<a href='http://pycodestyle.pycqa.org/en/stable"
            "/intro.html#error-codes'>pycodestyle error codes</a>")
        code_style_label = QLabel(
            _("Spyder can use pycodestyle to analyze your code for "
              "conformance to the {} convention. You can also "
              "manually show or hide specific warnings by their "
              "{}.").format(pep_url, code_style_codes_url))
        code_style_label.setOpenExternalLinks(True)
        code_style_label.setWordWrap(True)

        # Code style checkbox
        self.code_style_check = self.create_checkbox(
            _("Enable code style linting"),
            'pycodestyle')

        # Code style options
        self.code_style_filenames_match = self.create_lineedit(
            _("Only check filenames matching these patterns:"),
            'pycodestyle/filename', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Check Python files: *.py"))
        self.code_style_exclude = self.create_lineedit(
            _("Exclude files or directories matching these patterns:"),
            'pycodestyle/exclude', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Exclude all test files: (?!test_).*\\.py"))
        code_style_select = self.create_lineedit(
            _("Show the following errors or warnings:").format(
                code_style_codes_url),
            'pycodestyle/select', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Example codes: E113, W391"))
        code_style_ignore = self.create_lineedit(
            _("Ignore the following errors or warnings:"),
            'pycodestyle/ignore', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Example codes: E201, E303"))
        code_style_max_line_length = self.create_spinbox(
            _("Maximum allowed line length:"), None,
            'pycodestyle/max_line_length', min_=10, max_=500, step=1,
            tip=_("Default is 79"))

        # Code style layout
        code_style_g_layout = QGridLayout()
        code_style_g_layout.addWidget(
            self.code_style_filenames_match.label, 1, 0)
        code_style_g_layout.addWidget(
            self.code_style_filenames_match.textbox, 1, 1)
        code_style_g_layout.addWidget(self.code_style_exclude.label, 2, 0)
        code_style_g_layout.addWidget(self.code_style_exclude.textbox, 2, 1)
        code_style_g_layout.addWidget(code_style_select.label, 3, 0)
        code_style_g_layout.addWidget(code_style_select.textbox, 3, 1)
        code_style_g_layout.addWidget(code_style_ignore.label, 4, 0)
        code_style_g_layout.addWidget(code_style_ignore.textbox, 4, 1)
        code_style_g_layout.addWidget(code_style_max_line_length.plabel, 5, 0)
        code_style_g_layout.addWidget(
            code_style_max_line_length.spinbox, 5, 1)

        # Set Code style options enabled/disabled
        code_style_g_widget = QWidget()
        code_style_g_widget.setLayout(code_style_g_layout)
        code_style_g_widget.setEnabled(self.get_option('pycodestyle'))
        self.code_style_check.toggled.connect(code_style_g_widget.setEnabled)

        # Code style layout
        code_style_layout = QVBoxLayout()
        code_style_layout.addWidget(code_style_label)
        code_style_layout.addWidget(self.code_style_check)
        code_style_layout.addWidget(code_style_g_widget)

        code_style_widget = QWidget()
        code_style_widget.setLayout(code_style_layout)

        # --- Docstring tab ---
        # Docstring style label
        numpy_url = (
            "<a href='https://numpydoc.readthedocs.io/en/"
            "latest/format.html'>Numpy</a>")
        pep257_url = (
            "<a href='https://www.python.org/dev/peps/pep-0257/'>PEP 257</a>")
        docstring_style_codes = _(
            "<a href='http://www.pydocstyle.org/en/stable"
            "/error_codes.html'>page</a>")
        docstring_style_label = QLabel(
            _("Here you can decide if you want to perform style analysis on "
              "your docstrings according to the {} or {} conventions. You can "
              "also decide if you want to show or ignore specific errors, "
              "according to the codes found on this {}.").format(
                  numpy_url, pep257_url, docstring_style_codes))
        docstring_style_label.setOpenExternalLinks(True)
        docstring_style_label.setWordWrap(True)

        # Docstring style checkbox
        self.docstring_style_check = self.create_checkbox(
            _("Enable docstring style linting"),
            'pydocstyle')

        # Docstring style options
        docstring_style_convention = self.create_combobox(
            _("Choose the convention used to lint docstrings: "),
            (("Numpy", 'numpy'),
             ("PEP 257", 'pep257'),
             ("Custom", 'custom')),
            'pydocstyle/convention')
        self.docstring_style_select = self.create_lineedit(
            _("Show the following errors:"),
            'pydocstyle/select', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Example codes: D413, D414"))
        self.docstring_style_ignore = self.create_lineedit(
            _("Ignore the following errors:"),
            'pydocstyle/ignore', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Example codes: D107, D402"))
        self.docstring_style_match = self.create_lineedit(
            _("Only check filenames matching these patterns:"),
            'pydocstyle/match', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Skip test files: (?!test_).*\\.py"))
        self.docstring_style_match_dir = self.create_lineedit(
            _("Only check in directories matching these patterns:"),
            'pydocstyle/match_dir', alignment=Qt.Horizontal, word_wrap=False,
            placeholder=_("Skip dot directories: [^\\.].*"))

        # Custom option handling
        docstring_style_convention.combobox.currentTextChanged.connect(
                self.setup_docstring_style_convention)
        current_convention = docstring_style_convention.combobox.currentText()
        self.setup_docstring_style_convention(current_convention)

        # Docstring style layout
        docstring_style_g_layout = QGridLayout()
        docstring_style_g_layout.addWidget(
            docstring_style_convention.label, 1, 0)
        docstring_style_g_layout.addWidget(
            docstring_style_convention.combobox, 1, 1)
        docstring_style_g_layout.addWidget(
            self.docstring_style_select.label, 2, 0)
        docstring_style_g_layout.addWidget(
            self.docstring_style_select.textbox, 2, 1)
        docstring_style_g_layout.addWidget(
            self.docstring_style_ignore.label, 3, 0)
        docstring_style_g_layout.addWidget(
            self.docstring_style_ignore.textbox, 3, 1)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match.label, 4, 0)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match.textbox, 4, 1)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match_dir.label, 5, 0)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match_dir.textbox, 5, 1)

        # Set Docstring style options enabled/disabled
        docstring_style_g_widget = QWidget()
        docstring_style_g_widget.setLayout(docstring_style_g_layout)
        docstring_style_g_widget.setEnabled(self.get_option('pydocstyle'))
        self.docstring_style_check.toggled.connect(
            docstring_style_g_widget.setEnabled)

        # Docstring style layout
        docstring_style_layout = QVBoxLayout()
        docstring_style_layout.addWidget(docstring_style_label)
        docstring_style_layout.addWidget(self.docstring_style_check)
        docstring_style_layout.addWidget(docstring_style_g_widget)

        docstring_style_widget = QWidget()
        docstring_style_widget.setLayout(docstring_style_layout)

        # --- Advanced tab ---
        # Advanced label
        advanced_label = QLabel(
            _("<b>Warning</b>: Only modify these values if "
              "you know what you're doing!"))
        advanced_label.setWordWrap(True)
        advanced_label.setAlignment(Qt.AlignJustify)

        # Advanced options
        self.advanced_module = self.create_lineedit(
            _("Module for the Python language server: "),
            'advanced/module', alignment=Qt.Horizontal,
            word_wrap=False)
        self.advanced_host = self.create_lineedit(
            _("IP Address and port to bind the server to: "),
            'advanced/host', alignment=Qt.Horizontal,
            word_wrap=False)
        self.advanced_port = self.create_spinbox(
            ":", "", 'advanced/port', min_=1, max_=65535, step=1)
        self.external_server = self.create_checkbox(
            _("This is an external server"),
            'advanced/external')
        self.use_stdio = self.create_checkbox(
            _("Use stdio pipes to communicate with server"),
            'advanced/stdio')
        self.use_stdio.stateChanged.connect(self.disable_tcp)
        self.external_server.stateChanged.connect(self.disable_stdio)

        # Advanced layout
        advanced_g_layout = QGridLayout()
        advanced_g_layout.addWidget(self.advanced_module.label, 1, 0)
        advanced_g_layout.addWidget(self.advanced_module.textbox, 1, 1)
        advanced_g_layout.addWidget(self.advanced_host.label, 2, 0)

        advanced_host_port_g_layout = QGridLayout()
        advanced_host_port_g_layout.addWidget(self.advanced_host.textbox, 1, 0)
        advanced_host_port_g_layout.addWidget(self.advanced_port.plabel, 1, 1)
        advanced_host_port_g_layout.addWidget(self.advanced_port.spinbox, 1, 2)
        advanced_g_layout.addLayout(advanced_host_port_g_layout, 2, 1)

        advanced_widget = QWidget()
        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(advanced_label)
        advanced_layout.addSpacing(12)
        advanced_layout.addLayout(advanced_g_layout)
        advanced_layout.addWidget(self.external_server)
        advanced_layout.addWidget(self.use_stdio)
        advanced_widget.setLayout(advanced_layout)

        # --- Other servers tab ---
        # Section label
        servers_label = QLabel(
            _("Spyder uses the <a href=\"{lsp_url}\">Language Server "
              "Protocol</a> to provide code completion and linting "
              "for its Editor. Here, you can setup and configure LSP servers "
              "for languages other than Python, so Spyder can provide such "
              "features for those languages as well."
              ).format(lsp_url=LSP_URL))
        servers_label.setOpenExternalLinks(True)
        servers_label.setWordWrap(True)
        servers_label.setAlignment(Qt.AlignJustify)

        # Servers table
        table_group = QGroupBox(_('Available servers:'))
        self.table = LSPServerTable(self, text_color=ima.MAIN_FG_COLOR)
        self.table.setMaximumHeight(150)
        table_layout = QVBoxLayout()
        table_layout.addWidget(self.table)
        table_group.setLayout(table_layout)

        # Buttons
        self.reset_btn = QPushButton(_("Reset to default values"))
        self.new_btn = QPushButton(_("Set up a new server"))
        self.delete_btn = QPushButton(_("Delete currently selected server"))
        self.delete_btn.setEnabled(False)

        # Slots connected to buttons
        self.new_btn.clicked.connect(self.create_new_server)
        self.reset_btn.clicked.connect(self.reset_to_default)
        self.delete_btn.clicked.connect(self.delete_server)

        # Buttons layout
        btns = [self.new_btn, self.delete_btn, self.reset_btn]
        buttons_layout = QGridLayout()
        for i, btn in enumerate(btns):
            buttons_layout.addWidget(btn, i, 1)
        buttons_layout.setColumnStretch(0, 1)
        buttons_layout.setColumnStretch(1, 2)
        buttons_layout.setColumnStretch(2, 1)

        # Combined layout
        servers_widget = QWidget()
        servers_layout = QVBoxLayout()
        servers_layout.addSpacing(-10)
        servers_layout.addWidget(servers_label)
        servers_layout.addWidget(table_group)
        servers_layout.addSpacing(10)
        servers_layout.addLayout(buttons_layout)
        servers_widget.setLayout(servers_layout)

        # --- Tabs organization ---
        self.tabs = QTabWidget()
        self.tabs.addTab(self.create_tab(basic_features_group, advanced_group),
                    _('Introspection'))
        self.tabs.addTab(self.create_tab(linting_widget), _('Linting'))
        self.tabs.addTab(self.create_tab(code_style_widget), _('Code style'))
        self.tabs.addTab(self.create_tab(docstring_style_widget),
                    _('Docstring style'))
        self.tabs.addTab(self.create_tab(advanced_widget),
                    _('Advanced'))
        self.tabs.addTab(self.create_tab(servers_widget), _('Other languages'))

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.tabs)
        self.setLayout(vlayout)
Beispiel #30
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)
Beispiel #31
0
    def setup_page(self):
        # Connections group
        connections_group = QGroupBox(_("Automatic connections"))
        connections_label = QLabel(
            _("This pane can automatically "
              "show an object's help information after "
              "a left parenthesis is written next to it. "
              "Below you can decide to which plugin "
              "you want to connect it to turn on this "
              "feature."))
        connections_label.setWordWrap(True)
        editor_box = self.create_checkbox(_("Editor"), 'connect/editor')
        rope_installed = programs.is_module_installed('rope')
        jedi_installed = programs.is_module_installed('jedi', '>=0.8.1')
        editor_box.setEnabled(rope_installed or jedi_installed)
        if not rope_installed and not jedi_installed:
            editor_tip = _(
                "This feature requires the Rope or Jedi libraries.\n"
                "It seems you don't have either installed.")
            editor_box.setToolTip(editor_tip)
        python_box = self.create_checkbox(_("Python Console"),
                                          'connect/python_console')
        ipython_box = self.create_checkbox(_("IPython Console"),
                                           'connect/ipython_console')
        ipython_box.setEnabled(QTCONSOLE_INSTALLED)

        connections_layout = QVBoxLayout()
        connections_layout.addWidget(connections_label)
        connections_layout.addWidget(editor_box)
        connections_layout.addWidget(python_box)
        connections_layout.addWidget(ipython_box)
        connections_group.setLayout(connections_layout)

        # Features group
        features_group = QGroupBox(_("Additional features"))
        math_box = self.create_checkbox(_("Render mathematical equations"),
                                        'math')
        req_sphinx = programs.is_module_installed('sphinx', '>=1.1')
        math_box.setEnabled(req_sphinx)
        if not req_sphinx:
            sphinx_ver = programs.get_module_version('sphinx')
            sphinx_tip = _("This feature requires Sphinx 1.1 or superior.")
            sphinx_tip += "\n" + _(
                "Sphinx %s is currently installed.") % sphinx_ver
            math_box.setToolTip(sphinx_tip)

        features_layout = QVBoxLayout()
        features_layout.addWidget(math_box)
        features_group.setLayout(features_layout)

        # Source code group
        sourcecode_group = QGroupBox(_("Source code"))
        wrap_mode_box = self.create_checkbox(_("Wrap lines"), 'wrap')

        sourcecode_layout = QVBoxLayout()
        sourcecode_layout.addWidget(wrap_mode_box)
        sourcecode_group.setLayout(sourcecode_layout)

        # Final layout
        vlayout = QVBoxLayout()
        vlayout.addWidget(connections_group)
        vlayout.addWidget(features_group)
        vlayout.addWidget(sourcecode_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #32
0
    def __init__(self, settings: PartSettings):
        super().__init__()
        self.settings = settings
        self.save_translate_dict: typing.Dict[str, SaveBase] = {x.get_short_name(): x for x in save_dict.values()}
        self.plan = PlanPreview(self)
        self.save_plan_btn = QPushButton("Save")
        self.clean_plan_btn = QPushButton("Remove all")
        self.remove_btn = QPushButton("Remove")
        self.update_element_chk = QCheckBox("Update element")
        self.change_root = EnumComboBox(RootType)
        self.save_choose = QComboBox()
        self.save_choose.addItem("<none>")
        self.save_choose.addItems(list(self.save_translate_dict.keys()))
        self.save_btn = QPushButton("Save")
        self.segment_profile = SearchableListWidget()
        self.pipeline_profile = SearchableListWidget()
        self.segment_stack = QTabWidget()
        self.segment_stack.addTab(self.segment_profile, "Profile")
        self.segment_stack.addTab(self.pipeline_profile, "Pipeline")
        self.generate_mask_btn = QPushButton("Add mask")
        self.generate_mask_btn.setToolTip("Mask need to have unique name")
        self.mask_name = QLineEdit()
        self.mask_operation = EnumComboBox(MaskOperation)

        self.chanel_num = QSpinBox()
        self.choose_channel_for_measurements = QComboBox()
        self.choose_channel_for_measurements.addItems(
            ["Same as segmentation"] + [str(x + 1) for x in range(MAX_CHANNEL_NUM)]
        )
        self.units_choose = EnumComboBox(Units)
        self.units_choose.set_value(self.settings.get("units_value", Units.nm))
        self.chanel_num.setRange(0, 10)
        self.expected_node_type = None
        self.save_constructor = None

        self.chose_profile_btn = QPushButton("Add Profile")
        self.get_big_btn = QPushButton("Leave the biggest")
        self.get_big_btn.hide()
        self.get_big_btn.setDisabled(True)
        self.measurements_list = SearchableListWidget(self)
        self.measurement_name_prefix = QLineEdit(self)
        self.add_calculation_btn = QPushButton("Add measurement calculation")
        self.information = QTextEdit()
        self.information.setReadOnly(True)

        self.protect = False
        self.mask_set = set()
        self.calculation_plan = CalculationPlan()
        self.plan.set_plan(self.calculation_plan)
        self.segmentation_mask = MaskWidget(settings)
        self.file_mask = FileMask()

        self.change_root.currentIndexChanged.connect(self.change_root_type)
        self.save_choose.currentTextChanged.connect(self.save_changed)
        self.measurements_list.currentTextChanged.connect(self.show_measurement)
        self.segment_profile.currentTextChanged.connect(self.show_segment)
        self.measurements_list.currentTextChanged.connect(self.show_measurement_info)
        self.segment_profile.currentTextChanged.connect(self.show_segment_info)
        self.pipeline_profile.currentTextChanged.connect(self.show_segment_info)
        self.pipeline_profile.currentTextChanged.connect(self.show_segment)
        self.mask_name.textChanged.connect(self.mask_name_changed)
        self.generate_mask_btn.clicked.connect(self.create_mask)
        self.clean_plan_btn.clicked.connect(self.clean_plan)
        self.remove_btn.clicked.connect(self.remove_element)
        self.mask_name.textChanged.connect(self.mask_text_changed)
        self.chose_profile_btn.clicked.connect(self.add_segmentation)
        self.get_big_btn.clicked.connect(self.add_leave_biggest)
        self.add_calculation_btn.clicked.connect(self.add_measurement)
        self.save_plan_btn.clicked.connect(self.add_calculation_plan)
        # self.forgot_mask_btn.clicked.connect(self.forgot_mask)
        # self.cmap_save_btn.clicked.connect(self.save_to_cmap)
        self.save_btn.clicked.connect(self.add_save_to_project)
        self.update_element_chk.stateChanged.connect(self.mask_text_changed)
        self.update_element_chk.stateChanged.connect(self.show_measurement)
        self.update_element_chk.stateChanged.connect(self.show_segment)
        self.update_element_chk.stateChanged.connect(self.update_names)
        self.segment_stack.currentChanged.connect(self.change_segmentation_table)

        plan_box = QGroupBox("Prepare workflow:")
        lay = QVBoxLayout()
        lay.addWidget(self.plan)
        bt_lay = QGridLayout()
        bt_lay.setSpacing(1)
        bt_lay.addWidget(self.save_plan_btn, 0, 0)
        bt_lay.addWidget(self.clean_plan_btn, 0, 1)
        bt_lay.addWidget(self.remove_btn, 1, 0)
        bt_lay.addWidget(self.update_element_chk, 1, 1)
        lay.addLayout(bt_lay)
        plan_box.setLayout(lay)
        plan_box.setStyleSheet(group_sheet)

        other_box = QGroupBox("Other operations:")
        other_box.setContentsMargins(0, 0, 0, 0)
        bt_lay = QVBoxLayout()
        bt_lay.setSpacing(0)
        bt_lay.addWidget(QLabel("Root type:"))
        bt_lay.addWidget(self.change_root)
        bt_lay.addStretch(1)
        bt_lay.addWidget(QLabel("Saving:"))
        bt_lay.addWidget(self.save_choose)
        bt_lay.addWidget(self.save_btn)
        other_box.setLayout(bt_lay)
        other_box.setStyleSheet(group_sheet)

        mask_box = QGroupBox("Use mask from:")
        mask_box.setStyleSheet(group_sheet)
        self.mask_stack = QTabWidget()

        self.mask_stack.addTab(stretch_widget(self.file_mask), "File")
        self.mask_stack.addTab(stretch_widget(self.segmentation_mask), "Current ROI")
        self.mask_stack.addTab(stretch_widget(self.mask_operation), "Operations on masks")
        self.mask_stack.setTabToolTip(2, "Allows to create mask which is based on masks previously added to plan.")

        lay = QGridLayout()
        lay.setSpacing(0)
        lay.addWidget(self.mask_stack, 0, 0, 1, 2)
        label = QLabel("Mask name:")
        label.setToolTip("Needed if you would like to reuse this mask in tab 'Operations on masks'")
        self.mask_name.setToolTip("Needed if you would like to reuse this mask in tab 'Operations on masks'")
        lay.addWidget(label, 1, 0)
        lay.addWidget(self.mask_name, 1, 1)
        lay.addWidget(self.generate_mask_btn, 2, 0, 1, 2)
        mask_box.setLayout(lay)

        segment_box = QGroupBox("ROI extraction:")
        segment_box.setStyleSheet(group_sheet)
        lay = QVBoxLayout()
        lay.setSpacing(0)
        lay.addWidget(self.segment_stack)
        lay.addWidget(self.chose_profile_btn)
        lay.addWidget(self.get_big_btn)
        segment_box.setLayout(lay)

        measurement_box = QGroupBox("Set of measurements:")
        measurement_box.setStyleSheet(group_sheet)
        lay = QGridLayout()
        lay.setSpacing(0)
        lay.addWidget(self.measurements_list, 0, 0, 1, 2)
        lab = QLabel("Name prefix:")
        lab.setToolTip("Prefix added before each column name")
        lay.addWidget(lab, 1, 0)
        lay.addWidget(self.measurement_name_prefix, 1, 1)
        lay.addWidget(QLabel("Channel:"), 2, 0)
        lay.addWidget(self.choose_channel_for_measurements, 2, 1)
        lay.addWidget(QLabel("Units:"), 3, 0)
        lay.addWidget(self.units_choose, 3, 1)
        lay.addWidget(self.add_calculation_btn, 4, 0, 1, 2)
        measurement_box.setLayout(lay)

        info_box = QGroupBox("Information")
        info_box.setStyleSheet(group_sheet)
        lay = QVBoxLayout()
        lay.addWidget(self.information)
        info_box.setLayout(lay)

        layout = QGridLayout()
        fst_col = QVBoxLayout()
        fst_col.addWidget(plan_box, 1)
        fst_col.addWidget(mask_box)
        layout.addWidget(plan_box, 0, 0, 5, 1)
        # layout.addWidget(plan_box, 0, 0, 3, 1)
        # layout.addWidget(mask_box, 3, 0, 2, 1)
        # layout.addWidget(segmentation_mask_box, 1, 1)
        layout.addWidget(mask_box, 0, 2, 1, 2)
        layout.addWidget(other_box, 0, 1)
        layout.addWidget(segment_box, 1, 1, 1, 2)
        layout.addWidget(measurement_box, 1, 3)
        layout.addWidget(info_box, 3, 1, 1, 3)
        self.setLayout(layout)

        self.generate_mask_btn.setDisabled(True)
        self.chose_profile_btn.setDisabled(True)
        self.add_calculation_btn.setDisabled(True)

        self.mask_allow = False
        self.segment_allow = False
        self.file_mask_allow = False
        self.node_type = NodeType.root
        self.node_name = ""
        self.plan_node_changed.connect(self.mask_text_changed)
        self.plan.changed_node.connect(self.node_type_changed)
        self.plan_node_changed.connect(self.show_segment)
        self.plan_node_changed.connect(self.show_measurement)
        self.plan_node_changed.connect(self.mask_stack_change)
        self.mask_stack.currentChanged.connect(self.mask_stack_change)
        self.file_mask.value_changed.connect(self.mask_stack_change)
        self.mask_name.textChanged.connect(self.mask_stack_change)
        self.node_type_changed()
Beispiel #33
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.current_radio = None
        self.dedicated_radio = None
        self.systerm_radio = None

        self.runconf = RunConfiguration()

        firstrun_o = CONF.get("run", ALWAYS_OPEN_FIRST_RUN_OPTION, False)

        # --- General settings ----
        common_group = QGroupBox(_("General settings"))
        common_layout = QGridLayout()
        common_group.setLayout(common_layout)
        self.clo_cb = QCheckBox(_("Command line options:"))
        common_layout.addWidget(self.clo_cb, 0, 0)
        self.clo_edit = QLineEdit()
        self.clo_cb.toggled.connect(self.clo_edit.setEnabled)
        self.clo_edit.setEnabled(False)
        common_layout.addWidget(self.clo_edit, 0, 1)
        self.wd_cb = QCheckBox(_("Working directory:"))
        common_layout.addWidget(self.wd_cb, 1, 0)
        wd_layout = QHBoxLayout()
        self.wd_edit = QLineEdit()
        self.wd_cb.toggled.connect(self.wd_edit.setEnabled)
        self.wd_edit.setEnabled(False)
        wd_layout.addWidget(self.wd_edit)
        browse_btn = QPushButton(ima.icon("DirOpenIcon"), "", self)
        browse_btn.setToolTip(_("Select directory"))
        browse_btn.clicked.connect(self.select_directory)
        wd_layout.addWidget(browse_btn)
        common_layout.addLayout(wd_layout, 1, 1)
        self.post_mortem_cb = QCheckBox(_("Enter debugging mode when " "errors appear during execution"))
        common_layout.addWidget(self.post_mortem_cb)

        # --- Interpreter ---
        interpreter_group = QGroupBox(_("Console"))
        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)
        self.current_radio = QRadioButton(CURRENT_INTERPRETER)
        interpreter_layout.addWidget(self.current_radio)
        self.dedicated_radio = QRadioButton(DEDICATED_INTERPRETER)
        interpreter_layout.addWidget(self.dedicated_radio)
        self.systerm_radio = QRadioButton(SYSTERM_INTERPRETER)
        interpreter_layout.addWidget(self.systerm_radio)

        # --- Dedicated interpreter ---
        new_group = QGroupBox(_("Dedicated Python console"))
        self.current_radio.toggled.connect(new_group.setDisabled)
        new_layout = QGridLayout()
        new_group.setLayout(new_layout)
        self.interact_cb = QCheckBox(_("Interact with the Python " "console after execution"))
        new_layout.addWidget(self.interact_cb, 1, 0, 1, -1)

        self.show_kill_warning_cb = QCheckBox(_("Show warning when killing" " running process"))

        new_layout.addWidget(self.show_kill_warning_cb, 2, 0, 1, -1)
        self.pclo_cb = QCheckBox(_("Command line options:"))
        new_layout.addWidget(self.pclo_cb, 3, 0)
        self.pclo_edit = QLineEdit()
        self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled)
        self.pclo_edit.setEnabled(False)
        self.pclo_edit.setToolTip(_("<b>-u</b> is added to the " "other options you set here"))
        new_layout.addWidget(self.pclo_edit, 3, 1)

        # Checkbox to preserve the old behavior, i.e. always open the dialog
        # on first run
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog"))
        self.firstrun_cb.clicked.connect(self.set_firstrun_o)
        self.firstrun_cb.setChecked(firstrun_o)

        layout = QVBoxLayout()
        layout.addWidget(interpreter_group)
        layout.addWidget(common_group)
        layout.addWidget(new_group)
        layout.addWidget(hline)
        layout.addWidget(self.firstrun_cb)
        self.setLayout(layout)
Beispiel #34
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.dir = None
        self.runconf = RunConfiguration()
        firstrun_o = CONF.get('run', ALWAYS_OPEN_FIRST_RUN_OPTION, False)

        # --- Interpreter ---
        interpreter_group = QGroupBox(_("Console"))
        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)

        self.current_radio = QRadioButton(CURRENT_INTERPRETER)
        interpreter_layout.addWidget(self.current_radio)

        self.dedicated_radio = QRadioButton(DEDICATED_INTERPRETER)
        interpreter_layout.addWidget(self.dedicated_radio)

        self.systerm_radio = QRadioButton(SYSTERM_INTERPRETER)
        interpreter_layout.addWidget(self.systerm_radio)

        # --- General settings ----
        common_group = QGroupBox(_("General settings"))
        common_layout = QGridLayout()
        common_group.setLayout(common_layout)

        self.clear_var_cb = QCheckBox(CLEAR_ALL_VARIABLES)
        common_layout.addWidget(self.clear_var_cb, 0, 0)

        self.post_mortem_cb = QCheckBox(POST_MORTEM)
        common_layout.addWidget(self.post_mortem_cb, 1, 0)

        self.clo_cb = QCheckBox(_("Command line options:"))
        common_layout.addWidget(self.clo_cb, 2, 0)
        self.clo_edit = QLineEdit()
        self.clo_cb.toggled.connect(self.clo_edit.setEnabled)
        self.clo_edit.setEnabled(False)
        common_layout.addWidget(self.clo_edit, 2, 1)

        # --- Working directory ---
        wdir_group = QGroupBox(_("Working Directory settings"))
        wdir_layout = QVBoxLayout()
        wdir_group.setLayout(wdir_layout)

        self.file_dir_radio = QRadioButton(FILE_DIR)
        wdir_layout.addWidget(self.file_dir_radio)

        self.cwd_radio = QRadioButton(CW_DIR)
        wdir_layout.addWidget(self.cwd_radio)

        fixed_dir_layout = QHBoxLayout()
        self.fixed_dir_radio = QRadioButton(FIXED_DIR)
        fixed_dir_layout.addWidget(self.fixed_dir_radio)
        self.wd_edit = QLineEdit()
        self.fixed_dir_radio.toggled.connect(self.wd_edit.setEnabled)
        self.wd_edit.setEnabled(False)
        fixed_dir_layout.addWidget(self.wd_edit)
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select directory"))
        browse_btn.clicked.connect(self.select_directory)
        fixed_dir_layout.addWidget(browse_btn)
        wdir_layout.addLayout(fixed_dir_layout)

        # --- System terminal ---
        external_group = QGroupBox(_("External system terminal"))
        external_group.setDisabled(True)

        self.systerm_radio.toggled.connect(external_group.setEnabled)

        external_layout = QGridLayout()
        external_group.setLayout(external_layout)
        self.interact_cb = QCheckBox(INTERACT)
        external_layout.addWidget(self.interact_cb, 1, 0, 1, -1)

        self.pclo_cb = QCheckBox(_("Command line options:"))
        external_layout.addWidget(self.pclo_cb, 3, 0)
        self.pclo_edit = QLineEdit()
        self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled)
        self.pclo_edit.setEnabled(False)
        self.pclo_edit.setToolTip(_("<b>-u</b> is added to the "
                                    "other options you set here"))
        external_layout.addWidget(self.pclo_edit, 3, 1)

        # Checkbox to preserve the old behavior, i.e. always open the dialog
        # on first run
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog"))
        self.firstrun_cb.clicked.connect(self.set_firstrun_o)
        self.firstrun_cb.setChecked(firstrun_o)

        layout = QVBoxLayout()
        layout.addWidget(interpreter_group)
        layout.addWidget(common_group)
        layout.addWidget(wdir_group)
        layout.addWidget(external_group)
        layout.addWidget(hline)
        layout.addWidget(self.firstrun_cb)
        self.setLayout(layout)
Beispiel #35
0
    def setup_page(self):
        newcb = self.create_checkbox

        # Python executable Group
        pyexec_group = QGroupBox(_("Python interpreter"))
        pyexec_bg = QButtonGroup(pyexec_group)
        pyexec_label = QLabel(_("Select the Python interpreter for all Spyder "
                                "consoles"))
        def_exec_radio = self.create_radiobutton(
                                _("Default (i.e. the same as Spyder's)"),
                                'default', button_group=pyexec_bg)
        self.cus_exec_radio = self.create_radiobutton(
                                _("Use the following Python interpreter:"),
                                'custom', button_group=pyexec_bg)
        if os.name == 'nt':
            filters = _("Executables")+" (*.exe)"
        else:
            filters = None
        pyexec_file = self.create_browsefile('', 'executable', filters=filters)
        for le in self.lineedits:
            if self.lineedits[le][0] == 'executable':
                self.pyexec_edit = le
        def_exec_radio.toggled.connect(pyexec_file.setDisabled)
        self.cus_exec_radio.toggled.connect(pyexec_file.setEnabled)
        pyexec_layout = QVBoxLayout()
        pyexec_layout.addWidget(pyexec_label)
        pyexec_layout.addWidget(def_exec_radio)
        pyexec_layout.addWidget(self.cus_exec_radio)
        pyexec_layout.addWidget(pyexec_file)
        pyexec_group.setLayout(pyexec_layout)

        # UMR Group
        umr_group = QGroupBox(_("User Module Reloader (UMR)"))
        umr_label = QLabel(_("UMR forces Python to reload modules which were "
                             "imported when executing a file in a Python or "
                             "IPython console with the <i>runfile</i> "
                             "function."))
        umr_label.setWordWrap(True)
        umr_enabled_box = newcb(_("Enable UMR"), 'umr/enabled',
                                msg_if_enabled=True, msg_warning=_(
                        "This option will enable the User Module Reloader (UMR) "
                        "in Python/IPython consoles. UMR forces Python to "
                        "reload deeply modules during import when running a "
                        "Python script using the Spyder's builtin function "
                        "<b>runfile</b>."
                        "<br><br><b>1.</b> UMR may require to restart the "
                        "console in which it will be called "
                        "(otherwise only newly imported modules will be "
                        "reloaded when executing files)."
                        "<br><br><b>2.</b> If errors occur when re-running a "
                        "PyQt-based program, please check that the Qt objects "
                        "are properly destroyed (e.g. you may have to use the "
                        "attribute <b>Qt.WA_DeleteOnClose</b> on your main "
                        "window, using the <b>setAttribute</b> method)"),
                                )
        umr_verbose_box = newcb(_("Show reloaded modules list"),
                                'umr/verbose', msg_info=_(
                                "Please note that these changes will "
                                "be applied only to new consoles"))
        umr_namelist_btn = QPushButton(
                            _("Set UMR excluded (not reloaded) modules"))
        umr_namelist_btn.clicked.connect(self.set_umr_namelist)

        umr_layout = QVBoxLayout()
        umr_layout.addWidget(umr_label)
        umr_layout.addWidget(umr_enabled_box)
        umr_layout.addWidget(umr_verbose_box)
        umr_layout.addWidget(umr_namelist_btn)
        umr_group.setLayout(umr_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(pyexec_group)
        vlayout.addWidget(umr_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #36
0
    def setup_page(self):
        about_label = QLabel(_("The following are the default options for "
                               "running files.These options may be overriden "
                               "using the <b>Configuration per file</b> entry "
                               "of the <b>Run</b> menu."))
        about_label.setWordWrap(True)

        interpreter_group = QGroupBox(_("Console"))
        interpreter_bg = QButtonGroup(interpreter_group)
        self.current_radio = self.create_radiobutton(CURRENT_INTERPRETER,
                                CURRENT_INTERPRETER_OPTION, True,
                                button_group=interpreter_bg)
        self.dedicated_radio = self.create_radiobutton(DEDICATED_INTERPRETER,
                                DEDICATED_INTERPRETER_OPTION, False,
                                button_group=interpreter_bg)
        self.systerm_radio = self.create_radiobutton(SYSTERM_INTERPRETER,
                                SYSTERM_INTERPRETER_OPTION, False,
                                button_group=interpreter_bg)

        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)
        interpreter_layout.addWidget(self.current_radio)
        interpreter_layout.addWidget(self.dedicated_radio)
        interpreter_layout.addWidget(self.systerm_radio)
        
        general_group = QGroupBox(_("General settings"))
        post_mortem = self.create_checkbox(POST_MORTEM, 'post_mortem', False)
        clear_variables = self.create_checkbox(CLEAR_ALL_VARIABLES, 
            'clear_namespace', False)

        general_layout = QVBoxLayout()
        general_layout.addWidget(clear_variables)
        general_layout.addWidget(post_mortem)
        general_group.setLayout(general_layout)

        wdir_group = QGroupBox(_("Working Directory settings"))
        wdir_bg = QButtonGroup(wdir_group)
        wdir_label = QLabel(_("Default working directory is:"))
        wdir_label.setWordWrap(True)
        dirname_radio = self.create_radiobutton(
                    FILE_DIR,
                    WDIR_USE_SCRIPT_DIR_OPTION, True,
                    button_group=wdir_bg)
        cwd_radio = self.create_radiobutton(
                    CW_DIR,
                    WDIR_USE_CWD_DIR_OPTION, False,
                    button_group=wdir_bg)

        thisdir_radio = self.create_radiobutton(
                FIXED_DIR,
                WDIR_USE_FIXED_DIR_OPTION, False,
                button_group=wdir_bg)
        thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION,
                                           getcwd_or_home())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        dirname_radio.toggled.connect(thisdir_bd.setDisabled)
        cwd_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        wdir_layout = QVBoxLayout()
        wdir_layout.addWidget(wdir_label)
        wdir_layout.addWidget(dirname_radio)
        wdir_layout.addWidget(cwd_radio)
        wdir_layout.addLayout(thisdir_layout)
        wdir_group.setLayout(wdir_layout)


        external_group = QGroupBox(_("External system terminal"))
        interact_after = self.create_checkbox(INTERACT, 'interact', False)

        external_layout = QVBoxLayout()
        external_layout.addWidget(interact_after)
        external_group.setLayout(external_layout)

        firstrun_cb = self.create_checkbox(
                            ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"),
                            ALWAYS_OPEN_FIRST_RUN_OPTION, False)
        
        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(interpreter_group)
        vlayout.addWidget(general_group)
        vlayout.addWidget(wdir_group)
        vlayout.addWidget(external_group)
        vlayout.addWidget(firstrun_cb)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #37
0
    def setup_page(self):
        run_dlg = _("Run Settings")
        run_menu = _("Run")
        about_label = QLabel(
            _(
                "The following are the default <i>%s</i>. "
                "These options may be overriden using the "
                "<b>%s</b> dialog box (see the <b>%s</b> menu)"
            )
            % (run_dlg, run_dlg, run_menu)
        )
        about_label.setWordWrap(True)

        interpreter_group = QGroupBox(_("Console"))
        interpreter_bg = QButtonGroup(interpreter_group)
        self.current_radio = self.create_radiobutton(
            CURRENT_INTERPRETER, CURRENT_INTERPRETER_OPTION, True, button_group=interpreter_bg
        )
        self.dedicated_radio = self.create_radiobutton(
            DEDICATED_INTERPRETER, DEDICATED_INTERPRETER_OPTION, False, button_group=interpreter_bg
        )
        self.systerm_radio = self.create_radiobutton(
            SYSTERM_INTERPRETER, SYSTERM_INTERPRETER_OPTION, False, button_group=interpreter_bg
        )

        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)
        interpreter_layout.addWidget(self.current_radio)
        interpreter_layout.addWidget(self.dedicated_radio)
        interpreter_layout.addWidget(self.systerm_radio)

        general_group = QGroupBox("General settings")
        wdir_bg = QButtonGroup(general_group)
        wdir_label = QLabel(_("Default working directory is:"))
        wdir_label.setWordWrap(True)
        dirname_radio = self.create_radiobutton(
            _("the script directory"), WDIR_USE_SCRIPT_DIR_OPTION, True, button_group=wdir_bg
        )
        thisdir_radio = self.create_radiobutton(
            _("the following directory:"), WDIR_USE_FIXED_DIR_OPTION, False, button_group=wdir_bg
        )
        thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        dirname_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        post_mortem = self.create_checkbox(
            _("Enter debugging mode when errors appear during execution"), "post_mortem", False
        )

        general_layout = QVBoxLayout()
        general_layout.addWidget(wdir_label)
        general_layout.addWidget(dirname_radio)
        general_layout.addLayout(thisdir_layout)
        general_layout.addWidget(post_mortem)
        general_group.setLayout(general_layout)

        dedicated_group = QGroupBox(_("Dedicated Python console"))
        interact_after = self.create_checkbox(_("Interact with the Python console after execution"), "interact", False)
        show_warning = self.create_checkbox(_("Show warning when killing running processes"), "show_kill_warning", True)

        dedicated_layout = QVBoxLayout()
        dedicated_layout.addWidget(interact_after)
        dedicated_layout.addWidget(show_warning)
        dedicated_group.setLayout(dedicated_layout)

        firstrun_cb = self.create_checkbox(
            ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"), ALWAYS_OPEN_FIRST_RUN_OPTION, False
        )

        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(interpreter_group)
        vlayout.addWidget(general_group)
        vlayout.addWidget(dedicated_group)
        vlayout.addWidget(firstrun_cb)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #38
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.current_radio = None
        self.dedicated_radio = None
        self.systerm_radio = None

        self.runconf = RunConfiguration()

        firstrun_o = CONF.get('run', ALWAYS_OPEN_FIRST_RUN_OPTION, False)

        # --- General settings ----
        common_group = QGroupBox(_("General settings"))
        common_layout = QGridLayout()
        common_group.setLayout(common_layout)
        self.clo_cb = QCheckBox(_("Command line options:"))
        common_layout.addWidget(self.clo_cb, 0, 0)
        self.clo_edit = QLineEdit()
        self.clo_cb.toggled.connect(self.clo_edit.setEnabled)
        self.clo_edit.setEnabled(False)
        common_layout.addWidget(self.clo_edit, 0, 1)
        self.wd_cb = QCheckBox(_("Working directory:"))
        common_layout.addWidget(self.wd_cb, 1, 0)
        wd_layout = QHBoxLayout()
        self.wd_edit = QLineEdit()
        self.wd_cb.toggled.connect(self.wd_edit.setEnabled)
        self.wd_edit.setEnabled(False)
        wd_layout.addWidget(self.wd_edit)
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select directory"))
        browse_btn.clicked.connect(self.select_directory)
        wd_layout.addWidget(browse_btn)
        common_layout.addLayout(wd_layout, 1, 1)
        self.post_mortem_cb = QCheckBox(
            _("Enter debugging mode when "
              "errors appear during execution"))
        common_layout.addWidget(self.post_mortem_cb)

        # --- Interpreter ---
        interpreter_group = QGroupBox(_("Console"))
        interpreter_layout = QVBoxLayout()
        interpreter_group.setLayout(interpreter_layout)
        self.current_radio = QRadioButton(CURRENT_INTERPRETER)
        interpreter_layout.addWidget(self.current_radio)
        self.dedicated_radio = QRadioButton(DEDICATED_INTERPRETER)
        interpreter_layout.addWidget(self.dedicated_radio)
        self.systerm_radio = QRadioButton(SYSTERM_INTERPRETER)
        interpreter_layout.addWidget(self.systerm_radio)

        # --- Dedicated interpreter ---
        new_group = QGroupBox(_("Dedicated Python console"))
        self.current_radio.toggled.connect(new_group.setDisabled)
        new_layout = QGridLayout()
        new_group.setLayout(new_layout)
        self.interact_cb = QCheckBox(
            _("Interact with the Python "
              "console after execution"))
        new_layout.addWidget(self.interact_cb, 1, 0, 1, -1)

        self.show_kill_warning_cb = QCheckBox(
            _("Show warning when killing"
              " running process"))

        new_layout.addWidget(self.show_kill_warning_cb, 2, 0, 1, -1)
        self.pclo_cb = QCheckBox(_("Command line options:"))
        new_layout.addWidget(self.pclo_cb, 3, 0)
        self.pclo_edit = QLineEdit()
        self.pclo_cb.toggled.connect(self.pclo_edit.setEnabled)
        self.pclo_edit.setEnabled(False)
        self.pclo_edit.setToolTip(
            _("<b>-u</b> is added to the "
              "other options you set here"))
        new_layout.addWidget(self.pclo_edit, 3, 1)

        # Checkbox to preserve the old behavior, i.e. always open the dialog
        # on first run
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        self.firstrun_cb = QCheckBox(ALWAYS_OPEN_FIRST_RUN % _("this dialog"))
        self.firstrun_cb.clicked.connect(self.set_firstrun_o)
        self.firstrun_cb.setChecked(firstrun_o)

        layout = QVBoxLayout()
        layout.addWidget(interpreter_group)
        layout.addWidget(common_group)
        layout.addWidget(new_group)
        layout.addWidget(hline)
        layout.addWidget(self.firstrun_cb)
        self.setLayout(layout)
Beispiel #39
0
class TrackSeg(QGroupBox):
    """
    Track segmentation method panel

    """
    def __init__(
        self,
        parent,
        point_size=POINT_SIZE,
        spline_size=SPLINE_SIZE,
        track_file_extension=TRACK_FILE_EXT,
        spline_points_default=SPLINE_POINTS_DEFAULT,
        spline_smoothing_default=SPLINE_SMOOTHING_DEFAULT,
        fit_degree_default=FIT_DEGREE_DEFAULT,
        summarise_track_default=SUMMARISE_TRACK_DEFAULT,
    ):

        super(TrackSeg, self).__init__()
        self.parent = parent
        self.tree = None

        self.summarise_track_default = summarise_track_default

        # Point / Spline fitting settings
        self.point_size_default = POINT_SIZE  # Keep track of default
        self.point_size = point_size  # Initialise
        self.spline_points_default = spline_points_default
        self.spline_size_default = SPLINE_SIZE  # Keep track of default
        self.spline_size = spline_size  # Initialise
        self.spline_smoothing_default = spline_smoothing_default
        self.fit_degree_default = fit_degree_default

        # File formats
        self.track_file_extension = track_file_extension

        # Initialise spline and spline names
        self.splines = None
        self.spline_names = None

    def add_track_panel(self, row):
        self.track_panel = QGroupBox("Track tracing")
        track_layout = QGridLayout()

        add_button(
            "Add surface points",
            track_layout,
            self.add_surface_points,
            5,
            1,
        )

        add_button(
            "Add track",
            track_layout,
            self.add_track,
            6,
            0,
        )

        add_button(
            "Trace tracks",
            track_layout,
            self.run_track_analysis,
            6,
            1,
        )

        self.summarise_track_checkbox = add_checkbox(
            track_layout,
            self.summarise_track_default,
            "Summarise",
            0,
        )

        self.fit_degree = add_int_box(
            track_layout,
            self.fit_degree_default,
            1,
            5,
            "Fit degree",
            1,
        )

        self.spline_smoothing = add_float_box(
            track_layout,
            self.spline_smoothing_default,
            0,
            1,
            "Spline smoothing",
            0.1,
            2,
        )

        self.spline_points = add_int_box(
            track_layout,
            self.spline_points_default,
            1,
            10000,
            "Spline points",
            3,
        )

        track_layout.setColumnMinimumWidth(1, COLUMN_WIDTH)
        self.track_panel.setLayout(track_layout)
        self.parent.layout.addWidget(self.track_panel, row, 0, 1, 2)
        self.track_panel.setVisible(False)

    def toggle_track_panel(self):
        # TODO: Change color scheme directly when theme is switched
        # TODO: "text-align" property should follow constant SEGM_METHODS_PANEL_ALIGN
        if self.track_panel.isVisible():
            self.track_panel.setVisible(False)
            if self.parent.viewer.theme == "dark":
                self.parent.show_trackseg_button.setStyleSheet(
                    f"QPushButton {{ background-color: #414851; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                    f"QPushButton:pressed {{ background-color: #414851; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                )
            else:
                self.parent.show_trackseg_button.setStyleSheet(
                    f"QPushButton {{ background-color: #d6d0ce; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                    f"QPushButton:pressed {{ background-color: #d6d0ce; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                )

        else:
            self.track_panel.setVisible(True)
            if self.parent.viewer.theme == "dark":
                self.parent.show_trackseg_button.setStyleSheet(
                    f"QPushButton {{ background-color: #7e868f; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                    f"QPushButton:pressed {{ background-color: #7e868f; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                )
            else:
                self.parent.show_trackseg_button.setStyleSheet(
                    f"QPushButton {{ background-color: #fdf194; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                    f"QPushButton:pressed {{ background-color: #fdf194; text-align:{SEGM_METHODS_PANEL_ALIGN};}}"
                )

    def check_saved_track(self):
        track_files = glob(
            str(self.parent.paths.tracks_directory) + "/*" +
            self.track_file_extension)
        if self.parent.paths.tracks_directory.exists() and track_files != []:
            for track_file in track_files:
                self.parent.track_layers.append(
                    add_existing_track_layers(
                        self.parent.viewer,
                        track_file,
                        self.point_size,
                    ))

    def add_track(self):
        print("Adding a new track\n")
        self.splines = None
        self.spline_names = None
        self.track_panel.setVisible(True)  # Should be visible by default!
        add_new_track_layer(
            self.parent.viewer,
            self.parent.track_layers,
            self.point_size,
        )

    def add_surface_points(self):
        if self.parent.track_layers:
            print("Adding surface points (this may take a while)")
            if self.tree is None:
                self.create_brain_surface_tree()

            for track_layer in self.parent.track_layers:
                try:
                    _, index = self.tree.query(track_layer.data[0])
                except IndexError:
                    print(
                        f"{track_layer.name} does not appear to hold any data")
                    continue
                surface_point = self.tree.data[index]
                track_layer.data = np.vstack((surface_point, track_layer.data))
            print("Finished!\n")
        else:
            print("No tracks found.")

    def create_brain_surface_tree(self):
        self.tree = create_KDTree_from_image(self.parent.atlas_layer.data)

    def run_track_analysis(self, override=False):
        if self.parent.track_layers:
            if not override:
                choice = display_warning(
                    self.parent,
                    "About to analyse tracks",
                    "Existing files will be will be deleted. Proceed?",
                )
            else:
                choice = True  # for debugging

            if choice:
                print("Running track analysis")
                self.splines, self.spline_names = track_analysis(
                    self.parent.viewer,
                    self.parent.atlas,
                    self.parent.paths.tracks_directory,
                    self.parent.track_layers,
                    self.spline_size,
                    spline_points=self.spline_points.value(),
                    fit_degree=self.fit_degree.value(),
                    spline_smoothing=self.spline_smoothing.value(),
                    summarise_track=self.summarise_track_checkbox.isChecked(),
                )
                print("Finished!\n")
            else:
                print("Preventing analysis as user chose 'Cancel'")
        else:
            print("No tracks found.")
Beispiel #40
0
class PyDMChartingDisplay(Display):
    def __init__(self, parent=None, args=[], macros=None):
        """
        Create all the widgets, including any child dialogs.

        Parameters
        ----------
        parent : QWidget
            The parent widget of the charting display
        args : list
            The command parameters
        macros : str
            Macros to modify the UI parameters at runtime
        """
        super(PyDMChartingDisplay, self).__init__(parent=parent,
                                                  args=args,
                                                  macros=macros)

        self.channel_map = dict()
        self.setWindowTitle("PyDM Charting Tool")

        self.main_layout = QVBoxLayout()
        self.body_layout = QVBoxLayout()

        self.pv_layout = QHBoxLayout()
        self.pv_name_line_edt = QLineEdit()
        self.pv_name_line_edt.setAcceptDrops(True)
        self.pv_name_line_edt.installEventFilter(self)

        self.pv_protocol_cmb = QComboBox()
        self.pv_protocol_cmb.addItems(["ca://", "archive://"])

        self.pv_connect_push_btn = QPushButton("Connect")
        self.pv_connect_push_btn.clicked.connect(self.add_curve)

        self.tab_panel = QTabWidget()
        self.tab_panel.setMaximumWidth(450)
        self.curve_settings_tab = QWidget()
        self.chart_settings_tab = QWidget()

        self.charting_layout = QHBoxLayout()
        self.chart = PyDMTimePlot(plot_by_timestamps=False, plot_display=self)
        self.chart.setPlotTitle("Time Plot")

        self.splitter = QSplitter()

        self.curve_settings_layout = QVBoxLayout()
        self.curve_settings_layout.setAlignment(Qt.AlignTop)
        self.curve_settings_layout.setSizeConstraint(QLayout.SetMinAndMaxSize)
        self.curve_settings_layout.setSpacing(5)

        self.crosshair_settings_layout = QVBoxLayout()
        self.crosshair_settings_layout.setAlignment(Qt.AlignTop)
        self.crosshair_settings_layout.setSpacing(5)

        self.enable_crosshair_chk = QCheckBox("Enable Crosshair")
        self.cross_hair_coord_lbl = QLabel()

        self.curve_settings_inner_frame = QFrame()
        self.curve_settings_inner_frame.setLayout(self.curve_settings_layout)

        self.curve_settings_scroll = QScrollArea()
        self.curve_settings_scroll.setVerticalScrollBarPolicy(
            Qt.ScrollBarAsNeeded)
        self.curve_settings_scroll.setWidget(self.curve_settings_inner_frame)

        self.curves_tab_layout = QHBoxLayout()
        self.curves_tab_layout.addWidget(self.curve_settings_scroll)

        self.enable_crosshair_chk.setChecked(False)
        self.enable_crosshair_chk.clicked.connect(
            self.handle_enable_crosshair_checkbox_clicked)
        self.enable_crosshair_chk.clicked.emit(False)

        self.chart_settings_layout = QVBoxLayout()
        self.chart_settings_layout.setAlignment(Qt.AlignTop)

        self.chart_layout = QVBoxLayout()
        self.chart_panel = QWidget()

        self.chart_control_layout = QHBoxLayout()
        self.chart_control_layout.setAlignment(Qt.AlignHCenter)
        self.chart_control_layout.setSpacing(10)

        self.view_all_btn = QPushButton("View All")
        self.view_all_btn.clicked.connect(self.handle_view_all_button_clicked)
        self.view_all_btn.setEnabled(False)

        self.auto_scale_btn = QPushButton("Auto Scale")
        self.auto_scale_btn.clicked.connect(self.handle_auto_scale_btn_clicked)
        self.auto_scale_btn.setEnabled(False)

        self.reset_chart_btn = QPushButton("Reset")
        self.reset_chart_btn.clicked.connect(
            self.handle_reset_chart_btn_clicked)
        self.reset_chart_btn.setEnabled(False)

        self.resume_chart_text = "Resume"
        self.pause_chart_text = "Pause"
        self.pause_chart_btn = QPushButton(self.pause_chart_text)
        self.pause_chart_btn.clicked.connect(
            self.handle_pause_chart_btn_clicked)

        self.title_settings_layout = QVBoxLayout()
        self.title_settings_layout.setSpacing(10)

        self.title_settings_grpbx = QGroupBox()
        self.title_settings_grpbx.setFixedHeight(150)

        self.import_data_btn = QPushButton("Import Data...")
        self.import_data_btn.clicked.connect(
            self.handle_import_data_btn_clicked)

        self.export_data_btn = QPushButton("Export Data...")
        self.export_data_btn.clicked.connect(
            self.handle_export_data_btn_clicked)

        self.chart_title_lbl = QLabel(text="Chart Title")
        self.chart_title_line_edt = QLineEdit()
        self.chart_title_line_edt.setText(self.chart.getPlotTitle())
        self.chart_title_line_edt.textChanged.connect(
            self.handle_title_text_changed)

        self.chart_change_axis_settings_btn = QPushButton(
            text="Change Axis Settings...")
        self.chart_change_axis_settings_btn.clicked.connect(
            self.handle_change_axis_settings_clicked)

        self.update_datetime_timer = QTimer(self)
        self.update_datetime_timer.timeout.connect(
            self.handle_update_datetime_timer_timeout)

        self.chart_sync_mode_layout = QVBoxLayout()
        self.chart_sync_mode_layout.setSpacing(5)

        self.chart_sync_mode_grpbx = QGroupBox("Data Sampling Mode")
        self.chart_sync_mode_grpbx.setFixedHeight(80)

        self.chart_sync_mode_sync_radio = QRadioButton("Synchronous")
        self.chart_sync_mode_async_radio = QRadioButton("Asynchronous")
        self.chart_sync_mode_async_radio.setChecked(True)

        self.graph_drawing_settings_layout = QVBoxLayout()

        self.chart_redraw_rate_lbl = QLabel("Redraw Rate (Hz)")
        self.chart_redraw_rate_spin = QSpinBox()
        self.chart_redraw_rate_spin.setRange(MIN_REDRAW_RATE_HZ,
                                             MAX_REDRAW_RATE_HZ)
        self.chart_redraw_rate_spin.setValue(DEFAULT_REDRAW_RATE_HZ)
        self.chart_redraw_rate_spin.valueChanged.connect(
            self.handle_redraw_rate_changed)

        self.chart_data_sampling_rate_lbl = QLabel(
            "Asynchronous Data Sampling Rate (Hz)")
        self.chart_data_async_sampling_rate_spin = QSpinBox()
        self.chart_data_async_sampling_rate_spin.setRange(
            MIN_DATA_SAMPLING_RATE_HZ, MAX_DATA_SAMPLING_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.setValue(
            DEFAULT_DATA_SAMPLING_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.valueChanged.connect(
            self.handle_data_sampling_rate_changed)
        self.chart_data_sampling_rate_lbl.hide()
        self.chart_data_async_sampling_rate_spin.hide()

        self.chart_limit_time_span_layout = QHBoxLayout()
        self.chart_limit_time_span_layout.setSpacing(5)

        self.limit_time_plan_text = "Limit Time Span"
        self.chart_limit_time_span_chk = QCheckBox(self.limit_time_plan_text)
        self.chart_limit_time_span_chk.hide()
        self.chart_limit_time_span_lbl = QLabel("Hours : Minutes : Seconds")
        self.chart_limit_time_span_hours_line_edt = QLineEdit()
        self.chart_limit_time_span_minutes_line_edt = QLineEdit()
        self.chart_limit_time_span_seconds_line_edt = QLineEdit()
        self.chart_limit_time_span_activate_btn = QPushButton("Apply")
        self.chart_limit_time_span_activate_btn.setDisabled(True)

        self.chart_ring_buffer_size_lbl = QLabel("Ring Buffer Size")
        self.chart_ring_buffer_size_edt = QLineEdit()
        self.chart_ring_buffer_size_edt.installEventFilter(self)
        self.chart_ring_buffer_size_edt.textChanged.connect(
            self.handle_buffer_size_changed)
        self.chart_ring_buffer_size_edt.setText(str(DEFAULT_BUFFER_SIZE))

        self.show_legend_chk = QCheckBox("Show Legend")
        self.show_legend_chk.setChecked(self.chart.showLegend)
        self.show_legend_chk.clicked.connect(
            self.handle_show_legend_checkbox_clicked)

        self.graph_background_color_layout = QFormLayout()

        self.background_color_lbl = QLabel("Graph Background Color ")
        self.background_color_btn = QPushButton()
        self.background_color_btn.setStyleSheet(
            "background-color: " + self.chart.getBackgroundColor().name())
        self.background_color_btn.setContentsMargins(10, 0, 5, 5)
        self.background_color_btn.setMaximumWidth(20)
        self.background_color_btn.clicked.connect(
            self.handle_background_color_button_clicked)

        self.axis_settings_layout = QVBoxLayout()
        self.axis_settings_layout.setSpacing(5)

        self.show_x_grid_chk = QCheckBox("Show x Grid")
        self.show_x_grid_chk.setChecked(self.chart.showXGrid)
        self.show_x_grid_chk.clicked.connect(
            self.handle_show_x_grid_checkbox_clicked)

        self.show_y_grid_chk = QCheckBox("Show y Grid")
        self.show_y_grid_chk.setChecked(self.chart.showYGrid)
        self.show_y_grid_chk.clicked.connect(
            self.handle_show_y_grid_checkbox_clicked)

        self.axis_color_lbl = QLabel("Axis and Grid Color")
        self.axis_color_lbl.setEnabled(False)

        self.axis_color_btn = QPushButton()
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          DEFAULT_CHART_AXIS_COLOR.name())
        self.axis_color_btn.setContentsMargins(10, 0, 5, 5)
        self.axis_color_btn.setMaximumWidth(20)
        self.axis_color_btn.clicked.connect(
            self.handle_axis_color_button_clicked)
        self.axis_color_btn.setEnabled(False)

        self.grid_opacity_lbl = QLabel("Grid Opacity")
        self.grid_opacity_lbl.setEnabled(False)

        self.grid_opacity_slr = QSlider(Qt.Horizontal)
        self.grid_opacity_slr.setFocusPolicy(Qt.StrongFocus)
        self.grid_opacity_slr.setRange(0, 10)
        self.grid_opacity_slr.setValue(5)
        self.grid_opacity_slr.setTickInterval(1)
        self.grid_opacity_slr.setSingleStep(1)
        self.grid_opacity_slr.setTickPosition(QSlider.TicksBelow)
        self.grid_opacity_slr.valueChanged.connect(
            self.handle_grid_opacity_slider_mouse_release)
        self.grid_opacity_slr.setEnabled(False)

        self.reset_chart_settings_btn = QPushButton("Reset Chart Settings")
        self.reset_chart_settings_btn.clicked.connect(
            self.handle_reset_chart_settings_btn_clicked)

        self.curve_checkbox_panel = QWidget()

        self.graph_drawing_settings_grpbx = QGroupBox()
        self.graph_drawing_settings_grpbx.setFixedHeight(270)

        self.axis_settings_grpbx = QGroupBox()
        self.axis_settings_grpbx.setFixedHeight(180)

        self.app = QApplication.instance()
        self.setup_ui()

        self.curve_settings_disp = None
        self.axis_settings_disp = None
        self.chart_data_export_disp = None
        self.chart_data_import_disp = None
        self.grid_alpha = 5
        self.time_span_limit_hours = None
        self.time_span_limit_minutes = None
        self.time_span_limit_seconds = None
        self.data_sampling_mode = ASYNC_DATA_SAMPLING

    def minimumSizeHint(self):
        """
        The minimum recommended size of the main window.
        """
        return QSize(1490, 800)

    def ui_filepath(self):
        """
        The path to the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def ui_filename(self):
        """
        The name the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def setup_ui(self):
        """
        Initialize the widgets and layouts.
        """
        self.setLayout(self.main_layout)

        self.pv_layout.addWidget(self.pv_protocol_cmb)
        self.pv_layout.addWidget(self.pv_name_line_edt)
        self.pv_layout.addWidget(self.pv_connect_push_btn)
        QTimer.singleShot(0, self.pv_name_line_edt.setFocus)

        self.curve_settings_tab.setLayout(self.curves_tab_layout)
        self.chart_settings_tab.setLayout(self.chart_settings_layout)
        self.setup_chart_settings_layout()

        self.tab_panel.addTab(self.curve_settings_tab, "Curves")
        self.tab_panel.addTab(self.chart_settings_tab, "Chart")
        self.tab_panel.hide()

        self.crosshair_settings_layout.addWidget(self.enable_crosshair_chk)
        self.crosshair_settings_layout.addWidget(self.cross_hair_coord_lbl)

        self.chart_control_layout.addWidget(self.auto_scale_btn)
        self.chart_control_layout.addWidget(self.view_all_btn)
        self.chart_control_layout.addWidget(self.reset_chart_btn)
        self.chart_control_layout.addWidget(self.pause_chart_btn)
        self.chart_control_layout.addLayout(self.crosshair_settings_layout)
        self.chart_control_layout.addWidget(self.import_data_btn)
        self.chart_control_layout.addWidget(self.export_data_btn)

        self.chart_control_layout.setStretch(4, 15)
        self.chart_control_layout.insertSpacing(5, 350)

        self.chart_layout.addWidget(self.chart)
        self.chart_layout.addLayout(self.chart_control_layout)

        self.chart_panel.setLayout(self.chart_layout)

        self.splitter.addWidget(self.chart_panel)
        self.splitter.addWidget(self.tab_panel)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)

        self.charting_layout.addWidget(self.splitter)

        self.body_layout.addLayout(self.pv_layout)
        self.body_layout.addLayout(self.charting_layout)
        self.body_layout.addLayout(self.chart_control_layout)
        self.main_layout.addLayout(self.body_layout)

        self.enable_chart_control_buttons(False)

    def setup_chart_settings_layout(self):
        self.chart_sync_mode_sync_radio.toggled.connect(
            partial(self.handle_sync_mode_radio_toggle,
                    self.chart_sync_mode_sync_radio))
        self.chart_sync_mode_async_radio.toggled.connect(
            partial(self.handle_sync_mode_radio_toggle,
                    self.chart_sync_mode_async_radio))

        self.title_settings_layout.addWidget(self.chart_title_lbl)
        self.title_settings_layout.addWidget(self.chart_title_line_edt)
        self.title_settings_layout.addWidget(self.show_legend_chk)
        self.title_settings_layout.addWidget(
            self.chart_change_axis_settings_btn)
        self.title_settings_grpbx.setLayout(self.title_settings_layout)
        self.chart_settings_layout.addWidget(self.title_settings_grpbx)

        self.chart_sync_mode_layout.addWidget(self.chart_sync_mode_sync_radio)
        self.chart_sync_mode_layout.addWidget(self.chart_sync_mode_async_radio)
        self.chart_sync_mode_grpbx.setLayout(self.chart_sync_mode_layout)
        self.chart_settings_layout.addWidget(self.chart_sync_mode_grpbx)

        self.chart_settings_layout.addWidget(self.chart_sync_mode_grpbx)

        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_lbl)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_hours_line_edt)

        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_minutes_line_edt)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_seconds_line_edt)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_activate_btn)

        self.chart_limit_time_span_lbl.hide()
        self.chart_limit_time_span_hours_line_edt.hide()
        self.chart_limit_time_span_minutes_line_edt.hide()
        self.chart_limit_time_span_seconds_line_edt.hide()
        self.chart_limit_time_span_activate_btn.hide()

        self.chart_limit_time_span_hours_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)
        self.chart_limit_time_span_minutes_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)
        self.chart_limit_time_span_seconds_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)

        self.chart_limit_time_span_chk.clicked.connect(
            self.handle_limit_time_span_checkbox_clicked)
        self.chart_limit_time_span_activate_btn.clicked.connect(
            self.handle_chart_limit_time_span_activate_btn_clicked)
        self.chart_limit_time_span_activate_btn.installEventFilter(self)

        self.graph_background_color_layout.addRow(self.background_color_lbl,
                                                  self.background_color_btn)

        self.graph_drawing_settings_layout.addLayout(
            self.graph_background_color_layout)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_redraw_rate_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_redraw_rate_spin)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_data_sampling_rate_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_data_async_sampling_rate_spin)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_limit_time_span_chk)
        self.graph_drawing_settings_layout.addLayout(
            self.chart_limit_time_span_layout)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_ring_buffer_size_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_ring_buffer_size_edt)
        self.graph_drawing_settings_grpbx.setLayout(
            self.graph_drawing_settings_layout)

        self.axis_settings_layout.addWidget(self.show_x_grid_chk)
        self.axis_settings_layout.addWidget(self.show_y_grid_chk)
        self.axis_settings_layout.addWidget(self.axis_color_lbl)
        self.axis_settings_layout.addWidget(self.axis_color_btn)
        self.axis_settings_layout.addWidget(self.grid_opacity_lbl)
        self.axis_settings_layout.addWidget(self.grid_opacity_slr)
        self.axis_settings_grpbx.setLayout(self.axis_settings_layout)

        self.chart_settings_layout.addWidget(self.graph_drawing_settings_grpbx)
        self.chart_settings_layout.addWidget(self.axis_settings_grpbx)
        self.chart_settings_layout.addWidget(self.reset_chart_settings_btn)

        self.chart_sync_mode_async_radio.toggled.emit(True)
        self.update_datetime_timer.start(1000)

    def eventFilter(self, obj, event):
        """
        Handle key and mouse events for any applicable widget.

        Parameters
        ----------
        obj : QWidget
            The current widget that accepts the event
        event : QEvent
            The key or mouse event to handle

        Returns
        -------
            True if the event was handled successfully; False otherwise
        """
        if obj == self.pv_name_line_edt and event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
                self.add_curve()
                return True
        elif obj == self.chart_limit_time_span_activate_btn and event.type(
        ) == QEvent.KeyPress:
            if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
                self.handle_chart_limit_time_span_activate_btn_clicked()
                return True
        elif obj == self.chart_ring_buffer_size_edt:
            if event.type() == QEvent.KeyPress and (event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return) or \
                    event.type() == QEvent.FocusOut:
                try:
                    buffer_size = int(self.chart_ring_buffer_size_edt.text())
                    if buffer_size < MINIMUM_BUFFER_SIZE:
                        self.chart_ring_buffer_size_edt.setText(
                            str(MINIMUM_BUFFER_SIZE))
                except ValueError:
                    display_message_box(QMessageBox.Critical, "Invalid Values",
                                        "Only integer values are accepted.")
                return True
        return super(PyDMChartingDisplay, self).eventFilter(obj, event)

    def add_curve(self):
        """
        Add a new curve to the chart.
        """
        pv_name = self._get_full_pv_name(self.pv_name_line_edt.text())
        color = random_color()
        for k, v in self.channel_map.items():
            if color == v.color:
                color = random_color()

        self.add_y_channel(pv_name=pv_name, curve_name=pv_name, color=color)

    def handle_enable_crosshair_checkbox_clicked(self, is_checked):
        self.chart.enableCrosshair(is_checked)
        self.cross_hair_coord_lbl.setVisible(is_checked)

    def add_y_channel(self,
                      pv_name,
                      curve_name,
                      color,
                      line_style=Qt.SolidLine,
                      line_width=2,
                      symbol=None,
                      symbol_size=None):
        if pv_name in self.channel_map:
            logger.error("'{0}' has already been added.".format(pv_name))
            return

        curve = self.chart.addYChannel(y_channel=pv_name,
                                       name=curve_name,
                                       color=color,
                                       lineStyle=line_style,
                                       lineWidth=line_width,
                                       symbol=symbol,
                                       symbolSize=symbol_size)
        self.channel_map[pv_name] = curve
        self.generate_pv_controls(pv_name, color)

        self.enable_chart_control_buttons()
        self.app.establish_widget_connections(self)

    def generate_pv_controls(self, pv_name, curve_color):
        """
        Generate a set of widgets to manage the appearance of a curve. The set of widgets includes:
            1. A checkbox which shows the curve on the chart if checked, and hide the curve if not checked
            2. Two buttons -- Modify... and Remove. Modify... will bring up the Curve Settings dialog. Remove will
               delete the curve from the chart
        This set of widgets will be hidden initially, until the first curve is plotted.

        Parameters
        ----------
        pv_name: str
            The name of the PV the current curve is being plotted for

        curve_color : QColor
            The color of the curve to paint for the checkbox label to help the user track the curve to the checkbox
        """
        checkbox = QCheckBox()
        checkbox.setObjectName(pv_name)

        palette = checkbox.palette()
        palette.setColor(QPalette.Active, QPalette.WindowText, curve_color)
        checkbox.setPalette(palette)

        display_name = pv_name.split("://")[1]
        if len(display_name) > MAX_DISPLAY_PV_NAME_LENGTH:
            # Only display max allowed number of characters of the PV Name
            display_name = display_name[:int(MAX_DISPLAY_PV_NAME_LENGTH / 2) - 1] + "..." + \
                           display_name[-int(MAX_DISPLAY_PV_NAME_LENGTH / 2) + 2:]

        checkbox.setText(display_name)

        data_text = QLabel()
        data_text.setObjectName(pv_name)
        data_text.setPalette(palette)

        checkbox.setChecked(True)
        checkbox.clicked.connect(
            partial(self.handle_curve_chkbox_toggled, checkbox))

        curve_btn_layout = QHBoxLayout()

        modify_curve_btn = QPushButton("Modify...")
        modify_curve_btn.setObjectName(pv_name)
        modify_curve_btn.setMaximumWidth(100)
        modify_curve_btn.clicked.connect(
            partial(self.display_curve_settings_dialog, pv_name))

        focus_curve_btn = QPushButton("Focus")
        focus_curve_btn.setObjectName(pv_name)
        focus_curve_btn.setMaximumWidth(100)
        focus_curve_btn.clicked.connect(partial(self.focus_curve, pv_name))

        annotate_curve_btn = QPushButton("Annotate...")
        annotate_curve_btn.setObjectName(pv_name)
        annotate_curve_btn.setMaximumWidth(100)
        annotate_curve_btn.clicked.connect(
            partial(self.annotate_curve, pv_name))

        remove_curve_btn = QPushButton("Remove")
        remove_curve_btn.setObjectName(pv_name)
        remove_curve_btn.setMaximumWidth(100)
        remove_curve_btn.clicked.connect(partial(self.remove_curve, pv_name))

        curve_btn_layout.addWidget(modify_curve_btn)
        curve_btn_layout.addWidget(focus_curve_btn)
        curve_btn_layout.addWidget(annotate_curve_btn)
        curve_btn_layout.addWidget(remove_curve_btn)

        individual_curve_layout = QVBoxLayout()
        individual_curve_layout.addWidget(checkbox)
        individual_curve_layout.addWidget(data_text)
        individual_curve_layout.addLayout(curve_btn_layout)

        size_policy = QSizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Fixed)
        individual_curve_grpbx = QGroupBox()
        individual_curve_grpbx.setSizePolicy(size_policy)

        individual_curve_grpbx.setObjectName(pv_name)
        individual_curve_grpbx.setLayout(individual_curve_layout)

        self.curve_settings_layout.addWidget(individual_curve_grpbx)
        self.tab_panel.show()

    def handle_curve_chkbox_toggled(self, checkbox):
        """
        Handle a checkbox's checked and unchecked events.

        If a checkbox is checked, find the curve from the channel map. If found, re-draw the curve with its previous
        appearance settings.

        If a checkbox is unchecked, remove the curve from the chart, but keep the cached data in the channel map.

        Parameters
        ----------
        checkbox : QCheckBox
            The current checkbox being toggled
        """
        pv_name = self._get_full_pv_name(checkbox.text())

        if checkbox.isChecked():
            curve = self.channel_map.get(pv_name, None)
            if curve:
                self.chart.addLegendItem(curve, pv_name,
                                         self.show_legend_chk.isChecked())
                curve.show()
        else:
            curve = self.chart.findCurve(pv_name)
            if curve:
                curve.hide()
                self.chart.removeLegendItem(pv_name)

    def display_curve_settings_dialog(self, pv_name):
        """
        Bring up the Curve Settings dialog to modify the appearance of a curve.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for

        """
        self.curve_settings_disp = CurveSettingsDisplay(self, pv_name)
        self.curve_settings_disp.show()

    def focus_curve(self, pv_name):
        curve = self.chart.findCurve(pv_name)
        if curve:
            self.chart.plotItem.setYRange(curve.minY, curve.maxY, padding=0)

    def annotate_curve(self, pv_name):
        curve = self.chart.findCurve(pv_name)
        if curve:
            annot = TextItem(
                html=
                '<div style="text-align: center"><span style="color: #FFF;">This is the'
                '</span><br><span style="color: #FF0; font-size: 16pt;">PEAK</span></div>',
                anchor=(-0.3, 0.5),
                border='w',
                fill=(0, 0, 255, 100))
            annot = TextItem("test", anchor=(-0.3, 0.5))
            self.chart.annotateCurve(curve, annot)

    def remove_curve(self, pv_name):
        """
        Remove a curve from the chart permanently. This will also clear the channel map cache from retaining the
        removed curve's appearance settings.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for
        """
        curve = self.chart.findCurve(pv_name)
        if curve:
            self.chart.removeYChannel(curve)
            del self.channel_map[pv_name]
            self.chart.removeLegendItem(pv_name)

            widgets = self.findChildren(
                (QCheckBox, QLabel, QPushButton, QGroupBox), pv_name)
            for w in widgets:
                w.deleteLater()

        if len(self.chart.getCurves()) < 1:
            self.enable_chart_control_buttons(False)
            self.show_legend_chk.setChecked(False)

    def handle_title_text_changed(self, new_text):
        self.chart.setPlotTitle(new_text)

    def handle_change_axis_settings_clicked(self):
        self.axis_settings_disp = AxisSettingsDisplay(self)
        self.axis_settings_disp.show()

    def handle_limit_time_span_checkbox_clicked(self, is_checked):
        self.chart_limit_time_span_lbl.setVisible(is_checked)
        self.chart_limit_time_span_hours_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_minutes_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_seconds_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_activate_btn.setVisible(is_checked)

        self.chart_ring_buffer_size_lbl.setDisabled(is_checked)
        self.chart_ring_buffer_size_edt.setDisabled(is_checked)

        if not is_checked:
            self.chart_limit_time_span_chk.setText(self.limit_time_plan_text)

    def handle_time_span_edt_text_changed(self, new_text):
        try:
            self.time_span_limit_hours = int(
                self.chart_limit_time_span_hours_line_edt.text())
            self.time_span_limit_minutes = int(
                self.chart_limit_time_span_minutes_line_edt.text())
            self.time_span_limit_seconds = int(
                self.chart_limit_time_span_seconds_line_edt.text())
        except ValueError as e:
            self.time_span_limit_hours = None
            self.time_span_limit_minutes = None
            self.time_span_limit_seconds = None

        if self.time_span_limit_hours is not None and self.time_span_limit_minutes is not None and \
                self.time_span_limit_seconds is not None:
            self.chart_limit_time_span_activate_btn.setEnabled(True)
        else:
            self.chart_limit_time_span_activate_btn.setEnabled(False)

    def handle_chart_limit_time_span_activate_btn_clicked(self):
        if self.time_span_limit_hours is None or self.time_span_limit_minutes is None or \
                self.time_span_limit_seconds is None:
            display_message_box(
                QMessageBox.Critical, "Invalid Values",
                "Hours, minutes, and seconds expect only integer values.")
        else:
            timeout_milliseconds = (self.time_span_limit_hours * 3600 +
                                    self.time_span_limit_minutes * 60 +
                                    self.time_span_limit_seconds) * 1000
            self.chart.setTimeSpan(timeout_milliseconds / 1000.0)
            self.chart_ring_buffer_size_edt.setText(
                str(self.chart.getBufferSize()))

    def handle_buffer_size_changed(self, new_buffer_size):
        try:
            if new_buffer_size and int(new_buffer_size) > MINIMUM_BUFFER_SIZE:
                self.chart.setBufferSize(new_buffer_size)
        except ValueError:
            display_message_box(QMessageBox.Critical, "Invalid Values",
                                "Only integer values are accepted.")

    def handle_redraw_rate_changed(self, new_redraw_rate):
        self.chart.maxRedrawRate = new_redraw_rate

    def handle_data_sampling_rate_changed(self, new_data_sampling_rate):
        # The chart expects the value in milliseconds
        sampling_rate_seconds = 1 / new_data_sampling_rate
        self.chart.setUpdateInterval(sampling_rate_seconds)

    def handle_background_color_button_clicked(self):
        selected_color = QColorDialog.getColor()
        self.chart.setBackgroundColor(selected_color)
        self.background_color_btn.setStyleSheet("background-color: " +
                                                selected_color.name())

    def handle_axis_color_button_clicked(self):
        selected_color = QColorDialog.getColor()
        self.chart.setAxisColor(selected_color)
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          selected_color.name())

    def handle_grid_opacity_slider_mouse_release(self):
        self.grid_alpha = float(self.grid_opacity_slr.value()) / 10.0
        self.chart.setShowXGrid(self.show_x_grid_chk.isChecked(),
                                self.grid_alpha)
        self.chart.setShowYGrid(self.show_y_grid_chk.isChecked(),
                                self.grid_alpha)

    def handle_show_x_grid_checkbox_clicked(self, is_checked):
        self.chart.setShowXGrid(is_checked, self.grid_alpha)

        self.axis_color_lbl.setEnabled(is_checked
                                       or self.show_y_grid_chk.isChecked())
        self.axis_color_btn.setEnabled(is_checked
                                       or self.show_y_grid_chk.isChecked())
        self.grid_opacity_lbl.setEnabled(is_checked
                                         or self.show_y_grid_chk.isChecked())
        self.grid_opacity_slr.setEnabled(is_checked
                                         or self.show_y_grid_chk.isChecked())

    def handle_show_y_grid_checkbox_clicked(self, is_checked):
        self.chart.setShowYGrid(is_checked, self.grid_alpha)

        self.axis_color_lbl.setEnabled(is_checked
                                       or self.show_x_grid_chk.isChecked())
        self.axis_color_btn.setEnabled(is_checked
                                       or self.show_x_grid_chk.isChecked())
        self.grid_opacity_lbl.setEnabled(is_checked
                                         or self.show_x_grid_chk.isChecked())
        self.grid_opacity_slr.setEnabled(is_checked
                                         or self.show_x_grid_chk.isChecked())

    def handle_show_legend_checkbox_clicked(self, is_checked):
        self.chart.setShowLegend(is_checked)

    def handle_export_data_btn_clicked(self):
        self.chart_data_export_disp = ChartDataExportDisplay(self)
        self.chart_data_export_disp.show()

    def handle_import_data_btn_clicked(self):
        open_file_info = QFileDialog.getOpenFileName(self,
                                                     caption="Save File",
                                                     filter="*." +
                                                     IMPORT_FILE_FORMAT)
        open_file_name = open_file_info[0]
        if open_file_name:
            importer = SettingsImporter(self)
            importer.import_settings(open_file_name)

    def handle_sync_mode_radio_toggle(self, radio_btn):
        if radio_btn.isChecked():
            if radio_btn.text() == "Synchronous":
                self.data_sampling_mode = SYNC_DATA_SAMPLING

                self.chart_data_sampling_rate_lbl.hide()
                self.chart_data_async_sampling_rate_spin.hide()

                self.chart.resetTimeSpan()
                self.chart_limit_time_span_chk.setChecked(False)
                self.chart_limit_time_span_chk.clicked.emit(False)
                self.chart_limit_time_span_chk.hide()
                self.graph_drawing_settings_grpbx.setFixedHeight(180)

                self.chart.setUpdatesAsynchronously(False)
            elif radio_btn.text() == "Asynchronous":
                self.data_sampling_mode = ASYNC_DATA_SAMPLING

                self.chart_data_sampling_rate_lbl.show()
                self.chart_data_async_sampling_rate_spin.show()
                self.chart_limit_time_span_chk.show()
                self.graph_drawing_settings_grpbx.setFixedHeight(270)

                self.chart.setUpdatesAsynchronously(True)
        self.app.establish_widget_connections(self)

    def handle_auto_scale_btn_clicked(self):
        self.chart.resetAutoRangeX()
        self.chart.resetAutoRangeY()

    def handle_view_all_button_clicked(self):
        self.chart.getViewBox().autoRange()

    def handle_pause_chart_btn_clicked(self):
        if self.chart.pausePlotting():
            self.pause_chart_btn.setText(self.pause_chart_text)
        else:
            self.pause_chart_btn.setText(self.resume_chart_text)

    def handle_reset_chart_btn_clicked(self):
        self.chart.getViewBox().setXRange(DEFAULT_X_MIN, 0)
        self.chart.resetAutoRangeY()

    @Slot()
    def handle_reset_chart_settings_btn_clicked(self):
        self.chart_ring_buffer_size_edt.setText(str(DEFAULT_BUFFER_SIZE))

        self.chart_redraw_rate_spin.setValue(DEFAULT_REDRAW_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.setValue(
            DEFAULT_DATA_SAMPLING_RATE_HZ)
        self.chart_data_sampling_rate_lbl.hide()
        self.chart_data_async_sampling_rate_spin.hide()

        self.chart_sync_mode_async_radio.setChecked(True)
        self.chart_sync_mode_async_radio.toggled.emit(True)

        self.chart_limit_time_span_chk.setChecked(False)
        self.chart_limit_time_span_chk.setText(self.limit_time_plan_text)
        self.chart_limit_time_span_chk.clicked.emit(False)

        self.chart.setUpdatesAsynchronously(True)
        self.chart.resetTimeSpan()
        self.chart.resetUpdateInterval()
        self.chart.setBufferSize(DEFAULT_BUFFER_SIZE)

        self.chart.setBackgroundColor(DEFAULT_CHART_BACKGROUND_COLOR)
        self.background_color_btn.setStyleSheet(
            "background-color: " + DEFAULT_CHART_BACKGROUND_COLOR.name())

        self.chart.setAxisColor(DEFAULT_CHART_AXIS_COLOR)
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          DEFAULT_CHART_AXIS_COLOR.name())

        self.grid_opacity_slr.setValue(5)

        self.show_x_grid_chk.setChecked(False)
        self.show_x_grid_chk.clicked.emit(False)

        self.show_y_grid_chk.setChecked(False)
        self.show_y_grid_chk.clicked.emit(False)

        self.show_legend_chk.setChecked(False)

        self.chart.setShowXGrid(False)
        self.chart.setShowYGrid(False)
        self.chart.setShowLegend(False)

    def enable_chart_control_buttons(self, enabled=True):
        self.auto_scale_btn.setEnabled(enabled)
        self.view_all_btn.setEnabled(enabled)
        self.reset_chart_btn.setEnabled(enabled)
        self.pause_chart_btn.setText(self.pause_chart_text)
        self.pause_chart_btn.setEnabled(enabled)
        self.export_data_btn.setEnabled(enabled)

    def _get_full_pv_name(self, pv_name):
        """
        Append the protocol to the PV Name.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for
        """
        if pv_name and "://" not in pv_name:
            pv_name = ''.join([self.pv_protocol_cmb.currentText(), pv_name])
        return pv_name

    def handle_update_datetime_timer_timeout(self):
        current_label = self.chart.getBottomAxisLabel()
        new_label = "Current Time: " + PyDMChartingDisplay.get_current_datetime(
        )

        if X_AXIS_LABEL_SEPARATOR in current_label:
            current_label = current_label[current_label.
                                          find(X_AXIS_LABEL_SEPARATOR) +
                                          len(X_AXIS_LABEL_SEPARATOR):]
            new_label += X_AXIS_LABEL_SEPARATOR + current_label

        self.chart.setLabel("bottom", text=new_label)

    def update_curve_data(self, curve):
        """
        Determine if the PV is active. If not, disable the related PV controls. If the PV is active, update the PV
        controls' states.

        Parameters
        ----------
        curve : PlotItem
           A PlotItem, i.e. a plot, to draw on the chart.
        """
        pv_name = curve.name()
        max_x = self.chart.getViewBox().viewRange()[1][0]
        max_y = self.chart.getViewBox().viewRange()[1][1]
        current_y = curve.data_buffer[1, -1]

        widgets = self.findChildren((QCheckBox, QLabel, QPushButton), pv_name)
        for w in widgets:
            if np.isnan(current_y):
                if isinstance(w, QCheckBox):
                    w.setChecked(False)
            else:
                if isinstance(w, QCheckBox) and not w.isEnabled():
                    w.setChecked(True)
                if isinstance(w, QLabel):
                    w.clear()
                    w.setText(
                        "(yMin = {0:.3f}, yMax = {1:.3f}) y = {2:.3f}".format(
                            max_x, max_y, current_y))
                    w.show()
            w.setEnabled(not np.isnan(current_y))

            if isinstance(w, QPushButton) and w.text() == "Remove":
                # Enable the Remove button to make removing inactive PVs possible anytime
                w.setEnabled(True)

    def show_mouse_coordinates(self, x, y):
        self.cross_hair_coord_lbl.clear()
        self.cross_hair_coord_lbl.setText("x = {0:.3f}, y = {1:.3f}".format(
            x, y))

    @staticmethod
    def get_current_datetime():
        current_date = datetime.datetime.now().strftime("%b %d, %Y")
        current_time = datetime.datetime.now().strftime("%H:%M:%S")
        current_datetime = current_time + ' (' + current_date + ')'

        return current_datetime

    @property
    def gridAlpha(self):
        return self.grid_alpha
Beispiel #41
0
    def setup_page(self):
        self.ICON = ima.icon('genprefs')
        newcb = self.create_checkbox

        # --- Interface
        general_group = QGroupBox(_("General"))

        languages = LANGUAGE_CODES.items()
        language_choices = sorted([(val, key) for key, val in languages])
        language_combo = self.create_combobox(_('Language:'),
                                              language_choices,
                                              'interface_language',
                                              restart=True)

        opengl_options = ['Automatic', 'Desktop', 'Software', 'GLES']
        opengl_choices = list(zip(opengl_options,
                                  [c.lower() for c in opengl_options]))
        opengl_combo = self.create_combobox(_('Rendering engine:'),
                                            opengl_choices,
                                            'opengl',
                                            restart=True)

        single_instance_box = newcb(_("Use a single instance"),
                                    'single_instance',
                                    tip=_("Set this to open external<br> "
                                          "Python files in an already running "
                                          "instance (Requires a restart)"))

        prompt_box = newcb(_("Prompt when exiting"), 'prompt_on_exit')
        popup_console_box = newcb(_("Show internal Spyder errors to report "
                                    "them to Github"), 'show_internal_errors')
        check_updates = newcb(_("Check for updates on startup"),
                              'check_updates_on_startup')

        # Decide if it's possible to activate or not single instance mode
        if running_in_mac_app():
            self.set_option("single_instance", True)
            single_instance_box.setEnabled(False)

        comboboxes_advanced_layout = QHBoxLayout()
        cbs_adv_grid = QGridLayout()
        cbs_adv_grid.addWidget(language_combo.label, 0, 0)
        cbs_adv_grid.addWidget(language_combo.combobox, 0, 1)
        cbs_adv_grid.addWidget(opengl_combo.label, 1, 0)
        cbs_adv_grid.addWidget(opengl_combo.combobox, 1, 1)
        comboboxes_advanced_layout.addLayout(cbs_adv_grid)
        comboboxes_advanced_layout.addStretch(1)

        general_layout = QVBoxLayout()
        general_layout.addLayout(comboboxes_advanced_layout)
        general_layout.addWidget(single_instance_box)
        general_layout.addWidget(prompt_box)
        general_layout.addWidget(popup_console_box)
        general_layout.addWidget(check_updates)
        general_group.setLayout(general_layout)

        # --- Theme
        interface_group = QGroupBox(_("Interface"))

        vertdock_box = newcb(_("Vertical title bars in panes"),
                             'vertical_dockwidget_titlebars')
        verttabs_box = newcb(_("Vertical tabs in panes"),
                             'vertical_tabs')
        animated_box = newcb(_("Animated toolbars and panes"),
                             'animated_docks')
        tear_off_box = newcb(_("Tear off menus"), 'tear_off_menus',
                             tip=_("Set this to detach any<br> "
                                   "menu from the main window"))
        margin_box = newcb(_("Custom margin for panes:"),
                           'use_custom_margin')
        margin_spin = self.create_spinbox("", _("pixels"), 'custom_margin',
                                          0, 0, 30)
        margin_box.toggled.connect(margin_spin.spinbox.setEnabled)
        margin_box.toggled.connect(margin_spin.slabel.setEnabled)
        margin_spin.spinbox.setEnabled(self.get_option('use_custom_margin'))
        margin_spin.slabel.setEnabled(self.get_option('use_custom_margin'))

        cursor_box = newcb(_("Cursor blinking:"),
                           'use_custom_cursor_blinking')
        cursor_spin = self.create_spinbox(
            "", _("ms"),
            'custom_cursor_blinking',
            default=QApplication.cursorFlashTime(),
            min_=0, max_=5000, step=100)
        cursor_box.toggled.connect(cursor_spin.spinbox.setEnabled)
        cursor_box.toggled.connect(cursor_spin.slabel.setEnabled)
        cursor_spin.spinbox.setEnabled(
            self.get_option('use_custom_cursor_blinking'))
        cursor_spin.slabel.setEnabled(
            self.get_option('use_custom_cursor_blinking'))

        margins_cursor_layout = QGridLayout()
        margins_cursor_layout.addWidget(margin_box, 0, 0)
        margins_cursor_layout.addWidget(margin_spin.spinbox, 0, 1)
        margins_cursor_layout.addWidget(margin_spin.slabel, 0, 2)
        margins_cursor_layout.addWidget(cursor_box, 1, 0)
        margins_cursor_layout.addWidget(cursor_spin.spinbox, 1, 1)
        margins_cursor_layout.addWidget(cursor_spin.slabel, 1, 2)
        margins_cursor_layout.setColumnStretch(2, 100)

        # Layout interface
        interface_layout = QVBoxLayout()
        interface_layout.addWidget(vertdock_box)
        interface_layout.addWidget(verttabs_box)
        interface_layout.addWidget(animated_box)
        interface_layout.addWidget(tear_off_box)
        interface_layout.addLayout(margins_cursor_layout)
        interface_group.setLayout(interface_layout)

        # --- Status bar
        sbar_group = QGroupBox(_("Status bar"))
        show_status_bar = newcb(_("Show status bar"), 'show_status_bar')

        memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable',
                           tip=self.main.mem_status.toolTip())
        memory_spin = self.create_spinbox("", _(" ms"), 'memory_usage/timeout',
                                          min_=100, max_=1000000, step=100)
        memory_box.toggled.connect(memory_spin.setEnabled)
        memory_spin.setEnabled(self.get_option('memory_usage/enable'))
        memory_box.setEnabled(self.main.mem_status.is_supported())
        memory_spin.setEnabled(self.main.mem_status.is_supported())

        cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable',
                        tip=self.main.cpu_status.toolTip())
        cpu_spin = self.create_spinbox("", _(" ms"), 'cpu_usage/timeout',
                                       min_=100, max_=1000000, step=100)
        cpu_box.toggled.connect(cpu_spin.setEnabled)
        cpu_spin.setEnabled(self.get_option('cpu_usage/enable'))

        cpu_box.setEnabled(self.main.cpu_status.is_supported())
        cpu_spin.setEnabled(self.main.cpu_status.is_supported())

        status_bar_o = self.get_option('show_status_bar')
        show_status_bar.toggled.connect(memory_box.setEnabled)
        show_status_bar.toggled.connect(memory_spin.setEnabled)
        show_status_bar.toggled.connect(cpu_box.setEnabled)
        show_status_bar.toggled.connect(cpu_spin.setEnabled)
        memory_box.setEnabled(status_bar_o)
        memory_spin.setEnabled(status_bar_o)
        cpu_box.setEnabled(status_bar_o)
        cpu_spin.setEnabled(status_bar_o)

        # Layout status bar
        cpu_memory_layout = QGridLayout()
        cpu_memory_layout.addWidget(memory_box, 0, 0)
        cpu_memory_layout.addWidget(memory_spin, 0, 1)
        cpu_memory_layout.addWidget(cpu_box, 1, 0)
        cpu_memory_layout.addWidget(cpu_spin, 1, 1)

        sbar_layout = QVBoxLayout()
        sbar_layout.addWidget(show_status_bar)
        sbar_layout.addLayout(cpu_memory_layout)
        sbar_group.setLayout(sbar_layout)

        # --- Screen resolution Group (hidpi)
        screen_resolution_group = QGroupBox(_("Screen resolution"))
        screen_resolution_bg = QButtonGroup(screen_resolution_group)
        screen_resolution_label = QLabel(_("Configuration for high DPI "
                                           "screens<br><br>"
                                           "Please see "
                                           "<a href=\"{0}\">{0}</a><> "
                                           "for more information about "
                                           "these options (in "
                                           "English).").format(HDPI_QT_PAGE))
        screen_resolution_label.setWordWrap(True)

        normal_radio = self.create_radiobutton(
                                _("Normal"),
                                'normal_screen_resolution',
                                button_group=screen_resolution_bg)
        auto_scale_radio = self.create_radiobutton(
                                _("Enable auto high DPI scaling"),
                                'high_dpi_scaling',
                                button_group=screen_resolution_bg,
                                tip=_("Set this for high DPI displays"),
                                restart=True)

        custom_scaling_radio = self.create_radiobutton(
                                _("Set a custom high DPI scaling"),
                                'high_dpi_custom_scale_factor',
                                button_group=screen_resolution_bg,
                                tip=_("Set this for high DPI displays when "
                                      "auto scaling does not work"),
                                restart=True)

        custom_scaling_edit = self.create_lineedit(
            "",
            'high_dpi_custom_scale_factors',
            tip=_("Enter values for different screens "
                  "separated by semicolons ';', "
                  "float values are supported"),
            alignment=Qt.Horizontal,
            regex=r"[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*",
            restart=True)

        normal_radio.toggled.connect(custom_scaling_edit.setDisabled)
        auto_scale_radio.toggled.connect(custom_scaling_edit.setDisabled)
        custom_scaling_radio.toggled.connect(custom_scaling_edit.setEnabled)

        # Layout Screen resolution
        screen_resolution_layout = QVBoxLayout()
        screen_resolution_layout.addWidget(screen_resolution_label)

        screen_resolution_inner_layout = QGridLayout()
        screen_resolution_inner_layout.addWidget(normal_radio, 0, 0)
        screen_resolution_inner_layout.addWidget(auto_scale_radio, 1, 0)
        screen_resolution_inner_layout.addWidget(custom_scaling_radio, 2, 0)
        screen_resolution_inner_layout.addWidget(custom_scaling_edit, 2, 1)

        screen_resolution_layout.addLayout(screen_resolution_inner_layout)
        screen_resolution_group.setLayout(screen_resolution_layout)

        tabs = QTabWidget()
        tabs.addTab(self.create_tab(screen_resolution_group, interface_group),
                    _("Interface"))
        tabs.addTab(self.create_tab(general_group, sbar_group),
                    _("Advanced Settings"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
Beispiel #42
0
class KernelConnectionDialog(QDialog):
    """Dialog to connect to existing kernels (either local or remote)."""

    def __init__(self, parent=None):
        super(KernelConnectionDialog, self).__init__(parent)
        self.setWindowTitle(_('Connect to an existing kernel'))

        main_label = QLabel(_(
            "<p>Please select the JSON connection file (<i>e.g.</i> "
            "<tt>kernel-1234.json</tt>) of the existing kernel, and enter "
            "the SSH information if connecting to a remote machine. "
            "To learn more about starting external kernels and connecting "
            "to them, see <a href=\"https://docs.spyder-ide.org/"
            "ipythonconsole.html#connect-to-an-external-kernel\">"
            "our documentation</a>.</p>"))
        main_label.setWordWrap(True)
        main_label.setAlignment(Qt.AlignJustify)
        main_label.setOpenExternalLinks(True)

        # Connection file
        cf_label = QLabel(_('Connection file:'))
        self.cf = QLineEdit()
        self.cf.setPlaceholderText(_('Kernel connection file path'))
        self.cf.setMinimumWidth(350)
        cf_open_btn = QPushButton(_('Browse'))
        cf_open_btn.clicked.connect(self.select_connection_file)

        cf_layout = QHBoxLayout()
        cf_layout.addWidget(cf_label)
        cf_layout.addWidget(self.cf)
        cf_layout.addWidget(cf_open_btn)

        # Remote kernel groupbox
        self.rm_group = QGroupBox(_("This is a remote kernel (via SSH)"))

        # SSH connection
        hn_label = QLabel(_('Hostname:'))
        self.hn = QLineEdit()
        pn_label = QLabel(_('Port:'))
        self.pn = QLineEdit()
        self.pn.setMaximumWidth(75)
        self.pn.setText('22')
        un_label = QLabel(_('Username:'******'Password:'******'SSH keyfile:'))

        self.pw = QLineEdit()
        self.pw.setEchoMode(QLineEdit.Password)
        self.pw_radio.toggled.connect(self.pw.setEnabled)
        self.kf_radio.toggled.connect(self.pw.setDisabled)

        self.kf = QLineEdit()
        kf_open_btn = QPushButton(_('Browse'))
        kf_open_btn.clicked.connect(self.select_ssh_key)
        kf_layout = QHBoxLayout()
        kf_layout.addWidget(self.kf)
        kf_layout.addWidget(kf_open_btn)

        kfp_label = QLabel(_('Passphase:'))
        self.kfp = QLineEdit()
        self.kfp.setPlaceholderText(_('Optional'))
        self.kfp.setEchoMode(QLineEdit.Password)

        self.kf_radio.toggled.connect(self.kf.setEnabled)
        self.kf_radio.toggled.connect(self.kfp.setEnabled)
        self.kf_radio.toggled.connect(kf_open_btn.setEnabled)
        self.kf_radio.toggled.connect(kfp_label.setEnabled)
        self.pw_radio.toggled.connect(self.kf.setDisabled)
        self.pw_radio.toggled.connect(self.kfp.setDisabled)
        self.pw_radio.toggled.connect(kf_open_btn.setDisabled)
        self.pw_radio.toggled.connect(kfp_label.setDisabled)

        # SSH layout
        ssh_layout = QGridLayout()
        ssh_layout.addWidget(hn_label, 0, 0, 1, 2)
        ssh_layout.addWidget(self.hn, 0, 2)
        ssh_layout.addWidget(pn_label, 0, 3)
        ssh_layout.addWidget(self.pn, 0, 4)
        ssh_layout.addWidget(un_label, 1, 0, 1, 2)
        ssh_layout.addWidget(self.un, 1, 2, 1, 3)

        # SSH authentication layout
        auth_layout = QGridLayout()
        auth_layout.addWidget(self.pw_radio, 1, 0)
        auth_layout.addWidget(pw_label, 1, 1)
        auth_layout.addWidget(self.pw, 1, 2)
        auth_layout.addWidget(self.kf_radio, 2, 0)
        auth_layout.addWidget(kf_label, 2, 1)
        auth_layout.addLayout(kf_layout, 2, 2)
        auth_layout.addWidget(kfp_label, 3, 1)
        auth_layout.addWidget(self.kfp, 3, 2)
        auth_group.setLayout(auth_layout)

        # Remote kernel layout
        rm_layout = QVBoxLayout()
        rm_layout.addLayout(ssh_layout)
        rm_layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 8)))
        rm_layout.addWidget(auth_group)
        self.rm_group.setLayout(rm_layout)
        self.rm_group.setCheckable(True)
        self.rm_group.setChecked(False)
        self.rm_group.toggled.connect(self.pw_radio.setChecked)

        # Ok and Cancel buttons
        self.accept_btns = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)

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

        # Dialog layout
        layout = QVBoxLayout(self)
        layout.addWidget(main_label)
        layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 8)))
        layout.addLayout(cf_layout)
        layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 12)))
        layout.addWidget(self.rm_group)
        layout.addWidget(self.accept_btns)

    def select_connection_file(self):
        cf = getopenfilename(self, _('Select kernel connection file'),
                             jupyter_runtime_dir(), '*.json;;*.*')[0]
        self.cf.setText(cf)

    def select_ssh_key(self):
        kf = getopenfilename(self, _('Select SSH keyfile'),
                             get_home_dir(), '*.pem;;*')[0]
        self.kf.setText(kf)

    @staticmethod
    def get_connection_parameters(parent=None, dialog=None):
        if not dialog:
            dialog = KernelConnectionDialog(parent)
        result = dialog.exec_()
        is_remote = bool(dialog.rm_group.isChecked())
        accepted = result == QDialog.Accepted
        if is_remote:
            def falsy_to_none(arg):
                return arg if arg else None
            if dialog.hn.text() and dialog.un.text():
                port = dialog.pn.text() if dialog.pn.text() else '22'
                hostname = "{0}@{1}:{2}".format(dialog.un.text(),
                                                dialog.hn.text(),
                                                port)
            else:
                hostname = None
            if dialog.pw_radio.isChecked():
                password = falsy_to_none(dialog.pw.text())
                keyfile = None
            elif dialog.kf_radio.isChecked():
                keyfile = falsy_to_none(dialog.kf.text())
                password = falsy_to_none(dialog.kfp.text())
            else:  # imposible?
                keyfile = None
                password = None
            return (dialog.cf.text(), hostname, keyfile, password, accepted)
        else:
            path = dialog.cf.text()
            _dir, filename = osp.dirname(path), osp.basename(path)
            if _dir == '' and not filename.endswith('.json'):
                path = osp.join(jupyter_runtime_dir(), 'kernel-'+path+'.json')
            return (path, None, None, None, accepted)
Beispiel #43
0
class MagOffConvApp(SiriusMainWindow):
    """Offline converter interface."""

    def __init__(self, parent=None):
        """Init."""
        super().__init__(parent)
        self._normalizer = None
        self._last_edited = None
        self._setupUi()
        self.setWindowTitle('Offline Strength/Current Converter')

    def _setupUi(self):
        # Layout to enter
        matype_label = QLabel('Choose a magnet: ', self)
        self._matype_cb = QComboBox(self)
        self._matype_items = MASearch.get_pwrsupply_manames()
        self._matype_cb.addItem('Select...')
        self._matype_cb.addItems(self._matype_items)
        self._matype_cb.setEditable(True)
        self._matype_cb.setMaxVisibleItems(10)
        self._matype_cb.currentIndexChanged.connect(
            self._fill_normalizer_layout)
        hlmatype = QHBoxLayout()
        hlmatype.setAlignment(Qt.AlignLeft)
        hlmatype.addWidget(matype_label)
        hlmatype.addWidget(self._matype_cb)

        # Layout to enter normalizer data
        self._lb_current = QLabel('Current [A]: ')
        lb_arrow = QLabel('↔', self, alignment=Qt.AlignCenter)
        lb_arrow.setStyleSheet('min-width:1.2em; max-width:1.2em;')
        self._lb_strength = QLabel('Strength: ')
        self._lb_energy = QLabel('Dipole Energy [GeV]: ')
        self._lb_energy.setVisible(False)
        self._lb_quadfam_kl = QLabel('Family KL [1/m]: ')
        self._lb_quadfam_kl.setVisible(False)

        for name in ['_sb_current', '_sb_strength',
                     '_sb_energy', '_sb_quadfam_kl']:
            setattr(self, name, QDoubleSpinBoxPlus())
            sb = getattr(self, name)
            sb.setObjectName(name)
            sb.setValue(0)
            sb.setMinimum(-100000)
            sb.setMaximum(100000)
            sb.setDecimals(4)
            sb.setStyleSheet("min-width:8em; max-width:8em;")
            sb.editingFinished.connect(self._update_inputs)
            if name in ['_sb_current', '_sb_strength']:
                sb.setEnabled(False)
            else:
                sb.setVisible(False)

        norm_lay = QGridLayout()
        norm_lay.setAlignment(Qt.AlignLeft)
        norm_lay.setHorizontalSpacing(5)
        norm_lay.addItem(
            QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 0)
        norm_lay.addWidget(self._lb_current, 0, 1)
        norm_lay.addWidget(self._sb_current, 1, 1)
        norm_lay.addWidget(lb_arrow, 0, 2, 2, 1)
        norm_lay.addWidget(self._lb_strength, 0, 3)
        norm_lay.addWidget(self._sb_strength, 1, 3)
        norm_lay.addItem(
            QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 4)
        norm_lay.addWidget(self._lb_energy, 0, 5)
        norm_lay.addWidget(self._sb_energy, 1, 5)
        norm_lay.addItem(
            QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 6)
        norm_lay.addWidget(self._lb_quadfam_kl, 0, 7)
        norm_lay.addWidget(self._sb_quadfam_kl, 1, 7)
        self.norm_gb = QGroupBox('', self)
        self.norm_gb.setLayout(norm_lay)

        # General layout
        layout = QVBoxLayout()
        layout.setSpacing(20)
        layout.addWidget(
            QLabel('<h2>Offline Strength/Current Converter</h2>',
                   self, alignment=Qt.AlignCenter))
        layout.addLayout(hlmatype)
        layout.addWidget(self.norm_gb)
        cw = QWidget(self)
        cw.setObjectName('central_widget')
        cw.setStyleSheet("""#central_widget{min-width:42em;}""")
        cw.setLayout(layout)
        self.setCentralWidget(cw)
        self.setFocusPolicy(Qt.StrongFocus)

    def _fill_normalizer_layout(self, index):
        text = self.sender().currentText()
        if text not in self._matype_items:
            QMessageBox.critical(self, 'Error', 'Enter a valid magnet name!')
            self._sb_current.setEnabled(False)
            self._sb_strength.setEnabled(False)
            self._lb_energy.setVisible(False)
            self._sb_energy.setVisible(False)
            self._lb_quadfam_kl.setVisible(False)
            self._sb_quadfam_kl.setVisible(False)
            return

        # Reset all fields
        self._sb_current.setValue(0)
        self._sb_strength.setValue(0)
        self._sb_energy.setValue(0)
        self._sb_quadfam_kl.setValue(0)

        # Create normalizer and update limits if text is a valid magnet
        if index != 0:
            self._create_normalizer(text)

        # Update interface
        enbl_current = False
        enbl_strength = False
        show_energy = False
        show_quadfam_kl = False
        if Dipole.match(text):
            enbl_current = True
            enbl_strength = True
        elif Trim.match(text):
            enbl_current = True
            enbl_strength = True
            show_energy = True
            show_quadfam_kl = True
        elif Multipole.match(text) or PulsedMagnet.match(text):
            enbl_current = True
            enbl_strength = True
            show_energy = True
        self._sb_current.setEnabled(enbl_current)
        self._sb_strength.setEnabled(enbl_strength)
        self._lb_energy.setVisible(show_energy)
        self._sb_energy.setVisible(show_energy)
        self._lb_quadfam_kl.setVisible(show_quadfam_kl)
        self._sb_quadfam_kl.setVisible(show_quadfam_kl)

        # Update Strength label
        if Dipole.match(text):
            text_strength = 'Energy [GeV]: '
        elif Quadrupole.match(text):
            text_strength = 'KL [1/m]: '
        elif Trim.match(text):
            text_strength = 'KL (Fam + Trim) [1/m]: '
        elif Sextupole.match(text):
            text_strength = 'SL [1/m²]: '
        elif Corrector.match(text):
            text_strength = 'Kick [urad]: '
        elif PulsedMagnet.match(text):
            text_strength = 'Kick [mrad]: '
        else:
            text_strength = 'Strength: '
        self._lb_strength.setText(text_strength)

        # update limits, if necessary
        self._update_inputs()

    def _create_normalizer(self, maname):
        self._normalizer = NormalizerFactory.create(maname)

    def _update_inputs(self):
        sender = self.sender().objectName()
        if 'strength' in sender:
            self._last_edited = 's'
        elif 'current' in sender:
            self._last_edited = 'c'

        strength = self._sb_strength.value()
        current = self._sb_current.value()
        quadfam_kl = None
        energy = None
        if self._sb_quadfam_kl.isVisible():
            quadfam_kl = self._sb_quadfam_kl.value()
        if self._sb_energy.isVisible():
            energy = self._sb_energy.value()

        if self._last_edited == 's':
            current = self._conv_strength2curr(strength, energy, quadfam_kl)
            self._sb_current.setValue(current)
        else:
            strength = self._conv_curr2strength(current, energy, quadfam_kl)
            self._sb_strength.setValue(strength)

    def _conv_curr2strength(self, current, energy=None, quadfam_kl=None):
        if quadfam_kl is not None:
            strength = self._normalizer.conv_current_2_strength(
                currents=current, strengths_dipole=energy,
                strengths_family=quadfam_kl)
        elif energy is not None:
            strength = self._normalizer.conv_current_2_strength(
                currents=current, strengths_dipole=energy)
        else:
            strength = self._normalizer.conv_current_2_strength(
                currents=current)
        return strength

    def _conv_strength2curr(self, strength, energy=None, quadfam_kl=None):
        if quadfam_kl is not None:
            current = self._normalizer.conv_strength_2_current(
                strengths=strength, strengths_dipole=energy,
                strengths_family=quadfam_kl)
        elif energy is not None:
            current = self._normalizer.conv_strength_2_current(
                strengths=strength, strengths_dipole=energy)
        else:
            current = self._normalizer.conv_strength_2_current(
                strengths=strength)
        return current
Beispiel #44
0
    def add_color_scheme_stack(self, scheme_name, custom=False):
        """Add a stack for a given scheme and connects the CONF values."""
        color_scheme_groups = [(_('Text'), [
            "normal",
            "comment",
            "string",
            "number",
            "keyword",
            "builtin",
            "definition",
            "instance",
        ]),
                               (_('Highlight'), [
                                   "currentcell", "currentline", "occurrence",
                                   "matched_p", "unmatched_p", "ctrlclick"
                               ]),
                               (_('Background'), ["background", "sideareas"])]

        parent = self.parent
        line_edit = parent.create_lineedit(_("Scheme name:"),
                                           '{0}/name'.format(scheme_name))

        self.widgets[scheme_name] = {}

        # Widget setup
        line_edit.label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.setWindowTitle(_('Color scheme editor'))

        # Layout
        name_layout = QHBoxLayout()
        name_layout.addWidget(line_edit.label)
        name_layout.addWidget(line_edit.textbox)
        self.scheme_name_textbox[scheme_name] = line_edit.textbox

        if not custom:
            line_edit.textbox.setDisabled(True)
        if not self.isVisible():
            line_edit.setVisible(False)

        cs_layout = QVBoxLayout()
        cs_layout.addLayout(name_layout)

        h_layout = QHBoxLayout()
        v_layout = QVBoxLayout()

        for index, item in enumerate(color_scheme_groups):
            group_name, keys = item
            group_layout = QGridLayout()

            for row, key in enumerate(keys):
                option = "{0}/{1}".format(scheme_name, key)
                value = self.parent.get_option(option)
                name = syntaxhighlighters.COLOR_SCHEME_KEYS[key]

                if is_text_string(value):
                    label, clayout = parent.create_coloredit(
                        name,
                        option,
                        without_layout=True,
                    )
                    label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    group_layout.addWidget(label, row + 1, 0)
                    group_layout.addLayout(clayout, row + 1, 1)

                    # Needed to update temp scheme to obtain instant preview
                    self.widgets[scheme_name][key] = [clayout]
                else:
                    label, clayout, cb_bold, cb_italic = parent.create_scedit(
                        name,
                        option,
                        without_layout=True,
                    )
                    label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    group_layout.addWidget(label, row + 1, 0)
                    group_layout.addLayout(clayout, row + 1, 1)
                    group_layout.addWidget(cb_bold, row + 1, 2)
                    group_layout.addWidget(cb_italic, row + 1, 3)

                    # Needed to update temp scheme to obtain instant preview
                    self.widgets[scheme_name][key] = [
                        clayout, cb_bold, cb_italic
                    ]

            group_box = QGroupBox(group_name)
            group_box.setLayout(group_layout)

            if index == 0:
                h_layout.addWidget(group_box)
            else:
                v_layout.addWidget(group_box)

        h_layout.addLayout(v_layout)
        cs_layout.addLayout(h_layout)

        stackitem = QWidget()
        stackitem.setLayout(cs_layout)
        self.stack.addWidget(stackitem)
        self.order.append(scheme_name)
Beispiel #45
0
    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)
Beispiel #46
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Completion ---
        # Completion group
        self.completion_box = newcb(_("Enable code completion"),
                                    'code_completion')
        self.completion_hint_box = newcb(_("Show completion details"),
                                         'completions_hint',
                                         section='editor')
        self.completions_hint_after_ms = self.create_spinbox(
            _("Show completion detail after keyboard idle (ms):"),
            None,
            'completions_hint_after_ms',
            min_=0,
            max_=5000,
            step=10,
            tip=_("Default is 500"),
            section='editor')
        self.automatic_completion_box = newcb(_("Show completions on the fly"),
                                              'automatic_completions',
                                              section='editor')
        self.completions_after_characters = self.create_spinbox(
            _("Show automatic completions after characters entered:"),
            None,
            'automatic_completions_after_chars',
            min_=1,
            step=1,
            tip=_("Default is 3"),
            section='editor')
        self.completions_after_ms = self.create_spinbox(
            _("Show automatic completions after keyboard idle (ms):"),
            None,
            'automatic_completions_after_ms',
            min_=0,
            max_=5000,
            step=10,
            tip=_("Default is 300"),
            section='editor')
        code_snippets_box = newcb(_("Enable code snippets"), 'code_snippets')

        completion_layout = QGridLayout()
        completion_layout.addWidget(self.completion_box, 0, 0)
        completion_layout.addWidget(self.completion_hint_box, 1, 0)
        completion_layout.addWidget(self.completions_hint_after_ms.plabel, 2,
                                    0)
        completion_layout.addWidget(self.completions_hint_after_ms.spinbox, 2,
                                    1)
        completion_layout.addWidget(self.automatic_completion_box, 3, 0)
        completion_layout.addWidget(self.completions_after_characters.plabel,
                                    4, 0)
        completion_layout.addWidget(self.completions_after_characters.spinbox,
                                    4, 1)
        completion_layout.addWidget(self.completions_after_ms.plabel, 5, 0)
        completion_layout.addWidget(self.completions_after_ms.spinbox, 5, 1)
        completion_layout.addWidget(code_snippets_box, 6, 0)
        completion_layout.setColumnStretch(2, 6)
        completion_widget = QWidget()
        completion_widget.setLayout(completion_layout)

        self.completion_box.toggled.connect(self.check_completion_options)
        self.automatic_completion_box.toggled.connect(
            self.check_completion_options)

        # --- Introspection ---
        # Introspection group
        introspection_group = QGroupBox(_("Basic features"))
        goto_definition_box = newcb(
            _("Enable Go to definition"),
            'jedi_definition',
            tip=_("If enabled, left-clicking on an object name while \n"
                  "pressing the {} key will go to that object's definition\n"
                  "(if resolved).").format(self.CTRL))
        follow_imports_box = newcb(
            _("Follow imports when going to a "
              "definition"), 'jedi_definition/follow_imports')
        show_signature_box = newcb(_("Show calltips"), 'jedi_signature_help')
        enable_hover_hints_box = newcb(
            _("Enable hover hints"),
            'enable_hover_hints',
            tip=_("If enabled, hovering the mouse pointer over an object\n"
                  "name will display that object's signature and/or\n"
                  "docstring (if present)."))
        introspection_layout = QVBoxLayout()
        introspection_layout.addWidget(goto_definition_box)
        introspection_layout.addWidget(follow_imports_box)
        introspection_layout.addWidget(show_signature_box)
        introspection_layout.addWidget(enable_hover_hints_box)
        introspection_group.setLayout(introspection_layout)

        goto_definition_box.toggled.connect(follow_imports_box.setEnabled)

        # Advanced group
        advanced_group = QGroupBox(_("Advanced"))
        modules_textedit = self.create_textedit(
            _("Preload the following modules to make completion faster "
              "and more accurate:"), 'preload_modules')
        if is_dark_interface():
            modules_textedit.textbox.setStyleSheet(
                "border: 1px solid #32414B;")

        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(modules_textedit)
        advanced_group.setLayout(advanced_layout)

        # --- Linting ---
        # Linting options
        linting_label = QLabel(
            _("Spyder can optionally highlight syntax "
              "errors and possible problems with your "
              "code in the editor."))
        linting_label.setOpenExternalLinks(True)
        linting_label.setWordWrap(True)
        linting_check = self.create_checkbox(_("Enable basic linting"),
                                             'pyflakes')
        underline_errors_box = newcb(_("Underline errors and warnings"),
                                     'underline_errors',
                                     section='editor')
        linting_complexity_box = self.create_checkbox(
            _("Enable complexity linting with the Mccabe package"), 'mccabe')

        # Linting layout
        linting_layout = QVBoxLayout()
        linting_layout.addWidget(linting_label)
        linting_layout.addWidget(linting_check)
        linting_layout.addWidget(underline_errors_box)
        linting_layout.addWidget(linting_complexity_box)
        linting_widget = QWidget()
        linting_widget.setLayout(linting_layout)

        linting_check.toggled.connect(underline_errors_box.setEnabled)

        # --- Code style and formatting tab ---
        # Code style label
        pep_url = (
            '<a href="https://www.python.org/dev/peps/pep-0008">PEP 8</a>')
        code_style_codes_url = _(
            "<a href='http://pycodestyle.pycqa.org/en/stable"
            "/intro.html#error-codes'>pycodestyle error codes</a>")
        code_style_label = QLabel(
            _("Spyder can use pycodestyle to analyze your code for "
              "conformance to the {} convention. You can also "
              "manually show or hide specific warnings by their "
              "{}.").format(pep_url, code_style_codes_url))
        code_style_label.setOpenExternalLinks(True)
        code_style_label.setWordWrap(True)

        # Code style checkbox
        self.code_style_check = self.create_checkbox(
            _("Enable code style linting"), 'pycodestyle')

        # Code style options
        self.code_style_filenames_match = self.create_lineedit(
            _("Only check filenames matching these patterns:"),
            'pycodestyle/filename',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Check Python files: *.py"))
        self.code_style_exclude = self.create_lineedit(
            _("Exclude files or directories matching these patterns:"),
            'pycodestyle/exclude',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Exclude all test files: (?!test_).*\\.py"))
        code_style_select = self.create_lineedit(
            _("Show the following errors or warnings:").format(
                code_style_codes_url),
            'pycodestyle/select',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Example codes: E113, W391"))
        code_style_ignore = self.create_lineedit(
            _("Ignore the following errors or warnings:"),
            'pycodestyle/ignore',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Example codes: E201, E303"))
        self.code_style_max_line_length = self.create_spinbox(
            _("Maximum allowed line length:"),
            None,
            'pycodestyle/max_line_length',
            min_=10,
            max_=500,
            step=1,
            tip=_("Default is 79"))

        vertical_line_box = newcb(_("Show vertical line at that length"),
                                  'edge_line',
                                  section='editor')

        # Code style layout
        code_style_g_layout = QGridLayout()
        code_style_g_layout.addWidget(self.code_style_filenames_match.label, 1,
                                      0)
        code_style_g_layout.addWidget(self.code_style_filenames_match.textbox,
                                      1, 1)
        code_style_g_layout.addWidget(self.code_style_exclude.label, 2, 0)
        code_style_g_layout.addWidget(self.code_style_exclude.textbox, 2, 1)
        code_style_g_layout.addWidget(code_style_select.label, 3, 0)
        code_style_g_layout.addWidget(code_style_select.textbox, 3, 1)
        code_style_g_layout.addWidget(code_style_ignore.label, 4, 0)
        code_style_g_layout.addWidget(code_style_ignore.textbox, 4, 1)

        # Set Code style options enabled/disabled
        code_style_g_widget = QWidget()
        code_style_g_widget.setLayout(code_style_g_layout)
        code_style_g_widget.setEnabled(self.get_option('pycodestyle'))
        self.code_style_check.toggled.connect(code_style_g_widget.setEnabled)

        # Code style layout
        code_style_group = QGroupBox(_("Code style"))
        code_style_layout = QVBoxLayout()
        code_style_layout.addWidget(code_style_label)
        code_style_layout.addWidget(self.code_style_check)
        code_style_layout.addWidget(code_style_g_widget)
        code_style_group.setLayout(code_style_layout)

        # Maximum allowed line length layout
        line_length_group = QGroupBox(_("Line length"))
        line_length_layout = QVBoxLayout()
        line_length_layout.addWidget(self.code_style_max_line_length)
        line_length_layout.addWidget(vertical_line_box)
        line_length_group.setLayout(line_length_layout)

        # Code formatting label
        autopep8_url = (
            "<a href='https://github.com/hhatto/autopep8'>Autopep8</a>")
        yapf_url = ("<a href='https://github.com/google/yapf'>Yapf</a>")
        black_url = (
            "<a href='https://black.readthedocs.io/en/stable'>Black</a>")
        code_fmt_label = QLabel(
            _("Spyder can use {0}, {1} or {2} to format your code for "
              "conformance to the {3} convention.").format(
                  autopep8_url, yapf_url, black_url, pep_url))
        code_fmt_label.setOpenExternalLinks(True)
        code_fmt_label.setWordWrap(True)

        # Code formatting providers
        code_fmt_provider = self.create_combobox(
            _("Choose the code formatting provider: "),
            (("autopep8", 'autopep8'), ("black", 'black')), 'formatting')

        # Autoformat on save
        format_on_save_box = newcb(
            _("Autoformat files on save"),
            'format_on_save',
            tip=_("If enabled, autoformatting will take place when "
                  "saving a file"))

        # Code formatting layout
        code_fmt_group = QGroupBox(_("Code formatting"))
        code_fmt_layout = QVBoxLayout()
        code_fmt_layout.addWidget(code_fmt_label)
        code_fmt_layout.addWidget(code_fmt_provider)
        code_fmt_layout.addWidget(format_on_save_box)
        code_fmt_group.setLayout(code_fmt_layout)

        code_style_widget = QWidget()
        code_style_fmt_layout = QVBoxLayout()
        code_style_fmt_layout.addWidget(code_style_group)
        code_style_fmt_layout.addWidget(code_fmt_group)
        code_style_fmt_layout.addWidget(line_length_group)
        code_style_widget.setLayout(code_style_fmt_layout)

        # --- Docstring tab ---
        # Docstring style label
        numpy_url = ("<a href='https://numpydoc.readthedocs.io/en/"
                     "latest/format.html'>Numpy</a>")
        pep257_url = (
            "<a href='https://www.python.org/dev/peps/pep-0257/'>PEP 257</a>")
        docstring_style_codes = _(
            "<a href='http://www.pydocstyle.org/en/stable"
            "/error_codes.html'>page</a>")
        docstring_style_label = QLabel(
            _("Here you can decide if you want to perform style analysis on "
              "your docstrings according to the {} or {} conventions. You can "
              "also decide if you want to show or ignore specific errors, "
              "according to the codes found on this {}.").format(
                  numpy_url, pep257_url, docstring_style_codes))
        docstring_style_label.setOpenExternalLinks(True)
        docstring_style_label.setWordWrap(True)

        # Docstring style checkbox
        self.docstring_style_check = self.create_checkbox(
            _("Enable docstring style linting"), 'pydocstyle')

        # Docstring style options
        docstring_style_convention = self.create_combobox(
            _("Choose the convention used to lint docstrings: "),
            (("Numpy", 'numpy'), ("PEP 257", 'pep257'), ("Custom", 'custom')),
            'pydocstyle/convention')
        self.docstring_style_select = self.create_lineedit(
            _("Show the following errors:"),
            'pydocstyle/select',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Example codes: D413, D414"))
        self.docstring_style_ignore = self.create_lineedit(
            _("Ignore the following errors:"),
            'pydocstyle/ignore',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Example codes: D107, D402"))
        self.docstring_style_match = self.create_lineedit(
            _("Only check filenames matching these patterns:"),
            'pydocstyle/match',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Skip test files: (?!test_).*\\.py"))
        self.docstring_style_match_dir = self.create_lineedit(
            _("Only check in directories matching these patterns:"),
            'pydocstyle/match_dir',
            alignment=Qt.Horizontal,
            word_wrap=False,
            placeholder=_("Skip dot directories: [^\\.].*"))

        # Custom option handling
        docstring_style_convention.combobox.currentTextChanged.connect(
            self.setup_docstring_style_convention)
        current_convention = docstring_style_convention.combobox.currentText()
        self.setup_docstring_style_convention(current_convention)

        # Docstring style layout
        docstring_style_g_layout = QGridLayout()
        docstring_style_g_layout.addWidget(docstring_style_convention.label, 1,
                                           0)
        docstring_style_g_layout.addWidget(docstring_style_convention.combobox,
                                           1, 1)
        docstring_style_g_layout.addWidget(self.docstring_style_select.label,
                                           2, 0)
        docstring_style_g_layout.addWidget(self.docstring_style_select.textbox,
                                           2, 1)
        docstring_style_g_layout.addWidget(self.docstring_style_ignore.label,
                                           3, 0)
        docstring_style_g_layout.addWidget(self.docstring_style_ignore.textbox,
                                           3, 1)
        docstring_style_g_layout.addWidget(self.docstring_style_match.label, 4,
                                           0)
        docstring_style_g_layout.addWidget(self.docstring_style_match.textbox,
                                           4, 1)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match_dir.label, 5, 0)
        docstring_style_g_layout.addWidget(
            self.docstring_style_match_dir.textbox, 5, 1)

        # Set Docstring style options enabled/disabled
        docstring_style_g_widget = QWidget()
        docstring_style_g_widget.setLayout(docstring_style_g_layout)
        docstring_style_g_widget.setEnabled(self.get_option('pydocstyle'))
        self.docstring_style_check.toggled.connect(
            docstring_style_g_widget.setEnabled)

        # Docstring style layout
        docstring_style_layout = QVBoxLayout()
        docstring_style_layout.addWidget(docstring_style_label)
        docstring_style_layout.addWidget(self.docstring_style_check)
        docstring_style_layout.addWidget(docstring_style_g_widget)

        docstring_style_widget = QWidget()
        docstring_style_widget.setLayout(docstring_style_layout)

        # --- Snippets tab ---
        self.snippets_language = 'python'
        grammar_url = (
            "<a href=\"{0}/specifications/specification-current#snippet_syntax\">"
            "{1}</a>".format(LSP_URL, _('the LSP grammar')))
        snippets_info_label = QLabel(
            _("Spyder allows to define custom completion snippets to use "
              "in addition to the ones offered by the Language Server "
              "Protocol (LSP). Each snippet should follow {}.<br><br> "
              "<b>Note:</b> All changes will be effective only when applying "
              "the settings").format(grammar_url))
        snippets_info_label.setOpenExternalLinks(True)
        snippets_info_label.setWordWrap(True)
        snippets_info_label.setAlignment(Qt.AlignJustify)

        self.snippets_language_cb = QComboBox(self)
        self.snippets_language_cb.setToolTip(
            _('Programming language provided by the LSP server'))
        self.snippets_language_cb.addItems(LSP_LANGUAGES_PY)
        self.snippets_language_cb.setCurrentIndex(PYTHON_POS)
        self.snippets_language_cb.currentTextChanged.connect(
            self.change_language_snippets)

        snippet_lang_group = QGroupBox(_('Language'))
        snippet_lang_layout = QVBoxLayout()
        snippet_lang_layout.addWidget(self.snippets_language_cb)
        snippet_lang_group.setLayout(snippet_lang_layout)

        self.snippets_proxy = SnippetModelsProxy()
        self.snippets_table = SnippetTable(self,
                                           self.snippets_proxy,
                                           language=self.snippets_language)
        self.snippets_table.setMaximumHeight(180)

        snippet_table_group = QGroupBox(_('Available snippets'))
        snippet_table_layout = QVBoxLayout()
        snippet_table_layout.addWidget(self.snippets_table)
        snippet_table_group.setLayout(snippet_table_layout)

        # Buttons
        self.reset_snippets_btn = QPushButton(_("Reset to default values"))
        self.new_snippet_btn = QPushButton(_("Create a new snippet"))
        self.delete_snippet_btn = QPushButton(
            _("Delete currently selected snippet"))
        self.delete_snippet_btn.setEnabled(False)
        self.export_snippets_btn = QPushButton(_("Export snippets to JSON"))
        self.import_snippets_btn = QPushButton(_("Import snippets from JSON"))

        # Slots connected to buttons
        self.new_snippet_btn.clicked.connect(self.create_new_snippet)
        self.reset_snippets_btn.clicked.connect(self.reset_default_snippets)
        self.delete_snippet_btn.clicked.connect(self.delete_snippet)
        self.export_snippets_btn.clicked.connect(self.export_snippets)
        self.import_snippets_btn.clicked.connect(self.import_snippets)

        # Buttons layout
        btns = [
            self.new_snippet_btn, self.delete_snippet_btn,
            self.reset_snippets_btn, self.export_snippets_btn,
            self.import_snippets_btn
        ]
        sn_buttons_layout = QGridLayout()
        for i, btn in enumerate(btns):
            sn_buttons_layout.addWidget(btn, i, 1)
        sn_buttons_layout.setColumnStretch(0, 1)
        sn_buttons_layout.setColumnStretch(1, 2)
        sn_buttons_layout.setColumnStretch(2, 1)

        # Snippets layout
        snippets_layout = QVBoxLayout()
        snippets_layout.addWidget(snippets_info_label)
        snippets_layout.addWidget(snippet_lang_group)
        snippets_layout.addWidget(snippet_table_group)
        snippets_layout.addLayout(sn_buttons_layout)

        snippets_widget = QWidget()
        snippets_widget.setLayout(snippets_layout)

        # --- Advanced tab ---
        # Clients group
        clients_group = QGroupBox(_("Providers"))
        self.kite_enabled = newcb(_("Enable Kite "
                                    "(if the Kite engine is running)"),
                                  'enable',
                                  section='kite')
        self.fallback_enabled = newcb(_("Enable fallback completions"),
                                      'enable',
                                      section='fallback-completions')
        self.completions_wait_for_ms = self.create_spinbox(
            _("Time to wait for all providers to return (ms):"),
            None,
            'completions_wait_for_ms',
            min_=0,
            max_=5000,
            step=10,
            tip=_("Beyond this timeout, "
                  "the first available provider will be returned"),
            section='editor')

        clients_layout = QVBoxLayout()
        clients_layout.addWidget(self.kite_enabled)
        clients_layout.addWidget(self.fallback_enabled)
        clients_layout.addWidget(self.completions_wait_for_ms)
        clients_group.setLayout(clients_layout)

        kite_layout = QVBoxLayout()
        self.kite_cta = self.create_checkbox(_(
            "Notify me when Kite can provide missing completions"
            " (but is unavailable)"),
                                             'call_to_action',
                                             section='kite')
        kite_layout.addWidget(self.kite_cta)
        kite_group = QGroupBox(_('Kite configuration'))
        kite_group.setLayout(kite_layout)

        # Advanced label
        lsp_advanced_group = QGroupBox(
            _('Python Language Server configuration'))
        advanced_label = QLabel(
            _("<b>Warning</b>: Only modify these values if "
              "you know what you're doing!"))
        advanced_label.setWordWrap(True)
        advanced_label.setAlignment(Qt.AlignJustify)

        # Advanced settings checkbox
        self.advanced_options_check = self.create_checkbox(
            _("Enable advanced settings"), 'advanced/enabled')

        # Advanced options
        self.advanced_module = self.create_lineedit(
            _("Module for the Python language server: "),
            'advanced/module',
            alignment=Qt.Horizontal,
            word_wrap=False)
        self.advanced_host = self.create_lineedit(
            _("IP Address and port to bind the server to: "),
            'advanced/host',
            alignment=Qt.Horizontal,
            word_wrap=False)
        self.advanced_port = self.create_spinbox(":",
                                                 "",
                                                 'advanced/port',
                                                 min_=1,
                                                 max_=65535,
                                                 step=1)
        self.external_server = self.create_checkbox(
            _("This is an external server"), 'advanced/external')
        self.use_stdio = self.create_checkbox(
            _("Use stdio pipes to communicate with server"), 'advanced/stdio')
        self.use_stdio.stateChanged.connect(self.disable_tcp)
        self.external_server.stateChanged.connect(self.disable_stdio)

        # Advanced layout
        advanced_g_layout = QGridLayout()
        advanced_g_layout.addWidget(self.advanced_module.label, 1, 0)
        advanced_g_layout.addWidget(self.advanced_module.textbox, 1, 1)
        advanced_g_layout.addWidget(self.advanced_host.label, 2, 0)

        advanced_host_port_g_layout = QGridLayout()
        advanced_host_port_g_layout.addWidget(self.advanced_host.textbox, 1, 0)
        advanced_host_port_g_layout.addWidget(self.advanced_port.plabel, 1, 1)
        advanced_host_port_g_layout.addWidget(self.advanced_port.spinbox, 1, 2)
        advanced_g_layout.addLayout(advanced_host_port_g_layout, 2, 1)

        # External server and stdio options layout
        advanced_server_layout = QVBoxLayout()
        advanced_server_layout.addWidget(self.external_server)
        advanced_server_layout.addWidget(self.use_stdio)

        advanced_options_layout = QVBoxLayout()
        advanced_options_layout.addLayout(advanced_g_layout)
        advanced_options_layout.addLayout(advanced_server_layout)

        # Set advanced options enabled/disabled
        advanced_options_widget = QWidget()
        advanced_options_widget.setLayout(advanced_options_layout)
        advanced_options_widget.setEnabled(self.get_option('advanced/enabled'))
        self.advanced_options_check.toggled.connect(
            advanced_options_widget.setEnabled)
        self.advanced_options_check.toggled.connect(self.show_advanced_warning)

        # Advanced options layout
        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(advanced_label)
        advanced_layout.addWidget(self.advanced_options_check)
        advanced_layout.addWidget(advanced_options_widget)

        lsp_advanced_group.setLayout(advanced_layout)

        # --- Other servers tab ---
        # Section label
        servers_label = QLabel(
            _("Spyder uses the <a href=\"{lsp_url}\">Language Server "
              "Protocol</a> to provide code completion and linting "
              "for its Editor. Here, you can setup and configure LSP servers "
              "for languages other than Python, so Spyder can provide such "
              "features for those languages as well.").format(lsp_url=LSP_URL))
        servers_label.setOpenExternalLinks(True)
        servers_label.setWordWrap(True)
        servers_label.setAlignment(Qt.AlignJustify)

        # Servers table
        table_group = QGroupBox(_('Available servers:'))
        self.table = LSPServerTable(self, text_color=ima.MAIN_FG_COLOR)
        self.table.setMaximumHeight(150)
        table_layout = QVBoxLayout()
        table_layout.addWidget(self.table)
        table_group.setLayout(table_layout)

        # Buttons
        self.reset_btn = QPushButton(_("Reset to default values"))
        self.new_btn = QPushButton(_("Set up a new server"))
        self.delete_btn = QPushButton(_("Delete currently selected server"))
        self.delete_btn.setEnabled(False)

        # Slots connected to buttons
        self.new_btn.clicked.connect(self.create_new_server)
        self.reset_btn.clicked.connect(self.reset_to_default)
        self.delete_btn.clicked.connect(self.delete_server)

        # Buttons layout
        btns = [self.new_btn, self.delete_btn, self.reset_btn]
        buttons_layout = QGridLayout()
        for i, btn in enumerate(btns):
            buttons_layout.addWidget(btn, i, 1)
        buttons_layout.setColumnStretch(0, 1)
        buttons_layout.setColumnStretch(1, 2)
        buttons_layout.setColumnStretch(2, 1)

        # Combined layout
        servers_widget = QWidget()
        servers_layout = QVBoxLayout()
        servers_layout.addSpacing(-10)
        servers_layout.addWidget(servers_label)
        servers_layout.addWidget(table_group)
        servers_layout.addSpacing(10)
        servers_layout.addLayout(buttons_layout)
        servers_widget.setLayout(servers_layout)

        # --- Tabs organization ---
        self.tabs = QTabWidget()
        self.tabs.addTab(self.create_tab(completion_widget), _('Completion'))
        self.tabs.addTab(self.create_tab(linting_widget), _('Linting'))
        self.tabs.addTab(self.create_tab(introspection_group, advanced_group),
                         _('Introspection'))
        self.tabs.addTab(self.create_tab(code_style_widget),
                         _('Code style and formatting'))
        self.tabs.addTab(self.create_tab(docstring_style_widget),
                         _('Docstring style'))
        self.tabs.addTab(self.create_tab(snippets_widget), _('Snippets'))
        self.tabs.addTab(
            self.create_tab(clients_group, lsp_advanced_group, kite_group),
            _('Advanced'))
        self.tabs.addTab(self.create_tab(servers_widget), _('Other languages'))

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.tabs)
        self.setLayout(vlayout)
Beispiel #47
0
class ProjectDialog(QDialog):
    """Project creation dialog."""

    # path, type, packages
    sig_project_creation_requested = Signal(object, object, object)

    def __init__(self, parent):
        """Project creation dialog."""
        super(ProjectDialog, self).__init__(parent=parent)

        # Variables
        current_python_version = '.'.join([
            to_text_string(sys.version_info[0]),
            to_text_string(sys.version_info[1])
        ])
        python_versions = ['2.7', '3.4', '3.5']
        if current_python_version not in python_versions:
            python_versions.append(current_python_version)
            python_versions = sorted(python_versions)

        self.project_name = None
        self.location = get_home_dir()

        # Widgets
        self.groupbox = QGroupBox()
        self.radio_new_dir = QRadioButton(_("New directory"))
        self.radio_from_dir = QRadioButton(_("Existing directory"))

        self.label_project_name = QLabel(_('Project name'))
        self.label_location = QLabel(_('Location'))
        self.label_project_type = QLabel(_('Project type'))
        self.label_python_version = QLabel(_('Python version'))

        self.text_project_name = QLineEdit()
        self.text_location = QLineEdit(get_home_dir())
        self.combo_project_type = QComboBox()
        self.combo_python_version = QComboBox()

        self.button_select_location = QToolButton()
        self.button_cancel = QPushButton(_('Cancel'))
        self.button_create = QPushButton(_('Create'))

        self.bbox = QDialogButtonBox(Qt.Horizontal)
        self.bbox.addButton(self.button_cancel, QDialogButtonBox.ActionRole)
        self.bbox.addButton(self.button_create, QDialogButtonBox.ActionRole)

        # Widget setup
        self.combo_python_version.addItems(python_versions)
        self.radio_new_dir.setChecked(True)
        self.text_location.setEnabled(True)
        self.text_location.setReadOnly(True)
        self.button_select_location.setIcon(get_std_icon('DirOpenIcon'))
        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)
        self.button_create.setEnabled(False)
        self.combo_project_type.addItems(self._get_project_types())
        self.combo_python_version.setCurrentIndex(
            python_versions.index(current_python_version))
        self.setWindowTitle(_('Create new project'))
        self.setFixedWidth(500)
        self.label_python_version.setVisible(False)
        self.combo_python_version.setVisible(False)

        # Layouts
        layout_top = QHBoxLayout()
        layout_top.addWidget(self.radio_new_dir)
        layout_top.addWidget(self.radio_from_dir)
        layout_top.addStretch(1)
        self.groupbox.setLayout(layout_top)

        layout_grid = QGridLayout()
        layout_grid.addWidget(self.label_project_name, 0, 0)
        layout_grid.addWidget(self.text_project_name, 0, 1, 1, 2)
        layout_grid.addWidget(self.label_location, 1, 0)
        layout_grid.addWidget(self.text_location, 1, 1)
        layout_grid.addWidget(self.button_select_location, 1, 2)
        layout_grid.addWidget(self.label_project_type, 2, 0)
        layout_grid.addWidget(self.combo_project_type, 2, 1, 1, 2)
        layout_grid.addWidget(self.label_python_version, 3, 0)
        layout_grid.addWidget(self.combo_python_version, 3, 1, 1, 2)

        layout = QVBoxLayout()
        layout.addWidget(self.groupbox)
        layout.addSpacing(10)
        layout.addLayout(layout_grid)
        layout.addStretch()
        layout.addSpacing(20)
        layout.addWidget(self.bbox)

        self.setLayout(layout)

        # Signals and slots
        self.button_select_location.clicked.connect(self.select_location)
        self.button_create.clicked.connect(self.create_project)
        self.button_cancel.clicked.connect(self.close)
        self.radio_from_dir.clicked.connect(self.update_location)
        self.radio_new_dir.clicked.connect(self.update_location)
        self.text_project_name.textChanged.connect(self.update_location)

    def _get_project_types(self):
        """Get all available project types."""
        project_types = get_available_project_types()
        projects = []

        for project in project_types:
            projects.append(project.PROJECT_TYPE_NAME)

        return projects

    def select_location(self):
        """Select directory."""
        location = getexistingdirectory(self, _("Select directory"),
                                        self.location)
        if location:
            if is_writable(location):
                self.location = location
                self.update_location()

    def update_location(self, text=''):
        """Update text of location."""
        self.text_project_name.setEnabled(self.radio_new_dir.isChecked())
        name = self.text_project_name.text().strip()

        if name and self.radio_new_dir.isChecked():
            path = osp.join(self.location, name)
            self.button_create.setDisabled(os.path.isdir(path))
        elif self.radio_from_dir.isChecked():
            self.button_create.setEnabled(True)
            path = self.location
        else:
            self.button_create.setEnabled(False)
            path = self.location

        self.text_location.setText(path)

    def create_project(self):
        """Create project."""
        packages = [
            'python={0}'.format(self.combo_python_version.currentText())
        ]
        self.sig_project_creation_requested.emit(
            self.text_location.text(), self.combo_project_type.currentText(),
            packages)
        self.accept()
Beispiel #48
0
    def setup_page(self):
        newcb = self.create_checkbox

        # Python executable Group
        pyexec_group = QGroupBox(_("Python interpreter"))
        pyexec_bg = QButtonGroup(pyexec_group)
        pyexec_label = QLabel(_("Select the Python interpreter for all Spyder "
                                "consoles"))
        self.def_exec_radio = self.create_radiobutton(
            _("Default (i.e. the same as Spyder's)"),
            'default',
            button_group=pyexec_bg,
        )
        self.cus_exec_radio = self.create_radiobutton(
            _("Use the following Python interpreter:"),
            'custom',
            button_group=pyexec_bg,
        )

        if os.name == 'nt':
            filters = _("Executables")+" (*.exe)"
        else:
            filters = None

        pyexec_layout = QVBoxLayout()
        pyexec_layout.addWidget(pyexec_label)
        pyexec_layout.addWidget(self.def_exec_radio)
        pyexec_layout.addWidget(self.cus_exec_radio)
        self.validate_custom_interpreters_list()
        self.cus_exec_combo = self.create_file_combobox(
            _('Recent custom interpreters'),
            self.get_option('custom_interpreters_list'),
            'custom_interpreter',
            filters=filters,
            default_line_edit=True,
            adjust_to_contents=True,
            validate_callback=programs.is_python_interpreter,
        )
        self.def_exec_radio.toggled.connect(self.cus_exec_combo.setDisabled)
        self.cus_exec_radio.toggled.connect(self.cus_exec_combo.setEnabled)
        pyexec_layout.addWidget(self.cus_exec_combo)
        pyexec_group.setLayout(pyexec_layout)

        self.pyexec_edit = self.cus_exec_combo.combobox.lineEdit()

        # UMR Group
        umr_group = QGroupBox(_("User Module Reloader (UMR)"))
        umr_label = QLabel(_("UMR forces Python to reload modules which were "
                             "imported when executing a file in a Python or "
                             "IPython console with the <i>runfile</i> "
                             "function."))
        umr_label.setWordWrap(True)
        umr_enabled_box = newcb(
            _("Enable UMR"),
            'umr/enabled',
            msg_if_enabled=True,
            msg_warning=_(
                "This option will enable the User Module Reloader (UMR) "
                "in Python/IPython consoles. UMR forces Python to "
                "reload deeply modules during import when running a "
                "Python script using the Spyder's builtin function "
                "<b>runfile</b>."
                "<br><br><b>1.</b> UMR may require to restart the "
                "console in which it will be called "
                "(otherwise only newly imported modules will be "
                "reloaded when executing files)."
                "<br><br><b>2.</b> If errors occur when re-running a "
                "PyQt-based program, please check that the Qt objects "
                "are properly destroyed (e.g. you may have to use the "
                "attribute <b>Qt.WA_DeleteOnClose</b> on your main "
                "window, using the <b>setAttribute</b> method)"
            ),
        )
        umr_verbose_box = newcb(
            _("Show reloaded modules list"),
            'umr/verbose',
            msg_info=_("Please note that these changes will "
                       "be applied only to new consoles"),
        )
        umr_namelist_btn = QPushButton(
            _("Set UMR excluded (not reloaded) modules"))
        umr_namelist_btn.clicked.connect(self.set_umr_namelist)

        umr_layout = QVBoxLayout()
        umr_layout.addWidget(umr_label)
        umr_layout.addWidget(umr_enabled_box)
        umr_layout.addWidget(umr_verbose_box)
        umr_layout.addWidget(umr_namelist_btn)
        umr_group.setLayout(umr_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(pyexec_group)
        vlayout.addWidget(umr_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #49
0
class PlotSettingsWidget(QWidget):

    def __init__(self, settings, plotWidget, parent=None):
        super().__init__(parent)
        self.mainwindow = parent
        self.plotWidget = plotWidget

        # xmin
        self.xminLabel = QLabel(self.tr('xmin:'))
        self.xminSpinBox = CoordSpinBox()
        self.xminLabel.setBuddy(self.xminSpinBox)
        self.xminSpinBox.editingFinished.connect(self.change_limits)

        # xmax
        self.xmaxLabel = QLabel(self.tr('xmax:'))
        self.xmaxSpinBox = CoordSpinBox()
        self.xmaxLabel.setBuddy(self.xmaxSpinBox)
        self.xmaxSpinBox.editingFinished.connect(self.change_limits)

        # ymin
        self.yminLabel = QLabel(self.tr('ymin:'))
        self.yminSpinBox = CoordSpinBox()
        self.yminLabel.setBuddy(self.yminSpinBox)
        self.yminSpinBox.editingFinished.connect(self.change_limits)

        # ymax
        self.ymaxLabel = QLabel(self.tr('ymax:'))
        self.ymaxSpinBox = CoordSpinBox()
        self.ymaxLabel.setBuddy(self.ymaxSpinBox)
        self.ymaxSpinBox.editingFinished.connect(self.change_limits)

        # Autoscale Radio Group
        self.autoscaleButtonGroup = QButtonGroup()

        # Autoscale Group Box
        self.autoscaleGroupBox = QGroupBox()

        # autoscale
        self.autoscaleRadioButton = QRadioButton(self.tr("autoscale"))
        self.autoscaleButtonGroup.addButton(self.autoscaleRadioButton)

        # autotrack
        self.autoscrollRadioButton = QRadioButton(self.tr("autoscroll"))
        self.autoscaleButtonGroup.addButton(self.autoscrollRadioButton)

        # no autoscale
        self.manualscaleRadioButton = QRadioButton(self.tr("manual"))
        self.autoscaleButtonGroup.addButton(self.manualscaleRadioButton)

        layout = QVBoxLayout()
        layout.addWidget(self.autoscaleRadioButton)
        layout.addWidget(self.autoscrollRadioButton)
        layout.addWidget(self.manualscaleRadioButton)
        self.autoscaleGroupBox.setLayout(layout)

        # Layout
        layout = QGridLayout()
        layout.addWidget(self.xminLabel, 1, 0)
        layout.addWidget(self.xminSpinBox, 1, 1)
        layout.addWidget(self.xmaxLabel, 2, 0)
        layout.addWidget(self.xmaxSpinBox, 2, 1)
        layout.addWidget(self.yminLabel, 3, 0)
        layout.addWidget(self.yminSpinBox, 3, 1)
        layout.addWidget(self.ymaxLabel, 4, 0)
        layout.addWidget(self.ymaxSpinBox, 4, 1)
        layout.addWidget(self.autoscaleGroupBox, 5, 0, 1, 2)
        layout.setRowStretch(6, 1)
        self.setLayout(layout)

        # settings
        self.settings = settings
        self.settings.add_handler(S_XMIN, self.xminSpinBox)
        self.settings.add_handler(S_XMAX, self.xmaxSpinBox)
        self.settings.add_handler(S_YMIN, self.yminSpinBox)
        self.settings.add_handler(S_YMAX, self.ymaxSpinBox)
        self.settings.add_handler(S_AUTOSCALE, self.autoscaleButtonGroup)

    def refresh(self, state):
        pass

    def change_limits(self):
        if self.autoscale != AUTOSCALE_COMPLETE:
            self.plotWidget.xmin = self.xmin
            self.plotWidget.xmax = self.xmax
            self.plotWidget.ymin = self.ymin
            self.plotWidget.ymax = self.ymax
            self.plotWidget.draw()

    @property
    def xmin(self):
        return self.xminSpinBox.value()

    @property
    def xmax(self):
        return self.xmaxSpinBox.value()

    @property
    def ymin(self):
        return self.yminSpinBox.value()

    @property
    def ymax(self):
        return self.ymaxSpinBox.value()

    @property
    def autoscale(self):
        return self.autoscaleButtonGroup.checkedId()
class SegmentationWidget(QWidget):
    def __init__(
        self,
        viewer,
        boundaries_string=BOUNDARIES_STRING,
    ):
        super(SegmentationWidget, self).__init__()

        # general variables
        self.viewer = viewer

        # Disable / overwrite napari viewer functions
        # that either do not make sense or should be avoided by the user
        disable_napari_btns(self.viewer)
        disable_napari_key_bindings()
        # overwrite_napari_roll(self.viewer)

        # Main layers
        self.base_layer = []  # Contains registered brain / reference brain
        self.atlas_layer = []  # Contains annotations / region information

        # Track variables
        self.track_layers = []

        # Region variables
        self.label_layers = []

        # Atlas variables
        self.current_atlas_name = ""
        self.atlas = None

        self.boundaries_string = boundaries_string
        self.directory = ""
        # Set up segmentation methods
        self.region_seg = RegionSeg(self)
        self.track_seg = TrackSeg(self)

        # Generate main layout
        self.setup_main_layout()

        if DISPLAY_REGION_INFO:

            @self.viewer.mouse_move_callbacks.append
            def display_region_info(v, event):
                """
                Show brain region info on mouse over in status bar on the right
                """
                assert self.viewer == v
                if len(v.layers) and self.atlas_layer and self.atlas:
                    _, _, _, region_info = structure_from_viewer(
                        self.viewer.status, self.atlas_layer, self.atlas)
                    self.viewer.help = region_info

    def setup_main_layout(self):
        """
        Construct main layout of widget
        """
        self.layout = QGridLayout()
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setAlignment(QtCore.Qt.AlignTop)
        self.layout.setSpacing(4)

        # 3 Steps:
        # - Loading panel
        # - Segmentation methods panel
        # -> Individual segmentation methods (which are invisible at first)
        # - Saving panel

        self.add_loading_panel(1)
        self.add_segmentation_methods_panel(1)
        self.track_seg.add_track_panel(2)  # Track segmentation subpanel
        self.region_seg.add_region_panel(3)  # Region segmentation subpanel
        self.add_saving_panel(4)

        # Take care of status label
        self.status_label = QLabel()
        self.status_label.setText("Ready")
        self.layout.addWidget(self.status_label, 5, 0)

        self.setLayout(self.layout)

    # PANELS ###############################################################

    def add_segmentation_methods_panel(self, row, column=1):
        """
        Segmentation methods chooser panel:
            Toggle visibility of segmentation
            methods
        """
        self.toggle_methods_panel = QGroupBox("Segmentation")
        self.toggle_methods_layout = QGridLayout()
        self.toggle_methods_layout.setContentsMargins(10, 10, 10, 10)
        self.toggle_methods_layout.setSpacing(5)
        self.toggle_methods_layout.setAlignment(QtCore.Qt.AlignBottom)

        self.show_trackseg_button = add_button(
            "Track tracing",
            self.toggle_methods_layout,
            self.track_seg.toggle_track_panel,
            0,
            1,
            minimum_width=COLUMN_WIDTH,
            alignment=SEGM_METHODS_PANEL_ALIGN,
        )
        self.show_trackseg_button.setEnabled(False)

        self.show_regionseg_button = add_button(
            "Region segmentation",
            self.toggle_methods_layout,
            self.region_seg.toggle_region_panel,
            1,
            1,
            minimum_width=COLUMN_WIDTH,
            alignment=SEGM_METHODS_PANEL_ALIGN,
        )
        self.show_regionseg_button.setEnabled(False)

        self.toggle_methods_layout.setColumnMinimumWidth(1, COLUMN_WIDTH)
        self.toggle_methods_panel.setLayout(self.toggle_methods_layout)
        self.toggle_methods_panel.setVisible(True)

        self.layout.addWidget(self.toggle_methods_panel, row, column, 1, 1)

    def add_loading_panel(self, row, column=0):
        """
        Loading panel:
            - Load project (sample space)
            - Load project (atlas space)
            - Atlas chooser
        """
        self.load_data_panel = QGroupBox("Load data")
        self.load_data_layout = QGridLayout()
        self.load_data_layout.setSpacing(15)
        self.load_data_layout.setContentsMargins(10, 10, 10, 10)
        self.load_data_layout.setAlignment(QtCore.Qt.AlignBottom)

        self.load_button = add_button(
            "Load project (sample space)",
            self.load_data_layout,
            self.load_brainreg_directory_sample,
            0,
            0,
            minimum_width=COLUMN_WIDTH,
            alignment=LOADING_PANEL_ALIGN,
        )

        self.load_button_standard = add_button(
            "Load project (atlas space)",
            self.load_data_layout,
            self.load_brainreg_directory_standard,
            1,
            0,
            minimum_width=COLUMN_WIDTH,
            alignment=LOADING_PANEL_ALIGN,
        )

        self.add_atlas_menu(self.load_data_layout)

        self.load_data_layout.setColumnMinimumWidth(0, COLUMN_WIDTH)
        self.load_data_panel.setLayout(self.load_data_layout)
        self.load_data_panel.setVisible(True)

        self.layout.addWidget(self.load_data_panel, row, column, 1, 1)

    def add_saving_panel(self, row):
        """
        Saving/Export panel
        """
        self.save_data_panel = QGroupBox()
        self.save_data_layout = QGridLayout()

        self.export_button = add_button(
            "To brainrender",
            self.save_data_layout,
            self.export_to_brainrender,
            0,
            0,
            visibility=False,
        )
        self.save_button = add_button("Save",
                                      self.save_data_layout,
                                      self.save,
                                      0,
                                      1,
                                      visibility=False)

        self.save_data_layout.setColumnMinimumWidth(1, COLUMN_WIDTH)
        self.save_data_panel.setLayout(self.save_data_layout)
        self.layout.addWidget(self.save_data_panel, row, 0, 1, 2)

        self.save_data_panel.setVisible(False)

    # ATLAS INTERACTION ####################################################

    def add_atlas_menu(self, layout):
        list_of_atlasses = ["Load atlas"]
        available_atlases = get_available_atlases()
        for atlas in available_atlases.keys():
            atlas_desc = f"{atlas} v{available_atlases[atlas]}"
            list_of_atlasses.append(atlas_desc)
            atlas_menu, _ = add_combobox(
                layout,
                None,
                list_of_atlasses,
                2,
                0,
                label_stack=True,
                callback=self.initialise_atlas,
                width=COLUMN_WIDTH,
            )

        self.atlas_menu = atlas_menu

    def initialise_atlas(self):
        atlas_string = self.atlas_menu.currentText()
        atlas_name = atlas_string.split(" ")[0].strip()
        if atlas_name != self.current_atlas_name:
            status = self.remove_layers()
            if not status:  # Something prevented deletion
                self.reset_atlas_menu()
                return
        else:
            print(f"{atlas_string} already selected for segmentation.")
            self.reset_atlas_menu()
            return

        # Get / set output directory
        self.set_output_directory()
        if not self.directory:
            self.reset_atlas_menu()
            return

        self.current_atlas_name = atlas_name
        # Instantiate atlas layers
        self.load_atlas()

        self.directory = self.directory / atlas_name
        self.paths = Paths(self.directory, atlas_space=True)

        self.status_label.setText("Ready")
        # Set window title
        self.viewer.title = f"Atlas: {self.current_atlas_name}"
        self.initialise_segmentation_interface()
        # Check / load previous regions and tracks
        self.region_seg.check_saved_region()
        self.track_seg.check_saved_track()
        self.reset_atlas_menu()

    def set_output_directory(self):
        self.status_label.setText("Loading...")
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        self.directory = QFileDialog.getExistingDirectory(
            self,
            "Select output directory",
            options=options,
        )
        if self.directory != "":
            self.directory = Path(self.directory)

    def load_atlas(self):
        atlas = BrainGlobeAtlas(self.current_atlas_name)
        self.atlas = atlas
        self.base_layer = self.viewer.add_image(
            self.atlas.reference,
            name="Reference",
        )
        self.atlas_layer = self.viewer.add_labels(
            self.atlas.annotation,
            name=self.atlas.atlas_name,
            blending="additive",
            opacity=0.3,
            visible=False,
        )
        self.standard_space = True

    def reset_atlas_menu(self):
        # Reset menu for atlas - show initial description
        self.atlas_menu.blockSignals(True)
        self.atlas_menu.setCurrentIndex(0)
        self.atlas_menu.blockSignals(False)

    # BRAINREG INTERACTION #################################################

    def load_brainreg_directory_sample(self):
        self.get_brainreg_directory(standard_space=False)

    def load_brainreg_directory_standard(self):
        self.get_brainreg_directory(standard_space=True)

    def get_brainreg_directory(self, standard_space):
        """
        Shows file dialog to choose output directory
        and sets global directory info
        """
        if standard_space:
            self.plugin = "brainreg_standard"
            self.standard_space = True
        else:
            self.plugin = "brainreg"
            self.standard_space = False

        self.status_label.setText("Loading...")
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        brainreg_directory = QFileDialog.getExistingDirectory(
            self,
            "Select brainreg directory",
            options=options,
        )

        if not brainreg_directory:
            return

        if self.directory != brainreg_directory:
            status = self.remove_layers()
            if not status:
                return  # Something prevented deletion
            self.directory = Path(brainreg_directory)
        else:
            print(f"{str(brainreg_directory)} already loaded.")
            return

        # Otherwise, proceed loading brainreg dir
        self.load_brainreg_directory()

    def load_brainreg_directory(self):
        """
        Opens brainreg folder in napari.
        Calls initialise_loaded_data to set up layers / info.
        Then checks for previously loaded data.

        """
        try:
            self.viewer.open(str(self.directory), plugin=self.plugin)
            self.paths = Paths(
                self.directory,
                standard_space=self.standard_space,
            )
            self.initialise_loaded_data()
        except ValueError:
            print(f"The directory ({self.directory}) does not appear to be "
                  f"a brainreg directory, please try again.")
            return

        # Check / load previous regions and tracks
        self.region_seg.check_saved_region()
        self.track_seg.check_saved_track()

    def initialise_loaded_data(self):
        """
        Set up brainreg layers in napari / fill with new data and info

        """
        try:
            self.viewer.layers.remove(self.boundaries_string)
        except KeyError:
            pass

        self.base_layer = self.viewer.layers["Registered image"]
        self.metadata = self.base_layer.metadata
        self.atlas = self.metadata["atlas_class"]
        self.atlas_layer = self.viewer.layers[self.metadata["atlas"]]
        self.initialise_segmentation_interface()

        # Set window title
        self.viewer.title = (
            f"Brainreg: {self.metadata['atlas']} ({self.plugin})")
        self.status_label.setText("Ready")

    # MORE LAYOUT COMPONENTS ###########################################

    def initialise_segmentation_interface(self):
        self.reset_variables()
        self.initialise_image_view()
        self.save_data_panel.setVisible(True)
        self.save_button.setVisible(True)
        self.export_button.setVisible(self.standard_space)
        self.show_regionseg_button.setEnabled(True)
        self.show_trackseg_button.setEnabled(True)
        self.status_label.setText("Ready")

    def initialise_image_view(self):
        self.set_z_position()

    def set_z_position(self):
        midpoint = int(round(len(self.base_layer.data) / 2))
        self.viewer.dims.set_point(0, midpoint)

    def reset_variables(self):
        """
        Reset atlas scale dependent variables
        - point_size (Track segmentation)
        - spline_size (Track segmentation)
        - brush_size (Region segmentation)
        """
        self.mean_voxel_size = int(
            np.sum(self.atlas.resolution) / len(self.atlas.resolution))
        self.track_seg.point_size = (self.track_seg.point_size_default /
                                     self.mean_voxel_size)
        self.track_seg.spline_size = (self.track_seg.spline_size_default /
                                      self.mean_voxel_size)
        self.region_seg.brush_size = (self.region_seg.brush_size_default /
                                      self.mean_voxel_size)
        return

    def display_delete_warning(self):
        """
        Display a warning in a pop up that informs
        about deletion of all annotation layers
        """
        message_reply = QMessageBox.question(
            self,
            "About to remove layers",
            "All layers are about to be deleted. Proceed?",
            QMessageBox.Yes | QMessageBox.Cancel,
        )
        if message_reply == QMessageBox.Yes:
            return True
        else:
            return False

    def remove_layers(self):
        """
        TODO: This needs work. Runs into an error currently
        when switching from a annotated project to another one
        """
        if len(self.viewer.layers) != 0:
            # Check with user if that is really what is wanted
            if self.track_layers or self.label_layers:
                choice = self.display_delete_warning()
                if not choice:
                    print('Preventing deletion because user chose "Cancel"')
                    return False

            # Remove old layers
            for layer in list(self.viewer.layers):
                try:
                    self.viewer.layers.remove(layer)
                except IndexError:  # no idea why this happens
                    pass

        # There seems to be a napari bug trying to access previously used slider
        # values. Trying to circument for now
        self.viewer.window.qt_viewer.dims._last_used = None

        self.track_layers = []
        self.label_layers = []
        return True

    def save(self):
        if self.label_layers or self.track_layers:
            print("Saving")
            worker = save_all(
                self.paths.regions_directory,
                self.paths.tracks_directory,
                self.label_layers,
                self.track_layers,
                track_file_extension=TRACK_FILE_EXT,
            )
            worker.start()

    def export_to_brainrender(self):
        print("Exporting")
        max_axis_2 = self.base_layer.shape[2]
        worker = export_all(
            self.paths.regions_directory,
            self.paths.tracks_directory,
            self.label_layers,
            self.track_seg.splines,
            self.track_seg.spline_names,
            self.atlas.resolution[0],
            max_axis_2,
        )
        worker.start()
Beispiel #51
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)
Beispiel #52
0
    def setup_page(self):
        self.ICON = ima.icon('genprefs')
        newcb = self.create_checkbox

        # --- Interface
        general_group = QGroupBox(_("General"))
        languages = LANGUAGE_CODES.items()
        language_choices = sorted([(val, key) for key, val in languages])
        language_combo = self.create_combobox(_('Language'),
                                              language_choices,
                                              'interface_language',
                                              restart=True)

        general_layout = QVBoxLayout()
        general_layout.addWidget(language_combo)
        general_group.setLayout(general_layout)

        # --- Status bar
        sbar_group = QGroupBox(_("Status bar"))
        show_status_bar = newcb(_("Show status bar"), 'show_status_bar')

        memory_box = newcb(_("Show memory usage every"),
                           'memory_usage/enable',
                           tip=self.main.mem_status.toolTip())
        memory_spin = self.create_spinbox("",
                                          _(" ms"),
                                          'memory_usage/timeout',
                                          min_=100,
                                          max_=1000000,
                                          step=100)
        memory_box.toggled.connect(memory_spin.setEnabled)
        memory_spin.setEnabled(self.get_option('memory_usage/enable'))
        memory_box.setEnabled(self.main.mem_status.is_supported())
        memory_spin.setEnabled(self.main.mem_status.is_supported())

        cpu_box = newcb(_("Show CPU usage every"),
                        'cpu_usage/enable',
                        tip=self.main.cpu_status.toolTip())
        cpu_spin = self.create_spinbox("",
                                       _(" ms"),
                                       'cpu_usage/timeout',
                                       min_=100,
                                       max_=1000000,
                                       step=100)
        cpu_box.toggled.connect(cpu_spin.setEnabled)
        cpu_spin.setEnabled(self.get_option('cpu_usage/enable'))

        cpu_box.setEnabled(self.main.cpu_status.is_supported())
        cpu_spin.setEnabled(self.main.cpu_status.is_supported())

        status_bar_o = self.get_option('show_status_bar')
        show_status_bar.toggled.connect(memory_box.setEnabled)
        show_status_bar.toggled.connect(memory_spin.setEnabled)
        show_status_bar.toggled.connect(cpu_box.setEnabled)
        show_status_bar.toggled.connect(cpu_spin.setEnabled)
        memory_box.setEnabled(status_bar_o)
        memory_spin.setEnabled(status_bar_o)
        cpu_box.setEnabled(status_bar_o)
        cpu_spin.setEnabled(status_bar_o)

        # Layout status bar
        cpu_memory_layout = QGridLayout()
        cpu_memory_layout.addWidget(memory_box, 0, 0)
        cpu_memory_layout.addWidget(memory_spin, 0, 1)
        cpu_memory_layout.addWidget(cpu_box, 1, 0)
        cpu_memory_layout.addWidget(cpu_spin, 1, 1)

        sbar_layout = QVBoxLayout()
        sbar_layout.addWidget(show_status_bar)
        sbar_layout.addLayout(cpu_memory_layout)
        sbar_group.setLayout(sbar_layout)

        # --- Path
        path_group = QGroupBox(_("TODO"))

        tabs = QTabWidget()
        tabs.addTab(self.create_tab(path_group), _("Basic"))
        tabs.addTab(self.create_tab(general_group, sbar_group),
                    _("Advanced Settings"))

        vlayout = QVBoxLayout()
        vlayout.addWidget(tabs)
        self.setLayout(vlayout)
Beispiel #53
0
    def setup_page(self):
        about_label = QLabel(_("The <b>global working directory</b> is "
                    "the working directory for newly opened <i>consoles</i> "
                    "(Python/IPython consoles and terminals), for the "
                    "<i>file explorer</i>, for the <i>find in files</i> "
                    "plugin and for new files created in the <i>editor</i>."))
        about_label.setWordWrap(True)
        
        startup_group = QGroupBox(_("Startup"))
        startup_bg = QButtonGroup(startup_group)
        startup_label = QLabel(_("At startup, the global working "
                                       "directory is:"))
        startup_label.setWordWrap(True)
        lastdir_radio = self.create_radiobutton(
                                _("the same as in last session"),
                                'startup/use_last_directory', True,
                                _("At startup, Spyder will restore the "
                                        "global directory from last session"),
                                button_group=startup_bg)
        thisdir_radio = self.create_radiobutton(
                                _("the following directory:"),
                                'startup/use_fixed_directory', False,
                                _("At startup, the global working "
                                        "directory will be the specified path"),
                                button_group=startup_bg)
        thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
                                           getcwd())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        lastdir_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        editor_o_group = QGroupBox(_("Open file"))
        editor_o_label = QLabel(_("Files are opened from:"))
        editor_o_label.setWordWrap(True)
        editor_o_bg = QButtonGroup(editor_o_group)
        editor_o_radio1 = self.create_radiobutton(
                                _("the current file directory"),
                                'editor/open/browse_scriptdir',
                                button_group=editor_o_bg)
        editor_o_radio2 = self.create_radiobutton(
                                _("the global working directory"),
                                'editor/open/browse_workdir', 
                                button_group=editor_o_bg)
        
        editor_n_group = QGroupBox(_("New file"))
        editor_n_label = QLabel(_("Files are created in:"))
        editor_n_label.setWordWrap(True)
        editor_n_bg = QButtonGroup(editor_n_group)
        editor_n_radio1 = self.create_radiobutton(
                                _("the current file directory"),
                                'editor/new/browse_scriptdir',
                                button_group=editor_n_bg)
        editor_n_radio2 = self.create_radiobutton(
                                _("the global working directory"),
                                'editor/new/browse_workdir',
                                button_group=editor_n_bg)
        # Note: default values for the options above are set in plugin's
        #       constructor (see below)
        
        other_group = QGroupBox(_("Change to file base directory"))
        newcb = self.create_checkbox
        open_box = newcb(_("When opening a file"),
                         'editor/open/auto_set_to_basedir')
        save_box = newcb(_("When saving a file"),
                         'editor/save/auto_set_to_basedir')
        
        startup_layout = QVBoxLayout()
        startup_layout.addWidget(startup_label)
        startup_layout.addWidget(lastdir_radio)
        startup_layout.addLayout(thisdir_layout)
        startup_group.setLayout(startup_layout)

        editor_o_layout = QVBoxLayout()
        editor_o_layout.addWidget(editor_o_label)
        editor_o_layout.addWidget(editor_o_radio1)
        editor_o_layout.addWidget(editor_o_radio2)
        editor_o_group.setLayout(editor_o_layout)

        editor_n_layout = QVBoxLayout()
        editor_n_layout.addWidget(editor_n_label)
        editor_n_layout.addWidget(editor_n_radio1)
        editor_n_layout.addWidget(editor_n_radio2)
        editor_n_group.setLayout(editor_n_layout)
        
        other_layout = QVBoxLayout()
        other_layout.addWidget(open_box)
        other_layout.addWidget(save_box)
        other_group.setLayout(other_layout)
        
        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(startup_group)
        vlayout.addWidget(editor_o_group)
        vlayout.addWidget(editor_n_group)
        vlayout.addWidget(other_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #54
0
    def setup_page(self):
        about_label = QLabel(
            _("The <b>current working directory</b> is "
              "the working directory for IPython consoles "
              "and the current directory for the File Explorer."))
        about_label.setWordWrap(True)

        startup_group = QGroupBox(_("Startup"))
        startup_bg = QButtonGroup(startup_group)
        startup_label = QLabel(
            _("At startup, the current working "
              "directory is:"))
        startup_label.setWordWrap(True)
        lastdir_radio = self.create_radiobutton(
            _("The current project directory "
              "or user home directory "
              "(if no project is active)"),
            'startup/use_project_or_home_directory',
            True,
            _("At startup,"),  # TODO
            button_group=startup_bg)
        thisdir_radio = self.create_radiobutton(
            _("the following directory:"),
            'startup/use_fixed_directory',
            False,
            _("At startup, the current working "
              "directory will be the specified path"),
            button_group=startup_bg)
        thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
                                           getcwd_or_home())
        thisdir_radio.toggled.connect(thisdir_bd.setEnabled)
        lastdir_radio.toggled.connect(thisdir_bd.setDisabled)
        thisdir_layout = QHBoxLayout()
        thisdir_layout.addWidget(thisdir_radio)
        thisdir_layout.addWidget(thisdir_bd)

        startup_layout = QVBoxLayout()
        startup_layout.addWidget(startup_label)
        startup_layout.addWidget(lastdir_radio)
        startup_layout.addLayout(thisdir_layout)
        startup_group.setLayout(startup_layout)

        # Console Directory

        console_group = QGroupBox(_("Console directory"))
        console_label = QLabel(_("The working directory for new consoles is:"))
        console_label.setWordWrap(True)
        console_bg = QButtonGroup(console_group)
        console_project_radio = self.create_radiobutton(
            _("The current project directory "
              "or user home directory "
              "(if no project is active)"),
            'console/use_project_or_home_directory',
            True,
            button_group=console_bg)
        console_cwd_radio = self.create_radiobutton(
            _("The current working directory"),
            'console/use_cwd',
            False,
            button_group=console_bg)

        console_dir_radio = self.create_radiobutton(
            _("the following directory:"),
            'console/use_fixed_directory',
            False,
            _("The directory when a new console "
              "is open will be the specified path"),
            button_group=console_bg)
        console_dir_bd = self.create_browsedir("", 'console/fixed_directory',
                                               getcwd_or_home())
        console_dir_radio.toggled.connect(console_dir_bd.setEnabled)
        console_project_radio.toggled.connect(console_dir_bd.setDisabled)
        console_cwd_radio.toggled.connect(console_dir_bd.setDisabled)
        console_dir_layout = QHBoxLayout()
        console_dir_layout.addWidget(console_dir_radio)
        console_dir_layout.addWidget(console_dir_bd)

        console_layout = QVBoxLayout()
        console_layout.addWidget(console_label)
        console_layout.addWidget(console_project_radio)
        console_layout.addWidget(console_cwd_radio)
        console_layout.addLayout(console_dir_layout)
        console_group.setLayout(console_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(about_label)
        vlayout.addSpacing(10)
        vlayout.addWidget(startup_group)
        vlayout.addWidget(console_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Beispiel #55
0
    def setup_page(self):
        if ERR_MSG:
            label = QLabel(_("Could not load plugin:\n{0}".format(ERR_MSG)))
            layout = QVBoxLayout()
            layout.addWidget(label)
            self.setLayout(layout)
            return

        # Layout parameter
        indent = QCheckBox().sizeHint().width()

        # General options
        options_group = QGroupBox(_("Options"))
        # Hack : the spinbox widget will be added to self.spinboxes
        spinboxes_before = set(self.spinboxes)
        passes_spin = self.create_spinbox(
            _("Number of pep8 passes: "), "", 'passes',
            default=0, min_=0, max_=1000000, step=1)
        spinbox = set(self.spinboxes) - spinboxes_before
        spinbox = spinbox.pop()
        spinbox.setSpecialValueText(_("Infinite"))
        aggressive1_checkbox = self.create_checkbox(
            "Aggressivity level 1", "aggressive1", default=False)
        aggressive1_label = QLabel(_(
            "Allow possibly unsafe fixes (E711 and W6), shorten lines"
            " and remove trailing whitespace more aggressively (in"
            " docstrings and multiline strings)."))
        aggressive1_label.setWordWrap(True)
        aggressive1_label.setIndent(indent)
        font_description = aggressive1_label.font()
        font_description.setPointSizeF(font_description.pointSize() * 0.9)
        aggressive1_label.setFont(font_description)
        aggressive2_checkbox = self.create_checkbox(
            "Aggressivity level 2", "aggressive2", default=False)
        aggressive2_label = QLabel(_(
            "Allow more possibly unsafe fixes (E712) and shorten lines."))
        aggressive2_label.setWordWrap(True)
        aggressive2_label.setIndent(indent)
        aggressive2_label.setFont(font_description)

        aggressive1_checkbox.toggled.connect(
            aggressive2_checkbox.setEnabled)
        aggressive1_checkbox.toggled.connect(
            aggressive2_label.setEnabled)
        aggressive2_checkbox.setEnabled(aggressive1_checkbox.isChecked())
        aggressive2_label.setEnabled(aggressive1_checkbox.isChecked())

        # Enable/disable error codes
        fix_layout = QVBoxLayout()
        last_group = ""
        FIX_LIST.sort(key=lambda item: item[0][1])
        for code, description in FIX_LIST:
            # Create a new group if necessary
            if code[1] != last_group:
                last_group = code[1]
                group = QGroupBox(_(self.GROUPS.get(code[1], "")))
                fix_layout.addWidget(group)
                group_layout = QVBoxLayout(group)

            # Checkbox for the option
            text = code
            default = True
            if code in DEFAULT_IGNORE:
                text += _(" (UNSAFE)")
                default = False
            option = self.create_checkbox(text, code, default=default)

            # Label for description
            if code in self.CODES:
                label = QLabel("{autopep8} ({pep8}).".format(
                    autopep8=_(description).rstrip("."),
                    pep8=self.CODES[code]))
            else:
                label = QLabel(_(description))
            label.setWordWrap(True)
            label.setIndent(indent)
            label.setFont(font_description)

            # Add widgets to layout
            option_layout = QVBoxLayout()
            option_layout.setSpacing(0)
            option_layout.addWidget(option)
            option_layout.addWidget(label)
            group_layout.addLayout(option_layout)

            # Special cases
            if code in ("E711", "W6"):
                aggressive1_checkbox.toggled.connect(option.setEnabled)
                aggressive1_checkbox.toggled.connect(label.setEnabled)
                option.setEnabled(aggressive1_checkbox.isChecked())
                label.setEnabled(aggressive1_checkbox.isChecked())
            if code == "E712":
                def e712_enabled():
                    enabled = (aggressive1_checkbox.isChecked()
                               and aggressive2_checkbox.isChecked())
                    option.setEnabled(enabled)
                    label.setEnabled(enabled)
                aggressive1_checkbox.toggled.connect(e712_enabled)
                aggressive2_checkbox.toggled.connect(e712_enabled)
                e712_enabled()

        # General layout
        aggressive2_layout = QVBoxLayout()
        margins = aggressive2_layout.contentsMargins()
        margins.setLeft(indent)
        aggressive2_layout.setContentsMargins(margins)
        aggressive2_layout.addWidget(aggressive2_checkbox)
        aggressive2_layout.addWidget(aggressive2_label)

        options_layout = QVBoxLayout()
        options_layout.addWidget(passes_spin)
        options_layout.addWidget(aggressive1_checkbox)
        options_layout.addWidget(aggressive1_label)
        options_layout.addLayout(aggressive2_layout)
        options_group.setLayout(options_layout)

        widget_scroll = QWidget()
        widget_scroll.setLayout(fix_layout)
        fix_scroll = QScrollArea()
        fix_scroll.setWidget(widget_scroll)
        fix_scroll.setWidgetResizable(True)
        fig_out_layout = QVBoxLayout()
        fig_out_layout.addWidget(fix_scroll, 1)
        fix_group = QGroupBox(_("Errors/warnings to fix"))
        fix_group.setLayout(fig_out_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(options_group)
        vlayout.addWidget(fix_group, 1)
        self.setLayout(vlayout)
Beispiel #56
0
    def setupUI(self):

        layout = QVBoxLayout()

        columns = QHBoxLayout()
        leftColumn = QVBoxLayout()
        rightColumn = QVBoxLayout()

        self.collectionButton1, self.collectionButton2, self.collectionButton3, self.collectionButton4, self.collectionButton5, self.collectionButton6, self.collectionButton7, self.collectionButton8, self.collectionButton9, self.collectionButton10, self.collectionButton11, self.collectionButton12 = QPushButton(
        ), QPushButton(), QPushButton(), QPushButton(), QPushButton(
        ), QPushButton(), QPushButton(), QPushButton(), QPushButton(
        ), QPushButton(), QPushButton(), QPushButton()
        self.collectionButtons = (
            self.collectionButton1, self.collectionButton2,
            self.collectionButton3, self.collectionButton4,
            self.collectionButton5, self.collectionButton6,
            self.collectionButton7, self.collectionButton8,
            self.collectionButton9, self.collectionButton10,
            self.collectionButton11, self.collectionButton12)
        self.collectionColourButton1, self.collectionColourButton2, self.collectionColourButton3, self.collectionColourButton4, self.collectionColourButton5, self.collectionColourButton6, self.collectionColourButton7, self.collectionColourButton8, self.collectionColourButton9, self.collectionColourButton10, self.collectionColourButton11, self.collectionColourButton12 = QPushButton(
        ), QPushButton(), QPushButton(), QPushButton(), QPushButton(
        ), QPushButton(), QPushButton(), QPushButton(), QPushButton(
        ), QPushButton(), QPushButton(), QPushButton()
        self.collectionColourButtons = (
            self.collectionColourButton1, self.collectionColourButton2,
            self.collectionColourButton3, self.collectionColourButton4,
            self.collectionColourButton5, self.collectionColourButton6,
            self.collectionColourButton7, self.collectionColourButton8,
            self.collectionColourButton9, self.collectionColourButton10,
            self.collectionColourButton11, self.collectionColourButton12)
        self.collectionRadioButton1, self.collectionRadioButton2, self.collectionRadioButton3, self.collectionRadioButton4, self.collectionRadioButton5, self.collectionRadioButton6, self.collectionRadioButton7, self.collectionRadioButton8, self.collectionRadioButton9, self.collectionRadioButton10, self.collectionRadioButton11, self.collectionRadioButton12 = QRadioButton(
        ), QRadioButton(), QRadioButton(), QRadioButton(), QRadioButton(
        ), QRadioButton(), QRadioButton(), QRadioButton(), QRadioButton(
        ), QRadioButton(), QRadioButton(), QRadioButton()
        self.collectionRadioButtons = (
            self.collectionRadioButton1, self.collectionRadioButton2,
            self.collectionRadioButton3, self.collectionRadioButton4,
            self.collectionRadioButton5, self.collectionRadioButton6,
            self.collectionRadioButton7, self.collectionRadioButton8,
            self.collectionRadioButton9, self.collectionRadioButton10,
            self.collectionRadioButton11, self.collectionRadioButton12)
        for index, button in enumerate(self.collectionButtons):
            subLayout = QHBoxLayout()

            radioButton = self.collectionRadioButtons[index]
            radioButton.setFixedWidth(20)
            radioButton.toggled.connect(
                lambda checked, option=index: self.highlightOptionChanged(
                    checked, option))
            radioButton.setToolTip(
                config.thisTranslation["selectApplyHighlight"])
            subLayout.addWidget(radioButton)

            button.setText("collection" if __name__ ==
                           "__main__" else config.highlightCollections[index])
            button.setFixedWidth(170)
            button.setToolTip(config.thisTranslation["rename"])
            button.clicked.connect(partial(self.rename, index))
            subLayout.addWidget(button)

            button = self.collectionColourButtons[index]
            button.setFixedWidth(50)
            buttonStyle = "QPushButton {0}background-color: {2}; color: {3};{1}".format(
                "{", "}",
                config.highlightDarkThemeColours[index] if config.theme
                == "dark" else config.highlightLightThemeColours[index],
                "white" if config.theme == "dark" else "black")
            button.setStyleSheet(buttonStyle)
            button.setToolTip(config.thisTranslation["changeColour"])
            button.clicked.connect(partial(self.changeColor, index))
            subLayout.addWidget(button)
            combo = QComboBox()
            combo.setToolTip(config.thisTranslation["filterHighlight"])
            combo.addItems(self.searchList)
            #for index, toolTip in enumerate(self.searchListToolTips):
            #combo.setItemData(index, toolTip, Qt.ToolTipRole)
            combo.setFixedWidth(100)
            combo.currentIndexChanged.connect(
                lambda selectedIndex, index=index: self.searchHighlight(
                    selectedIndex, index))
            subLayout.addWidget(combo)

            leftColumn.addLayout(subLayout) if (
                index % 2 == 0) else rightColumn.addLayout(subLayout)

        columns.addLayout(leftColumn)
        columns.addLayout(rightColumn)
        layout.addLayout(columns)

        subLayout0 = QHBoxLayout()
        subLayout = QHBoxLayout()
        self.noHighlightRadioButton = QRadioButton()
        self.noHighlightRadioButton.setFixedWidth(20)
        self.noHighlightRadioButton.toggled.connect(
            self.highlightOptionChanged)
        self.noHighlightRadioButton.setToolTip(
            config.thisTranslation["selectRemoveHighlight"])
        subLayout.addWidget(self.noHighlightRadioButton)
        button = QPushButton(config.thisTranslation["noHightlight"])
        button.setToolTip(config.thisTranslation["selectRemoveHighlight"])
        button.clicked.connect(lambda: self.highlightOptionChanged(True))
        subLayout.addWidget(button)
        subLayout0.addLayout(subLayout)
        subLayout = QHBoxLayout()
        button = QPushButton(config.thisTranslation["allCollections"])
        button.setToolTip(config.thisTranslation["allCollections"])
        button.clicked.connect(lambda: self.searchHighlight(1, "all"))
        subLayout.addWidget(button)
        #subLayout.addWidget(QLabel("All Collections in:"))
        combo = QComboBox()
        combo.setToolTip(config.thisTranslation["filterHighlight"])
        combo.addItems(self.searchList)
        combo.setFixedWidth(100)
        combo.currentIndexChanged.connect(
            lambda selectedIndex: self.searchHighlight(selectedIndex, "all"))
        subLayout.addWidget(combo)
        subLayout0.addLayout(subLayout)
        layout.addLayout(subLayout0)

        layout.addStretch()

        box = QGroupBox(config.thisTranslation["menu_highlights"])
        box.setLayout(layout)

        mainLayout = QVBoxLayout()
        mainLayout.setSpacing(0)
        mainLayout.addWidget(box)
        mainLayout.addStretch()
        self.setLayout(mainLayout)
Beispiel #57
0
    def generate_pv_controls(self, pv_name, curve_color):
        """
        Generate a set of widgets to manage the appearance of a curve. The set of widgets includes:
            1. A checkbox which shows the curve on the chart if checked, and hide the curve if not checked
            2. Two buttons -- Modify... and Remove. Modify... will bring up the Curve Settings dialog. Remove will
               delete the curve from the chart
        This set of widgets will be hidden initially, until the first curve is plotted.

        Parameters
        ----------
        pv_name: str
            The name of the PV the current curve is being plotted for

        curve_color : QColor
            The color of the curve to paint for the checkbox label to help the user track the curve to the checkbox
        """
        checkbox = QCheckBox()
        checkbox.setObjectName(pv_name)

        palette = checkbox.palette()
        palette.setColor(QPalette.Active, QPalette.WindowText, curve_color)
        checkbox.setPalette(palette)

        display_name = pv_name.split("://")[1]
        if len(display_name) > MAX_DISPLAY_PV_NAME_LENGTH:
            # Only display max allowed number of characters of the PV Name
            display_name = display_name[:int(MAX_DISPLAY_PV_NAME_LENGTH / 2) - 1] + "..." + \
                           display_name[-int(MAX_DISPLAY_PV_NAME_LENGTH / 2) + 2:]

        checkbox.setText(display_name)

        data_text = QLabel()
        data_text.setObjectName(pv_name)
        data_text.setPalette(palette)

        checkbox.setChecked(True)
        checkbox.clicked.connect(
            partial(self.handle_curve_chkbox_toggled, checkbox))

        curve_btn_layout = QHBoxLayout()

        modify_curve_btn = QPushButton("Modify...")
        modify_curve_btn.setObjectName(pv_name)
        modify_curve_btn.setMaximumWidth(100)
        modify_curve_btn.clicked.connect(
            partial(self.display_curve_settings_dialog, pv_name))

        focus_curve_btn = QPushButton("Focus")
        focus_curve_btn.setObjectName(pv_name)
        focus_curve_btn.setMaximumWidth(100)
        focus_curve_btn.clicked.connect(partial(self.focus_curve, pv_name))

        annotate_curve_btn = QPushButton("Annotate...")
        annotate_curve_btn.setObjectName(pv_name)
        annotate_curve_btn.setMaximumWidth(100)
        annotate_curve_btn.clicked.connect(
            partial(self.annotate_curve, pv_name))

        remove_curve_btn = QPushButton("Remove")
        remove_curve_btn.setObjectName(pv_name)
        remove_curve_btn.setMaximumWidth(100)
        remove_curve_btn.clicked.connect(partial(self.remove_curve, pv_name))

        curve_btn_layout.addWidget(modify_curve_btn)
        curve_btn_layout.addWidget(focus_curve_btn)
        curve_btn_layout.addWidget(annotate_curve_btn)
        curve_btn_layout.addWidget(remove_curve_btn)

        individual_curve_layout = QVBoxLayout()
        individual_curve_layout.addWidget(checkbox)
        individual_curve_layout.addWidget(data_text)
        individual_curve_layout.addLayout(curve_btn_layout)

        size_policy = QSizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Fixed)
        individual_curve_grpbx = QGroupBox()
        individual_curve_grpbx.setSizePolicy(size_policy)

        individual_curve_grpbx.setObjectName(pv_name)
        individual_curve_grpbx.setLayout(individual_curve_layout)

        self.curve_settings_layout.addWidget(individual_curve_grpbx)
        self.tab_panel.show()
Beispiel #58
0
    def setupUI(self):
        width, height  = self.determine_dialog_dimensions()

        self.setMinimumSize(width, height)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setWindowTitle("About Mantid Workbench")
        self.setStyleSheet(f"""QDialog {{
    background-color: rgb(190, 230, 190);
}}
QLabel{{
    font: {self.rescale_w(14)}px;
}}
QPushButton{{
    font: {self.rescale_w(14)}px;
}}
QCommandLinkButton{{
    font: {self.rescale_w(22)}px;
    background-color: rgba(255, 255, 255, 0);
    border-radius: {self.rescale_w(15)}px;
}}
QCommandLinkButton:hover {{
    background-color: rgba(45, 105, 45, 40);
}}""")

        # version label section at th etop
        parent_layout = QVBoxLayout()
        parent_layout.addSpacerItem(QSpacerItem(self.rescale_w(20),self.rescale_h(70),vPolicy=QSizePolicy.Fixed))
        self.lbl_version.setText("version ")
        self.lbl_version.setIndent(self.rescale_w(115))
        self.lbl_version.setStyleSheet(f"""color: rgb(215, 215, 215);
font: {self.rescale_w(28)}pt;
font-weight: bold;
font-size: {self.rescale_w(28)}px""")
        parent_layout.addWidget(self.lbl_version)
        parent_layout.addSpacerItem(QSpacerItem(self.rescale_w(20),self.rescale_h(40),
                                                vPolicy=QSizePolicy.MinimumExpanding))

        # split into the two columns
        two_box_layout = QHBoxLayout()
        # left side Welcome and Tutorial
        left_layout = QVBoxLayout()
        left_layout.setContentsMargins(self.rescale_w(5), 0, self.rescale_w(10), 0)
        left_layout.setSpacing(0)
        # welcome label
        lbl_welcome = QLabel()
        lbl_welcome.setStyleSheet(f"color: rgb(45, 105, 45); font-size: {self.rescale_w(28)}px;")
        lbl_welcome.setText("Welcome")
        left_layout.addWidget(lbl_welcome)
        # release notes
        self.setup_command_link_button(self.clb_release_notes, "Release Notes",
                                       ':/images/Notepad-Bloc-notes-icon-48x48.png')
        left_layout.addWidget(self.clb_release_notes)
        # sample datasets
        self.setup_command_link_button(self.clb_sample_datasets, "Sample Datasets",
                                       ':/images/download-icon-48x48.png')
        left_layout.addWidget(self.clb_sample_datasets)
        # Tutorials Label
        lbl_tutorials = QLabel()
        lbl_tutorials.setStyleSheet(f"color: rgb(45, 105, 45); font-size: {self.rescale_w(28)}px;")
        lbl_tutorials.setText("Tutorials")
        left_layout.addWidget(lbl_tutorials)
        # Mantid Introduction
        self.setup_command_link_button(self.clb_mantid_introduction, "Mantid Introduction",
                                       ':/images/Misc-Tutorial-icon-48x48.png')
        left_layout.addWidget(self.clb_mantid_introduction)
        # Introduction to python
        self.setup_command_link_button(self.clb_python_introduction, "Introduction to Python",
                                       ':/images/Python-icon-48x48.png')
        left_layout.addWidget(self.clb_python_introduction)
        # Python in Mantid
        self.setup_command_link_button(self.clb_python_in_mantid, "Python In Mantid",
                                       ':/images/Circle_cog_48x48.png')
        left_layout.addWidget(self.clb_python_in_mantid)
        # Extending Mantid with python
        self.setup_command_link_button(self.clb_extending_mantid, "Extending Mantid with Python",
                                       ':/images/Plugin-Python-icon-48x48.png')
        left_layout.addWidget(self.clb_extending_mantid)

        # right hand side Setup and facility icons
        right_layout = QVBoxLayout()
        right_layout.setSpacing(0)
        # personal setup
        grp_personal_setup = QGroupBox()
        grp_personal_setup.setStyleSheet(f"""QGroupBox {{
     border: {self.rescale_w(3)}px solid  rgb(38, 128, 20);;
     border-radius: {self.rescale_w(10)}px;
     background-color: rgb(240, 240, 240);
}}
QGroupBox QLabel{{
    font: {self.rescale_w(12)}px;
    color: rgb(121, 121, 121);
}}
QGroupBox QComboBox{{
    font: {self.rescale_w(12)}px;
}}
font: {self.rescale_w(12)}px;
""")
        grp_personal_setup_layout = QVBoxLayout()
        grp_personal_setup_layout.setContentsMargins(self.rescale_w(9),
                                                     self.rescale_h(1),
                                                     self.rescale_w(9),
                                                     self.rescale_h(9))
        grp_personal_setup_layout.setSpacing(0)
        grp_personal_setup.setLayout(grp_personal_setup_layout)
        lbl_personal_setup = QLabel()
        lbl_personal_setup.setStyleSheet(f"color: rgb(38, 128, 20);\nfont-size: {self.rescale_w(18)}px;")
        lbl_personal_setup.setText("Personal Setup")
        lbl_personal_setup.setAlignment(Qt.AlignHCenter)
        grp_personal_setup_layout.addWidget(lbl_personal_setup)
        personal_setup_form_layout = QFormLayout()
        personal_setup_form_layout.setHorizontalSpacing(self.rescale_w(5))
        personal_setup_form_layout.setVerticalSpacing(self.rescale_h(5))
        personal_setup_form_layout.setLabelAlignment(Qt.AlignRight)
        # default Facility
        lbl_default_facilty = QLabel()
        lbl_default_facilty.setText("Default Facility")
        personal_setup_form_layout.addRow(lbl_default_facilty, self.cb_facility)
        # default instrument
        lbl_default_instrument = QLabel()
        lbl_default_instrument.setText("Default Instrument")
        personal_setup_form_layout.addRow(lbl_default_instrument, self.cb_instrument)
        # Set Data Directories
        lbl_mud = QLabel()
        lbl_mud.setText("Set data directories")
        self.pb_manage_user_directories.setText("Manage User Directories")
        personal_setup_form_layout.addRow(lbl_mud, self.pb_manage_user_directories)
        # Usage data
        lbl_allow_usage_data = QLabel()
        lbl_allow_usage_data.setText("Report Usage Data")
        usagelayout = QHBoxLayout()
        usagelayout.setContentsMargins(0, 0, 0, 0)
        self.chk_allow_usage_data.setChecked(True)
        self.chk_allow_usage_data.setStyleSheet(f"padding: {self.rescale_w(4)}px;")
        usagelayout.addWidget(self.chk_allow_usage_data)
        usagelayout.addSpacerItem(QSpacerItem(self.rescale_w(40), self.rescale_h(20), hPolicy=QSizePolicy.Expanding))
        self.lbl_privacy_policy.setText(r'<html><head/><body><p>'
                                        r'<a href="https://www.mantidproject.org/MantidProject:Privacy_policy'
                                        r'#Usage_Data_recorded_in_Mantid">'
                                        r'<span style=" text-decoration: underline; color:#0000ff;">'
                                        r'Privacy Policy</span></a></p></body></html>')
        self.lbl_privacy_policy.setOpenExternalLinks(False)
        usagelayout.addWidget(self.lbl_privacy_policy)
        personal_setup_form_layout.addRow(lbl_allow_usage_data,usagelayout)
        grp_personal_setup_layout.addLayout(personal_setup_form_layout)
        right_layout.addWidget(grp_personal_setup)
        right_layout.addSpacerItem(QSpacerItem(self.rescale_w(20), self.rescale_h(40), vPolicy=QSizePolicy.Expanding))

        # facility icons
        # Row one
        icon_layout_top = QHBoxLayout()
        icon_layout_top.setContentsMargins(0, self.rescale_h(10), 0, 0)
        icon_layout_top.setSpacing(0)
        icon_layout_top.addWidget(self.create_label_with_image(112, 50, ':/images/ISIS_Logo_Transparent.gif'))
        icon_layout_top.addSpacerItem(QSpacerItem(self.rescale_w(10), self.rescale_h(20), hPolicy=QSizePolicy.Fixed))
        icon_layout_top.addWidget(self.create_label_with_image(94, 50, ':/images/ess_logo_transparent_small.png'))
        icon_layout_top.addSpacerItem(QSpacerItem(self.rescale_w(40), 20,hPolicy=QSizePolicy.Expanding))
        right_layout.addLayout(icon_layout_top)
        # Row two
        icon_layout_middle = QHBoxLayout()
        icon_layout_middle.setContentsMargins(0, self.rescale_h(10), 0, 0)
        icon_layout_middle.setSpacing(0)
        icon_layout_middle.addWidget(self.create_label_with_image(200, 30, ':/images/Ornl_hfir_sns_logo_small.png'))
        icon_layout_middle.addSpacerItem(QSpacerItem(self.rescale_w(40), self.rescale_h(20),
                                                     hPolicy=QSizePolicy.Expanding))
        right_layout.addLayout(icon_layout_middle)
        # Row three
        icon_layout_bottom = QHBoxLayout()
        icon_layout_bottom.setContentsMargins(0, self.rescale_h(10), 0, 0)
        icon_layout_bottom.setSpacing(0)
        icon_layout_bottom.addWidget(self.create_label_with_image(110, 40, ':/images/Tessella_Logo_Transparent.gif'))
        icon_layout_bottom.addSpacerItem(QSpacerItem(self.rescale_w(10), self.rescale_h(20), hPolicy=QSizePolicy.Fixed))
        icon_layout_bottom.addWidget(self.create_label_with_image(50, 50, ':/images/ILL_logo.png'))
        icon_layout_bottom.addSpacerItem(QSpacerItem(self.rescale_w(10), self.rescale_h(20), hPolicy=QSizePolicy.Fixed))
        icon_layout_bottom.addWidget(self.create_label_with_image(92, 50, ':/images/CSNS_Logo_Short.png'))
        icon_layout_bottom.addSpacerItem(QSpacerItem(self.rescale_w(40), self.rescale_h(20),
                                                     hPolicy=QSizePolicy.Expanding))
        right_layout.addLayout(icon_layout_bottom)

        # end the two box layout
        two_box_layout.addLayout(left_layout)
        two_box_layout.addLayout(right_layout)
        parent_layout.addLayout(two_box_layout)

        # footer
        footer_layout = QHBoxLayout()
        # do not show again
        do_not_show_layout = QVBoxLayout()
        do_not_show_layout.setContentsMargins(self.rescale_w(15), 0, 0, 0)
        do_not_show_layout.setSpacing(self.rescale_w(2))
        do_not_show_layout.addSpacerItem(QSpacerItem(1,self.rescale_h(1), vPolicy=QSizePolicy.Expanding))
        lbl_update = QLabel()
        lbl_update.setMinimumSize(self.rescale_w(400),0)
        lbl_update.setStyleSheet("color: rgb(25,125,25);")
        lbl_update.setText('You can revisit this dialog by selecting "About" on the Help menu.')
        lbl_update.setAlignment(Qt.AlignBottom)
        do_not_show_layout.addWidget(lbl_update)

        do_not_show_checkbox_layout = QHBoxLayout()
        self.chk_do_not_show_until_next_release.setChecked(True)
        do_not_show_checkbox_layout.addWidget(self.chk_do_not_show_until_next_release)
        do_not_show_checkbox_layout.addSpacerItem(QSpacerItem(self.rescale_w(10), self.rescale_h(2),
                                                              hPolicy=QSizePolicy.Fixed))
        lbl_do_not_show = QLabel()
        lbl_do_not_show.setStyleSheet("color: rgb(25,125,25);")
        lbl_do_not_show.setText('Do not show again until next release')
        do_not_show_checkbox_layout.addWidget(lbl_do_not_show)
        do_not_show_checkbox_layout.addSpacerItem(QSpacerItem(self.rescale_w(40),10, hPolicy=QSizePolicy.Expanding))
        do_not_show_layout.addLayout(do_not_show_checkbox_layout)
        footer_layout.addLayout(do_not_show_layout)

        # Close button
        close_button_layout = QVBoxLayout()
        close_button_layout.addSpacerItem(QSpacerItem(20,self.rescale_h(15), vPolicy=QSizePolicy.Expanding))
        self.pb_close.setText("Close")
        self.pb_close.setDefault(True)
        close_button_layout.addWidget(self.pb_close)
        footer_layout.addLayout(close_button_layout)
        footer_layout.addSpacerItem(QSpacerItem(self.rescale_w(100), self.rescale_h(20), hPolicy=QSizePolicy.Fixed))
        parent_layout.addLayout(footer_layout)
        self.setLayout(parent_layout)

        self.setAttribute(Qt.WA_DeleteOnClose, True)
Beispiel #59
0
    def __init__(self, parent=None):
        super(KernelConnectionDialog, self).__init__(parent)
        self.setWindowTitle(_('Connect to an existing kernel'))

        main_label = QLabel(_(
            "<p>Please select the JSON connection file (<i>e.g.</i> "
            "<tt>kernel-1234.json</tt>) of the existing kernel, and enter "
            "the SSH information if connecting to a remote machine. "
            "To learn more about starting external kernels and connecting "
            "to them, see <a href=\"https://docs.spyder-ide.org/"
            "ipythonconsole.html#connect-to-an-external-kernel\">"
            "our documentation</a>.</p>"))
        main_label.setWordWrap(True)
        main_label.setAlignment(Qt.AlignJustify)
        main_label.setOpenExternalLinks(True)

        # Connection file
        cf_label = QLabel(_('Connection file:'))
        self.cf = QLineEdit()
        self.cf.setPlaceholderText(_('Kernel connection file path'))
        self.cf.setMinimumWidth(350)
        cf_open_btn = QPushButton(_('Browse'))
        cf_open_btn.clicked.connect(self.select_connection_file)

        cf_layout = QHBoxLayout()
        cf_layout.addWidget(cf_label)
        cf_layout.addWidget(self.cf)
        cf_layout.addWidget(cf_open_btn)

        # Remote kernel groupbox
        self.rm_group = QGroupBox(_("This is a remote kernel (via SSH)"))

        # SSH connection
        hn_label = QLabel(_('Hostname:'))
        self.hn = QLineEdit()
        pn_label = QLabel(_('Port:'))
        self.pn = QLineEdit()
        self.pn.setMaximumWidth(75)
        self.pn.setText('22')
        un_label = QLabel(_('Username:'******'Password:'******'SSH keyfile:'))

        self.pw = QLineEdit()
        self.pw.setEchoMode(QLineEdit.Password)
        self.pw_radio.toggled.connect(self.pw.setEnabled)
        self.kf_radio.toggled.connect(self.pw.setDisabled)

        self.kf = QLineEdit()
        kf_open_btn = QPushButton(_('Browse'))
        kf_open_btn.clicked.connect(self.select_ssh_key)
        kf_layout = QHBoxLayout()
        kf_layout.addWidget(self.kf)
        kf_layout.addWidget(kf_open_btn)

        kfp_label = QLabel(_('Passphase:'))
        self.kfp = QLineEdit()
        self.kfp.setPlaceholderText(_('Optional'))
        self.kfp.setEchoMode(QLineEdit.Password)

        self.kf_radio.toggled.connect(self.kf.setEnabled)
        self.kf_radio.toggled.connect(self.kfp.setEnabled)
        self.kf_radio.toggled.connect(kf_open_btn.setEnabled)
        self.kf_radio.toggled.connect(kfp_label.setEnabled)
        self.pw_radio.toggled.connect(self.kf.setDisabled)
        self.pw_radio.toggled.connect(self.kfp.setDisabled)
        self.pw_radio.toggled.connect(kf_open_btn.setDisabled)
        self.pw_radio.toggled.connect(kfp_label.setDisabled)

        # SSH layout
        ssh_layout = QGridLayout()
        ssh_layout.addWidget(hn_label, 0, 0, 1, 2)
        ssh_layout.addWidget(self.hn, 0, 2)
        ssh_layout.addWidget(pn_label, 0, 3)
        ssh_layout.addWidget(self.pn, 0, 4)
        ssh_layout.addWidget(un_label, 1, 0, 1, 2)
        ssh_layout.addWidget(self.un, 1, 2, 1, 3)

        # SSH authentication layout
        auth_layout = QGridLayout()
        auth_layout.addWidget(self.pw_radio, 1, 0)
        auth_layout.addWidget(pw_label, 1, 1)
        auth_layout.addWidget(self.pw, 1, 2)
        auth_layout.addWidget(self.kf_radio, 2, 0)
        auth_layout.addWidget(kf_label, 2, 1)
        auth_layout.addLayout(kf_layout, 2, 2)
        auth_layout.addWidget(kfp_label, 3, 1)
        auth_layout.addWidget(self.kfp, 3, 2)
        auth_group.setLayout(auth_layout)

        # Remote kernel layout
        rm_layout = QVBoxLayout()
        rm_layout.addLayout(ssh_layout)
        rm_layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 8)))
        rm_layout.addWidget(auth_group)
        self.rm_group.setLayout(rm_layout)
        self.rm_group.setCheckable(True)
        self.rm_group.setChecked(False)
        self.rm_group.toggled.connect(self.pw_radio.setChecked)

        # Ok and Cancel buttons
        self.accept_btns = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal, self)

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

        # Dialog layout
        layout = QVBoxLayout(self)
        layout.addWidget(main_label)
        layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 8)))
        layout.addLayout(cf_layout)
        layout.addSpacerItem(QSpacerItem(QSpacerItem(0, 12)))
        layout.addWidget(self.rm_group)
        layout.addWidget(self.accept_btns)
    def __init__(self, device: Device):
        super(FastCCDController, self).__init__(device)

        camera_layout = QVBoxLayout()
        camera_panel = QGroupBox('Camera State')
        camera_panel.setLayout(camera_layout)

        camera_layout.addWidget(
            PyDMLabel(init_channel=f'ca://{device.cam.state.pvname}'))

        camera_layout.addWidget(
            PyDMPushButton(
                pressValue=1,
                init_channel=f'ca://{device.cam.initialize.setpoint_pvname}',
                label='Initialize'))
        camera_layout.addWidget(
            PyDMPushButton(
                pressValue=1,
                init_channel=f'ca://{device.cam.shutdown.setpoint_pvname}',
                label='Shutdown'))

        dg_layout = QHBoxLayout()
        dg_panel = QGroupBox('Delay Gen State')
        dg_panel.setLayout(dg_layout)

        dg_state_layout = QVBoxLayout()
        dg_layout.addLayout(dg_state_layout)
        dg_state_layout.addWidget(
            PyDMLabel(init_channel=f'ca://{device.dg1.state.pvname}'))

        dg_state_layout.addWidget(
            PyDMPushButton(
                pressValue=1,
                init_channel=f'ca://{device.dg1.initialize.setpoint_pvname}',
                label='Initialize'))
        dg_state_layout.addWidget(
            PyDMPushButton(
                pressValue=1,
                init_channel=f'ca://{device.dg1.reset.setpoint_pvname}',
                label='Reset'))

        dg_shutter_layout = QVBoxLayout()
        dg_layout.addLayout(dg_shutter_layout)
        dg_shutter_layout.addWidget(
            PyDMLabel(
                init_channel=f'ca://{device.dg1.shutter_enabled.pvname}'))
        dg_shutter_layout.addWidget(
            PyDMPushButton(
                pressValue=0,
                init_channel=
                f'ca://{device.dg1.shutter_enabled.setpoint_pvname}',
                label='Enable Trigger'))
        dg_shutter_layout.addWidget(
            PyDMPushButton(
                pressValue=2,
                init_channel=
                f'ca://{device.dg1.shutter_enabled.setpoint_pvname}',
                label='Keep Closed'))
        dg_shutter_layout.addWidget(
            PyDMPushButton(
                pressValue=1,
                init_channel=
                f'ca://{device.dg1.shutter_enabled.setpoint_pvname}',
                label='Keep Open'))

        self.hlayout.addWidget(camera_panel)
        self.hlayout.addWidget(dg_panel)
        self.passive.setVisible(
            False)  # active mode is useless for fastccd at COSMIC-Scattering

        # Subscribe to the error status PV so we can create notifications
        # (only relevant for cam init errors for now)
        self.device.cam.error_status.subscribe(self.report_error, 'value')

        # TODO: pull from settingsplugin
        self.db = Broker.named('local').v2

        happi_settings = plugin_manager.get_plugin_by_name(
            "happi_devices", "SettingsPlugin")

        # Find coupled devices and add them so they'll be used with RE
        def from_device_container(container) -> Device:
            try:
                return from_container(container.device)
            except Exception as e:
                logError(e)
                return None

        self.async_poll_devices = list(
            map(from_device_container,
                happi_settings.search(source='labview')))
        self.async_poll_devices += map(
            from_device_container, happi_settings.search(prefix=device.prefix))

        # Remove errored from_container devices (Nones)
        self.async_poll_devices = list(
            filter(lambda device: device, self.async_poll_devices))

        self.async_poll_devices.remove(device)

        self.metadata["projections"] = [{
            'name': 'NXsas',
            'version': '0.1.0',
            'projection': {
                NXsas.DATA_PROJECTION_KEY: {
                    'type': 'linked',
                    'stream': 'primary',
                    'location': 'event',
                    'field': f"{device.name}_image"
                },
                NXsas.AZIMUTHAL_ANGLE_PROJECTION_KEY: {
                    'type': 'linked',
                    'stream': 'labview',
                    'location': 'event',
                    'field': 'detector_rotate'
                },
                # TODO: source this from somewhere
                NXsas.ENERGY_PROJECTION_KEY: {
                    'type': 'linked',
                    'stream': 'labview',
                    'location': 'event',
                    'field': 'mono_energy'
                },
                NXsas.INCIDENCE_ANGLE_PROJECTION_KEY: {
                    'type': 'linked',
                    'stream': 'labview',
                    'location': 'event',
                    'field': 'sample_rotate_steppertheta'
                },
                # TODO: CHECK IF THIS EXISTS
                # FIXME: Is this the right motor???
                NXsas.DETECTOR_TRANSLATION_X_PROJECTION_KEY: {
                    'type': 'linked',
                    'stream': 'labview',
                    'location': 'event',
                    'field': 'det_translate'
                },
            },
            'configuration': {
                'detector_name': 'fastccd',
                'sdd': 0.5,
                'geometry_mode': 'transmission',
                'poni1': 480,
                'poni2': 1025
            }
        }]