Пример #1
0
def create_window():
    # Create app and widgets
    app = QApplication(sys.argv)
    win = QMainWindow()
    main_area = QWidget()
    button_area = QWidget()
    scroll_area = QScrollArea()
    button = QPushButton("Start Video")
    btn_grab = QPushButton("Grab Frame")

    # Create layouts
    vbox = QVBoxLayout()
    hbox = QHBoxLayout()

    # Fill Layouts
    vbox.addWidget(scroll_area)
    vbox.addWidget(button_area)
    hbox.addStretch()
    hbox.addWidget(button)
    hbox.addWidget(btn_grab)

    # Assign layouts to widgets
    main_area.setLayout(vbox)
    button_area.setLayout(hbox)
    scroll_area.setLayout(QVBoxLayout())

    # Attach some child widgets directly
    win.setCentralWidget(main_area)

    return app, win, button, btn_grab, scroll_area
Пример #2
0
    def __init__(self, parent, model):
        super(AlgorithmMonitorDialog, self).__init__(parent)
        self.tree = QTreeWidget(self)
        self.tree.setColumnCount(3)
        self.tree.setSelectionMode(QTreeWidget.NoSelection)
        self.tree.setColumnWidth(0, 220)
        self.tree.setHeaderLabels(['Algorithm', 'Progress', ''])
        header = self.tree.header()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        header.setSectionResizeMode(2, QHeaderView.Fixed)
        header.setStretchLastSection(False)

        button_layout = QHBoxLayout()
        self.close_button = QPushButton('Close')
        button_layout.addStretch()
        button_layout.addWidget(self.close_button)

        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        layout.addLayout(button_layout)
        self.setLayout(layout)

        self.setWindowTitle('Mantid - Algorithm progress')
        self.setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png"))
        self.resize(500, 300)

        self.presenter = AlgorithmProgressDialogPresenter(self, model)
        self.presenter.update_gui()
Пример #3
0
 def create_combobox(self, text, choices, option, default=NoDefault,
                     tip=None, restart=False):
     """choices: couples (name, key)"""
     label = QLabel(text)
     combobox = QComboBox()
     if tip is not None:
         combobox.setToolTip(tip)
     for name, key in choices:
         if not (name is None and key is None):
             combobox.addItem(name, to_qvariant(key))
     # Insert separators
     count = 0
     for index, item in enumerate(choices):
         name, key = item
         if name is None and key is None:
             combobox.insertSeparator(index + count)
             count += 1
     self.comboboxes[combobox] = (option, default)
     layout = QHBoxLayout()
     layout.addWidget(label)
     layout.addWidget(combobox)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.label = label
     widget.combobox = combobox
     widget.setLayout(layout)
     combobox.restart_required = restart
     combobox.label_text = text
     return widget
Пример #4
0
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.setWindowTitle("Spyder %s: %s" % (__version__,
                                               _("Dependencies")))
        self.setWindowIcon(ima.icon('tooloptions'))
        self.setModal(True)

        self.treewidget = DependenciesTreeWidget(self)

        self.label = QLabel(_("Optional modules are not required to run "
                              "Spyder but enhance its functions."))
        self.label2 = QLabel(_("<b>Note:</b> New dependencies or changed ones "
                               "will be correctly detected only after Spyder "
                               "is restarted."))

        btn = QPushButton(_("Copy to clipboard"), )
        btn.clicked.connect(self.copy_to_clipboard)
        bbox = QDialogButtonBox(QDialogButtonBox.Ok)
        bbox.accepted.connect(self.accept)
        hlayout = QHBoxLayout()
        hlayout.addWidget(btn)
        hlayout.addStretch()
        hlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.treewidget)
        vlayout.addWidget(self.label)
        vlayout.addWidget(self.label2)
        vlayout.addLayout(hlayout)

        self.setLayout(vlayout)
        self.resize(840, 560)
Пример #5
0
 def create_scedit(self, text, option, default=NoDefault, tip=None,
                   without_layout=False):
     label = QLabel(text)
     clayout = ColorLayout(QColor(Qt.black), self)
     clayout.lineedit.setMaximumWidth(80)
     if tip is not None:
         clayout.setToolTip(tip)
     cb_bold = QCheckBox()
     cb_bold.setIcon(ima.icon('bold'))
     cb_bold.setToolTip(_("Bold"))
     cb_italic = QCheckBox()
     cb_italic.setIcon(ima.icon('italic'))
     cb_italic.setToolTip(_("Italic"))
     self.scedits[(clayout, cb_bold, cb_italic)] = (option, default)
     if without_layout:
         return label, clayout, cb_bold, cb_italic
     layout = QHBoxLayout()
     layout.addWidget(label)
     layout.addLayout(clayout)
     layout.addSpacing(10)
     layout.addWidget(cb_bold)
     layout.addWidget(cb_italic)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.setLayout(layout)
     return widget
Пример #6
0
    def __init__(self, parent=None, show_fullpath=True, fullpath_sorting=True,
                 show_all_files=True, show_comments=True, options_button=None):
        QWidget.__init__(self, parent)

        self.treewidget = OutlineExplorerTreeWidget(self,
                                            show_fullpath=show_fullpath,
                                            fullpath_sorting=fullpath_sorting,
                                            show_all_files=show_all_files,
                                            show_comments=show_comments)

        self.visibility_action = create_action(self,
                                           _("Show/hide outline explorer"),
                                           icon='outline_explorer_vis.png',
                                           toggled=self.toggle_visibility)
        self.visibility_action.setChecked(True)
        
        btn_layout = QHBoxLayout()
        for btn in self.setup_buttons():
            btn.setAutoRaise(True)
            btn.setIconSize(QSize(16, 16))
            btn_layout.addWidget(btn)
        if options_button:
            btn_layout.addStretch()
            btn_layout.addWidget(options_button, Qt.AlignRight)

        layout = create_plugin_layout(btn_layout, self.treewidget)
        self.setLayout(layout)
Пример #7
0
    def __init__(self, parent, name_filters=[],
                 show_all=True, show_hscrollbar=True, options_button=None):
        QWidget.__init__(self, parent)

        self.name_filters = name_filters
        self.show_all = show_all
        self.show_hscrollbar = show_hscrollbar

        self.treewidget = ExplorerTreeWidget(self, self.show_hscrollbar)
        self.treewidget.setup(name_filters=self.name_filters,
                              show_all=self.show_all)
        self.treewidget.setup_view()
        self.treewidget.hide()

        self.emptywidget = ExplorerTreeWidget(self)

        if options_button:
            btn_layout = QHBoxLayout()
            btn_layout.setAlignment(Qt.AlignLeft)
            btn_layout.addStretch()
            btn_layout.addWidget(options_button, Qt.AlignRight)
            layout = create_plugin_layout(btn_layout)
        else:
            layout = QVBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.emptywidget)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)
Пример #8
0
class AlgorithmProgressWidget(QWidget):
    """
    Widget consisting of a progress bar and a button.
    """
    def __init__(self, parent=None):
        super(AlgorithmProgressWidget, self).__init__(parent)
        self.progress_bar = None
        self.details_button = QPushButton('Details')
        self.details_button.clicked.connect(self.show_dialog)
        self.layout = QHBoxLayout()
        self.layout.addStretch()
        self.layout.addWidget(self.details_button)
        self.setLayout(self.layout)
        self.presenter = AlgorithmProgressPresenter(self)

    def show_progress_bar(self):
        if self.progress_bar is None:
            self.progress_bar = QProgressBar()
            self.progress_bar.setAlignment(Qt.AlignHCenter)
            self.layout.insertWidget(0, self.progress_bar)
            self.layout.removeItem(self.layout.takeAt(1))

    def hide_progress_bar(self):
        if self.progress_bar is not None:
            self.layout.insertStretch(0)
            self.layout.removeWidget(self.progress_bar)
            self.progress_bar.close()
            self.progress_bar = None

    def show_dialog(self):
        dialog = AlgorithmMonitorDialog(self, self.presenter.model)
        dialog.show()
Пример #9
0
    def setup_and_check(self, data, title=''):
        """
        Setup DataFrameEditor:
        return False if data is not supported, True otherwise
        """
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = to_text_string(title) + " - %s" % data.__class__.__name__
        else:
            title = _("%s editor") % data.__class__.__name__
        if isinstance(data, Series):
            self.is_series = True
            data = data.to_frame()

        self.setWindowTitle(title)
        self.resize(600, 500)

        self.dataModel = DataFrameModel(data, parent=self)
        self.dataTable = DataFrameView(self, self.dataModel)

        self.layout.addWidget(self.dataTable)
        self.setLayout(self.layout)
        self.setMinimumSize(400, 300)
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        btn_layout = QHBoxLayout()

        btn = QPushButton(_("Format"))
        # disable format button for int type
        btn_layout.addWidget(btn)
        btn.clicked.connect(self.change_format)
        btn = QPushButton(_('Resize'))
        btn_layout.addWidget(btn)
        btn.clicked.connect(self.resize_to_contents)

        bgcolor = QCheckBox(_('Background color'))
        bgcolor.setChecked(self.dataModel.bgcolor_enabled)
        bgcolor.setEnabled(self.dataModel.bgcolor_enabled)
        bgcolor.stateChanged.connect(self.change_bgcolor_enable)
        btn_layout.addWidget(bgcolor)

        self.bgcolor_global = QCheckBox(_('Column min/max'))
        self.bgcolor_global.setChecked(self.dataModel.colum_avg_enabled)
        self.bgcolor_global.setEnabled(not self.is_series and
                                       self.dataModel.bgcolor_enabled)
        self.bgcolor_global.stateChanged.connect(self.dataModel.colum_avg)
        btn_layout.addWidget(self.bgcolor_global)

        btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        btn_layout.addWidget(bbox)

        self.layout.addLayout(btn_layout, 2, 0)

        return True
Пример #10
0
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.main = parent

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

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

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

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

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

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

        self.setLayout(vlayout)

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

        # Ensures that the config is present on spyder first run
        CONF.set('main', 'interface_language', load_lang_conf())
Пример #11
0
    def __init__(self, text, title='', font=None, parent=None,
                 readonly=False, size=(400, 300)):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        self.text = None
        self.btn_save_and_close = None
        
        # Display text as unicode if it comes as bytes, so users see 
        # its right representation
        if is_binary_string(text):
            self.is_binary = True
            text = to_text_string(text, 'utf8')
        else:
            self.is_binary = False
        
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        # Text edit
        self.edit = QTextEdit(parent)
        self.edit.setReadOnly(readonly)
        self.edit.textChanged.connect(self.text_changed)
        self.edit.setPlainText(text)
        if font is None:
            font = get_font()
        self.edit.setFont(font)
        self.layout.addWidget(self.edit)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        btn_layout.addStretch()
        if not readonly:
            self.btn_save_and_close = QPushButton(_('Save and Close'))
            self.btn_save_and_close.setDisabled(True)
            self.btn_save_and_close.clicked.connect(self.accept)
            btn_layout.addWidget(self.btn_save_and_close)

        self.btn_close = QPushButton(_('Close'))
        self.btn_close.setAutoDefault(True)
        self.btn_close.setDefault(True)
        self.btn_close.clicked.connect(self.reject)
        btn_layout.addWidget(self.btn_close)

        self.layout.addLayout(btn_layout)

        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        
        self.setWindowIcon(ima.icon('edit'))
        self.setWindowTitle(_("Text editor") + \
                            "%s" % (" - "+str(title) if str(title) else ""))
        self.resize(size[0], size[1])
Пример #12
0
 def add_button_box(self, stdbtns):
     """Create dialog button box and add it to the dialog layout"""
     bbox = QDialogButtonBox(stdbtns)
     run_btn = bbox.addButton(_("Run"), QDialogButtonBox.AcceptRole)
     run_btn.clicked.connect(self.run_btn_clicked)
     bbox.accepted.connect(self.accept)
     bbox.rejected.connect(self.reject)
     btnlayout = QHBoxLayout()
     btnlayout.addStretch(1)
     btnlayout.addWidget(bbox)
     self.layout().addLayout(btnlayout)
Пример #13
0
    def __init__(self, parent=None, namespace=None, commands=[], message=None,
                 exitfunc=None, profile=False, multithreaded=False):
        SpyderPluginWidget.__init__(self, parent)

        logger.info("Initializing...")
        self.dialog_manager = DialogManager()

        # Shell
        light_background = self.get_option('light_background')
        self.shell = InternalShell(parent, namespace, commands, message,
                                   self.get_option('max_line_count'),
                                   self.get_plugin_font(), exitfunc, profile,
                                   multithreaded,
                                   light_background=light_background)
        self.shell.status.connect(lambda msg: self.show_message.emit(msg, 0))
        self.shell.go_to_error.connect(self.go_to_error)
        self.shell.focus_changed.connect(lambda: self.focus_changed.emit())

        # Redirecting some signals:
        self.shell.redirect_stdio.connect(lambda state:
                                          self.redirect_stdio.emit(state))
        
        # Initialize plugin
        self.initialize_plugin()

        # Find/replace widget
        self.find_widget = FindReplace(self)
        self.find_widget.set_editor(self.shell)
        self.find_widget.hide()
        self.register_widget_shortcuts(self.find_widget)

        # Main layout
        btn_layout = QHBoxLayout()
        btn_layout.setAlignment(Qt.AlignLeft)
        btn_layout.addStretch()
        btn_layout.addWidget(self.options_button, Qt.AlignRight)
        layout = create_plugin_layout(btn_layout)
        layout.addWidget(self.shell)
        layout.addWidget(self.find_widget)
        self.setLayout(layout)
        
        # Parameters
        self.shell.toggle_wrap_mode(self.get_option('wrap'))
            
        # Accepting drops
        self.setAcceptDrops(True)

        # Traceback MessageBox
        self.error_dlg = None
        self.error_traceback = ""
        self.dismiss_error = False
Пример #14
0
 def create_coloredit(self, text, option, default=NoDefault, tip=None,
                      without_layout=False):
     label = QLabel(text)
     clayout = ColorLayout(QColor(Qt.black), self)
     clayout.lineedit.setMaximumWidth(80)
     if tip is not None:
         clayout.setToolTip(tip)
     self.coloredits[clayout] = (option, default)
     if without_layout:
         return label, clayout
     layout = QHBoxLayout()
     layout.addWidget(label)
     layout.addLayout(clayout)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.setLayout(layout)
     return widget
Пример #15
0
 def __init__(self, parent=None):
     super(ConnectionInspector, self).__init__(parent, Qt.Window)
     connections = self.fetch_data()
     self.table_view = ConnectionTableView(connections, self)
     self.setLayout(QVBoxLayout(self))
     self.layout().addWidget(self.table_view)
     button_layout = QHBoxLayout()
     self.layout().addItem(button_layout)
     self.save_status_label = QLabel(self)
     button_layout.addWidget(self.save_status_label)
     button_layout.addStretch()
     self.save_button = QPushButton(self)
     self.save_button.setText("Save list to file...")
     self.save_button.clicked.connect(self.save_list_to_file)
     button_layout.addWidget(self.save_button)
     self.update_timer = QTimer(parent=self)
     self.update_timer.setInterval(1500)
     self.update_timer.timeout.connect(self.update_data)
     self.update_timer.start()
Пример #16
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
Пример #17
0
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.setWindowTitle("Spyder %s: %s" % (__version__,
                                               _("Dependencies")))
        self.setWindowIcon(ima.icon('tooloptions'))
        self.setModal(True)

        self.view = DependenciesTableView(self, [])

        opt_mods = ['NumPy', 'Matplotlib', 'Pandas', 'SymPy']
        self.label = QLabel(_("Spyder depends on several Python modules to "
                              "provide the right functionality for all its "
                              "panes. The table below shows the required "
                              "and installed versions (if any) of all of "
                              "them.<br><br>"
                              "<b>Note</b>: You can safely use Spyder "
                              "without the following modules installed: "
                              "<b>%s</b> and <b>%s</b>.<br><br>"
                              "Please also note that new "
                              "dependencies or changed ones will be correctly "
                              "detected only after Spyder is restarted.")
                              % (', '.join(opt_mods[:-1]), opt_mods[-1]))
        self.label.setWordWrap(True)
        self.label.setAlignment(Qt.AlignJustify)
        self.label.setContentsMargins(5, 8, 12, 10)

        btn = QPushButton(_("Copy to clipboard"), )
        btn.clicked.connect(self.copy_to_clipboard)
        bbox = QDialogButtonBox(QDialogButtonBox.Ok)
        bbox.accepted.connect(self.accept)
        hlayout = QHBoxLayout()
        hlayout.addWidget(btn)
        hlayout.addStretch()
        hlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(self.label)
        vlayout.addWidget(self.view)
        vlayout.addLayout(hlayout)

        self.setLayout(vlayout)
        self.resize(630, 420)
Пример #18
0
    def create_controls(self):
        self.setWindowTitle(tr("Updating via pip"))

        wFlags = self.windowFlags()
        if Qt.WindowCloseButtonHint == (wFlags & Qt.WindowCloseButtonHint):
            wFlags ^= Qt.WindowCloseButtonHint
            self.setWindowFlags(wFlags)
        vbox = QVBoxLayout()
        self.output = QTextEdit()
        if self.parent() and hasattr(self.parent(), 'console'):
            self.output.setFont(self.parent().console.font)
        vbox.addWidget(self.output)
        hbox = QHBoxLayout()
        hbox.addStretch()
        self.btn_close = QPushButton(tr("Close"))
        self.btn_close.clicked.connect(self.accept)
        self.btn_close.setEnabled(False)
        hbox.addWidget(self.btn_close)
        vbox.addLayout(hbox)
        self.setLayout(vbox)
Пример #19
0
    def _init_ui(self):
        # LINE 1: Data component drop down
        self.component_prompt = QLabel("Data Component:")
        self.component_prompt.setWordWrap(True)
        # Add the data component labels to the drop down, with the ComponentID
        # set as the userData:
        if self.parent is not None and hasattr(self.parent, 'data_components'):
            self.label_data = [(str(cid), cid) for cid in self.parent.data_components]
        else:
            self.label_data = [(str(cid), cid) for cid in self.data.visible_components]

        default_index = 0
        self.component_combo = QComboBox()
        self.component_combo.setFixedWidth(200)
        update_combobox(self.component_combo, self.label_data, default_index=default_index)
        self.component_combo.currentIndexChanged.connect(self.update_unit_layout)

        # hbl is short for Horizontal Box Layout
        hbl1 = QHBoxLayout()
        hbl1.addWidget(self.component_prompt)
        hbl1.addWidget(self.component_combo)
        hbl1.addStretch(1)

        # LINE 2: Unit conversion layout
        # This layout is filled by CubeVizUnit
        self.unit_layout = QHBoxLayout()  # this is hbl2

        # LINE 3: Message box
        self.message_box = QLabel("")
        hbl3 = QHBoxLayout()
        hbl3.addWidget(self.message_box)
        hbl3.addStretch(1)

        # Line 4: Buttons
        ok_text = "Convert Data" if self.convert_data else "Convert Displayed Units"
        ok_function = self.convert_data_units if self.convert_data else self.convert_displayed_units
        self.okButton = QPushButton(ok_text)
        self.okButton.clicked.connect(ok_function)
        self.okButton.setDefault(True)

        self.cancelButton = QPushButton("Cancel")
        self.cancelButton.clicked.connect(self.cancel)

        hbl4 = QHBoxLayout()
        hbl4.addStretch(1)
        hbl4.addWidget(self.cancelButton)
        hbl4.addWidget(self.okButton)

        vbl = QVBoxLayout()
        vbl.addLayout(hbl1)
        vbl.addLayout(self.unit_layout)
        vbl.addLayout(hbl3)
        vbl.addLayout(hbl4)
        self.setLayout(vbl)
        self.vbl = vbl

        self.update_unit_layout(default_index)

        self.show()
Пример #20
0
 def create_spinbox(self, prefix, suffix, option, default=NoDefault,
                    min_=None, max_=None, step=None, tip=None):
     widget = QWidget(self)
     if prefix:
         plabel = QLabel(prefix)
         widget.plabel = plabel
     else:
         plabel = None
     if suffix:
         slabel = QLabel(suffix)
         widget.slabel = slabel
     else:
         slabel = None
     if step is not None:
         if type(step) is int:
             spinbox = QSpinBox()
         else:
             spinbox = QDoubleSpinBox()
             spinbox.setDecimals(1)
         spinbox.setSingleStep(step)
     else:
         spinbox = QSpinBox()
     if min_ is not None:
         spinbox.setMinimum(min_)
     if max_ is not None:
         spinbox.setMaximum(max_)
     if tip is not None:
         spinbox.setToolTip(tip)
     self.spinboxes[spinbox] = (option, default)
     layout = QHBoxLayout()
     for subwidget in (plabel, spinbox, slabel):
         if subwidget is not None:
             layout.addWidget(subwidget)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget.spinbox = spinbox
     widget.setLayout(layout)
     return widget
Пример #21
0
    def final_dialog(self, label):
        """
        Final dialog that to show where the calculated collapsed cube was put.

        :param label:
        :return:
        """

        final_dialog = QDialog()

        # Create data component label and input box
        widget_desc = QLabel('The collapsed cube was added as an overlay with label "{}". {}'.format(
            label, self._extra_message))
        widget_desc.setWordWrap(True)
        widget_desc.setFixedWidth(350)
        widget_desc.setAlignment((Qt.AlignLeft | Qt.AlignTop))

        hb_desc = QHBoxLayout()
        hb_desc.addWidget(widget_desc)

        # Create Ok button
        okButton = QPushButton("Ok")
        okButton.clicked.connect(lambda: final_dialog.close())
        okButton.setDefault(True)

        hb_buttons = QHBoxLayout()
        hb_buttons.addStretch(1)
        hb_buttons.addWidget(okButton)

        # Add description and buttons to popup box
        vbl = QVBoxLayout()
        vbl.addLayout(hb_desc)
        vbl.addLayout(hb_buttons)

        final_dialog.setLayout(vbl)
        final_dialog.setMaximumWidth(400)
        final_dialog.show()
Пример #22
0
    def add_new_row(self, _metadata, row=0):

        self.main_window.postprocessing_ui.table.insertRow(row)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        _widget.setEnabled(True)
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)

        _widget.stateChanged.connect(lambda state=0, row=row:
                                     self.parent.table_select_state_changed(state, row))
        self.main_window_postprocessing_ui.table.setCellWidget(row, 0, _new_widget)

        _item = QTableWidgetItem(_metadata['name'])
        self.main_window_postprocessing_ui.table.setItem(row, 1, _item)

        _item = QTableWidgetItem(_metadata['runs'])
        self.main_window_postprocessing_ui.table.setItem(row, 2, _item)

        if not _metadata['sample_formula']:
            _item = QTableWidgetItem(_metadata['sample_formula'])
            self.main_window_postprocessing_ui.table.setItem(row, 3, _item)

        if not _metadata['mass_density']:
            _item = QTableWidgetItem(_metadata['mass_density'])
            self.main_window_postprocessing_ui.table.setItem(row, 4, _item)

        if not _metadata['radius']:
            _item = QTableWidgetItem(_metadata['radius'])
            self.main_window_postprocessing_ui.table.setItem(row, 5, _item)

        if not _metadata['packing_fraction']:
            _item = QTableWidgetItem(_metadata['packing_fraction'])
            self.main_window_postprocessing_ui.table.setItem(row, 6, _item)

        _widget = QComboBox()
        _widget.addItem("cylindrical")
        _widget.addItem("spherical")
        if _metadata['sample_shape'] == 'spherical':
            _widget.setCurrentIndex(1)
        self.main_window_postprocessing_ui.table.setCellWidget(row, 7, _widget)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        if _metadata['do_abs_correction'] == 'go':
            _widget.setCheckState(Qt.Checked)
        _widget.setStyleSheet("border:  2px; solid-black")
        _widget.setEnabled(True)
        _layout.addStretch()
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        self.main_window_postprocessing_ui.table.setCellWidget(row, 8, _new_widget)
Пример #23
0
 def __init__(self, parent, options_button=None):
     QWidget.__init__(self, parent)
     
     self.setWindowTitle("Breakpoints")        
     self.dictwidget = BreakpointTableView(self, 
                            self._load_all_breakpoints())
     if options_button:
         btn_layout = QHBoxLayout()
         btn_layout.setAlignment(Qt.AlignLeft)
         btn_layout.addStretch()
         btn_layout.addWidget(options_button, Qt.AlignRight)
         layout = create_plugin_layout(btn_layout, self.dictwidget)
     else:
         layout = QVBoxLayout()
         layout.addWidget(self.dictwidget)
     self.setLayout(layout)
     self.dictwidget.clear_all_breakpoints.connect(
                                  lambda: self.clear_all_breakpoints.emit())
     self.dictwidget.clear_breakpoint.connect(
                      lambda s1, lino: self.clear_breakpoint.emit(s1, lino))
     self.dictwidget.edit_goto.connect(
                     lambda s1, lino, s2: self.edit_goto.emit(s1, lino, s2))
     self.dictwidget.set_or_edit_conditional_breakpoint.connect(
                     lambda: self.set_or_edit_conditional_breakpoint.emit())
Пример #24
0
    def setup_widgets_for_orientation(self, new_orientation):
        """
        Reconstruct the widget given the orientation.

        Parameters
        ----------
        new_orientation : int
            Qt.Horizontal or Qt.Vertical
        """
        if new_orientation not in (Qt.Horizontal, Qt.Vertical):
            logger.error("Invalid orientation '{0}'. The existing layout will not change.".format(new_orientation))
            return

        layout = None
        if new_orientation == Qt.Horizontal:
            layout = QVBoxLayout()
            layout.setContentsMargins(4, 0, 4, 4)
            label_layout = QHBoxLayout()
            label_layout.addWidget(self.low_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.high_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)
        elif new_orientation == Qt.Vertical:
            layout = QHBoxLayout()
            layout.setContentsMargins(0, 4, 4, 4)
            label_layout = QVBoxLayout()
            label_layout.addWidget(self.high_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.low_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)

        if self.layout() is not None:
            # Trick to remove the existing layout by re-parenting it in an empty widget.
            QWidget().setLayout(self.layout())
        self.setLayout(layout)
Пример #25
0
    def __init__(self, parent, opacity, duration, easing_curve, tour=None):
        super(FadingTipBox, self).__init__(parent, opacity, duration,
                                           easing_curve)
        self.holder = self.anim  # needed for qt to work
        self.parent = parent
        self.tour = tour

        self.frames = None
        self.color_top = QColor.fromRgb(230, 230, 230)
        self.color_back = QColor.fromRgb(255, 255, 255)
        self.offset_shadow = 0
        self.fixed_width = 300

        self.key_pressed = None

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint |
                            Qt.WindowStaysOnTopHint)
        self.setModal(False)

        # Widgets
        def toolbutton(icon):
            bt = QToolButton()
            bt.setAutoRaise(True)
            bt.setIcon(icon)
            return bt

        self.button_close = toolbutton(ima.icon("tour.close"))
        self.button_home = toolbutton(ima.icon("tour.home"))
        self.button_previous = toolbutton(ima.icon("tour.previous"))
        self.button_end = toolbutton(ima.icon("tour.end"))
        self.button_next = toolbutton(ima.icon("tour.next"))
        self.button_run = QPushButton(_('Run code'))
        self.button_disable = None
        self.button_current = QToolButton()
        self.label_image = QLabel()

        self.label_title = QLabel()
        self.combo_title = QComboBox()
        self.label_current = QLabel()
        self.label_content = QLabel()

        self.label_content.setMinimumWidth(self.fixed_width)
        self.label_content.setMaximumWidth(self.fixed_width)

        self.label_current.setAlignment(Qt.AlignCenter)

        self.label_content.setWordWrap(True)

        self.widgets = [self.label_content, self.label_title,
                        self.label_current, self.combo_title,
                        self.button_close, self.button_run, self.button_next,
                        self.button_previous, self.button_end,
                        self.button_home, self.button_current]

        arrow = get_image_path('hide.png')

        self.stylesheet = '''QComboBox {
                             padding-left: 5px;
                             background-color: rgbs(230,230,230,100%);
                             border-width: 0px;
                             border-radius: 0px;
                             min-height:20px;
                             max-height:20px;
                             }

                             QComboBox::drop-down  {
                             subcontrol-origin: padding;
                             subcontrol-position: top left;
                             border-width: 0px;
                             }
                             
                             QComboBox::down-arrow {
                             image: url(''' + arrow + ''');
                             }
                             
                             '''
        # Windows fix, slashes should be always in unix-style
        self.stylesheet = self.stylesheet.replace('\\', '/')

        self.setFocusPolicy(Qt.StrongFocus)
        for widget in self.widgets:
            widget.setFocusPolicy(Qt.NoFocus)
            widget.setStyleSheet(self.stylesheet)

        layout_top = QHBoxLayout()
        layout_top.addWidget(self.combo_title)
        layout_top.addStretch()
        layout_top.addWidget(self.button_close)
        layout_top.addSpacerItem(QSpacerItem(self.offset_shadow,
                                             self.offset_shadow))

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.label_content)
        layout_content.addWidget(self.label_image)
        layout_content.addSpacerItem(QSpacerItem(5, 5))

        layout_run = QHBoxLayout()
        layout_run.addStretch()
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        layout_run.addSpacerItem(QSpacerItem(self.offset_shadow,
                                             self.offset_shadow))

        layout_navigation = QHBoxLayout()
        layout_navigation.addWidget(self.button_home)
        layout_navigation.addWidget(self.button_previous)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.label_current)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.button_next)
        layout_navigation.addWidget(self.button_end)
        layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow,
                                                    self.offset_shadow))

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_content)
        layout.addLayout(layout_run)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_navigation)
        layout.addSpacerItem(QSpacerItem(self.offset_shadow,
                                         self.offset_shadow))

        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.setLayout(layout)

        self.set_funcs_before_fade_in([self._disable_widgets])
        self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus])
        self.set_funcs_before_fade_out([self._disable_widgets])

        self.setContextMenuPolicy(Qt.CustomContextMenu)
Пример #26
0
    def _init_ui(self):

        # Line 1: Color map
        self.colormap_label = QLabel("Color Scheme: ")

        self.colormap_combo = QColormapCombo()
        self.colormap_combo.addItem("", userData=cm.viridis)
        self.colormap_combo._update_icons()
        self.colormap_combo.setCurrentIndex(self._colormap_index)
        self.colormap_combo.setMaximumWidth(150)
        self.colormap_combo.currentIndexChanged.connect(
            self._on_colormap_change)

        #   hbl is short for Horizontal Box Layout
        hbl1 = QHBoxLayout()
        hbl1.addWidget(self.colormap_label)
        hbl1.addWidget(self.colormap_combo)

        # Line 2: Display contour labels
        self.contour_label_checkBox = QCheckBox("Contour labels (font size):")
        if self.contour_settings.add_contour_label:
            self.contour_label_checkBox.setChecked(True)
        self.contour_label_checkBox.toggled.connect(self.toggle_labels)

        font_string = str(self.contour_settings.font_size)
        self.font_size_input = QLineEdit(font_string)
        self.font_size_input.setFixedWidth(150)
        self.font_size_input.setDisabled(
            not self.contour_settings.add_contour_label)

        hbl2 = QHBoxLayout()
        hbl2.addWidget(self.contour_label_checkBox)
        hbl2.addWidget(self.font_size_input)

        # Line 3: Contour Spacing
        self.custom_spacing_checkBox = QCheckBox("Contour spacing (interval):")
        if self.is_custom_spacing:
            self.custom_spacing_checkBox.setChecked(True)
        self.custom_spacing_checkBox.toggled.connect(self.custom_spacing)

        self.spacing_input = QLineEdit()
        self.spacing_input.setFixedWidth(150)
        self.spacing_input.setDisabled(not self.is_custom_spacing)
        spacing = ""
        if self.is_custom_spacing:
            spacing = str(self.contour_settings.spacing)
        elif self.contour_settings.data_spacing is not None:
            spacing = self.contour_settings.data_spacing
            spacing = "{0:1.4f}".format(spacing)
        self.spacing_default_text = spacing
        self.spacing_input.setText(spacing)

        hbl3 = QHBoxLayout()
        hbl3.addWidget(self.custom_spacing_checkBox)
        hbl3.addWidget(self.spacing_input)

        # Line 4: Vmax
        self.vmax_checkBox = QCheckBox("Set max:")

        self.vmax_input = QLineEdit()
        self.vmax_input.setFixedWidth(150)
        self.vmax_input.setDisabled(not self.is_vmax)

        vmax = ""
        if self.is_vmax:
            self.vmax_checkBox.setChecked(True)
            vmax = str(self.contour_settings.vmax)
        elif self.contour_settings.data_max is not None:
            vmax = self.contour_settings.data_max
            vmax = "{0:1.4f}".format(vmax)
        self.vmax_input.setText(vmax)
        self.vmax_default_text = vmax

        self.vmax_checkBox.toggled.connect(self.toggle_vmax)

        hbl4 = QHBoxLayout()
        hbl4.addWidget(self.vmax_checkBox)
        hbl4.addWidget(self.vmax_input)

        # Line 5: Vmin
        self.vmin_checkBox = QCheckBox("Set min:")

        self.vmin_input = QLineEdit()
        self.vmin_input.setFixedWidth(150)
        self.vmin_input.setDisabled(not self.is_vmin)

        vmin = ""
        if self.is_vmin:
            self.vmin_checkBox.setChecked(True)
            vmin = str(self.contour_settings.vmin)
        elif self.contour_settings.data_min is not None:
            vmin = self.contour_settings.data_min
            vmin = "{0:1.4f}".format(vmin)
        self.vmin_input.setText(vmin)
        self.vmin_default_text = vmin

        self.vmin_checkBox.toggled.connect(self.toggle_vmin)

        hbl5 = QHBoxLayout()
        hbl5.addWidget(self.vmin_checkBox)
        hbl5.addWidget(self.vmin_input)

        # Line f:
        self.previewButton = QPushButton("Preview")
        self.previewButton.clicked.connect(self.preview)

        self.defaultButton = QPushButton("Reset")
        self.defaultButton.clicked.connect(self.default)

        self.okButton = QPushButton("OK")
        self.okButton.clicked.connect(self.finish)
        self.okButton.setDefault(True)

        self.cancelButton = QPushButton("Cancel")
        self.cancelButton.clicked.connect(self.cancel)

        hblf = QHBoxLayout()
        hblf.addStretch(1)
        hblf.addWidget(self.previewButton)
        hblf.addWidget(self.defaultButton)
        hblf.addWidget(self.cancelButton)
        hblf.addWidget(self.okButton)

        vbl = QVBoxLayout()
        vbl.addLayout(hbl1)
        vbl.addLayout(hbl2)
        vbl.addLayout(hbl3)
        vbl.addLayout(hbl4)
        vbl.addLayout(hbl5)
        vbl.addLayout(hblf)

        self.setLayout(vbl)

        self.show()
Пример #27
0
    def _setupUi(self):
        ld_maindev = QLabel('<h3>General Settings</h3>',
                            self,
                            alignment=Qt.AlignCenter)

        # # Delay Lines
        ld_adcclock = QLabel('ADC Clock', self)
        sb_adcclock = PyDMSpinbox(self, self.dev_pref + ':ECLDEL0')
        sb_adcclock.showStepExponent = False
        fr_adcclock = SiriusFrame(self, self.dev_pref + ':ECLDEL0_SUBWR')
        fr_adcclock.add_widget(sb_adcclock)

        ld_fidclock = QLabel('Fiducial Clock', self)
        sb_fidclock = PyDMSpinbox(self, self.dev_pref + ':ECLDEL1')
        sb_fidclock.showStepExponent = False
        fr_fidclock = SiriusFrame(self, self.dev_pref + ':ECLDEL1_SUBWR')
        fr_fidclock.add_widget(sb_fidclock)

        ld_fiducial = QLabel('Fiducial', self)
        sb_fiducial = PyDMSpinbox(self, self.dev_pref + ':ECLDEL2')
        sb_fiducial.showStepExponent = False
        fr_fiducial = SiriusFrame(self, self.dev_pref + ':ECLDEL2_SUBWR')
        fr_fiducial.add_widget(sb_fiducial)

        ld_dacclock = QLabel('DAC Clock', self)
        sb_dacclock = PyDMSpinbox(self, self.dev_pref + ':ECLDEL3')
        sb_dacclock.showStepExponent = False
        fr_dacclock = SiriusFrame(self, self.dev_pref + ':ECLDEL3_SUBWR')
        fr_dacclock.add_widget(sb_dacclock)

        gbox_delaylines = QGroupBox('Delay lines', self)
        lay_delaylines = QGridLayout(gbox_delaylines)
        lay_delaylines.addWidget(ld_adcclock, 0, 0)
        lay_delaylines.addWidget(fr_adcclock, 0, 1)
        lay_delaylines.addWidget(ld_fidclock, 1, 0)
        lay_delaylines.addWidget(fr_fidclock, 1, 1)
        lay_delaylines.addWidget(ld_fiducial, 2, 0)
        lay_delaylines.addWidget(fr_fiducial, 2, 1)
        lay_delaylines.addWidget(ld_dacclock, 3, 0)
        lay_delaylines.addWidget(fr_dacclock, 3, 1)

        # # Thresholds and offsets
        ld_lvl = QLabel('<h4>Level</h4>', self, alignment=Qt.AlignCenter)
        ld_enbl = QLabel('<h4>Enbl</h4>', self, alignment=Qt.AlignCenter)
        ld_v = QLabel('<h4>V</h4>', self, alignment=Qt.AlignCenter)
        ld_edge = QLabel('<h4>Edge</h4>', self, alignment=Qt.AlignCenter)

        ld_fid = QLabel('Fiducial', self)
        cb_fidlvl = PyDMEnumComboBox(self, self.dev_pref + ':LEVEL_FID')
        cb_fidlvlenbl = PyDMEnumComboBox(self,
                                         self.dev_pref + ':LEVEL_FID_ENABLE')
        cb_fidlvlenbl.setStyleSheet('max-width:3em;')
        sb_fidv = PyDMSpinbox(self, self.dev_pref + ':AD5644_V_CH9')
        sb_fidv.showStepExponent = False
        sb_fidv.showUnits = True
        fr_fidv = SiriusFrame(self, self.dev_pref + ':AD5644CH9_SUBWR')
        fr_fidv.add_widget(sb_fidv)

        ld_trg1 = QLabel('Trigger 1', self)
        cb_trg1lvl = PyDMEnumComboBox(self, self.dev_pref + ':LEVEL_TRIG1')
        cb_trg1lvlenbl = PyDMEnumComboBox(
            self, self.dev_pref + ':LEVEL_TRIG1_ENABLE')
        cb_trg1lvlenbl.setStyleSheet('max-width:3em;')
        sb_trg1lvlv = PyDMSpinbox(self, self.dev_pref + ':LEVEL_VTRIG1')
        sb_trg1lvlv.showStepExponent = False
        sb_trg1lvlv.showUnits = True
        fr_trg1lvlv = SiriusFrame(self, self.dev_pref + ':AD5644CH10_SUBWR')
        fr_trg1lvlv.add_widget(sb_trg1lvlv)
        cb_trg1edge = PyDMEnumComboBox(self, self.dev_pref + ':TRIG1INV')
        cb_trg1edge.setStyleSheet('max-width:3.2em;')

        ld_trg2 = QLabel('Trigger 2', self)
        cb_trg2lvl = PyDMEnumComboBox(self, self.dev_pref + ':LEVEL_TRIG2')
        cb_trg2lvlenbl = PyDMEnumComboBox(
            self, self.dev_pref + ':LEVEL_TRIG2_ENABLE')
        cb_trg2lvlenbl.setStyleSheet('max-width:3em;')
        sb_trg2lvlv = PyDMSpinbox(self, self.dev_pref + ':LEVEL_VTRIG2')
        sb_trg2lvlv.showStepExponent = False
        sb_trg2lvlv.showUnits = True
        fr_trg2lvlv = SiriusFrame(self, self.dev_pref + ':AD5644CH8_SUBWR')
        fr_trg2lvlv.add_widget(sb_trg2lvlv)
        cb_trg2edge = PyDMEnumComboBox(self, self.dev_pref + ':TRIG2INV')
        cb_trg2edge.setStyleSheet('max-width:3.2em;')

        ld_dacoff = QLabel('DAC Offset', self)
        sb_dacoff = PyDMSpinbox(self, self.dev_pref + ':AD5644_V_CH11')
        sb_dacoff.showStepExponent = False
        sb_dacoff.showUnits = True
        fr_dacoff = SiriusFrame(self, self.dev_pref + ':AD5644CH11_SUBWR')
        fr_dacoff.add_widget(sb_dacoff)

        gbox_thoff = QGroupBox('Thresholds and Offsets', self)
        lay_thoff = QGridLayout(gbox_thoff)
        lay_thoff.addWidget(ld_lvl, 0, 1)
        lay_thoff.addWidget(ld_enbl, 0, 2)
        lay_thoff.addWidget(ld_v, 0, 3)
        lay_thoff.addWidget(ld_edge, 0, 4)
        lay_thoff.addWidget(ld_fid, 1, 0)
        lay_thoff.addWidget(cb_fidlvl, 1, 1)
        lay_thoff.addWidget(cb_fidlvlenbl, 1, 2)
        lay_thoff.addWidget(fr_fidv, 1, 3)
        lay_thoff.addWidget(ld_trg1, 2, 0)
        lay_thoff.addWidget(cb_trg1lvl, 2, 1)
        lay_thoff.addWidget(cb_trg1lvlenbl, 2, 2)
        lay_thoff.addWidget(fr_trg1lvlv, 2, 3)
        lay_thoff.addWidget(cb_trg1edge, 2, 4)
        lay_thoff.addWidget(ld_trg2, 3, 0)
        lay_thoff.addWidget(cb_trg2lvl, 3, 1)
        lay_thoff.addWidget(cb_trg2lvlenbl, 3, 2)
        lay_thoff.addWidget(fr_trg2lvlv, 3, 3)
        lay_thoff.addWidget(cb_trg2edge, 3, 4)
        lay_thoff.addWidget(ld_dacoff, 4, 0)
        lay_thoff.addWidget(fr_dacoff, 4, 3)
        lay_thoff.setColumnStretch(0, 3)
        lay_thoff.setColumnStretch(1, 2)
        lay_thoff.setColumnStretch(2, 1)
        lay_thoff.setColumnStretch(3, 5)
        lay_thoff.setColumnStretch(4, 1)

        # # FIR
        ld_sfir = QLabel('Shaper FIR ([C0 2^17 C2])', self)

        ld_firc0 = QLabel('C0', self)
        sb_firc0 = PyDMSpinbox(self, self.dev_pref + ':SHAPE_C0')
        sb_firc0.showStepExponent = False
        fr_firc0 = SiriusFrame(self, self.dev_pref + ':SHAPE_C0_SUBWR')
        fr_firc0.add_widget(sb_firc0)

        ld_firc2 = QLabel('C2', self)
        sb_firc2 = PyDMSpinbox(self, self.dev_pref + ':SHAPE_C2')
        sb_firc2.showStepExponent = False
        fr_firc2 = SiriusFrame(self, self.dev_pref + ':SHAPE_C2_SUBWR')
        fr_firc2.add_widget(sb_firc2)

        lay_fir = QHBoxLayout()
        lay_fir.addStretch()
        lay_fir.addWidget(ld_sfir)
        lay_fir.addStretch()
        lay_fir.addWidget(ld_firc0)
        lay_fir.addWidget(fr_firc0)
        lay_fir.addStretch()
        lay_fir.addWidget(ld_firc2)
        lay_fir.addWidget(fr_firc2)
        lay_fir.addStretch()

        lay = QGridLayout(self)
        lay.addWidget(ld_maindev, 0, 1, 1, 2)
        lay.addWidget(gbox_delaylines, 1, 1)
        lay.addWidget(gbox_thoff, 1, 2)
        lay.addLayout(lay_fir, 2, 1, 1, 2)
        lay.setColumnStretch(0, 3)
        lay.setColumnStretch(3, 3)
        lay.setRowStretch(3, 3)

        self.setStyleSheet("""SiriusFrame{max-height: 1.8em;}""")
Пример #28
0
    def setup(self,
              check_all=None,
              exclude_private=None,
              exclude_uppercase=None,
              exclude_capitalized=None,
              exclude_unsupported=None,
              excluded_names=None,
              minmax=None,
              dataframe_format=None):
        """
        Setup the namespace browser with provided settings.

        Args:
            dataframe_format (string): default floating-point format for 
                DataFrame editor
        """
        assert self.shellwidget is not None

        self.check_all = check_all
        self.exclude_private = exclude_private
        self.exclude_uppercase = exclude_uppercase
        self.exclude_capitalized = exclude_capitalized
        self.exclude_unsupported = exclude_unsupported
        self.excluded_names = excluded_names
        self.minmax = minmax
        self.dataframe_format = dataframe_format

        if self.editor is not None:
            self.editor.setup_menu(minmax)
            self.editor.set_dataframe_format(dataframe_format)
            self.exclude_private_action.setChecked(exclude_private)
            self.exclude_uppercase_action.setChecked(exclude_uppercase)
            self.exclude_capitalized_action.setChecked(exclude_capitalized)
            self.exclude_unsupported_action.setChecked(exclude_unsupported)
            self.refresh_table()
            return

        self.editor = RemoteCollectionsEditorTableView(
            self,
            None,
            minmax=minmax,
            dataframe_format=dataframe_format,
            get_value_func=self.get_value,
            set_value_func=self.set_value,
            new_value_func=self.set_value,
            remove_values_func=self.remove_values,
            copy_value_func=self.copy_value,
            is_list_func=self.is_list,
            get_len_func=self.get_len,
            is_array_func=self.is_array,
            is_image_func=self.is_image,
            is_dict_func=self.is_dict,
            is_data_frame_func=self.is_data_frame,
            is_series_func=self.is_series,
            get_array_shape_func=self.get_array_shape,
            get_array_ndim_func=self.get_array_ndim,
            plot_func=self.plot,
            imshow_func=self.imshow,
            show_image_func=self.show_image)

        self.editor.sig_option_changed.connect(self.sig_option_changed.emit)
        self.editor.sig_files_dropped.connect(self.import_data)

        # Setup layout
        blayout = QHBoxLayout()
        toolbar = self.setup_toolbar(exclude_private, exclude_uppercase,
                                     exclude_capitalized, exclude_unsupported)
        for widget in toolbar:
            blayout.addWidget(widget)

        # Options menu
        options_button = create_toolbutton(self,
                                           text=_('Options'),
                                           icon=ima.icon('tooloptions'))
        options_button.setPopupMode(QToolButton.InstantPopup)
        menu = QMenu(self)
        editor = self.editor
        actions = [
            self.exclude_private_action, self.exclude_uppercase_action,
            self.exclude_capitalized_action, self.exclude_unsupported_action,
            None
        ]
        if is_module_installed('numpy'):
            actions.append(editor.minmax_action)
        add_actions(menu, actions)
        options_button.setMenu(menu)

        blayout.addStretch()
        blayout.addWidget(options_button)

        layout = create_plugin_layout(blayout, self.editor)
        self.setLayout(layout)

        self.sig_option_changed.connect(self.option_changed)
Пример #29
0
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)

        self.setWindowTitle("Profiler")

        self.output = None
        self.error_output = None

        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None

        self.filecombo = PythonModulesComboBox(self)

        self.start_button = create_toolbutton(self,
                                              icon=ima.icon('run'),
                                              text=_("Profile"),
                                              tip=_("Run profiler"),
                                              triggered=lambda: self.start(),
                                              text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                             icon=ima.icon('stop'),
                                             text=_("Stop"),
                                             tip=_("Stop current profiling"),
                                             text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often.

        browse_button = create_toolbutton(self,
                                          icon=ima.icon('fileopen'),
                                          tip=_('Select Python script'),
                                          triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(self,
                                            icon=ima.icon('log'),
                                            text=_("Output"),
                                            text_beside_icon=True,
                                            tip=_("Show program's output"),
                                            triggered=self.show_log)

        self.datatree = ProfilerDataTree(self)

        self.collapse_button = create_toolbutton(
            self,
            icon=ima.icon('collapse'),
            triggered=lambda dD: self.datatree.change_view(-1),
            tip=_('Collapse one level up'))
        self.expand_button = create_toolbutton(
            self,
            icon=ima.icon('expand'),
            triggered=lambda dD: self.datatree.change_view(1),
            tip=_('Expand one level down'))

        self.save_button = create_toolbutton(self,
                                             text_beside_icon=True,
                                             text=_("Save data"),
                                             icon=ima.icon('filesave'),
                                             triggered=self.save_data,
                                             tip=_('Save profiling data'))
        self.load_button = create_toolbutton(
            self,
            text_beside_icon=True,
            text=_("Load data"),
            icon=ima.icon('fileimport'),
            triggered=self.compare,
            tip=_('Load profiling data for comparison'))
        self.clear_button = create_toolbutton(self,
                                              text_beside_icon=True,
                                              text=_("Clear comparison"),
                                              icon=ima.icon('editdelete'),
                                              triggered=self.clear)

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        hlayout2.addWidget(self.save_button)
        hlayout2.addWidget(self.load_button)
        hlayout2.addWidget(self.clear_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)
        self.start_button.setEnabled(False)
        self.clear_button.setEnabled(False)

        if not is_profiler_installed():
            # This should happen only on certain GNU/Linux distributions
            # or when this a home-made Python build because the Python
            # profilers are included in the Python standard library
            for widget in (self.datatree, self.filecombo, self.start_button,
                           self.stop_button):
                widget.setDisabled(True)
            url = 'https://docs.python.org/3/library/profile.html'
            text = '%s <a href=%s>%s</a>' % (_('Please install'), url,
                                             _("the Python profiler modules"))
            self.datelabel.setText(text)
        else:
            pass  # self.show_data()
Пример #30
0
    def setup_and_check(self, data, title=''):
        """
        Setup DataFrameEditor:
        return False if data is not supported, True otherwise.
        Supported types for data are DataFrame, Series and DatetimeIndex.
        """
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = to_text_string(title) + " - %s" % data.__class__.__name__
        else:
            title = _("%s editor") % data.__class__.__name__
        if isinstance(data, Series):
            self.is_series = True
            data = data.to_frame()
        elif isinstance(data, DatetimeIndex):
            data = DataFrame(data)

        self.setWindowTitle(title)
        self.resize(600, 500)

        self.dataModel = DataFrameModel(data, parent=self)
        self.dataTable = DataFrameView(self, self.dataModel)

        self.layout.addWidget(self.dataTable)
        self.setLayout(self.layout)
        self.setMinimumSize(400, 300)
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        btn_layout = QHBoxLayout()

        btn = QPushButton(_("Format"))
        # disable format button for int type
        btn_layout.addWidget(btn)
        btn.clicked.connect(self.change_format)
        btn = QPushButton(_('Resize'))
        btn_layout.addWidget(btn)
        btn.clicked.connect(self.resize_to_contents)

        bgcolor = QCheckBox(_('Background color'))
        bgcolor.setChecked(self.dataModel.bgcolor_enabled)
        bgcolor.setEnabled(self.dataModel.bgcolor_enabled)
        bgcolor.stateChanged.connect(self.change_bgcolor_enable)
        btn_layout.addWidget(bgcolor)

        self.bgcolor_global = QCheckBox(_('Column min/max'))
        self.bgcolor_global.setChecked(self.dataModel.colum_avg_enabled)
        self.bgcolor_global.setEnabled(not self.is_series
                                       and self.dataModel.bgcolor_enabled)
        self.bgcolor_global.stateChanged.connect(self.dataModel.colum_avg)
        btn_layout.addWidget(self.bgcolor_global)

        btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        btn_layout.addWidget(bbox)

        self.layout.addLayout(btn_layout, 2, 0)

        return True
    def __init__(self, parent):
        QWidget.__init__(self, parent)

        self.setWindowTitle("Memory profiler")

        self.output = None
        self.error_output = None

        self.use_colors = True

        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None

        self.filecombo = PythonModulesComboBox(self)

        self.start_button = create_toolbutton(self,
                                              icon=get_icon('run.png'),
                                              text=_("Profile memory usage"),
                                              tip=_("Run memory profiler"),
                                              triggered=self.start,
                                              text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                             icon=get_icon('terminate.png'),
                                             text=_("Stop"),
                                             tip=_("Stop current profiling"),
                                             text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often.

        browse_button = create_toolbutton(self,
                                          icon=get_icon('fileopen.png'),
                                          tip=_('Select Python script'),
                                          triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(self,
                                            icon=get_icon('log.png'),
                                            text=_("Output"),
                                            text_beside_icon=True,
                                            tip=_("Show program's output"),
                                            triggered=self.show_log)

        self.datatree = MemoryProfilerDataTree(self)

        self.collapse_button = create_toolbutton(
            self,
            icon=get_icon('collapse.png'),
            triggered=lambda dD=-1: self.datatree.collapseAll(),
            tip=_('Collapse all'))
        self.expand_button = create_toolbutton(
            self,
            icon=get_icon('expand.png'),
            triggered=lambda dD=1: self.datatree.expandAll(),
            tip=_('Expand all'))

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)
        self.start_button.setEnabled(False)

        if not is_memoryprofiler_installed():
            for widget in (self.datatree, self.filecombo, self.log_button,
                           self.start_button, self.stop_button, browse_button,
                           self.collapse_button, self.expand_button):
                widget.setDisabled(True)
            text = _(
                '<b>Please install the <a href="%s">memory_profiler module</a></b>'
            ) % WEBSITE_URL
            self.datelabel.setText(text)
            self.datelabel.setOpenExternalLinks(True)
        else:
            pass  # self.show_data()
Пример #32
0
    def __init__(self, plugin, id_,
                 history_filename, config_options,
                 additional_options, interpreter_versions,
                 connection_file=None, hostname=None,
                 menu_actions=None, slave=False,
                 external_kernel=False, given_name=None,
                 options_button=None,
                 show_elapsed_time=False,
                 reset_warning=True,
                 ask_before_restart=True,
                 css_path=None):
        super(ClientWidget, self).__init__(plugin)
        SaveHistoryMixin.__init__(self, history_filename)

        # --- Init attrs
        self.plugin = plugin
        self.id_ = id_
        self.connection_file = connection_file
        self.hostname = hostname
        self.menu_actions = menu_actions
        self.slave = slave
        self.external_kernel = external_kernel
        self.given_name = given_name
        self.show_elapsed_time = show_elapsed_time
        self.reset_warning = reset_warning
        self.ask_before_restart = ask_before_restart

        # --- Other attrs
        self.options_button = options_button
        self.stop_button = None
        self.reset_button = None
        self.stop_icon = ima.icon('stop')
        self.history = []
        self.allow_rename = True
        self.stderr_dir = None
        self.is_error_shown = False
        self.restart_thread = None

        if css_path is None:
            self.css_path = CSS_PATH
        else:
            self.css_path = css_path

        # --- Widgets
        self.shellwidget = ShellWidget(config=config_options,
                                       ipyclient=self,
                                       additional_options=additional_options,
                                       interpreter_versions=interpreter_versions,
                                       external_kernel=external_kernel,
                                       local_kernel=True)

        self.infowidget = plugin.infowidget
        self.blank_page = self._create_blank_page()
        self.loading_page = self._create_loading_page()
        # To keep a reference to the page to be displayed
        # in infowidget
        self.info_page = None
        self._before_prompt_is_ready()

        # Elapsed time
        self.time_label = None
        self.t0 = time.monotonic()
        self.timer = QTimer(self)
        self.show_time_action = create_action(self, _("Show elapsed time"),
                                         toggled=self.set_elapsed_time_visible)

        # --- Layout
        self.layout = QVBoxLayout()
        toolbar_buttons = self.get_toolbar_buttons()

        hlayout = QHBoxLayout()
        hlayout.addWidget(self.create_time_label())
        hlayout.addStretch(0)
        for button in toolbar_buttons:
            hlayout.addWidget(button)

        self.layout.addLayout(hlayout)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.shellwidget)
        self.layout.addWidget(self.infowidget)
        self.setLayout(self.layout)

        # --- Exit function
        self.exit_callback = lambda: plugin.close_client(client=self)

        # --- Dialog manager
        self.dialog_manager = DialogManager()

        # Show timer
        self.update_time_label_visibility()

        # Poll for stderr changes
        self.stderr_mtime = 0
        self.stderr_timer = QTimer(self)
        self.stderr_timer.timeout.connect(self.poll_stderr_file_change)
        self.stderr_timer.setInterval(1000)
        self.stderr_timer.start()
Пример #33
0
    def __init__(self,
                 parent=None,
                 tags=None,
                 content_urls=None,
                 content_path=CONTENT_PATH,
                 image_path=IMAGE_DATA_PATH,
                 config=CONF,
                 bundle_path=LINKS_INFO_PATH,
                 saved_content_path=CONTENT_JSON_PATH,
                 tab_name=''):
        """Community tab."""
        super(CommunityTab, self).__init__(parent=parent)

        self._tab_name = ''
        self.content_path = content_path
        self.image_path = image_path
        self.bundle_path = bundle_path
        self.saved_content_path = saved_content_path
        self.config = config

        self._parent = parent
        self._downloaded_thumbnail_urls = []
        self._downloaded_urls = []
        self._downloaded_filepaths = []
        self.api = AnacondaAPI()
        self.content_urls = content_urls
        self.content_info = []
        self.step = 0
        self.step_size = 1
        self.tags = tags
        self.timer_load = QTimer()
        self.pixmaps = {}
        self.filter_widgets = []
        self.default_pixmap = QPixmap(VIDEO_ICON_PATH).scaled(
            100, 60, Qt.KeepAspectRatio, Qt.FastTransformation)

        # Widgets
        self.text_filter = LineEditSearch()
        self.list = ListWidgetContent()
        self.frame_header = FrameTabHeader()
        self.frame_content = FrameTabContent()

        # Widget setup
        self.timer_load.setInterval(333)
        self.list.setAttribute(Qt.WA_MacShowFocusRect, False)
        self.text_filter.setPlaceholderText('Search')
        self.text_filter.setAttribute(Qt.WA_MacShowFocusRect, False)
        self.setObjectName("Tab")

        self.list.setMinimumHeight(200)
        fm = self.text_filter.fontMetrics()
        self.text_filter.setMaximumWidth(fm.width('M' * 23))

        # Layouts
        self.filters_layout = QHBoxLayout()

        layout_header = QHBoxLayout()
        layout_header.addLayout(self.filters_layout)
        layout_header.addStretch()
        layout_header.addWidget(self.text_filter)
        self.frame_header.setLayout(layout_header)

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.list)
        self.frame_content.setLayout(layout_content)

        layout = QVBoxLayout()
        layout.addWidget(self.frame_header)
        layout.addWidget(self.frame_content)
        self.setLayout(layout)

        # Signals
        self.timer_load.timeout.connect(self.set_content_list)
        self.text_filter.textChanged.connect(self.filter_content)
Пример #34
0
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Pylint")
        
        self.output = None
        self.error_output = None
        
        self.max_entries = max_entries
        self.rdata = []
        if osp.isfile(self.DATAPATH):
            try:
                data = pickle.loads(open(self.DATAPATH, 'rb').read())
                if data[0] == self.VERSION:
                    self.rdata = data[1:]
            except (EOFError, ImportError):
                pass

        self.filecombo = PythonModulesComboBox(self)
        if self.rdata:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())
        
        self.start_button = create_toolbutton(self, icon=ima.icon('run'),
                                    text=_("Analyze"),
                                    tip=_("Run analysis"),
                                    triggered=self.start, text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                             icon=ima.icon('stop'),
                                             text=_("Stop"),
                                             tip=_("Stop current analysis"),
                                             text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        self.filecombo.valid.connect(self.show_data)

        browse_button = create_toolbutton(self, icon=ima.icon('fileopen'),
                               tip=_('Select Python file'),
                               triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self, icon=ima.icon('log'),
                                    text=_("Output"),
                                    text_beside_icon=True,
                                    tip=_("Complete output"),
                                    triggered=self.show_log)
        self.treewidget = ResultsTree(self)
        
        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        self.show_data()
Пример #35
0
    def __init__(self, parent, search_text, search_text_regexp, search_path,
                 exclude, exclude_idx, exclude_regexp, supported_encodings,
                 in_python_path, more_options):
        QWidget.__init__(self, parent)

        if search_path is None:
            search_path = getcwd()

        self.path = ''
        self.project_path = None
        self.file_path = None

        if not isinstance(search_text, (list, tuple)):
            search_text = [search_text]
        if not isinstance(search_path, (list, tuple)):
            search_path = [search_path]
        if not isinstance(exclude, (list, tuple)):
            exclude = [exclude]

        self.supported_encodings = supported_encodings

        # Layout 1
        hlayout1 = QHBoxLayout()
        self.search_text = PatternComboBox(self, search_text,
                                           _("Search pattern"))
        self.edit_regexp = create_toolbutton(self,
                                             icon=ima.icon('advanced'),
                                             tip=_('Regular expression'))
        self.edit_regexp.setCheckable(True)
        self.edit_regexp.setChecked(search_text_regexp)
        self.more_widgets = ()
        self.more_options = create_toolbutton(self,
                                              toggled=self.toggle_more_options)
        self.more_options.setCheckable(True)
        self.more_options.setChecked(more_options)

        self.ok_button = create_toolbutton(self,
                                           text=_("Search"),
                                           icon=ima.icon('find'),
                                           triggered=lambda: self.find.emit(),
                                           tip=_("Start search"),
                                           text_beside_icon=True)
        self.ok_button.clicked.connect(self.update_combos)
        self.stop_button = create_toolbutton(
            self,
            text=_("Stop"),
            icon=ima.icon('editclear'),
            triggered=lambda: self.stop.emit(),
            tip=_("Stop search"),
            text_beside_icon=True)
        self.stop_button.setEnabled(False)
        for widget in [
                self.search_text, self.edit_regexp, self.ok_button,
                self.stop_button, self.more_options
        ]:
            hlayout1.addWidget(widget)

        # Layout 2
        hlayout2 = QHBoxLayout()
        self.exclude_pattern = PatternComboBox(self, exclude,
                                               _("Excluded filenames pattern"))
        if exclude_idx is not None and exclude_idx >= 0 \
           and exclude_idx < self.exclude_pattern.count():
            self.exclude_pattern.setCurrentIndex(exclude_idx)
        self.exclude_regexp = create_toolbutton(self,
                                                icon=ima.icon('advanced'),
                                                tip=_('Regular expression'))
        self.exclude_regexp.setCheckable(True)
        self.exclude_regexp.setChecked(exclude_regexp)
        exclude_label = QLabel(_("Exclude:"))
        exclude_label.setBuddy(self.exclude_pattern)
        for widget in [
                exclude_label, self.exclude_pattern, self.exclude_regexp
        ]:
            hlayout2.addWidget(widget)

        # Layout 3
        hlayout3 = QHBoxLayout()

        self.global_path_search = QRadioButton(_("Path"), self)
        self.global_path_search.setChecked(True)
        self.global_path_search.setToolTip(
            _("Search in all files and "
              "directories present on the"
              "current Spyder path"))

        self.project_search = QRadioButton(_("Project"), self)
        self.project_search.setToolTip(
            _("Search in all files and "
              "directories present on the"
              "current project path (If opened)"))

        self.project_search.setEnabled(False)

        self.file_search = QRadioButton(_("File"), self)
        self.file_search.setToolTip(_("Search in current opened file"))

        for wid in [
                self.global_path_search, self.project_search, self.file_search
        ]:
            hlayout3.addWidget(wid)

        hlayout3.addStretch(1)

        self.search_text.valid.connect(lambda valid: self.find.emit())
        self.exclude_pattern.valid.connect(lambda valid: self.find.emit())

        vlayout = QVBoxLayout()
        vlayout.setContentsMargins(0, 0, 0, 0)
        vlayout.addLayout(hlayout1)
        vlayout.addLayout(hlayout2)
        vlayout.addLayout(hlayout3)
        self.more_widgets = (hlayout2, )
        self.toggle_more_options(more_options)
        self.setLayout(vlayout)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
Пример #36
0
    def setup_and_check(self,
                        data,
                        title='',
                        readonly=False,
                        xlabels=None,
                        ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        readonly = readonly or not self.data.flags.writeable
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)

        if data.ndim > 3:
            self.error(
                _("Arrays with more than 3 dimensions are not "
                  "supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(
                _("The 'xlabels' argument length do no match array "
                  "column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(
                _("The 'ylabels' argument length do no match array row "
                  "number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn == 'object':
                # If the array doesn't have shape, we can't display it
                if data.shape == ():
                    self.error(
                        _("Object arrays without shape are not "
                          "supported"))
                    return False
                # We don't know what's inside these arrays, so we can't handle
                # edits
                self.readonly = readonly = True
            elif (dtn not in SUPPORTED_FORMATS and not dtn.startswith('str')
                  and not dtn.startswith('unicode')):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        if title:
            title = to_text_string(title) + " - " + _("NumPy object array")
        else:
            title = _("Array editor")
        if readonly:
            title += ' (' + _('read only') + ')'
        self.setWindowTitle(title)

        # ---- Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(
                    ArrayEditorWidget(self, data[name], readonly, xlabels,
                                      ylabels))
        elif is_masked_array:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels))
        elif data.ndim == 3:
            # We create here the necessary widgets for current_dim_changed to
            # work. The rest are created below.
            # QSpinBox
            self.index_spin = QSpinBox(self, keyboardTracking=False)
            self.index_spin.valueChanged.connect(self.change_active_widget)

            # Labels
            self.shape_label = QLabel()
            self.slicing_label = QLabel()

            # Set the widget to display when launched
            self.current_dim_changed(self.last_dim)
        else:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))

        self.arraywidget = self.stack.currentWidget()
        self.arraywidget.model.dataChanged.connect(self.save_and_close_enable)
        self.stack.currentChanged.connect(self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # ---- Top row of buttons
        btn_layout_top = None
        if is_record_array or is_masked_array or data.ndim == 3:
            btn_layout_top = QHBoxLayout()

            if is_record_array:
                btn_layout_top.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not is_text_string(title):
                            title = repr(title)
                        text += ' - ' + title
                    names.append(text)
            else:
                names = [_('Masked data'), _('Data'), _('Mask')]

            if data.ndim == 3:
                # QComboBox
                names = [str(i) for i in range(3)]
                ra_combo = QComboBox(self)
                ra_combo.addItems(names)
                ra_combo.currentIndexChanged.connect(self.current_dim_changed)

                # Adding the widgets to layout
                label = QLabel(_("Axis:"))
                btn_layout_top.addWidget(label)
                btn_layout_top.addWidget(ra_combo)
                btn_layout_top.addWidget(self.shape_label)

                label = QLabel(_("Index:"))
                btn_layout_top.addWidget(label)
                btn_layout_top.addWidget(self.index_spin)

                btn_layout_top.addWidget(self.slicing_label)
            else:
                ra_combo = QComboBox(self)
                ra_combo.currentIndexChanged.connect(
                    self.stack.setCurrentIndex)
                ra_combo.addItems(names)
                btn_layout_top.addWidget(ra_combo)

            if is_masked_array:
                label = QLabel(
                    _("<u>Warning</u>: Changes are applied separately"))
                label.setToolTip(
                    _("For performance reasons, changes applied "
                      "to masked arrays won't be reflected in "
                      "array's data (and vice-versa)."))
                btn_layout_top.addWidget(label)

            btn_layout_top.addStretch()

        # ---- Bottom row of buttons
        btn_layout_bottom = QHBoxLayout()

        btn_format = QPushButton(_("Format"))
        # disable format button for int type
        btn_format.setEnabled(is_float(self.arraywidget.data.dtype))
        btn_layout_bottom.addWidget(btn_format)
        btn_format.clicked.connect(lambda: self.arraywidget.change_format())

        btn_resize = QPushButton(_("Resize"))
        btn_layout_bottom.addWidget(btn_resize)
        btn_resize.clicked.connect(
            lambda: self.arraywidget.view.resize_to_contents())

        self.bgcolor = QCheckBox(_('Background color'))
        self.bgcolor.setEnabled(self.arraywidget.model.bgcolor_enabled)
        self.bgcolor.setChecked(self.arraywidget.model.bgcolor_enabled)
        self.bgcolor.stateChanged.connect(
            lambda state: self.arraywidget.model.bgcolor(state))
        btn_layout_bottom.addWidget(self.bgcolor)

        btn_layout_bottom.addStretch()

        if not readonly:
            self.btn_save_and_close = QPushButton(_('Save and Close'))
            self.btn_save_and_close.setDisabled(True)
            self.btn_save_and_close.clicked.connect(self.accept)
            btn_layout_bottom.addWidget(self.btn_save_and_close)

        # mx change
        # self.btn_close = QPushButton(_('Close'))
        # self.btn_close.setAutoDefault(True)
        # self.btn_close.setDefault(True)
        # self.btn_close.clicked.connect(self.reject)
        # btn_layout_bottom.addWidget(self.btn_close)

        # ---- Final layout
        btn_layout_bottom.setContentsMargins(4, 4, 4, 4)
        if btn_layout_top is not None:
            btn_layout_top.setContentsMargins(4, 4, 4, 4)
            self.layout.addLayout(btn_layout_top, 2, 0)
            self.layout.addLayout(btn_layout_bottom, 3, 0)
        else:
            self.layout.addLayout(btn_layout_bottom, 2, 0)

        # Set minimum size
        self.setMinimumSize(500, 300)

        # Make the dialog act as a window
        # self.setWindowFlags(Qt.Window)    # mx change

        return True
Пример #37
0
class FigureBrowser(QWidget):
    """
    Widget to browse the figures that were sent by the kernel to the IPython
    console to be plotted inline.
    """
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()

    def __init__(self,
                 parent,
                 options_button=None,
                 plugin_actions=[],
                 background_color=None):
        super(FigureBrowser, self).__init__(parent)

        self.shellwidget = None
        self.is_visible = True
        self.figviewer = None
        self.setup_in_progress = False
        self.background_color = background_color

        # Options :
        self.mute_inline_plotting = None
        self.show_plot_outline = None

        # Option actions :
        self.mute_inline_action = None
        self.show_plot_outline_action = None

        self.options_button = options_button
        self.plugin_actions = plugin_actions

    def setup(self, mute_inline_plotting=None, show_plot_outline=None):
        """Setup the figure browser with provided settings."""
        assert self.shellwidget is not None

        self.mute_inline_plotting = mute_inline_plotting
        self.show_plot_outline = show_plot_outline

        if self.figviewer is not None:
            self.mute_inline_action.setChecked(mute_inline_plotting)
            self.show_plot_outline_action.setChecked(show_plot_outline)
            return

        self.figviewer = FigureViewer(background_color=self.background_color)
        self.figviewer.setStyleSheet("FigureViewer{"
                                     "border: 1px solid lightgrey;"
                                     "border-top-width: 0px;"
                                     "border-bottom-width: 0px;"
                                     "border-left-width: 0px;"
                                     "}")
        self.thumbnails_sb = ThumbnailScrollBar(
            self.figviewer, background_color=self.background_color)

        # Option actions :
        self.setup_option_actions(mute_inline_plotting, show_plot_outline)

        # Create the layout :
        main_widget = QSplitter()
        main_widget.addWidget(self.figviewer)
        main_widget.addWidget(self.thumbnails_sb)
        main_widget.setFrameStyle(QScrollArea().frameStyle())

        self.tools_layout = QHBoxLayout()
        toolbar = self.setup_toolbar()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        layout = create_plugin_layout(self.tools_layout, main_widget)
        self.setLayout(layout)

    def setup_toolbar(self):
        """Setup the toolbar"""
        savefig_btn = create_toolbutton(
            self,
            icon=ima.icon('filesave'),
            tip=_("Save Image As..."),
            triggered=self.thumbnails_sb.save_current_figure_as)

        saveall_btn = create_toolbutton(
            self,
            icon=ima.icon('save_all'),
            tip=_("Save All Images..."),
            triggered=self.thumbnails_sb.save_all_figures_as)

        closefig_btn = create_toolbutton(self,
                                         icon=ima.icon('editclear'),
                                         tip=_("Remove image"),
                                         triggered=self.close_figure)

        closeall_btn = create_toolbutton(
            self,
            icon=ima.icon('filecloseall'),
            tip=_("Remove all images from the explorer"),
            triggered=self.close_all_figures)

        vsep1 = QFrame()
        vsep1.setFrameStyle(53)

        goback_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowBack'),
                                       tip=_("Previous Figure"),
                                       triggered=self.go_previous_thumbnail)

        gonext_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowForward'),
                                       tip=_("Next Figure"),
                                       triggered=self.go_next_thumbnail)

        vsep2 = QFrame()
        vsep2.setFrameStyle(53)

        zoom_out_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_out'),
            tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
            triggered=self.zoom_out)

        zoom_in_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_in'),
            tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
            triggered=self.zoom_in)

        self.zoom_disp = QSpinBox()
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(zoom_out_btn)
        layout.addWidget(zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [
            savefig_btn, saveall_btn, closefig_btn, closeall_btn, vsep1,
            goback_btn, gonext_btn, vsep2, zoom_pan
        ]

    def setup_option_actions(self, mute_inline_plotting, show_plot_outline):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True
        self.mute_inline_action = create_action(
            self,
            _("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda state: self.option_changed('mute_inline_plotting',
                                                      state))
        self.mute_inline_action.setChecked(mute_inline_plotting)

        self.show_plot_outline_action = create_action(
            self,
            _("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=self.show_fig_outline_in_viewer)
        self.show_plot_outline_action.setChecked(show_plot_outline)

        self.actions = [self.mute_inline_action, self.show_plot_outline_action]
        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            # When the FigureBowser widget is instatiated outside of the
            # plugin (for testing purpose for instance), we need to create
            # the options_button and set its menu.
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(self.tools_layout.count() - 1,
                                           self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def option_changed(self, option, value):
        """Handle when the value of an option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        if self.setup_in_progress is False:
            self.sig_option_changed.emit(option, value)

    def show_fig_outline_in_viewer(self, state):
        """Draw a frame around the figure viewer if state is True."""
        if state is True:
            self.figviewer.figcanvas.setStyleSheet(
                "FigureCanvas{border: 1px solid lightgrey;}")
        else:
            self.figviewer.figcanvas.setStyleSheet("FigureCanvas{}")
        self.option_changed('show_plot_outline', state)

    def set_shellwidget(self, shellwidget):
        """Bind the shellwidget instance to the figure browser"""
        self.shellwidget = shellwidget
        shellwidget.set_figurebrowser(self)
        shellwidget.sig_new_inline_figure.connect(self._handle_new_figure)

    def get_actions(self):
        """Get the actions of the widget."""
        return self.actions

    def _handle_new_figure(self, fig, fmt):
        """
        Handle when a new figure is sent to the IPython console by the
        kernel.
        """
        self.thumbnails_sb.add_thumbnail(fig, fmt)

    # ---- Toolbar Handlers
    def zoom_in(self):
        """Zoom the figure in by a single step in the figure viewer."""
        self.figviewer.zoom_in()

    def zoom_out(self):
        """Zoom the figure out by a single step in the figure viewer."""
        self.figviewer.zoom_out()

    def go_previous_thumbnail(self):
        """
        Select the thumbnail previous to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_previous_thumbnail()

    def go_next_thumbnail(self):
        """
        Select the thumbnail next to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_next_thumbnail()

    def close_figure(self):
        """Close the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_current_thumbnail()

    def close_all_figures(self):
        """Close all the figures in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_all_thumbnails()
Пример #38
0
    def __init__(self, *, gpc, gui_vars):
        super().__init__()

        self._enable_events = False

        # Global processing classes
        self.gpc = gpc
        # Global GUI variables (used for control of GUI state)
        self.gui_vars = gui_vars

        self.combo_plot_type = QComboBox()
        self.combo_plot_type.addItems(["LinLog", "Linear"])
        # Values are received and sent to the model, the don't represent the displayed text
        self.combo_plot_type_values = ["linlog", "linear"]

        self.cb_show_spectrum = QCheckBox("Show spectrum")

        self.cb_show_fit = QCheckBox("Show fit")

        self.rb_selected_region = QRadioButton("Selected region")
        self.rb_selected_region.setChecked(True)

        self.rb_full_spectrum = QRadioButton("Full spectrum")

        self.bgroup = QButtonGroup()
        self.bgroup.addButton(self.rb_selected_region)
        self.bgroup.addButton(self.rb_full_spectrum)

        self.pb_escape_peak = QPushButton("Escape Peak ...")
        self.pb_escape_peak.clicked.connect(self.pb_escape_peak_clicked)

        self.pb_add_line = QPushButton("Add Line")
        self.pb_add_line.clicked.connect(self.pb_add_line_clicked)

        self.pb_remove_line = QPushButton("Remove Line")
        self.pb_remove_line.clicked.connect(self.pb_remove_line_clicked)

        self.element_selection = ElementSelection()
        eline_sample_list = ["Li_K", "B_K", "C_K", "N_K", "Fe_K", "Userpeak1"]
        self.element_selection.set_item_list(eline_sample_list)
        self.element_selection.signal_current_item_changed.connect(
            self.element_selection_item_changed)

        self.mpl_canvas = FigureCanvas(self.gpc.plot_model._fig)
        self.mpl_toolbar = NavigationToolbar(self.mpl_canvas, self)

        # Keep layout without change when canvas is hidden (invisible)
        sp_retain = self.mpl_canvas.sizePolicy()
        sp_retain.setRetainSizeWhenHidden(True)
        self.mpl_canvas.setSizePolicy(sp_retain)

        self.widgets_enable_events(True)

        vbox = QVBoxLayout()

        hbox = QHBoxLayout()
        hbox.addWidget(self.combo_plot_type)
        hbox.addWidget(self.cb_show_spectrum)
        hbox.addWidget(self.cb_show_fit)
        hbox.addStretch(1)
        hbox.addWidget(self.rb_selected_region)
        hbox.addWidget(self.rb_full_spectrum)
        vbox.addLayout(hbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.pb_escape_peak)
        hbox.addStretch(1)
        hbox.addWidget(self.pb_add_line)
        hbox.addWidget(self.pb_remove_line)
        hbox.addSpacing(20)
        hbox.addWidget(self.element_selection)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        vbox.addWidget(self.mpl_toolbar)
        vbox.addWidget(self.mpl_canvas)
        self.setLayout(vbox)

        self._set_tooltips()
Пример #39
0
    def __init__(self,
                 parent,
                 opacity,
                 duration,
                 easing_curve,
                 tour=None,
                 color_top=None,
                 color_back=None,
                 combobox_background=None):
        super(FadingTipBox, self).__init__(parent, opacity, duration,
                                           easing_curve)
        self.holder = self.anim  # needed for qt to work
        self.parent = parent
        self.tour = tour

        self.frames = None
        self.offset_shadow = 0
        self.fixed_width = 300

        self.key_pressed = None

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint)
        self.setModal(False)

        # Widgets
        def toolbutton(icon):
            bt = QToolButton()
            bt.setAutoRaise(True)
            bt.setIcon(icon)
            return bt

        self.button_close = toolbutton(ima.icon("tour.close"))
        self.button_home = toolbutton(ima.icon("tour.home"))
        self.button_previous = toolbutton(ima.icon("tour.previous"))
        self.button_end = toolbutton(ima.icon("tour.end"))
        self.button_next = toolbutton(ima.icon("tour.next"))
        self.button_run = QPushButton(_('Run code'))
        self.button_disable = None
        self.button_current = QToolButton()
        self.label_image = QLabel()

        self.label_title = QLabel()
        self.combo_title = QComboBox()
        self.label_current = QLabel()
        self.label_content = QLabel()

        self.label_content.setMinimumWidth(self.fixed_width)
        self.label_content.setMaximumWidth(self.fixed_width)

        self.label_current.setAlignment(Qt.AlignCenter)

        self.label_content.setWordWrap(True)

        self.widgets = [
            self.label_content, self.label_title, self.label_current,
            self.combo_title, self.button_close, self.button_run,
            self.button_next, self.button_previous, self.button_end,
            self.button_home, self.button_current
        ]

        arrow = get_image_path('hide.png')

        self.color_top = color_top
        self.color_back = color_back
        self.combobox_background = combobox_background
        self.stylesheet = '''QComboBox {{
                             padding-left: 5px;
                             background-color: {}
                             border-width: 0px;
                             border-radius: 0px;
                             min-height:20px;
                             max-height:20px;
                             }}

                             QComboBox::drop-down  {{
                             subcontrol-origin: padding;
                             subcontrol-position: top left;
                             border-width: 0px;
                             }}

                             QComboBox::down-arrow {{
                             image: url({});
                             }}

                             '''.format(self.combobox_background.name(), arrow)
        # Windows fix, slashes should be always in unix-style
        self.stylesheet = self.stylesheet.replace('\\', '/')

        self.setFocusPolicy(Qt.StrongFocus)
        for widget in self.widgets:
            widget.setFocusPolicy(Qt.NoFocus)
            widget.setStyleSheet(self.stylesheet)

        layout_top = QHBoxLayout()
        layout_top.addWidget(self.combo_title)
        layout_top.addStretch()
        layout_top.addWidget(self.button_close)
        layout_top.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.label_content)
        layout_content.addWidget(self.label_image)
        layout_content.addSpacerItem(QSpacerItem(5, 5))

        layout_run = QHBoxLayout()
        layout_run.addStretch()
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        layout_run.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_navigation = QHBoxLayout()
        layout_navigation.addWidget(self.button_home)
        layout_navigation.addWidget(self.button_previous)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.label_current)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.button_next)
        layout_navigation.addWidget(self.button_end)
        layout_navigation.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_content)
        layout.addLayout(layout_run)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_navigation)
        layout.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.setLayout(layout)

        self.set_funcs_before_fade_in([self._disable_widgets])
        self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus])
        self.set_funcs_before_fade_out([self._disable_widgets])

        self.setContextMenuPolicy(Qt.CustomContextMenu)
Пример #40
0
    def setup_and_check(self,
                        data,
                        title='',
                        readonly=False,
                        xlabels=None,
                        ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        self.data.flags.writeable = True
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)

        if data.ndim > 3:
            self.error(
                _("Arrays with more than 3 dimensions are not "
                  "supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(
                _("The 'xlabels' argument length do no match array "
                  "column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(
                _("The 'ylabels' argument length do no match array row "
                  "number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('str') \
               and not dtn.startswith('unicode'):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = to_text_string(title) + " - " + _("NumPy array")
        else:
            title = _("Array editor")
        if readonly:
            title += ' (' + _('read only') + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)

        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(
                    ArrayEditorWidget(self, data[name], readonly, xlabels,
                                      ylabels))
        elif is_masked_array:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels))
        elif data.ndim == 3:
            pass
        else:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
        self.arraywidget = self.stack.currentWidget()
        if self.arraywidget:
            self.arraywidget.model.dataChanged.connect(
                self.save_and_close_enable)
        self.stack.currentChanged.connect(self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array or data.ndim == 3:
            if is_record_array:
                btn_layout.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not is_text_string(title):
                            title = repr(title)
                        text += ' - ' + title
                    names.append(text)
            else:
                names = [_('Masked data'), _('Data'), _('Mask')]
            if data.ndim == 3:
                # QSpinBox
                self.index_spin = QSpinBox(self, keyboardTracking=False)
                self.index_spin.valueChanged.connect(self.change_active_widget)
                # QComboBox
                names = [str(i) for i in range(3)]
                ra_combo = QComboBox(self)
                ra_combo.addItems(names)
                ra_combo.currentIndexChanged.connect(self.current_dim_changed)
                # Adding the widgets to layout
                label = QLabel(_("Axis:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(ra_combo)
                self.shape_label = QLabel()
                btn_layout.addWidget(self.shape_label)
                label = QLabel(_("Index:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(self.index_spin)
                self.slicing_label = QLabel()
                btn_layout.addWidget(self.slicing_label)
                # set the widget to display when launched
                self.current_dim_changed(self.last_dim)
            else:
                ra_combo = QComboBox(self)
                ra_combo.currentIndexChanged.connect(
                    self.stack.setCurrentIndex)
                ra_combo.addItems(names)
                btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel(
                    _("<u>Warning</u>: changes are applied separately"))
                label.setToolTip(_("For performance reasons, changes applied "\
                                   "to masked array won't be reflected in "\
                                   "array's data (and vice-versa)."))
                btn_layout.addWidget(label)

        btn_layout.addStretch()

        if not readonly:
            self.btn_save_and_close = QPushButton(_('Save and Close'))
            self.btn_save_and_close.setDisabled(True)
            self.btn_save_and_close.clicked.connect(self.accept)
            btn_layout.addWidget(self.btn_save_and_close)

        self.btn_close = QPushButton(_('Close'))
        self.btn_close.setAutoDefault(True)
        self.btn_close.setDefault(True)
        self.btn_close.clicked.connect(self.reject)
        btn_layout.addWidget(self.btn_close)
        self.layout.addLayout(btn_layout, 2, 0)

        self.setMinimumSize(400, 300)

        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)

        return True
Пример #41
0
class NamespaceBrowser(QWidget):
    """Namespace browser (global variables explorer widget)"""
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()
    sig_free_memory = Signal()

    def __init__(self, parent, options_button=None, plugin_actions=[]):
        QWidget.__init__(self, parent)

        self.shellwidget = None
        self.is_visible = True
        self.setup_in_progress = None

        # Remote dict editor settings
        self.check_all = None
        self.exclude_private = None
        self.exclude_uppercase = None
        self.exclude_capitalized = None
        self.exclude_unsupported = None
        self.excluded_names = None
        self.minmax = None

        # Other setting
        self.dataframe_format = None
        self.show_callable_attributes = None
        self.show_special_attributes = None

        self.editor = None
        self.exclude_private_action = None
        self.exclude_uppercase_action = None
        self.exclude_capitalized_action = None
        self.exclude_unsupported_action = None
        self.options_button = options_button
        self.actions = None
        self.plugin_actions = plugin_actions

        self.filename = None

    def setup(self,
              check_all=None,
              exclude_private=None,
              exclude_uppercase=None,
              exclude_capitalized=None,
              exclude_unsupported=None,
              excluded_names=None,
              minmax=None,
              dataframe_format=None,
              show_callable_attributes=None,
              show_special_attributes=None):
        """
        Setup the namespace browser with provided settings.

        Args:
            dataframe_format (string): default floating-point format for 
                DataFrame editor
        """
        assert self.shellwidget is not None

        self.check_all = check_all
        self.exclude_private = exclude_private
        self.exclude_uppercase = exclude_uppercase
        self.exclude_capitalized = exclude_capitalized
        self.exclude_unsupported = exclude_unsupported
        self.excluded_names = excluded_names
        self.minmax = minmax
        self.dataframe_format = dataframe_format
        self.show_callable_attributes = show_callable_attributes
        self.show_special_attributes = show_special_attributes

        if self.editor is not None:
            self.editor.setup_menu(minmax)
            self.editor.set_dataframe_format(dataframe_format)
            self.exclude_private_action.setChecked(exclude_private)
            self.exclude_uppercase_action.setChecked(exclude_uppercase)
            self.exclude_capitalized_action.setChecked(exclude_capitalized)
            self.exclude_unsupported_action.setChecked(exclude_unsupported)
            self.refresh_table()
            return

        self.editor = RemoteCollectionsEditorTableView(
            self,
            data=None,
            minmax=minmax,
            shellwidget=self.shellwidget,
            dataframe_format=dataframe_format,
            show_callable_attributes=show_callable_attributes,
            show_special_attributes=show_special_attributes)

        self.editor.sig_option_changed.connect(self.sig_option_changed.emit)
        self.editor.sig_files_dropped.connect(self.import_data)
        self.editor.sig_free_memory.connect(self.sig_free_memory.emit)

        self.setup_option_actions(exclude_private, exclude_uppercase,
                                  exclude_capitalized, exclude_unsupported)

        # Setup toolbar layout.

        self.tools_layout = QHBoxLayout()
        toolbar = self.setup_toolbar()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        # Setup layout.

        layout = create_plugin_layout(self.tools_layout, self.editor)
        self.setLayout(layout)

        self.sig_option_changed.connect(self.option_changed)

    def set_shellwidget(self, shellwidget):
        """Bind shellwidget instance to namespace browser"""
        self.shellwidget = shellwidget
        shellwidget.set_namespacebrowser(self)

    def get_actions(self):
        """Get actions of the widget."""
        return self.actions

    def setup_toolbar(self):
        """Setup toolbar"""
        load_button = create_toolbutton(self,
                                        text=_('Import data'),
                                        icon=ima.icon('fileimport'),
                                        triggered=lambda: self.import_data())
        self.save_button = create_toolbutton(
            self,
            text=_("Save data"),
            icon=ima.icon('filesave'),
            triggered=lambda: self.save_data(self.filename))
        self.save_button.setEnabled(False)
        save_as_button = create_toolbutton(self,
                                           text=_("Save data as..."),
                                           icon=ima.icon('filesaveas'),
                                           triggered=self.save_data)
        reset_namespace_button = create_toolbutton(
            self,
            text=_("Remove all variables"),
            icon=ima.icon('editdelete'),
            triggered=self.reset_namespace)

        return [
            load_button, self.save_button, save_as_button,
            reset_namespace_button
        ]

    def setup_option_actions(self, exclude_private, exclude_uppercase,
                             exclude_capitalized, exclude_unsupported):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True

        self.exclude_private_action = create_action(
            self,
            _("Exclude private references"),
            tip=_("Exclude references which name starts"
                  " with an underscore"),
            toggled=lambda state: self.sig_option_changed.emit(
                'exclude_private', state))
        self.exclude_private_action.setChecked(exclude_private)

        self.exclude_uppercase_action = create_action(
            self,
            _("Exclude all-uppercase references"),
            tip=_("Exclude references which name is uppercase"),
            toggled=lambda state: self.sig_option_changed.emit(
                'exclude_uppercase', state))
        self.exclude_uppercase_action.setChecked(exclude_uppercase)

        self.exclude_capitalized_action = create_action(
            self,
            _("Exclude capitalized references"),
            tip=_("Exclude references which name starts with an "
                  "uppercase character"),
            toggled=lambda state: self.sig_option_changed.emit(
                'exclude_capitalized', state))
        self.exclude_capitalized_action.setChecked(exclude_capitalized)

        self.exclude_unsupported_action = create_action(
            self,
            _("Exclude unsupported data types"),
            tip=_("Exclude references to unsupported data types"
                  " (i.e. which won't be handled/saved correctly)"),
            toggled=lambda state: self.sig_option_changed.emit(
                'exclude_unsupported', state))
        self.exclude_unsupported_action.setChecked(exclude_unsupported)

        self.actions = [
            self.exclude_private_action, self.exclude_uppercase_action,
            self.exclude_capitalized_action, self.exclude_unsupported_action
        ]
        if is_module_installed('numpy'):
            self.actions.extend([MENU_SEPARATOR, self.editor.minmax_action])

        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(self.tools_layout.count() - 1,
                                           self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def option_changed(self, option, value):
        """Option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        self.refresh_table()

    def get_view_settings(self):
        """Return dict editor view settings"""
        settings = {}
        for name in REMOTE_SETTINGS:
            settings[name] = getattr(self, name)
        return settings

    def refresh_table(self):
        """Refresh variable table"""
        if self.is_visible and self.isVisible():
            self.shellwidget.refresh_namespacebrowser()
            try:
                self.editor.resizeRowToContents()
            except TypeError:
                pass

    def process_remote_view(self, remote_view):
        """Process remote view"""
        if remote_view is not None:
            self.set_data(remote_view)

    def set_var_properties(self, properties):
        """Set properties of variables"""
        if properties is not None:
            self.editor.var_properties = properties

    def set_data(self, data):
        """Set data."""
        if data != self.editor.model.get_data():
            self.editor.set_data(data)
            self.editor.adjust_columns()

    def collapse(self):
        """Collapse."""
        self.sig_collapse.emit()

    @Slot(bool)
    @Slot(list)
    def import_data(self, filenames=None):
        """Import data from text file."""
        title = _("Import data")
        if filenames is None:
            if self.filename is None:
                basedir = getcwd_or_home()
            else:
                basedir = osp.dirname(self.filename)
            filenames, _selfilter = getopenfilenames(self, title, basedir,
                                                     iofunctions.load_filters)
            if not filenames:
                return
        elif is_text_string(filenames):
            filenames = [filenames]

        for filename in filenames:
            self.filename = to_text_string(filename)
            if os.name == "nt":
                self.filename = remove_backslashes(self.filename)
            ext = osp.splitext(self.filename)[1].lower()

            if ext not in iofunctions.load_funcs:
                buttons = QMessageBox.Yes | QMessageBox.Cancel
                answer = QMessageBox.question(
                    self, title,
                    _("<b>Unsupported file extension '%s'</b><br><br>"
                      "Would you like to import it anyway "
                      "(by selecting a known file format)?") % ext, buttons)
                if answer == QMessageBox.Cancel:
                    return
                formats = list(iofunctions.load_extensions.keys())
                item, ok = QInputDialog.getItem(self, title,
                                                _('Open file as:'), formats, 0,
                                                False)
                if ok:
                    ext = iofunctions.load_extensions[to_text_string(item)]
                else:
                    return

            load_func = iofunctions.load_funcs[ext]

            # 'import_wizard' (self.setup_io)
            if is_text_string(load_func):
                # Import data with import wizard
                error_message = None
                try:
                    text, _encoding = encoding.read(self.filename)
                    base_name = osp.basename(self.filename)
                    editor = ImportWizard(
                        self,
                        text,
                        title=base_name,
                        varname=fix_reference_name(base_name))
                    if editor.exec_():
                        var_name, clip_data = editor.get_data()
                        self.editor.new_value(var_name, clip_data)
                except Exception as error:
                    error_message = str(error)
            else:
                QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
                QApplication.processEvents()
                error_message = self.shellwidget.load_data(self.filename, ext)
                self.shellwidget._kernel_reply = None
                QApplication.restoreOverrideCursor()
                QApplication.processEvents()

            if error_message is not None:
                QMessageBox.critical(
                    self, title,
                    _("<b>Unable to load '%s'</b>"
                      "<br><br>Error message:<br>%s") %
                    (self.filename, error_message))
            self.refresh_table()

    @Slot()
    def reset_namespace(self):
        warning = CONF.get('ipython_console', 'show_reset_namespace_warning')
        self.shellwidget.reset_namespace(warning=warning, message=True)
        self.editor.automatic_column_width = True

    @Slot()
    def save_data(self, filename=None):
        """Save data"""
        if filename is None:
            filename = self.filename
            if filename is None:
                filename = getcwd_or_home()
            filename, _selfilter = getsavefilename(self, _("Save data"),
                                                   filename,
                                                   iofunctions.save_filters)
            if filename:
                self.filename = filename
            else:
                return False
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        QApplication.processEvents()

        error_message = self.shellwidget.save_namespace(self.filename)
        self.shellwidget._kernel_reply = None

        QApplication.restoreOverrideCursor()
        QApplication.processEvents()
        if error_message is not None:
            if 'Some objects could not be saved:' in error_message:
                save_data_message = (
                    _('<b>Some objects could not be saved:</b>') +
                    '<br><br><code>{obj_list}</code>'.format(
                        obj_list=error_message.split(': ')[1]))
            else:
                save_data_message = _(
                    '<b>Unable to save current workspace</b>'
                    '<br><br>Error message:<br>') + error_message
            QMessageBox.critical(self, _("Save data"), save_data_message)
        self.save_button.setEnabled(self.filename is not None)
Пример #42
0
class ColorbarWidget(QWidget):
    colorbarChanged = Signal()  # The parent should simply redraw their canvas
    scaleNormChanged = Signal()
    # register additional color maps from file
    register_customized_colormaps()
    # create the list
    cmap_list = sorted(
        [cmap for cmap in cm.cmap_d.keys() if not cmap.endswith('_r')])

    def __init__(self, parent=None, default_norm_scale=None):
        """
        :param default_scale: None uses linear, else either a string or tuple(string, other arguments), e.g. tuple('Power', exponent)
        """

        super(ColorbarWidget, self).__init__(parent)

        self.setWindowTitle("Colorbar")
        self.setMaximumWidth(100)

        self.cmap = QComboBox()
        self.cmap.addItems(self.cmap_list)
        self.cmap.currentIndexChanged.connect(self.cmap_index_changed)
        self.crev = QCheckBox('Reverse')
        self.crev.stateChanged.connect(self.crev_checked_changed)

        self.cmin = QLineEdit()
        self.cmin_value = 0
        self.cmin.setMaximumWidth(100)
        self.cmin.editingFinished.connect(self.clim_changed)
        self.cmin_layout = QHBoxLayout()
        self.cmin_layout.addStretch()
        self.cmin_layout.addWidget(self.cmin)
        self.cmin_layout.addStretch()

        self.linear_validator = QDoubleValidator(parent=self)
        self.log_validator = QDoubleValidator(MIN_LOG_VALUE,
                                              sys.float_info.max, 3, self)
        self.cmax = QLineEdit()
        self.cmax_value = 1
        self.cmax.setMaximumWidth(100)
        self.cmax.editingFinished.connect(self.clim_changed)
        self.cmax_layout = QHBoxLayout()
        self.cmax_layout.addStretch()
        self.cmax_layout.addWidget(self.cmax)
        self.cmax_layout.addStretch()

        norm_scale = 'Linear'
        powerscale_value = 2
        if default_norm_scale in NORM_OPTS:
            norm_scale = default_norm_scale
        if isinstance(default_norm_scale,
                      tuple) and default_norm_scale[0] in NORM_OPTS:
            norm_scale = default_norm_scale[0]
            if norm_scale == 'Power':
                powerscale_value = float(default_norm_scale[1])

        self.norm_layout = QHBoxLayout()
        self.norm = QComboBox()
        self.norm.addItems(NORM_OPTS)
        self.norm.setCurrentText(norm_scale)
        self.norm.currentIndexChanged.connect(self.norm_changed)
        self.update_clim_validator()

        self.powerscale = QLineEdit()
        self.powerscale_value = powerscale_value
        self.powerscale.setText(str(powerscale_value))
        self.powerscale.setValidator(QDoubleValidator(0.001, 100, 3))
        self.powerscale.setMaximumWidth(50)
        self.powerscale.editingFinished.connect(self.norm_changed)
        self.powerscale_label = QLabel("n=")
        if norm_scale != 'Power':
            self.powerscale.hide()
            self.powerscale_label.hide()

        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.norm)
        self.norm_layout.addStretch()
        self.norm_layout.addWidget(self.powerscale_label)
        self.norm_layout.addWidget(self.powerscale)

        self.autoscale = QCheckBox("Autoscaling")
        self.autoscale.setChecked(True)
        self.autoscale.stateChanged.connect(self.update_clim)

        self.canvas = FigureCanvas(Figure())
        if parent:
            # Set facecolor to match parent
            self.canvas.figure.set_facecolor(
                parent.palette().window().color().getRgbF())
        self.ax = self.canvas.figure.add_axes([0.0, 0.02, 0.2, 0.97])

        # layout
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(2)
        self.layout.addWidget(self.cmap)
        self.layout.addWidget(self.crev)
        self.layout.addLayout(self.cmax_layout)
        self.layout.addWidget(self.canvas, stretch=1)
        self.layout.addLayout(self.cmin_layout)
        self.layout.addLayout(self.norm_layout)
        self.layout.addWidget(self.autoscale)

    def set_mappable(self, mappable):
        """
        When a new plot is created this method should be called with the new mappable
        """
        # sanity check the mappable
        mappable = self._validate_mappable(mappable)
        self.ax.clear()
        try:  # Use current cmap
            cmap = get_current_cmap(self.colorbar)
        except AttributeError:
            # else use default
            cmap = ConfigService.getString("plots.images.Colormap")
        self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
        self.cmin_value, self.cmax_value = mappable.get_clim()
        self.update_clim_text()
        self.cmap_changed(cmap, False)

        mappable_cmap = get_current_cmap(mappable)

        if mappable_cmap.name.endswith('_r'):
            self.crev.setChecked(True)
        else:
            self.crev.setChecked(False)
        self.cmap.setCurrentIndex(
            self.cmap_list.index(mappable_cmap.name.replace('_r', '')))

        self.redraw()

    def cmap_index_changed(self):
        self.cmap_changed(self.cmap.currentText(), self.crev.isChecked())

    def crev_checked_changed(self):
        self.cmap_changed(self.cmap.currentText(), self.crev.isChecked())

    def cmap_changed(self, name, rev):
        if rev:
            name += '_r'
        self.colorbar.mappable.set_cmap(name)
        if mpl_version_info() >= (3, 1):
            self.colorbar.update_normal(self.colorbar.mappable)
        else:
            self.colorbar.set_cmap(name)
        self.redraw()

    def mappable_changed(self):
        """
        Updates the colormap and min/max values of the colorbar
        when the plot changes via settings.
        """
        mappable_cmap = get_current_cmap(self.colorbar.mappable)
        low, high = self.colorbar.mappable.get_clim()
        self.cmin_value = low
        self.cmax_value = high
        self.update_clim_text()
        self.cmap.setCurrentIndex(
            sorted(cm.cmap_d.keys()).index(mappable_cmap.name))
        self.redraw()

    def norm_changed(self):
        """
        Called when a different normalization is selected
        """
        idx = self.norm.currentIndex()
        if NORM_OPTS[idx] == 'Power':
            self.powerscale.show()
            self.powerscale_label.show()
        else:
            self.powerscale.hide()
            self.powerscale_label.hide()
        self.colorbar.mappable.set_norm(self.get_norm())
        self.set_mappable(self.colorbar.mappable)
        self.update_clim_validator()
        self.scaleNormChanged.emit()

    def get_norm(self):
        """
        This will create a matplotlib.colors.Normalize from selected idx, limits and powerscale
        """
        idx = self.norm.currentIndex()
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        if NORM_OPTS[idx] == 'Power':
            if self.powerscale.hasAcceptableInput():
                self.powerscale_value = float(self.powerscale.text())
            return PowerNorm(gamma=self.powerscale_value, vmin=cmin, vmax=cmax)
        elif NORM_OPTS[idx] == "SymmetricLog10":
            return SymLogNorm(
                1e-8 if cmin is None else max(1e-8,
                                              abs(cmin) * 1e-3),
                vmin=cmin,
                vmax=cmax)
        elif NORM_OPTS[idx] == "Log":
            cmin = MIN_LOG_VALUE if cmin is not None and cmin <= 0 else cmin
            return LogNorm(vmin=cmin, vmax=cmax)
        else:
            return Normalize(vmin=cmin, vmax=cmax)

    def get_colorbar_scale(self):
        norm = self.colorbar.norm
        scale = 'linear'
        kwargs = {}
        if isinstance(norm, SymLogNorm):
            scale = 'symlog'
        elif isinstance(norm, LogNorm):
            scale = 'log'
        elif isinstance(norm, PowerNorm):
            scale = 'function'
            kwargs = {
                'functions': (lambda x: np.power(x, norm.gamma),
                              lambda x: np.power(x, 1 / norm.gamma))
            }
        return scale, kwargs

    def clim_changed(self):
        """
        Called when either the min or max is changed. Will unset the autoscale.
        """
        self.autoscale.blockSignals(True)
        self.autoscale.setChecked(False)
        self.autoscale.blockSignals(False)
        self.update_clim()

    def update_clim(self):
        """
        This will update the clim of the plot based on min, max, and autoscale
        """
        if self.autoscale.isChecked():
            self._autoscale_clim()
        else:
            self._manual_clim()

        self.colorbar.mappable.set_clim(self.cmin_value, self.cmax_value)
        self.redraw()

    def update_clim_text(self):
        """
        Update displayed limit values based on stored ones
        """
        self.cmin.setText("{:.4}".format(self.cmin_value))
        self.cmax.setText("{:.4}".format(self.cmax_value))

    def redraw(self):
        """
        Redraws the colobar and emits signal to cause the parent to redraw
        """
        self.colorbar.update_ticks()
        self.colorbar.draw_all()
        self.canvas.draw_idle()
        self.colorbarChanged.emit()

    def update_clim_validator(self):
        if NORM_OPTS[self.norm.currentIndex()] == "Log":
            self.cmin.setValidator(self.log_validator)
            self.cmax.setValidator(self.log_validator)
        else:
            self.cmin.setValidator(self.linear_validator)
            self.cmax.setValidator(self.linear_validator)

    def _autoscale_clim(self):
        """Update stored colorbar limits
        The new limits are found from the colobar data """
        if hasattr(self.colorbar.mappable, "get_array_clipped_to_bounds"):
            data = self.colorbar.mappable.get_array_clipped_to_bounds()
        else:
            # in nonorthog view get passed a QuadMesh that doesn't have the above method
            # however the data from get_array for MDEvent ws is already clipped (not for MDHisto)
            data = self.colorbar.mappable.get_array()
        norm = NORM_OPTS[self.norm.currentIndex()]
        try:
            try:
                masked_data = data[~data.mask]
                # use the smallest positive value as vmin when using log scale,
                # matplotlib will take care of the data skipping part.
                masked_data = masked_data[
                    masked_data > 0] if norm == "Log" else masked_data

                # If any dimension is zero then we have no data in the display area
                data_is_empty = any(
                    map(lambda dim: dim == 0, masked_data.shape))

                self.cmin_value = 0. if data_is_empty else masked_data.min()
                self.cmax_value = 0. if data_is_empty else masked_data.max()
            except (AttributeError, IndexError):
                data = data[np.nonzero(data)] if norm == "Log" else data
                self.cmin_value = np.nanmin(data)
                self.cmax_value = np.nanmax(data)
        except (ValueError, RuntimeWarning):
            # all values mask
            pass
        self.update_clim_text()

    def _manual_clim(self):
        """Update stored colorbar limits
        The new limits are found from user input"""
        if self.cmin.hasAcceptableInput():
            cmin = float(self.cmin.text())
            if cmin < self.cmax_value:
                self.cmin_value = cmin
            else:  # reset values back
                self.update_clim_text()
        if self.cmax.hasAcceptableInput():
            cmax = float(self.cmax.text())
            if cmax > self.cmin_value:
                self.cmax_value = cmax
            else:  # reset values back
                self.update_clim_text()

    def _create_linear_normalize_object(self):
        if self.autoscale.isChecked():
            cmin = cmax = None
        else:
            cmin = self.cmin_value
            cmax = self.cmax_value
        return Normalize(vmin=cmin, vmax=cmax)

    def _validate_mappable(self, mappable):
        """Disable the Log option if no positive value can be found from given data (image)"""
        index = NORM_OPTS.index("Log")
        if mappable.get_array() is not None:
            if np.all(mappable.get_array() <= 0):
                self.norm.model().item(index, 0).setEnabled(False)
                self.norm.setItemData(
                    index, "Log scale is disabled for non-positive data",
                    Qt.ToolTipRole)
                if isinstance(mappable.norm, LogNorm):
                    mappable.norm = self._create_linear_normalize_object()
                    self.norm.blockSignals(True)
                    self.norm.setCurrentIndex(0)
                    self.norm.blockSignals(False)
            else:
                if not self.norm.model().item(index, 0).isEnabled():
                    self.norm.model().item(index, 0).setEnabled(True)
                    self.norm.setItemData(index, "", Qt.ToolTipRole)

        return mappable
Пример #43
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')
        showcodefolding_box = newcb(_("Show code folding"), 'code_folding')
        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(showcodefolding_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)"))
        strip_mode_box = newcb(
            _("Automatically strip trailing spaces on changed lines"),
            'strip_trailing_spaces_on_modify',
            default=True,
            tip=
            _("If enabled, modified lines of code (excluding strings)\n"
              "will have their trailing whitespace stripped when leaving them.\n"
              "If disabled, only whitespace added by Spyder will be stripped."
              ))
        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)
        add_newline_box = newcb(_(
            "Insert a newline at the end if one does not exist when saving "
            "a file"),
                                'add_newline',
                                default=False)
        remove_trail_newline_box = newcb(
            _("Trim all newlines after the final one when saving a file"),
            'always_remove_trailing_newlines',
            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',
                                            default=4,
                                            min_=1,
                                            max_=8,
                                            step=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.addWidget(add_newline_box)
        sourcecode_layout.addWidget(remove_trail_newline_box)
        sourcecode_layout.addWidget(strip_mode_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'),
            (_("Sphinx"), 'Sphinxdoc'),
        )
        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)
Пример #44
0
    def __init__(self, parent, opacity, duration, easing_curve, tour=None):
        super(FadingTipBox, self).__init__(parent, opacity, duration,
                                           easing_curve)
        self.holder = self.anim  # needed for qt to work
        self.parent = parent
        self.tour = tour

        self.frames = None
        self.color_top = QColor.fromRgb(230, 230, 230)
        self.color_back = QColor.fromRgb(255, 255, 255)
        self.offset_shadow = 0
        self.fixed_width = 300

        self.key_pressed = None

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint)
        self.setModal(False)

        # Widgets
        self.button_home = QPushButton("<<")
        self.button_close = QPushButton("X")
        self.button_previous = QPushButton(" < ")
        self.button_end = QPushButton(">>")
        self.button_next = QPushButton(" > ")
        self.button_run = QPushButton(_('Run code'))
        self.button_disable = None
        self.button_current = QToolButton()
        self.label_image = QLabel()

        self.label_title = QLabel()
        self.combo_title = QComboBox()
        self.label_current = QLabel()
        self.label_content = QLabel()

        self.label_content.setMinimumWidth(self.fixed_width)
        self.label_content.setMaximumWidth(self.fixed_width)

        self.label_current.setAlignment(Qt.AlignCenter)

        self.label_content.setWordWrap(True)

        self.widgets = [
            self.label_content, self.label_title, self.label_current,
            self.combo_title, self.button_close, self.button_run,
            self.button_next, self.button_previous, self.button_end,
            self.button_home, self.button_current
        ]

        arrow = get_image_path('hide.png')

        self.stylesheet = '''QPushButton {
                             background-color: rgbs(200,200,200,100%);
                             color: rgbs(0,0,0,100%);
                             border-style: outset;
                             border-width: 1px;
                             border-radius: 3px;
                             border-color: rgbs(100,100,100,100%);
                             padding: 2px;
                             }

                             QPushButton:hover {
                             background-color: rgbs(150, 150, 150, 100%);
                             }

                             QPushButton:disabled {
                             background-color: rgbs(230,230,230,100%);
                             color: rgbs(200,200,200,100%);
                             border-color: rgbs(200,200,200,100%);
                             }

                             QComboBox {
                             padding-left: 5px;
                             background-color: rgbs(230,230,230,100%);
                             border-width: 0px;
                             border-radius: 0px;
                             min-height:20px;
                             max-height:20px;
                             }

                             QComboBox::drop-down  {
                             subcontrol-origin: padding;
                             subcontrol-position: top left;
                             border-width: 0px;
                             }
                             
                             QComboBox::down-arrow {
                             image: url(''' + arrow + ''');
                             }
                             
                             '''
        # Windows fix, slashes should be always in unix-style
        self.stylesheet = self.stylesheet.replace('\\', '/')

        self.setFocusPolicy(Qt.StrongFocus)
        for widget in self.widgets:
            widget.setFocusPolicy(Qt.NoFocus)
            widget.setStyleSheet(self.stylesheet)

        layout_top = QHBoxLayout()
        layout_top.addWidget(self.combo_title)
        layout_top.addStretch()
        layout_top.addWidget(self.button_close)
        layout_top.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.label_content)
        layout_content.addWidget(self.label_image)
        layout_content.addSpacerItem(QSpacerItem(5, 5))

        layout_run = QHBoxLayout()
        layout_run.addStretch()
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        layout_run.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_navigation = QHBoxLayout()
        layout_navigation.addWidget(self.button_home)
        layout_navigation.addWidget(self.button_previous)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.label_current)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.button_next)
        layout_navigation.addWidget(self.button_end)
        layout_navigation.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_content)
        layout.addLayout(layout_run)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_navigation)
        layout.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.setLayout(layout)

        self.set_funcs_before_fade_in([self._disable_widgets])
        self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus])
        self.set_funcs_before_fade_out([self._disable_widgets])

        self.setContextMenuPolicy(Qt.CustomContextMenu)
Пример #45
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(check_file=True):
            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)
        screen_resolution_label.setOpenExternalLinks(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 ';'.\n"
                  "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)
Пример #46
0
class PluginListItem(QFrame):
    def __init__(
        self,
        package_name: str,
        version: str = '',
        url: str = '',
        summary: str = '',
        author: str = '',
        license: str = "UNKNOWN",
        *,
        plugin_name: str = None,
        parent: QWidget = None,
        enabled: bool = True,
        installed: bool = False,
        npe_version=1,
    ):
        super().__init__(parent)
        self.setup_ui(enabled)
        self.plugin_name.setText(package_name)
        self.package_name.setText(version)
        self.summary.setText(summary)
        self.package_author.setText(author)
        self.cancel_btn.setVisible(False)

        self.help_button.setText(trans._("Website"))
        self.help_button.setObjectName("help_button")
        if npe_version != 1:
            self._handle_npe2_plugin()

        if installed:
            self.enabled_checkbox.show()
            self.action_button.setText(trans._("uninstall"))
            self.action_button.setObjectName("remove_button")
        else:
            self.enabled_checkbox.hide()
            self.action_button.setText(trans._("install"))
            self.action_button.setObjectName("install_button")

    def _handle_npe2_plugin(self):
        npe2_icon = QLabel(self)
        icon = QColoredSVGIcon.from_resources('logo_silhouette')
        npe2_icon.setPixmap(icon.colored(color='#33F0FF').pixmap(20, 20))
        self.row1.insertWidget(2, QLabel('npe2'))
        self.row1.insertWidget(2, npe2_icon)
        self.enabled_checkbox.setEnabled(False)
        self.enabled_checkbox.setToolTip(
            trans.
            _('This is a npe2 plugin and cannot be enabled/disabled at this time.'
              ))

    def _get_dialog(self) -> QDialog:
        p = self.parent()
        while not isinstance(p, QDialog) and p.parent():
            p = p.parent()
        return p

    def set_busy(self, text: str, update: bool = False):
        self.item_status.setText(text)
        self.cancel_btn.setVisible(True)
        if not update:
            self.action_button.setVisible(False)
        else:
            self.update_btn.setVisible(False)

    def setup_ui(self, enabled=True):
        self.v_lay = QVBoxLayout(self)
        self.v_lay.setContentsMargins(-1, 6, -1, 6)
        self.v_lay.setSpacing(0)
        self.row1 = QHBoxLayout()
        self.enabled_checkbox = QCheckBox(self)
        self.enabled_checkbox.setChecked(enabled)
        self.enabled_checkbox.stateChanged.connect(self._on_enabled_checkbox)
        self.enabled_checkbox.setToolTip(trans._("enable/disable"))
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.enabled_checkbox.sizePolicy().hasHeightForWidth())
        self.enabled_checkbox.setSizePolicy(sizePolicy)
        self.enabled_checkbox.setMinimumSize(QSize(20, 0))
        self.enabled_checkbox.setText("")
        self.row1.addWidget(self.enabled_checkbox)
        self.plugin_name = QLabel(self)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.plugin_name.sizePolicy().hasHeightForWidth())
        self.plugin_name.setSizePolicy(sizePolicy)
        font15 = QFont()
        font15.setPointSize(15)
        self.plugin_name.setFont(font15)
        self.row1.addWidget(self.plugin_name)

        self.item_status = QLabel(self)
        self.item_status.setObjectName("small_italic_text")
        self.item_status.setSizePolicy(sizePolicy)
        self.row1.addWidget(self.item_status)
        self.row1.addStretch()

        self.package_name = QLabel(self)
        self.package_name.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                       | Qt.AlignVCenter)
        self.row1.addWidget(self.package_name)

        self.cancel_btn = QPushButton("cancel", self)
        self.cancel_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.cancel_btn.setObjectName("remove_button")
        self.row1.addWidget(self.cancel_btn)

        self.update_btn = QPushButton(self)
        self.update_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.update_btn.setObjectName("install_button")
        self.row1.addWidget(self.update_btn)
        self.update_btn.setVisible(False)
        self.help_button = QPushButton(self)
        self.action_button = QPushButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.action_button.sizePolicy().hasHeightForWidth())
        self.help_button.setSizePolicy(sizePolicy)
        self.action_button.setSizePolicy(sizePolicy)
        self.row1.addWidget(self.help_button)
        self.row1.addWidget(self.action_button)
        self.v_lay.addLayout(self.row1)
        self.row2 = QHBoxLayout()
        self.error_indicator = QPushButton()
        self.error_indicator.setObjectName("warning_icon")
        self.error_indicator.setCursor(Qt.PointingHandCursor)
        self.error_indicator.hide()
        self.row2.addWidget(self.error_indicator)
        self.row2.setContentsMargins(-1, 4, 0, -1)
        self.summary = QElidingLabel(parent=self)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.summary.sizePolicy().hasHeightForWidth())
        self.summary.setSizePolicy(sizePolicy)
        self.summary.setObjectName("small_text")
        self.row2.addWidget(self.summary)
        self.package_author = QLabel(self)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.package_author.sizePolicy().hasHeightForWidth())
        self.package_author.setSizePolicy(sizePolicy)
        self.package_author.setObjectName("small_text")
        self.row2.addWidget(self.package_author)
        self.v_lay.addLayout(self.row2)

    def _on_enabled_checkbox(self, state: int):
        """Called with `state` when checkbox is clicked."""
        enabled = bool(state)
        current_distname = self.plugin_name.text()
        for plugin_name, _, distname in plugin_manager.iter_available():
            if distname and distname == current_distname:
                plugin_manager.set_blocked(plugin_name, not enabled)
Пример #47
0
    def setup(self,
              check_all=None,
              exclude_private=None,
              exclude_uppercase=None,
              exclude_capitalized=None,
              exclude_unsupported=None,
              excluded_names=None,
              truncate=None,
              minmax=None,
              remote_editing=None,
              autorefresh=None):
        """Setup the namespace browser"""
        assert self.shellwidget is not None

        self.check_all = check_all
        self.exclude_private = exclude_private
        self.exclude_uppercase = exclude_uppercase
        self.exclude_capitalized = exclude_capitalized
        self.exclude_unsupported = exclude_unsupported
        self.excluded_names = excluded_names
        self.truncate = truncate
        self.minmax = minmax
        self.remote_editing = remote_editing
        self.autorefresh = autorefresh

        if self.editor is not None:
            self.editor.setup_menu(truncate, minmax)
            self.exclude_private_action.setChecked(exclude_private)
            self.exclude_uppercase_action.setChecked(exclude_uppercase)
            self.exclude_capitalized_action.setChecked(exclude_capitalized)
            self.exclude_unsupported_action.setChecked(exclude_unsupported)
            # Don't turn autorefresh on for IPython kernels
            # See Issue 1450
            if not self.is_ipykernel:
                self.auto_refresh_button.setChecked(autorefresh)
            self.refresh_table()
            return

        # Dict editor:
        if self.is_internal_shell:
            self.editor = CollectionsEditorTableView(self,
                                                     None,
                                                     truncate=truncate,
                                                     minmax=minmax)
        else:
            self.editor = RemoteCollectionsEditorTableView(
                self,
                None,
                truncate=truncate,
                minmax=minmax,
                remote_editing=remote_editing,
                get_value_func=self.get_value,
                set_value_func=self.set_value,
                new_value_func=self.set_value,
                remove_values_func=self.remove_values,
                copy_value_func=self.copy_value,
                is_list_func=self.is_list,
                get_len_func=self.get_len,
                is_array_func=self.is_array,
                is_image_func=self.is_image,
                is_dict_func=self.is_dict,
                is_data_frame_func=self.is_data_frame,
                is_series_func=self.is_series,
                get_array_shape_func=self.get_array_shape,
                get_array_ndim_func=self.get_array_ndim,
                oedit_func=self.oedit,
                plot_func=self.plot,
                imshow_func=self.imshow,
                show_image_func=self.show_image)
        self.editor.sig_option_changed.connect(self.sig_option_changed.emit)
        self.editor.sig_files_dropped.connect(self.import_data)

        # Setup layout
        layout = QVBoxLayout()
        blayout = QHBoxLayout()
        toolbar = self.setup_toolbar(exclude_private, exclude_uppercase,
                                     exclude_capitalized, exclude_unsupported,
                                     autorefresh)
        for widget in toolbar:
            blayout.addWidget(widget)

        # Options menu
        options_button = create_toolbutton(self,
                                           text=_('Options'),
                                           icon=ima.icon('tooloptions'))
        options_button.setPopupMode(QToolButton.InstantPopup)
        menu = QMenu(self)
        editor = self.editor
        actions = [
            self.exclude_private_action, self.exclude_uppercase_action,
            self.exclude_capitalized_action, self.exclude_unsupported_action,
            None, editor.truncate_action
        ]
        if is_module_installed('numpy'):
            actions.append(editor.minmax_action)
        add_actions(menu, actions)
        options_button.setMenu(menu)

        blayout.addStretch()
        blayout.addWidget(options_button)
        layout.addLayout(blayout)
        layout.addWidget(self.editor)
        self.setLayout(layout)
        layout.setContentsMargins(0, 0, 0, 0)

        self.sig_option_changed.connect(self.option_changed)
Пример #48
0
class NapariQtNotification(QDialog):
    """Notification dialog frame, appears at the bottom right of the canvas.

    By default, only the first line of the notification is shown, and the text
    is elided.  Double-clicking on the text (or clicking the chevron icon) will
    expand to show the full notification.  The dialog will autmatically
    disappear in ``DISMISS_AFTER`` milliseconds, unless hovered or clicked.

    Parameters
    ----------
    message : str
        The message that will appear in the notification
    severity : str or NotificationSeverity, optional
        Severity level {'error', 'warning', 'info', 'none'}.  Will determine
        the icon associated with the message.
        by default NotificationSeverity.WARNING.
    source : str, optional
        A source string for the notifcation (intended to show the module and
        or package responsible for the notification), by default None
    actions : list of tuple, optional
        A sequence of 2-tuples, where each tuple is a string and a callable.
        Each tuple will be used to create button in the dialog, where the text
        on the button is determine by the first item in the tuple, and a
        callback function to call when the button is pressed is the second item
        in the tuple. by default ()
    """

    MAX_OPACITY = 0.9
    FADE_IN_RATE = 220
    FADE_OUT_RATE = 120
    DISMISS_AFTER = 4000
    MIN_WIDTH = 400

    message: MultilineElidedLabel
    source_label: QLabel
    severity_icon: QLabel

    def __init__(
            self,
            message: str,
            severity: Union[str, NotificationSeverity] = 'WARNING',
            source: Optional[str] = None,
            actions: ActionSequence = (),
    ):
        super().__init__()

        from ..qt_main_window import _QtMainWindow

        current_window = _QtMainWindow.current()
        if current_window is not None:
            canvas = current_window.qt_viewer._canvas_overlay
            self.setParent(canvas)
            canvas.resized.connect(self.move_to_bottom_right)

        self.setupUi()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setup_buttons(actions)
        self.setMouseTracking(True)

        self.severity_icon.setText(NotificationSeverity(severity).as_icon())
        self.message.setText(message)
        if source:
            self.source_label.setText(
                trans._('Source: {source}', source=source))

        self.close_button.clicked.connect(self.close)
        self.expand_button.clicked.connect(self.toggle_expansion)

        self.timer = QTimer()
        self.opacity = QGraphicsOpacityEffect()
        self.setGraphicsEffect(self.opacity)
        self.opacity_anim = QPropertyAnimation(self.opacity, b"opacity", self)
        self.geom_anim = QPropertyAnimation(self, b"geometry", self)
        self.move_to_bottom_right()

    def move_to_bottom_right(self, offset=(8, 8)):
        """Position widget at the bottom right edge of the parent."""
        if not self.parent():
            return
        sz = self.parent().size() - self.size() - QSize(*offset)
        self.move(QPoint(sz.width(), sz.height()))

    def slide_in(self):
        """Run animation that fades in the dialog with a slight slide up."""
        geom = self.geometry()
        self.geom_anim.setDuration(self.FADE_IN_RATE)
        self.geom_anim.setStartValue(geom.translated(0, 20))
        self.geom_anim.setEndValue(geom)
        self.geom_anim.setEasingCurve(QEasingCurve.OutQuad)
        # fade in
        self.opacity_anim.setDuration(self.FADE_IN_RATE)
        self.opacity_anim.setStartValue(0)
        self.opacity_anim.setEndValue(self.MAX_OPACITY)
        self.geom_anim.start()
        self.opacity_anim.start()

    def show(self):
        """Show the message with a fade and slight slide in from the bottom."""
        super().show()
        self.slide_in()
        if self.DISMISS_AFTER > 0:
            self.timer.setInterval(self.DISMISS_AFTER)
            self.timer.setSingleShot(True)
            self.timer.timeout.connect(self.close)
        self.timer.start()

    def mouseMoveEvent(self, event):
        """On hover, stop the self-destruct timer"""
        self.timer.stop()

    def mouseDoubleClickEvent(self, event):
        """Expand the notification on double click."""
        self.toggle_expansion()

    def close(self):
        """Fade out then close."""
        self.opacity_anim.setDuration(self.FADE_OUT_RATE)
        self.opacity_anim.setStartValue(self.MAX_OPACITY)
        self.opacity_anim.setEndValue(0)
        self.opacity_anim.start()
        self.opacity_anim.finished.connect(super().close)

    def toggle_expansion(self):
        """Toggle the expanded state of the notification frame."""
        self.contract() if self.property('expanded') else self.expand()
        self.timer.stop()

    def expand(self):
        """Expanded the notification so that the full message is visible."""
        curr = self.geometry()
        self.geom_anim.setDuration(100)
        self.geom_anim.setStartValue(curr)
        new_height = self.sizeHint().height()
        delta = new_height - curr.height()
        self.geom_anim.setEndValue(
            QRect(curr.x(),
                  curr.y() - delta, curr.width(), new_height))
        self.geom_anim.setEasingCurve(QEasingCurve.OutQuad)
        self.geom_anim.start()
        self.setProperty('expanded', True)
        self.style().unpolish(self.expand_button)
        self.style().polish(self.expand_button)

    def contract(self):
        """Contract notification to a single elided line of the message."""
        geom = self.geometry()
        self.geom_anim.setDuration(100)
        self.geom_anim.setStartValue(geom)
        dlt = geom.height() - self.minimumHeight()
        self.geom_anim.setEndValue(
            QRect(geom.x(),
                  geom.y() + dlt, geom.width(),
                  geom.height() - dlt))
        self.geom_anim.setEasingCurve(QEasingCurve.OutQuad)
        self.geom_anim.start()
        self.setProperty('expanded', False)
        self.style().unpolish(self.expand_button)
        self.style().polish(self.expand_button)

    def setupUi(self):
        """Set up the UI during initialization."""
        self.setWindowFlags(Qt.SubWindow)
        self.setMinimumWidth(self.MIN_WIDTH)
        self.setMaximumWidth(self.MIN_WIDTH)
        self.setMinimumHeight(40)
        self.setSizeGripEnabled(False)
        self.setModal(False)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setContentsMargins(2, 2, 2, 2)
        self.verticalLayout.setSpacing(0)

        self.row1_widget = QWidget(self)
        self.row1 = QHBoxLayout(self.row1_widget)
        self.row1.setContentsMargins(12, 12, 12, 8)
        self.row1.setSpacing(4)
        self.severity_icon = QLabel(self.row1_widget)
        self.severity_icon.setObjectName("severity_icon")
        self.severity_icon.setMinimumWidth(30)
        self.severity_icon.setMaximumWidth(30)
        self.row1.addWidget(self.severity_icon, alignment=Qt.AlignTop)
        self.message = MultilineElidedLabel(self.row1_widget)
        self.message.setMinimumWidth(self.MIN_WIDTH - 200)
        self.message.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        self.row1.addWidget(self.message, alignment=Qt.AlignTop)
        self.expand_button = QPushButton(self.row1_widget)
        self.expand_button.setObjectName("expand_button")
        self.expand_button.setCursor(Qt.PointingHandCursor)
        self.expand_button.setMaximumWidth(20)
        self.expand_button.setFlat(True)

        self.row1.addWidget(self.expand_button, alignment=Qt.AlignTop)
        self.close_button = QPushButton(self.row1_widget)
        self.close_button.setObjectName("close_button")
        self.close_button.setCursor(Qt.PointingHandCursor)
        self.close_button.setMaximumWidth(20)
        self.close_button.setFlat(True)

        self.row1.addWidget(self.close_button, alignment=Qt.AlignTop)
        self.verticalLayout.addWidget(self.row1_widget, 1)
        self.row2_widget = QWidget(self)
        self.row2_widget.hide()
        self.row2 = QHBoxLayout(self.row2_widget)
        self.source_label = QLabel(self.row2_widget)
        self.source_label.setObjectName("source_label")
        self.row2.addWidget(self.source_label, alignment=Qt.AlignBottom)
        self.row2.addStretch()
        self.row2.setContentsMargins(12, 2, 16, 12)
        self.row2_widget.setMaximumHeight(34)
        self.row2_widget.setStyleSheet('QPushButton{'
                                       'padding: 4px 12px 4px 12px; '
                                       'font-size: 11px;'
                                       'min-height: 18px; border-radius: 0;}')
        self.verticalLayout.addWidget(self.row2_widget, 0)
        self.setProperty('expanded', False)
        self.resize(self.MIN_WIDTH, 40)

    def setup_buttons(self, actions: ActionSequence = ()):
        """Add buttons to the dialog.

        Parameters
        ----------
        actions : tuple, optional
            A sequence of 2-tuples, where each tuple is a string and a
            callable. Each tuple will be used to create button in the dialog,
            where the text on the button is determine by the first item in the
            tuple, and a callback function to call when the button is pressed
            is the second item in the tuple. by default ()
        """
        if isinstance(actions, dict):
            actions = list(actions.items())

        for text, callback in actions:
            btn = QPushButton(text)

            def call_back_with_self(callback, self):
                """
                We need a higher order function this to capture the reference to self.
                """
                def _inner():
                    return callback(self)

                return _inner

            btn.clicked.connect(call_back_with_self(callback, self))
            btn.clicked.connect(self.close)
            self.row2.addWidget(btn)
        if actions:
            self.row2_widget.show()
            self.setMinimumHeight(self.row2_widget.maximumHeight() +
                                  self.minimumHeight())

    def sizeHint(self):
        """Return the size required to show the entire message."""
        return QSize(
            super().sizeHint().width(),
            self.row2_widget.height() + self.message.sizeHint().height(),
        )

    @classmethod
    def from_notification(cls,
                          notification: Notification) -> NapariQtNotification:

        from ...utils.notifications import ErrorNotification

        actions = notification.actions

        if isinstance(notification, ErrorNotification):

            def show_tb(parent):
                tbdialog = QDialog(parent=parent.parent())
                tbdialog.setModal(True)
                # this is about the minimum width to not get rewrap
                # and the minimum height to not have scrollbar
                tbdialog.resize(650, 270)
                tbdialog.setLayout(QVBoxLayout())

                text = QTextEdit()
                text.setHtml(notification.as_html())
                text.setReadOnly(True)
                btn = QPushButton(trans._('Enter Debugger'))

                def _enter_debug_mode():
                    btn.setText(
                        trans.
                        _('Now Debugging. Please quit debugger in console to continue'
                          ))
                    _debug_tb(notification.exception.__traceback__)
                    btn.setText(trans._('Enter Debugger'))

                btn.clicked.connect(_enter_debug_mode)
                tbdialog.layout().addWidget(text)
                tbdialog.layout().addWidget(btn, 0, Qt.AlignRight)
                tbdialog.show()

            actions = tuple(notification.actions) + (
                (trans._('View Traceback'), show_tb), )
        else:
            actions = notification.actions

        return cls(
            message=notification.message,
            severity=notification.severity,
            source=notification.source,
            actions=actions,
        )

    @classmethod
    def show_notification(cls, notification: Notification):
        from ...utils.settings import SETTINGS

        # after https://github.com/napari/napari/issues/2370,
        # the os.getenv can be removed (and NAPARI_CATCH_ERRORS retired)
        if (os.getenv("NAPARI_CATCH_ERRORS") not in ('0', 'False')
                and notification.severity >=
                SETTINGS.application.gui_notification_level):
            application_instance = QApplication.instance()
            if application_instance:
                # Check if this is running from a thread
                if application_instance.thread() != QThread.currentThread():
                    dispatcher = getattr(application_instance, "_dispatcher",
                                         None)
                    if dispatcher:
                        dispatcher.sig_notified.emit(notification)

                    return

            cls.from_notification(notification).show()
Пример #49
0
    def setup(self):
        """Setup the ShortcutEditor with the provided arguments."""
        # Widgets
        icon_info = HelperToolButton()
        icon_info.setIcon(ima.get_std_icon('MessageBoxInformation'))
        layout_icon_info = QVBoxLayout()
        layout_icon_info.setContentsMargins(0, 0, 0, 0)
        layout_icon_info.setSpacing(0)
        layout_icon_info.addWidget(icon_info)
        layout_icon_info.addStretch(100)

        self.label_info = QLabel()
        self.label_info.setText(
            _("Press the new shortcut and select 'Ok' to confirm, "
              "click 'Cancel' to revert to the previous state, "
              "or use 'Clear' to unbind the command from a shortcut."))
        self.label_info.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.label_info.setWordWrap(True)
        layout_info = QHBoxLayout()
        layout_info.setContentsMargins(0, 0, 0, 0)
        layout_info.addLayout(layout_icon_info)
        layout_info.addWidget(self.label_info)
        layout_info.setStretch(1, 100)

        self.label_current_sequence = QLabel(_("Current shortcut:"))
        self.text_current_sequence = QLabel(self.current_sequence)

        self.label_new_sequence = QLabel(_("New shortcut:"))
        self.text_new_sequence = ShortcutLineEdit(self)
        self.text_new_sequence.setPlaceholderText(_("Press shortcut."))

        self.helper_button = HelperToolButton()
        self.helper_button.setIcon(QIcon())
        self.label_warning = QLabel()
        self.label_warning.setWordWrap(True)
        self.label_warning.setAlignment(Qt.AlignTop | Qt.AlignLeft)

        self.button_default = QPushButton(_('Default'))
        self.button_ok = QPushButton(_('Ok'))
        self.button_ok.setEnabled(False)
        self.button_clear = QPushButton(_('Clear'))
        self.button_cancel = QPushButton(_('Cancel'))
        button_box = QHBoxLayout()
        button_box.addWidget(self.button_default)
        button_box.addStretch(100)
        button_box.addWidget(self.button_ok)
        button_box.addWidget(self.button_clear)
        button_box.addWidget(self.button_cancel)

        # New Sequence button box
        self.btn_clear_sequence = create_toolbutton(
            self,
            icon=ima.icon('editclear'),
            tip=_("Clear all entered key sequences"),
            triggered=self.clear_new_sequence)
        self.button_back_sequence = create_toolbutton(
            self,
            icon=ima.icon('previous'),
            tip=_("Remove last key sequence entered"),
            triggered=self.back_new_sequence)

        newseq_btnbar = QHBoxLayout()
        newseq_btnbar.setSpacing(0)
        newseq_btnbar.setContentsMargins(0, 0, 0, 0)
        newseq_btnbar.addWidget(self.button_back_sequence)
        newseq_btnbar.addWidget(self.btn_clear_sequence)

        # Setup widgets
        self.setWindowTitle(_('Shortcut: {0}').format(self.name))
        self.helper_button.setToolTip('')
        style = """
            QToolButton {
              margin:1px;
              border: 0px solid grey;
              padding:0px;
              border-radius: 0px;
            }"""
        self.helper_button.setStyleSheet(style)
        icon_info.setToolTip('')
        icon_info.setStyleSheet(style)

        # Layout
        layout_sequence = QGridLayout()
        layout_sequence.setContentsMargins(0, 0, 0, 0)
        layout_sequence.addLayout(layout_info, 0, 0, 1, 4)
        layout_sequence.addItem(QSpacerItem(15, 15), 1, 0, 1, 4)
        layout_sequence.addWidget(self.label_current_sequence, 2, 0)
        layout_sequence.addWidget(self.text_current_sequence, 2, 2)
        layout_sequence.addWidget(self.label_new_sequence, 3, 0)
        layout_sequence.addWidget(self.helper_button, 3, 1)
        layout_sequence.addWidget(self.text_new_sequence, 3, 2)
        layout_sequence.addLayout(newseq_btnbar, 3, 3)
        layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2)
        layout_sequence.setColumnStretch(2, 100)
        layout_sequence.setRowStretch(4, 100)

        layout = QVBoxLayout(self)
        layout.addLayout(layout_sequence)
        layout.addSpacing(10)
        layout.addLayout(button_box)
        layout.setSizeConstraint(layout.SetFixedSize)

        # Signals
        self.button_ok.clicked.connect(self.accept_override)
        self.button_clear.clicked.connect(self.unbind_shortcut)
        self.button_cancel.clicked.connect(self.reject)
        self.button_default.clicked.connect(self.set_sequence_to_default)

        # Set all widget to no focus so that we can register <Tab> key
        # press event.
        widgets = (self.label_warning, self.helper_button,
                   self.text_new_sequence, self.button_clear,
                   self.button_default, self.button_cancel, self.button_ok,
                   self.btn_clear_sequence, self.button_back_sequence)
        for w in widgets:
            w.setFocusPolicy(Qt.NoFocus)
            w.clearFocus()
Пример #50
0
    def __init__(self, parent, project_types):
        """Project creation dialog."""
        super(ProjectDialog, self).__init__(parent=parent)
        self.plugin = parent
        self._project_types = project_types
        self.project_data = {}

        # 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.label_information = QLabel("")

        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)
        for (id_, name) in [(pt_id, pt.get_name()) for pt_id, pt
                            in project_types.items()]:
            self.combo_project_type.addItem(name, id_)

        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_grid.addWidget(self.label_information, 4, 0, 1, 3)

        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)
Пример #51
0
    def __init__(self, parent=None):
        """Home applications tab."""
        super(HomeTab, self).__init__(parent)

        # Variables
        self._parent = parent
        self.api = AnacondaAPI()
        self.applications = None
        self.style_sheet = None
        self.app_timers = None
        self.current_prefix = None

        # Widgets
        self.list = ListWidgetApplication()
        self.button_channels = ButtonHomeChannels('Channels')
        self.button_refresh = ButtonHomeRefresh('Refresh')
        self.combo = ComboHomeEnvironment()
        self.frame_top = FrameTabHeader(self)
        self.frame_body = FrameTabContent(self)
        self.frame_bottom = FrameTabFooter(self)
        self.label_home = LabelHome('Applications on')
        self.label_status_action = QLabel('')
        self.label_status = QLabel('')
        self.progress_bar = QProgressBar()
        self.first_widget = self.combo

        # Widget setup
        self.setObjectName('Tab')
        self.progress_bar.setTextVisible(False)
        self.list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        # Layout
        layout_top = QHBoxLayout()
        layout_top.addWidget(self.label_home)
        layout_top.addWidget(SpacerHorizontal())
        layout_top.addWidget(self.combo)
        layout_top.addWidget(SpacerHorizontal())
        layout_top.addWidget(self.button_channels)
        layout_top.addWidget(SpacerHorizontal())
        layout_top.addStretch()
        layout_top.addWidget(self.button_refresh)
        self.frame_top.setLayout(layout_top)

        layout_body = QVBoxLayout()
        layout_body.addWidget(self.list)
        self.frame_body.setLayout(layout_body)

        layout_bottom = QHBoxLayout()
        layout_bottom.addWidget(self.label_status_action)
        layout_bottom.addWidget(SpacerHorizontal())
        layout_bottom.addWidget(self.label_status)
        layout_bottom.addStretch()
        layout_bottom.addWidget(self.progress_bar)
        self.frame_bottom.setLayout(layout_bottom)

        layout = QVBoxLayout()
        layout.addWidget(self.frame_top)
        layout.addWidget(self.frame_body)
        layout.addWidget(self.frame_bottom)
        self.setLayout(layout)

        # Signals
        self.list.sig_conda_action_requested.connect(
            self.sig_conda_action_requested)
        self.list.sig_url_clicked.connect(self.sig_url_clicked)
        self.list.sig_launch_action_requested.connect(
            self.sig_launch_action_requested)
        self.button_channels.clicked.connect(self.show_channels)
        self.button_refresh.clicked.connect(self.refresh_cards)
        self.progress_bar.setVisible(False)
Пример #52
0
    def __init__(self, parent):
        super(KiteInstallation, self).__init__(parent)

        # Left side
        action_layout = QVBoxLayout()
        progress_layout = QHBoxLayout()
        self._progress_widget = QWidget(self)
        self._progress_widget.setFixedHeight(50)
        self._progress_filter = HoverEventFilter()
        self._progress_bar = QProgressBar(self)
        self._progress_bar.setFixedWidth(180)
        self._progress_widget.installEventFilter(self._progress_filter)
        cancel_button = QPushButton()
        cancel_button.setIcon(ima.icon('DialogCloseButton'))
        cancel_button.hide()
        progress_layout.addWidget(self._progress_bar, alignment=Qt.AlignLeft)
        progress_layout.addWidget(cancel_button)
        self._progress_widget.setLayout(progress_layout)

        self._progress_label = QLabel(_('Downloading'))
        install_info = QLabel(
            _("Kite comes with a native app called the Copilot <br>"
              "which provides you with real time <br>"
              "documentation as you code.<br><br>"
              "When Kite is done installing, the Copilot will <br>"
              "launch automatically and guide you throught the <br>"
              "rest of the setup process."))

        button_layout = QHBoxLayout()
        ok_button = QPushButton(_('OK'))
        button_layout.addStretch()
        button_layout.addWidget(ok_button)
        button_layout.addStretch()

        action_layout.addStretch()
        action_layout.addWidget(self._progress_label)
        action_layout.addWidget(self._progress_widget)
        action_layout.addWidget(install_info)
        action_layout.addSpacing(10)
        action_layout.addLayout(button_layout)
        action_layout.addStretch()

        # Right side
        copilot_image_source = get_image_path('kite_copilot.png')

        copilot_image = QPixmap(copilot_image_source)
        copilot_label = QLabel()
        screen = QApplication.primaryScreen()
        device_pixel_ratio = screen.devicePixelRatio()
        if device_pixel_ratio > 1:
            copilot_image.setDevicePixelRatio(device_pixel_ratio)
            copilot_label.setPixmap(copilot_image)
        else:
            image_height = copilot_image.height() * 0.4
            image_width = copilot_image.width() * 0.4
            copilot_label.setPixmap(
                copilot_image.scaled(image_width, image_height,
                                     Qt.KeepAspectRatio,
                                     Qt.SmoothTransformation))

        # Layout
        general_layout = QHBoxLayout()
        general_layout.addLayout(action_layout)
        general_layout.addWidget(copilot_label)

        self.setLayout(general_layout)

        # Signals
        ok_button.clicked.connect(self.sig_ok_button_clicked)
        cancel_button.clicked.connect(self.sig_cancel_button_clicked)
        self._progress_filter.sig_hover_enter.connect(
            lambda: cancel_button.show())
        self._progress_filter.sig_hover_leave.connect(
            lambda: cancel_button.hide())
Пример #53
0
    def __init__(self, parent, max_entries=100):
        QWidget.__init__(self, parent)
        
        self.setWindowTitle("Profiler")
        
        self.output = None
        self.error_output = None
        
        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None
        
        self.filecombo = PythonModulesComboBox(self)
        
        self.start_button = create_toolbutton(self, icon=ima.icon('run'),
                                    text=_("Profile"),
                                    tip=_("Run profiler"),
                                    triggered=lambda : self.start(),
                                    text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                             icon=ima.icon('stop'),
                                             text=_("Stop"),
                                             tip=_("Stop current profiling"),
                                             text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        #self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often. 

        browse_button = create_toolbutton(self, icon=ima.icon('fileopen'),
                                          tip=_('Select Python script'),
                                          triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(self, icon=ima.icon('log'),
                                            text=_("Output"),
                                            text_beside_icon=True,
                                            tip=_("Show program's output"),
                                            triggered=self.show_log)

        self.datatree = ProfilerDataTree(self)

        self.collapse_button = create_toolbutton(self,
                                                 icon=ima.icon('collapse'),
                                                 triggered=lambda dD:
                                                 self.datatree.change_view(-1),
                                                 tip=_('Collapse one level up'))
        self.expand_button = create_toolbutton(self,
                                               icon=ima.icon('expand'),
                                               triggered=lambda dD:
                                               self.datatree.change_view(1),
                                               tip=_('Expand one level down'))
                                
        self.save_button = create_toolbutton(self, text_beside_icon=True,
                                             text=_("Save data"),
                                             icon=ima.icon('filesave'),
                                             triggered=self.save_data,
                                             tip=_('Save profiling data'))
        self.load_button = create_toolbutton(self, text_beside_icon=True,
                            text=_("Load data"),
                            icon=ima.icon('fileimport'),
                            triggered=self.compare,
                            tip=_('Load profiling data for comparison'))
        self.clear_button = create_toolbutton(self, text_beside_icon=True,
                                              text=_("Clear comparison"),
                                              icon=ima.icon('editdelete'),
                                              triggered=self.clear)

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)
        hlayout2.addWidget(self.save_button)
        hlayout2.addWidget(self.load_button)
        hlayout2.addWidget(self.clear_button)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)
        
        self.process = None
        self.set_running_state(False)
        self.start_button.setEnabled(False)
        self.clear_button.setEnabled(False)

        if not is_profiler_installed():
            # This should happen only on certain GNU/Linux distributions 
            # or when this a home-made Python build because the Python 
            # profilers are included in the Python standard library
            for widget in (self.datatree, self.filecombo,
                           self.start_button, self.stop_button):
                widget.setDisabled(True)
            url = 'http://docs.python.org/library/profile.html'
            text = '%s <a href=%s>%s</a>' % (_('Please install'), url,
                                             _("the Python profiler modules"))
            self.datelabel.setText(text)
        else:
            pass # self.show_data()
Пример #54
0
class ObjectExplorer(QDialog):
    """Object explorer main widget window."""
    # TODO: Use signal to trigger update of configs
    sig_option_changed = Signal(str, object)

    _browsers = []  # Keep lists of browser windows.

    def __init__(self,
                 obj,
                 name='',
                 expanded=False,
                 resize_to_contents=True,
                 parent=None,
                 attribute_columns=DEFAULT_ATTR_COLS,
                 attribute_details=DEFAULT_ATTR_DETAILS,
                 show_callable_attributes=False,
                 show_special_attributes=False,
                 reset=False):
        """
        Constructor

        :param name: name of the object as it will appear in the root node
        :param expanded: show the first visible root element expanded
        :param resize_to_contents: resize columns to contents ignoring width
            of the attributes
        :param obj: any Python object or variable
        :param attribute_columns: list of AttributeColumn objects that
            define which columns are present in the table and their defaults
        :param attribute_details: list of AttributeDetails objects that define
            which attributes can be selected in the details pane.
        :param show_callable_attributes: if True rows where the 'is attribute'
            and 'is callable' columns are both True, are displayed.
            Otherwise they are hidden.
        :param show_special_attributes: if True rows where the 'is attribute'
            is True and the object name starts and ends with two underscores,
            are displayed. Otherwise they are hidden.
        :param reset: If true the persistent settings, such as column widths,
            are reset.
        """
        QDialog.__init__(self, parent=parent)

        self._instance_nr = self._add_instance()

        # Model
        self._attr_cols = attribute_columns
        self._attr_details = attribute_details

        self._tree_model = TreeModel(obj,
                                     obj_name=name,
                                     attr_cols=self._attr_cols)

        self._proxy_tree_model = TreeProxyModel(
            show_callable_attributes=show_callable_attributes,
            show_special_attributes=show_special_attributes)

        self._proxy_tree_model.setSourceModel(self._tree_model)
        # self._proxy_tree_model.setSortRole(RegistryTableModel.SORT_ROLE)
        self._proxy_tree_model.setDynamicSortFilter(True)
        # self._proxy_tree_model.setSortCaseSensitivity(Qt.CaseInsensitive)

        # Views
        self._setup_actions()
        self._setup_menu(show_callable_attributes=show_callable_attributes,
                         show_special_attributes=show_special_attributes)
        self._setup_views()
        if name:
            name = "{} -".format(name)
        self.setWindowTitle("{} {}".format(name, EDITOR_NAME))
        self.setWindowFlags(Qt.Window)

        self._resize_to_contents = resize_to_contents
        self._readViewSettings(reset=reset)

        # Update views with model
        self.toggle_show_special_attribute_action.setChecked(
            show_special_attributes)
        self.toggle_show_callable_action.setChecked(show_callable_attributes)

        # Select first row so that a hidden root node will not be selected.
        first_row_index = self._proxy_tree_model.firstItemIndex()
        self.obj_tree.setCurrentIndex(first_row_index)
        if self._tree_model.inspectedNodeIsVisible or expanded:
            self.obj_tree.expand(first_row_index)

    def _add_instance(self):
        """
        Adds the browser window to the list of browser references.
        If a None is present in the list it is inserted at that position,
        otherwise it is appended to the list. The index number is returned.

        This mechanism is used so that repeatedly creating and closing windows
        does not increase the instance number, which is used in writing
        the persistent settings.
        """
        try:
            idx = self._browsers.index(None)
        except ValueError:
            self._browsers.append(self)
            idx = len(self._browsers) - 1
        else:
            self._browsers[idx] = self

        return idx

    def _remove_instance(self):
        """Sets the reference in the browser list to None."""
        idx = self._browsers.index(self)
        self._browsers[idx] = None

    def _make_show_column_function(self, column_idx):
        """Creates a function that shows or hides a column."""
        show_column = lambda checked: self.obj_tree.setColumnHidden(
            column_idx, not checked)
        return show_column

    def _setup_actions(self):
        """Creates the main window actions."""
        # Show/hide callable objects
        self.toggle_show_callable_action = \
            QAction(_("Show callable attributes"), self, checkable=True,
                    shortcut=QKeySequence("Alt+C"),
                    statusTip=_("Shows/hides attributes "
                                "that are callable (functions, methods, etc)"))
        self.toggle_show_callable_action.toggled.connect(
            self._proxy_tree_model.setShowCallables)

        # Show/hide special attributes
        self.toggle_show_special_attribute_action = \
            QAction(_("Show __special__ attributes"), self, checkable=True,
                    shortcut=QKeySequence("Alt+S"),
                    statusTip=_("Shows or hides __special__ attributes"))
        self.toggle_show_special_attribute_action.toggled.connect(
            self._proxy_tree_model.setShowSpecialAttributes)

    def _setup_menu(self,
                    show_callable_attributes=False,
                    show_special_attributes=False):
        """Sets up the main menu."""
        self.tools_layout = QHBoxLayout()

        callable_attributes = create_toolbutton(
            self,
            text=_("Show callable attributes"),
            icon=ima.icon("class"),
            toggled=self._toggle_show_callable_attributes_action)
        callable_attributes.setCheckable(True)
        callable_attributes.setChecked(show_callable_attributes)
        self.tools_layout.addWidget(callable_attributes)

        special_attributes = create_toolbutton(
            self,
            text=_("Show __special__ attributes"),
            icon=ima.icon("private2"),
            toggled=self._toggle_show_special_attributes_action)
        special_attributes.setCheckable(True)
        special_attributes.setChecked(show_special_attributes)
        self.tools_layout.addWidget(special_attributes)

        self.tools_layout.addStretch()

        self.options_button = create_toolbutton(self,
                                                text=_('Options'),
                                                icon=ima.icon('tooloptions'))
        self.options_button.setPopupMode(QToolButton.InstantPopup)

        self.show_cols_submenu = QMenu(self)
        self.options_button.setMenu(self.show_cols_submenu)
        # Don't show menu arrow and remove padding
        if is_dark_interface():
            self.options_button.setStyleSheet(
                ("QToolButton::menu-indicator{image: none;}\n"
                 "QToolButton{padding: 3px;}"))
        else:
            self.options_button.setStyleSheet(
                "QToolButton::menu-indicator{image: none;}")
        self.tools_layout.addWidget(self.options_button)

    @Slot()
    def _toggle_show_callable_attributes_action(self):
        """Toggle show callable atributes action."""
        action_checked = not self.toggle_show_callable_action.isChecked()
        self.toggle_show_callable_action.setChecked(action_checked)
        self.sig_option_changed.emit('show_callable_attributes',
                                     action_checked)

    @Slot()
    def _toggle_show_special_attributes_action(self):
        """Toggle show special attributes action."""
        action_checked = (
            not self.toggle_show_special_attribute_action.isChecked())
        self.toggle_show_special_attribute_action.setChecked(action_checked)
        self.sig_option_changed.emit('show_special_attributes', action_checked)

    def _setup_views(self):
        """Creates the UI widgets."""
        self.central_splitter = QSplitter(self, orientation=Qt.Vertical)
        layout = create_plugin_layout(self.tools_layout, self.central_splitter)
        self.setLayout(layout)

        # Tree widget
        self.obj_tree = ToggleColumnTreeView()
        self.obj_tree.setAlternatingRowColors(True)
        self.obj_tree.setModel(self._proxy_tree_model)
        self.obj_tree.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.obj_tree.setUniformRowHeights(True)
        self.obj_tree.setAnimated(True)
        self.obj_tree.add_header_context_menu()

        # Stretch last column?
        # It doesn't play nice when columns are hidden and then shown again.
        obj_tree_header = self.obj_tree.header()
        obj_tree_header.setSectionsMovable(True)
        obj_tree_header.setStretchLastSection(False)
        add_actions(self.show_cols_submenu,
                    self.obj_tree.toggle_column_actions_group.actions())

        self.central_splitter.addWidget(self.obj_tree)

        # Bottom pane
        bottom_pane_widget = QWidget()
        bottom_layout = QHBoxLayout()
        bottom_layout.setSpacing(0)
        bottom_layout.setContentsMargins(5, 5, 5, 5)  # left top right bottom
        bottom_pane_widget.setLayout(bottom_layout)
        self.central_splitter.addWidget(bottom_pane_widget)

        group_box = QGroupBox(_("Details"))
        bottom_layout.addWidget(group_box)

        v_group_layout = QVBoxLayout()
        h_group_layout = QHBoxLayout()
        h_group_layout.setContentsMargins(2, 2, 2, 2)  # left top right bottom
        group_box.setLayout(v_group_layout)
        v_group_layout.addLayout(h_group_layout)

        # Radio buttons
        radio_widget = QWidget()
        radio_layout = QVBoxLayout()
        radio_layout.setContentsMargins(0, 0, 0, 0)  # left top right bottom
        radio_widget.setLayout(radio_layout)

        self.button_group = QButtonGroup(self)
        for button_id, attr_detail in enumerate(self._attr_details):
            radio_button = QRadioButton(attr_detail.name)
            radio_layout.addWidget(radio_button)
            self.button_group.addButton(radio_button, button_id)

        self.button_group.buttonClicked[int].connect(
            self._change_details_field)
        self.button_group.button(0).setChecked(True)

        radio_layout.addStretch(1)
        h_group_layout.addWidget(radio_widget)

        # Editor widget
        self.editor = CodeEditor(self)
        self.editor.setReadOnly(True)
        h_group_layout.addWidget(self.editor)

        # Warining label about repr
        repr_label = QLabel(
            _("(*) Some objects have very large repr's, "
              "which can freeze Spyder. Please use this "
              "with care."))
        v_group_layout.addWidget(repr_label)

        # Splitter parameters
        self.central_splitter.setCollapsible(0, False)
        self.central_splitter.setCollapsible(1, True)
        self.central_splitter.setSizes([500, 320])
        self.central_splitter.setStretchFactor(0, 10)
        self.central_splitter.setStretchFactor(1, 0)

        # Connect signals
        # Keep a temporary reference of the selection_model to prevent
        # segfault in PySide.
        # See http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/222
        selection_model = self.obj_tree.selectionModel()
        selection_model.currentChanged.connect(self._update_details)

    # End of setup_methods
    def _readViewSettings(self, reset=False):
        """
        Reads the persistent program settings.

        :param reset: If True, the program resets to its default settings.
        """
        pos = QPoint(20 * self._instance_nr, 20 * self._instance_nr)
        window_size = QSize(825, 650)
        details_button_idx = 0

        header = self.obj_tree.header()
        header_restored = False

        if reset:
            logger.debug("Resetting persistent view settings")
        else:
            pos = pos
            window_size = window_size
            details_button_idx = details_button_idx
            #            splitter_state = settings.value("central_splitter/state")
            splitter_state = None
            if splitter_state:
                self.central_splitter.restoreState(splitter_state)
#            header_restored = self.obj_tree.read_view_settings(
#                'table/header_state',
#                settings, reset)
            header_restored = False

        if not header_restored:
            column_sizes = [col.width for col in self._attr_cols]
            column_visible = [col.col_visible for col in self._attr_cols]

            for idx, size in enumerate(column_sizes):
                if not self._resize_to_contents and size > 0:  # Just in case
                    header.resizeSection(idx, size)
                else:
                    header.setSectionResizeMode(QHeaderView.ResizeToContents)

            for idx, visible in enumerate(column_visible):
                elem = self.obj_tree.toggle_column_actions_group.actions()[idx]
                elem.setChecked(visible)

        self.resize(window_size)

        button = self.button_group.button(details_button_idx)
        if button is not None:
            button.setChecked(True)

    @Slot(QModelIndex, QModelIndex)
    def _update_details(self, current_index, _previous_index):
        """Shows the object details in the editor given an index."""
        tree_item = self._proxy_tree_model.treeItem(current_index)
        self._update_details_for_item(tree_item)

    def _change_details_field(self, _button_id=None):
        """Changes the field that is displayed in the details pane."""
        # logger.debug("_change_details_field: {}".format(_button_id))
        current_index = self.obj_tree.selectionModel().currentIndex()
        tree_item = self._proxy_tree_model.treeItem(current_index)
        self._update_details_for_item(tree_item)

    def _update_details_for_item(self, tree_item):
        """Shows the object details in the editor given an tree_item."""
        try:
            # obj = tree_item.obj
            button_id = self.button_group.checkedId()
            assert button_id >= 0, ("No radio button selected. "
                                    "Please report this bug.")
            attr_details = self._attr_details[button_id]
            data = attr_details.data_fn(tree_item)
            self.editor.setPlainText(data)
            self.editor.setWordWrapMode(attr_details.line_wrap)
            show_blanks = CONF.get('editor', 'blank_spaces')
            update_scrollbar = CONF.get('editor', 'scroll_past_end')
            scheme_name = CONF.get('appearance', 'selected')
            self.editor.setup_editor(tab_mode=False,
                                     font=get_font(),
                                     show_blanks=show_blanks,
                                     color_scheme=scheme_name,
                                     scroll_past_end=update_scrollbar)
            self.editor.set_text(data)
            if attr_details.name == 'Source code':
                self.editor.set_language('Python')
            else:
                self.editor.set_language('Rst')
        except Exception as ex:
            self.editor.setStyleSheet("color: red;")
            stack_trace = traceback.format_exc()
            self.editor.setPlainText("{}\n\n{}".format(ex, stack_trace))
            self.editor.setWordWrapMode(
                QTextOption.WrapAtWordBoundaryOrAnywhere)

    def _finalize(self):
        """
        Cleans up resources when this window is closed.
        Disconnects all signals for this window.
        """
        self.toggle_show_callable_action.toggled.disconnect(
            self._proxy_tree_model.setShowCallables)
        self.toggle_show_special_attribute_action.toggled.disconnect(
            self._proxy_tree_model.setShowSpecialAttributes)
        self.button_group.buttonClicked[int].disconnect(
            self._change_details_field)
        selection_model = self.obj_tree.selectionModel()
        selection_model.currentChanged.disconnect(self._update_details)

    def closeEvent(self, event):
        """Called when the window is closed."""
        logger.debug("closeEvent")
        self._finalize()
        self.close()
        event.accept()
        self._remove_instance()
        self.about_to_quit()
        logger.debug("Closed {} window {}".format(EDITOR_NAME,
                                                  self._instance_nr))

    def about_to_quit(self):
        """Called when application is about to quit."""
        # Sanity check
        for idx, bw in enumerate(self._browsers):
            if bw is not None:
                raise AssertionError("Reference not"
                                     " cleaned up: {}".format(idx))

    @classmethod
    def create_explorer(cls, *args, **kwargs):
        """
        Creates and shows and ObjectExplorer window.

        The *args and **kwargs will be passed to the ObjectExplorer constructor

        A (class attribute) reference to the browser window is kept to prevent
        it from being garbage-collected.
        """
        object_explorer = cls(*args, **kwargs)
        object_explorer.exec_()
        return object_explorer
    def __init__(self, parent):
        QWidget.__init__(self, parent)

        self.setWindowTitle("Line profiler")

        self.output = None
        self.error_output = None

        self.use_colors = True

        self._last_wdir = None
        self._last_args = None
        self._last_pythonpath = None

        self.filecombo = PythonModulesComboBox(self)

        self.start_button = create_toolbutton(
            self, icon=get_icon('run.png'),
            text=_("Profile by line"),
            tip=_("Run line profiler"),
            triggered=self.start, text_beside_icon=True)
        self.stop_button = create_toolbutton(
            self,
            icon=get_icon('terminate.png'),
            text=_("Stop"),
            tip=_("Stop current profiling"),
            text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        #self.filecombo.valid.connect(self.show_data)
        # FIXME: The combobox emits this signal on almost any event
        #        triggering show_data() too early, too often.

        browse_button = create_toolbutton(
            self, icon=get_icon('fileopen.png'),
            tip=_('Select Python script'),
            triggered=self.select_file)

        self.datelabel = QLabel()

        self.log_button = create_toolbutton(
            self, icon=get_icon('log.png'),
            text=_("Output"),
            text_beside_icon=True,
            tip=_("Show program's output"),
            triggered=self.show_log)

        self.datatree = LineProfilerDataTree(self)

        self.collapse_button = create_toolbutton(
            self,
            icon=get_icon('collapse.png'),
            triggered=lambda dD=-1: self.datatree.collapseAll(),
            tip=_('Collapse all'))
        self.expand_button = create_toolbutton(
            self,
            icon=get_icon('expand.png'),
            triggered=lambda dD=1: self.datatree.expandAll(),
            tip=_('Expand all'))

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.collapse_button)
        hlayout2.addWidget(self.expand_button)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.datatree)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)
        self.start_button.setEnabled(False)

        if not is_lineprofiler_installed():
            for widget in (self.datatree, self.filecombo, self.log_button,
                           self.start_button, self.stop_button, browse_button,
                           self.collapse_button, self.expand_button):
                widget.setDisabled(True)
            text = _(
                '<b>Please install the <a href="%s">line_profiler module</a></b>'
                ) % WEBSITE_URL
            self.datelabel.setText(text)
            self.datelabel.setOpenExternalLinks(True)
        else:
            pass  # self.show_data()
Пример #56
0
    def __init__(self,
                 parent,
                 max_entries=100,
                 options_button=None,
                 text_color=None,
                 prevrate_color=None):
        super().__init__(parent)

        self.setWindowTitle("Pylint")

        self.output = None
        self.error_output = None
        self.filename = None
        self.text_color = text_color
        self.prevrate_color = prevrate_color

        self.max_entries = max_entries
        self.rdata = []
        if osp.isfile(self.DATAPATH):
            try:
                data = pickle.loads(open(self.DATAPATH, 'rb').read())
                if data[0] == self.VERSION:
                    self.rdata = data[1:]
            except (EOFError, ImportError):
                pass

        self.filecombo = PythonModulesComboBox(self)

        self.start_button = create_toolbutton(
            self,
            icon=ima.icon('run'),
            text=_("Analyze"),
            tip=_("Run analysis"),
            triggered=self.analyze_button_handler,
            text_beside_icon=True)
        self.stop_button = create_toolbutton(self,
                                             icon=ima.icon('stop'),
                                             text=_("Stop"),
                                             tip=_("Stop current analysis"),
                                             text_beside_icon=True)
        self.filecombo.valid.connect(self.start_button.setEnabled)
        self.filecombo.valid.connect(self.check_new_file)

        browse_button = create_toolbutton(self,
                                          icon=ima.icon('fileopen'),
                                          tip=_('Select Python file'),
                                          triggered=self.select_file)

        self.ratelabel = QLabel()
        self.datelabel = QLabel()
        self.log_button = create_toolbutton(self,
                                            icon=ima.icon('log'),
                                            text=_("Output"),
                                            text_beside_icon=True,
                                            tip=_("Complete output"),
                                            triggered=self.show_log)
        self.treewidget = ResultsTree(self)

        hlayout1 = QHBoxLayout()
        hlayout1.addWidget(self.filecombo)
        hlayout1.addWidget(browse_button)
        hlayout1.addWidget(self.start_button)
        hlayout1.addWidget(self.stop_button)
        if options_button:
            hlayout1.addWidget(options_button)

        hlayout2 = QHBoxLayout()
        hlayout2.addWidget(self.ratelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.datelabel)
        hlayout2.addStretch()
        hlayout2.addWidget(self.log_button)

        layout = QVBoxLayout()
        layout.addLayout(hlayout1)
        layout.addLayout(hlayout2)
        layout.addWidget(self.treewidget)
        self.setLayout(layout)

        self.process = None
        self.set_running_state(False)
        self.show_data()

        if self.rdata:
            self.remove_obsolete_items()
            self.filecombo.addItems(self.get_filenames())
            self.start_button.setEnabled(self.filecombo.is_valid())
        else:
            self.start_button.setEnabled(False)
Пример #57
0
class FigureBrowser(QWidget):
    """
    Widget to browse the figures that were sent by the kernel to the IPython
    console to be plotted inline.
    """
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()

    def __init__(self, parent=None, options_button=None, plugin_actions=[],
                 background_color=None):
        super(FigureBrowser, self).__init__(parent)

        self.shellwidget = None
        self.is_visible = True
        self.figviewer = None
        self.setup_in_progress = False
        self.background_color = background_color

        # Options :
        self.mute_inline_plotting = None
        self.show_plot_outline = None

        # Option actions :
        self.mute_inline_action = None
        self.show_plot_outline_action = None

        self.options_button = options_button
        self.plugin_actions = plugin_actions
        self.shortcuts = self.create_shortcuts()

    def setup(self, mute_inline_plotting=None, show_plot_outline=None):
        """Setup the figure browser with provided settings."""
        assert self.shellwidget is not None

        self.mute_inline_plotting = mute_inline_plotting
        self.show_plot_outline = show_plot_outline

        if self.figviewer is not None:
            self.mute_inline_action.setChecked(mute_inline_plotting)
            self.show_plot_outline_action.setChecked(show_plot_outline)
            return

        self.figviewer = FigureViewer(background_color=self.background_color)
        self.figviewer.setStyleSheet("FigureViewer{"
                                     "border: 1px solid lightgrey;"
                                     "border-top-width: 0px;"
                                     "border-bottom-width: 0px;"
                                     "border-left-width: 0px;"
                                     "}")
        self.thumbnails_sb = ThumbnailScrollBar(
            self.figviewer, background_color=self.background_color)

        # Option actions :
        self.setup_option_actions(mute_inline_plotting, show_plot_outline)

        # Create the layout :
        main_widget = QSplitter()
        main_widget.addWidget(self.figviewer)
        main_widget.addWidget(self.thumbnails_sb)
        main_widget.setFrameStyle(QScrollArea().frameStyle())

        self.tools_layout = QHBoxLayout()
        toolbar = self.setup_toolbar()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        layout = create_plugin_layout(self.tools_layout, main_widget)
        self.setLayout(layout)

    def setup_toolbar(self):
        """Setup the toolbar"""
        savefig_btn = create_toolbutton(
                self, icon=ima.icon('filesave'),
                tip=_("Save Image As..."),
                triggered=self.save_figure)

        saveall_btn = create_toolbutton(
                self, icon=ima.icon('save_all'),
                tip=_("Save All Images..."),
                triggered=self.save_all_figures)

        copyfig_btn = create_toolbutton(
            self, icon=ima.icon('editcopy'),
            tip=_("Copy plot to clipboard as image (%s)" %
                  get_shortcut('plots', 'copy')),
            triggered=self.copy_figure)

        closefig_btn = create_toolbutton(
                self, icon=ima.icon('editclear'),
                tip=_("Remove image"),
                triggered=self.close_figure)

        closeall_btn = create_toolbutton(
                self, icon=ima.icon('filecloseall'),
                tip=_("Remove all images from the explorer"),
                triggered=self.close_all_figures)

        vsep1 = QFrame()
        vsep1.setFrameStyle(53)

        goback_btn = create_toolbutton(
                self, icon=ima.icon('ArrowBack'),
                tip=_("Previous Figure ({})".format(
                      get_shortcut('plots', 'previous figure'))),
                triggered=self.go_previous_thumbnail)

        gonext_btn = create_toolbutton(
                self, icon=ima.icon('ArrowForward'),
                tip=_("Next Figure ({})".format(
                      get_shortcut('plots', 'next figure'))),
                triggered=self.go_next_thumbnail)

        vsep2 = QFrame()
        vsep2.setFrameStyle(53)

        zoom_out_btn = create_toolbutton(
                self, icon=ima.icon('zoom_out'),
                tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
                triggered=self.zoom_out)

        zoom_in_btn = create_toolbutton(
                self, icon=ima.icon('zoom_in'),
                tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
                triggered=self.zoom_in)

        self.zoom_disp = QSpinBox()
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(zoom_out_btn)
        layout.addWidget(zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [savefig_btn, saveall_btn, copyfig_btn, closefig_btn,
                closeall_btn, vsep1, goback_btn, gonext_btn, vsep2, zoom_pan]

    def setup_option_actions(self, mute_inline_plotting, show_plot_outline):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True
        self.mute_inline_action = create_action(
            self, _("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda state:
            self.option_changed('mute_inline_plotting', state)
            )
        self.mute_inline_action.setChecked(mute_inline_plotting)

        self.show_plot_outline_action = create_action(
            self, _("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=self.show_fig_outline_in_viewer
            )
        self.show_plot_outline_action.setChecked(show_plot_outline)

        self.actions = [self.mute_inline_action, self.show_plot_outline_action]
        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            # When the FigureBowser widget is instatiated outside of the
            # plugin (for testing purpose for instance), we need to create
            # the options_button and set its menu.
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(
                self.tools_layout.count() - 1, self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def create_shortcuts(self):
        """Create shortcuts for this widget."""
        # Configurable
        copyfig = config_shortcut(self.copy_figure, context='plots',
                                  name='copy', parent=self)
        prevfig = config_shortcut(self.go_previous_thumbnail, context='plots',
                                  name='previous figure', parent=self)
        nextfig = config_shortcut(self.go_next_thumbnail, context='plots',
                                  name='next figure', parent=self)

        return [copyfig, prevfig, nextfig]

    def get_shortcut_data(self):
        """
        Return shortcut data, a list of tuples (shortcut, text, default).

        shortcut (QShortcut or QAction instance)
        text (string): action/shortcut description
        default (string): default key sequence
        """
        return [sc.data for sc in self.shortcuts]

    def option_changed(self, option, value):
        """Handle when the value of an option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        if self.setup_in_progress is False:
            self.sig_option_changed.emit(option, value)

    def show_fig_outline_in_viewer(self, state):
        """Draw a frame around the figure viewer if state is True."""
        if state is True:
            self.figviewer.figcanvas.setStyleSheet(
                    "FigureCanvas{border: 1px solid lightgrey;}")
        else:
            self.figviewer.figcanvas.setStyleSheet("FigureCanvas{}")
        self.option_changed('show_plot_outline', state)

    def set_shellwidget(self, shellwidget):
        """Bind the shellwidget instance to the figure browser"""
        self.shellwidget = shellwidget
        shellwidget.set_figurebrowser(self)
        shellwidget.sig_new_inline_figure.connect(self._handle_new_figure)

    def get_actions(self):
        """Get the actions of the widget."""
        return self.actions

    def _handle_new_figure(self, fig, fmt):
        """
        Handle when a new figure is sent to the IPython console by the
        kernel.
        """
        self.thumbnails_sb.add_thumbnail(fig, fmt)

    # ---- Toolbar Handlers
    def zoom_in(self):
        """Zoom the figure in by a single step in the figure viewer."""
        self.figviewer.zoom_in()

    def zoom_out(self):
        """Zoom the figure out by a single step in the figure viewer."""
        self.figviewer.zoom_out()

    def go_previous_thumbnail(self):
        """
        Select the thumbnail previous to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_previous_thumbnail()

    def go_next_thumbnail(self):
        """
        Select the thumbnail next to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_next_thumbnail()

    def save_figure(self):
        """Save the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.save_current_figure_as()

    def save_all_figures(self):
        """Save all the figures in a selected directory."""
        return self.thumbnails_sb.save_all_figures_as()

    def close_figure(self):
        """Close the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_current_thumbnail()

    def close_all_figures(self):
        """Close all the figures in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_all_thumbnails()

    def copy_figure(self):
        """Copy figure from figviewer to clipboard."""
        if self.figviewer and self.figviewer.figcanvas.fig:
            self.figviewer.figcanvas.copy_figure()
Пример #58
0
    def __init__(self, parent):
        """Create About Spyder dialog with general information."""
        QDialog.__init__(self, parent)
        self.setWindowFlags(
            self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        versions = get_versions()
        # Show Git revision for development version
        revlink = ''
        if versions['revision']:
            rev = versions['revision']
            revlink = " (<a href='https://github.com/spyder-ide/spyder/" \
                      "commit/%s'>Commit: <br> %s</a>)" % (rev, rev)

        # Get current font properties
        font = self.font()
        font_family = font.family()
        buttons_padding = DialogStyle.ButtonsPadding
        buttons_font_size = DialogStyle.ButtonsFontSize
        font_size = DialogStyle.ContentFontSize
        dialog_background_color = QStylePalette.COLOR_BACKGROUND_2
        self.label_overview = QLabel((
            """
            <div style='font-family: "{font_family}";
                        font-size: {font_size};
                        font-weight: normal;
                        '>
            <br>
            <p>
            <b> Spyder IDE</b>
            <br> <br>
            The Scientific Python Development Environment |
            <a href="{website_url}">Spyder-IDE.org</a>
            <br>
            <p>
            Python {python_ver} {bitness}-bit | Qt {qt_ver} |
            {qt_api} {qt_api_ver} | {os_name} {os_ver}
            </p>
            <br> <br>
            <a href="{github_url}">GitHub </a>| <a href="{twitter_url}">
            Twitter </a>|
            <a href="{facebook_url}">Facebook </a>| <a href="{youtube_url}">
            YouTube </a>|
            <a href="{instagram_url}">Instagram </a>

            </div>""").format(
                website_url=__website_url__,
                github_url=__project_url__,
                twitter_url="https://twitter.com/Spyder_IDE",
                facebook_url="https://www.facebook.com/SpyderIDE",
                youtube_url="https://www.youtube.com/Spyder-IDE",
                instagram_url="https://www.instagram.com/spyderide/",
                python_ver=versions['python'],
                bitness=versions['bitness'],
                qt_ver=versions['qt'],
                qt_api=versions['qt_api'],
                qt_api_ver=versions['qt_api_ver'],
                os_name=versions['system'],
                os_ver=versions['release'],
                font_family=font_family,
                font_size=font_size,
            )
        )

        self.label_community = QLabel((
            """
            <div style='font-family: "{font_family}";
                        font-size: {font_size};
                        font-weight: normal;
                        '>
            <br>
            <p>
            Created by Pierre Raybaut; current maintainer is Carlos Cordoba.
            Developed by the
            <a href="{github_url}/graphs/contributors">international
            Spyder community</a>. Many thanks to all the Spyder beta testers
            and dedicated users.
            </p>
            <p>For help with Spyder errors and crashes, please read our
            <a href="{trouble_url}">Troubleshooting Guide</a>, and for bug
            reports and feature requests, visit our
            <a href="{github_url}">Github site</a>. For project discussion,
            see our <a href="{forum_url}">Google Group</a>.
            </p>
            <p>
            This project is part of a larger effort to promote and
            facilitate the use of Python for scientific and engineering
            software development.
            The popular Python distributions
            <a href="https://www.anaconda.com/download/">Anaconda</a> and
            <a href="https://winpython.github.io/">WinPython</a>
            also contribute to this plan.
            </p>
            </div>""").format(
                github_url=__project_url__,
                trouble_url=__trouble_url__,
                forum_url=__forum_url__,
                font_family=font_family,
                font_size=font_size,
            ))
        self.label_legal = QLabel((
            """
            <div style='font-family: "{font_family}";
                        font-size: {font_size};
                        font-weight: normal;
                        '>
            <br>
            <p>
            Copyright &copy; 2009-2020 Spyder Project Contributors and
            <a href="{github_url}/blob/master/AUTHORS.txt">others</a>.
            Distributed under the terms of the
            <a href="{github_url}/blob/master/LICENSE.txt">MIT License</a>.
            </p>
            <p>
            <p>Certain source files under other compatible permissive
            licenses and/or originally by other authors.
            Spyder 3 theme icons derived from
            <a href="https://fontawesome.com/">Font Awesome</a> 4.7
            (&copy; 2016 David Gandy; SIL OFL 1.1) and
            <a href="http://materialdesignicons.com/">Material Design</a>
            (&copy; 2014 Austin Andrews; SIL OFL 1.1).
            Most Spyder 2 theme icons sourced from the
            <a href="https://www.everaldo.com">Crystal Project iconset</a>
            (&copy; 2006-2007 Everaldo Coelho; LGPL 2.1+).
            Other icons from
            <a href="http://p.yusukekamiyamane.com/">Yusuke Kamiyamane</a>
            (&copy; 2013 Yusuke Kamiyamane; CC-BY 3.0),
            the <a href="http://www.famfamfam.com/lab/icons/silk/">FamFamFam
            Silk icon set</a> 1.3 (&copy; 2006 Mark James; CC-BY 2.5), and
            the <a href="https://www.kde.org/">KDE Oxygen icons</a>
            (&copy; 2007 KDE Artists; LGPL 3.0+).
            </p>
            <p>
            Splash screen photo by
            <a href="https://unsplash.com/@benchaccounting?utm_source=
            unsplash&utm_medium=referral&utm_content=creditCopyText">Bench
            Accounting</a> on <a href="https://unsplash.com/?utm_source=
            unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash
            </a>
            </p>
            <p>
            See the <a href="{github_url}/blob/master/NOTICE.txt">NOTICE</a>
            file for full legal information.
            </p>
            </div>
            """).format(
                github_url=__project_url__,
                font_family=font_family,
                font_size=font_size,
            )
        )

        for label in [self.label_overview, self.label_community,
                      self.label_legal]:
            label.setWordWrap(True)
            label.setAlignment(Qt.AlignTop)
            label.setOpenExternalLinks(True)
            label.setTextInteractionFlags(Qt.TextBrowserInteraction)
            label.setContentsMargins(15, 0, 25, 0)

        icon_filename = "spyder_about"
        pixmap = QPixmap(get_image_path(icon_filename))
        self.label_pic = QLabel(self)
        self.label_pic.setPixmap(
            pixmap.scaledToWidth(100, Qt.SmoothTransformation))
        self.label_pic.setAlignment(Qt.AlignBottom)
        self.info = QLabel((
            """
            <div style='font-family: "{font_family}";
                font-size: {font_size};
                font-weight: normal;
                '>
            <p>
            <b>Spyder IDE</b>
            <br>{spyder_ver}
            <br> {revision}
            <br> """).format(
            spyder_ver=versions['spyder'],
            revision=revlink,
            font_family=font_family,
            font_size=font_size))
        self.info.setAlignment(Qt.AlignHCenter)

        btn = QPushButton(_("Copy version info"), )
        bbox = QDialogButtonBox(QDialogButtonBox.Ok)
        bbox.setStyleSheet(
           f"font-size: {buttons_font_size};"
           f"padding: {buttons_padding}"
         )
        btn.setStyleSheet(
           f"font-size: {buttons_font_size};"
           f"padding: {buttons_padding}"
         )

        # Widget setup
        self.setWindowIcon(ima.icon('MessageBoxInformation'))
        self.setModal(False)

        # Layout
        piclayout = QVBoxLayout()
        piclayout.addWidget(self.label_pic)
        piclayout.addWidget(self.info)
        piclayout.setContentsMargins(20, 0, 15, 0)

        scroll_overview = QScrollArea(self)
        scroll_overview.setWidgetResizable(True)
        scroll_overview.setWidget(self.label_overview)

        scroll_community = QScrollArea(self)
        scroll_community.setWidgetResizable(True)
        scroll_community.setWidget(self.label_community)

        scroll_legal = QScrollArea(self)
        scroll_legal.setWidgetResizable(True)
        scroll_legal.setWidget(self.label_legal)

        self.tabs = QTabWidget()
        self.tabs.addTab(scroll_overview, _('Overview'))
        self.tabs.addTab(scroll_community, _('Community'))
        self.tabs.addTab(scroll_legal, _('Legal'))
        self.tabs.setStyleSheet(
            f"background-color: {dialog_background_color}")
        tabslayout = QHBoxLayout()
        tabslayout.addWidget(self.tabs)
        tabslayout.setSizeConstraint(tabslayout.SetFixedSize)
        tabslayout.setContentsMargins(0, 15, 15, 0)

        btmhlayout = QHBoxLayout()
        btmhlayout.addWidget(btn)
        btmhlayout.addWidget(bbox)
        btmhlayout.setContentsMargins(100, 20, 0, 20)
        btmhlayout.addStretch()

        vlayout = QVBoxLayout()
        vlayout.addLayout(tabslayout)
        vlayout.addLayout(btmhlayout)
        vlayout.setSizeConstraint(vlayout.SetFixedSize)

        mainlayout = QHBoxLayout(self)
        mainlayout.addLayout(piclayout)
        mainlayout.addLayout(vlayout)

        # Signals
        btn.clicked.connect(self.copy_to_clipboard)
        bbox.accepted.connect(self.accept)

        # Size
        self.resize(550, 430)

        # Style
        css = APP_STYLESHEET.get_copy()
        css = css.get_stylesheet()
        css.QDialog.setValues(backgroundColor=dialog_background_color)
        css.QLabel.setValues(backgroundColor=dialog_background_color)
        self.setStyleSheet(str(css))
Пример #59
0
    def __init__(self,
                 parent,
                 name=None,
                 prefix=None,
                 channels=(),
                 active_channels=(),
                 conda_url='https://conda.anaconda.org',
                 conda_api_url='https://api.anaconda.org',
                 setup=True,
                 data_directory=None,
                 extra_metadata={}):

        super(CondaPackagesWidget, self).__init__(parent)

        # Check arguments: active channels, must be witbhin channels
        for ch in active_channels:
            if ch not in channels:
                raise Exception("'active_channels' must be also within "
                                "'channels'")

        if data_directory is None:
            data_directory = self.CONDA_CONF_PATH

        self._parent = parent
        self._current_action_name = ''
        self._hide_widgets = False
        self._metadata = extra_metadata  # From repo.continuum
        self._metadata_links = {}        # Bundled metadata
        self.api = ManagerAPI()
        self.busy = False
        self.data_directory = data_directory
        self.conda_url = conda_url
        self.conda_api_url = conda_api_url
        self.name = name
        self.package_blacklist = []
        self.prefix = prefix
        self.root_prefix = self.api.ROOT_PREFIX
        self.style_sheet = None
        self.message = ''
        self.apply_actions_dialog = None
        self.conda_errors = []
        self.message_box_error = None
        self.token = None

        if channels:
            self._channels = channels
            self._active_channels = active_channels
        else:
            self._channels = self.api.conda_get_condarc_channels()
            self._active_channels = self._channels[:]

        # Widgets
        self.cancel_dialog = ClosePackageManagerDialog
        self.bbox = QDialogButtonBox(Qt.Horizontal)
        self.button_cancel = ButtonPackageCancel('Cancel')
        self.button_channels = ButtonPackageChannels(_('Channels'))
        self.button_ok = ButtonPackageOk(_('Ok'))
        self.button_update = ButtonPackageUpdate(_('Update package index...'))
        self.button_apply = ButtonPackageApply(_('Apply'))
        self.button_clear = ButtonPackageClear(_('Clear'))
        self.combobox_filter = DropdownPackageFilter(self)
        self.frame_top = FramePackageTop()
        self.frame_bottom = FramePackageTop()
        self.progress_bar = ProgressBarPackage(self)
        self.status_bar = LabelPackageStatus(self)
        self.table = TableCondaPackages(self)
        self.textbox_search = LineEditSearch(self)
        self.widgets = [self.button_update, self.button_channels,
                        self.combobox_filter, self.textbox_search, self.table,
                        self.button_ok, self.button_apply, self.button_clear]
        self.table_first_row = FirstRowWidget(
            widget_before=self.textbox_search)
        self.table_last_row = LastRowWidget(
            widgets_after=[self.button_apply, self.button_clear,
                           self.button_cancel, self.combobox_filter])

        # Widgets setup
        for button in [self.button_cancel, self.button_apply,
                       self.button_clear, self.button_ok, self.button_update,
                       self.button_channels]:
            button.setDefault(True)
        max_height = self.status_bar.fontMetrics().height()
        max_width = self.textbox_search.fontMetrics().width('M'*23)
        self.bbox.addButton(self.button_ok, QDialogButtonBox.ActionRole)
        self.button_ok.setAutoDefault(True)
        self.button_ok.setDefault(True)
        self.button_ok.setMaximumSize(QSize(0, 0))
        self.button_ok.setVisible(False)
        self.button_channels.setCheckable(True)
        self.combobox_filter.addItems([k for k in C.COMBOBOX_VALUES_ORDERED])
        self.combobox_filter.setMinimumWidth(120)
        self.progress_bar.setMaximumHeight(max_height*1.2)
        self.progress_bar.setMaximumWidth(max_height*12)
        self.progress_bar.setTextVisible(False)
        self.progress_bar.setVisible(False)
        self.setMinimumSize(QSize(480, 300))
        self.setWindowTitle(_("Conda Package Manager"))
        self.status_bar.setFixedHeight(max_height*1.5)
        self.textbox_search.setMaximumWidth(max_width)
        self.textbox_search.setPlaceholderText('Search Packages')
        self.table_first_row.setMaximumHeight(0)
        self.table_last_row.setMaximumHeight(0)
        self.table_last_row.setVisible(False)
        self.table_first_row.setVisible(False)

        # Layout
        top_layout = QHBoxLayout()
        top_layout.addWidget(self.combobox_filter)
        top_layout.addWidget(self.button_channels)
        top_layout.addWidget(self.button_update)
        top_layout.addWidget(self.textbox_search)
        top_layout.addStretch()
        top_layout.setContentsMargins(0, 0, 0, 0)
        self.frame_top.setLayout(top_layout)

        middle_layout = QVBoxLayout()
        middle_layout.addWidget(self.table_first_row)
        middle_layout.addWidget(self.table)
        middle_layout.addWidget(self.table_last_row)

        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.status_bar)
        bottom_layout.addStretch()
        bottom_layout.addWidget(self.progress_bar)
        bottom_layout.addWidget(self.button_cancel)
        bottom_layout.addWidget(self.button_apply)
        bottom_layout.addWidget(self.button_clear)
        bottom_layout.setContentsMargins(0, 0, 0, 0)
        self.frame_bottom.setLayout(bottom_layout)

        layout = QVBoxLayout(self)
        layout.addWidget(self.frame_top)
        layout.addLayout(middle_layout)
        layout.addWidget(self.frame_bottom)
        self.setLayout(layout)

        self.setTabOrder(self.combobox_filter, self.button_channels)
        self.setTabOrder(self.button_channels, self.button_update)
        self.setTabOrder(self.button_update, self.textbox_search)
        self.setTabOrder(self.textbox_search, self.table_first_row)
        self.setTabOrder(self.table, self.table_last_row)
        self.setTabOrder(self.table_last_row, self.button_apply)
        self.setTabOrder(self.button_apply, self.button_clear)
        self.setTabOrder(self.button_clear, self.button_cancel)

        # Signals and slots
        self.api.sig_repodata_updated.connect(self._repodata_updated)
        self.combobox_filter.currentIndexChanged.connect(self.filter_package)
        self.button_apply.clicked.connect(self.apply_multiple_actions)
        self.button_clear.clicked.connect(self.clear_actions)
        self.button_cancel.clicked.connect(self.cancel_process)
        self.button_channels.clicked.connect(self.show_channels_dialog)
        self.button_update.clicked.connect(self.update_package_index)
        self.textbox_search.textChanged.connect(self.search_package)
        self.table.sig_conda_action_requested.connect(self._run_conda_action)
        self.table.sig_actions_updated.connect(self.update_actions)
        self.table.sig_pip_action_requested.connect(self._run_pip_action)
        self.table.sig_status_updated.connect(self.update_status)
        self.table.sig_next_focus.connect(self.table_last_row.handle_tab)
        self.table.sig_previous_focus.connect(
            lambda: self.table_first_row.widget_before.setFocus())
        self.table_first_row.sig_enter_first.connect(self._handle_tab_focus)
        self.table_last_row.sig_enter_last.connect(self._handle_backtab_focus)

        # Setup
        self.api.client_set_domain(conda_api_url)
        self.api.set_data_directory(self.data_directory)
        self._load_bundled_metadata()
        self.update_actions(0)

        if setup:
            self.set_environment(name=name, prefix=prefix)
            self.setup()
Пример #60
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events.selected_label.connect(
            self._on_selected_label_change
        )
        self.layer.events.brush_size.connect(self._on_brush_size_change)
        self.layer.events.contiguous.connect(self._on_contiguous_change)
        self.layer.events.n_edit_dimensions.connect(
            self._on_n_edit_dimensions_change
        )
        self.layer.events.contour.connect(self._on_contour_change)
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.events.preserve_labels.connect(
            self._on_preserve_labels_change
        )
        self.layer.events.color_mode.connect(self._on_color_mode_change)

        # selection spinbox
        self.selectionSpinBox = QtLargeIntSpinBox()
        layer_dtype = get_dtype(layer)
        self.selectionSpinBox.set_dtype(layer_dtype)
        self.selectionSpinBox.setKeyboardTracking(False)
        self.selectionSpinBox.valueChanged.connect(self.changeSelection)
        self.selectionSpinBox.setAlignment(Qt.AlignCenter)
        self._on_selected_label_change()

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        sld.valueChanged.connect(self.changeSize)
        self.brushSizeSlider = sld
        self._on_brush_size_change()

        contig_cb = QCheckBox()
        contig_cb.setToolTip(trans._('contiguous editing'))
        contig_cb.stateChanged.connect(self.change_contig)
        self.contigCheckBox = contig_cb
        self._on_contiguous_change()

        ndim_sb = QSpinBox()
        self.ndimSpinBox = ndim_sb
        ndim_sb.setToolTip(trans._('number of dimensions for label editing'))
        ndim_sb.valueChanged.connect(self.change_n_edit_dim)
        ndim_sb.setMinimum(2)
        ndim_sb.setMaximum(self.layer.ndim)
        ndim_sb.setSingleStep(1)
        ndim_sb.setAlignment(Qt.AlignCenter)
        self._on_n_edit_dimensions_change()

        self.contourSpinBox = QtLargeIntSpinBox()
        self.contourSpinBox.set_dtype(layer_dtype)
        self.contourSpinBox.setToolTip(trans._('display contours of labels'))
        self.contourSpinBox.valueChanged.connect(self.change_contour)
        self.contourSpinBox.setKeyboardTracking(False)
        self.contourSpinBox.setAlignment(Qt.AlignCenter)
        self._on_contour_change()

        preserve_labels_cb = QCheckBox()
        preserve_labels_cb.setToolTip(
            trans._('preserve existing labels while painting')
        )
        preserve_labels_cb.stateChanged.connect(self.change_preserve_labels)
        self.preserveLabelsCheckBox = preserve_labels_cb
        self._on_preserve_labels_change()

        selectedColorCheckbox = QCheckBox()
        selectedColorCheckbox.setToolTip(
            trans._("Display only selected label")
        )
        selectedColorCheckbox.stateChanged.connect(self.toggle_selected_mode)
        self.selectedColorCheckbox = selectedColorCheckbox

        # shuffle colormap button
        self.colormapUpdate = QtModePushButton(
            None,
            'shuffle',
            slot=self.changeColor,
            tooltip=trans._('shuffle colors'),
        )

        self.panzoom_button = QtModeRadioButton(
            layer,
            'zoom',
            Mode.PAN_ZOOM,
            checked=True,
        )
        action_manager.bind_button(
            'napari:activate_label_pan_zoom_mode', self.panzoom_button
        )

        self.pick_button = QtModeRadioButton(layer, 'picker', Mode.PICK)
        action_manager.bind_button(
            'napari:activate_label_picker_mode', self.pick_button
        )

        self.paint_button = QtModeRadioButton(layer, 'paint', Mode.PAINT)
        action_manager.bind_button(
            'napari:activate_paint_mode', self.paint_button
        )

        self.fill_button = QtModeRadioButton(
            layer,
            'fill',
            Mode.FILL,
        )
        action_manager.bind_button(
            'napari:activate_fill_mode',
            self.fill_button,
            extra_tooltip_text=trans._(
                "Toggle with {shortcut}",
                shortcut=Shortcut("Control"),
            ),
        )

        self.erase_button = QtModeRadioButton(
            layer,
            'erase',
            Mode.ERASE,
        )
        action_manager.bind_button(
            'napari:activate_label_erase_mode',
            self.erase_button,
            extra_tooltip_text=trans._(
                "Toggle with {shortcut}",
                shortcut=Shortcut("Alt"),
            ),
        )

        # don't bind with action manager as this would remove "Toggle with {shortcut}"

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.paint_button)
        self.button_group.addButton(self.pick_button)
        self.button_group.addButton(self.fill_button)
        self.button_group.addButton(self.erase_button)
        self._on_editable_change()

        button_row = QHBoxLayout()
        button_row.addStretch(1)
        button_row.addWidget(self.colormapUpdate)
        button_row.addWidget(self.erase_button)
        button_row.addWidget(self.fill_button)
        button_row.addWidget(self.paint_button)
        button_row.addWidget(self.pick_button)
        button_row.addWidget(self.panzoom_button)
        button_row.setSpacing(4)
        button_row.setContentsMargins(0, 0, 0, 5)

        color_mode_comboBox = QComboBox(self)
        for index, (data, text) in enumerate(
            LABEL_COLOR_MODE_TRANSLATIONS.items()
        ):
            data = data.value
            color_mode_comboBox.addItem(text, data)

            if self.layer.color_mode == data:
                color_mode_comboBox.setCurrentIndex(index)

        color_mode_comboBox.activated[str].connect(self.change_color_mode)
        self.colorModeComboBox = color_mode_comboBox
        self._on_color_mode_change()

        color_layout = QHBoxLayout()
        self.colorBox = QtColorBox(layer)
        color_layout.addWidget(self.colorBox)
        color_layout.addWidget(self.selectionSpinBox)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_row, 0, 0, 1, 4)
        self.grid_layout.addWidget(QLabel(trans._('label:')), 1, 0, 1, 1)
        self.grid_layout.addLayout(color_layout, 1, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 2, 0, 1, 1)
        self.grid_layout.addWidget(self.opacitySlider, 2, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('brush size:')), 3, 0, 1, 1)
        self.grid_layout.addWidget(self.brushSizeSlider, 3, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 5, 0, 1, 1)
        self.grid_layout.addWidget(self.blendComboBox, 5, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('color mode:')), 6, 0, 1, 1)
        self.grid_layout.addWidget(self.colorModeComboBox, 6, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('contour:')), 7, 0, 1, 1)
        self.grid_layout.addWidget(self.contourSpinBox, 7, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('n edit dim:')), 8, 0, 1, 1)
        self.grid_layout.addWidget(self.ndimSpinBox, 8, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('contiguous:')), 9, 0, 1, 1)
        self.grid_layout.addWidget(self.contigCheckBox, 9, 1, 1, 1)
        self.grid_layout.addWidget(
            QLabel(trans._('preserve labels:')), 10, 0, 1, 2
        )
        self.grid_layout.addWidget(self.preserveLabelsCheckBox, 10, 1, 1, 1)
        self.grid_layout.addWidget(
            QLabel(trans._('show selected:')), 10, 2, 1, 1
        )
        self.grid_layout.addWidget(self.selectedColorCheckbox, 10, 3, 1, 1)
        self.grid_layout.setRowStretch(10, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)