def minimumSize(self): size = QSize() for item in self.item_list: size = size.expandedTo(item.minimumSize()) #size += QSize(2*self.margin(), 2*self.margin()) size += QSize(2*8, 2*8) return size
def sizeHint(self): """Returns the widget size hint (based on the editor font size) """ fm = QFontMetricsF(self.editor.font()) size_hint = QSize(fm.height(), fm.height()) if size_hint.width() > 16: size_hint.setWidth(16) return size_hint
def readSettings(self, settings): qapp = QApplication.instance() qapp.setAttribute(Qt.AA_UseHighDpiPixmaps) if hasattr(Qt, 'AA_EnableHighDpiScaling'): qapp.setAttribute(Qt.AA_EnableHighDpiScaling, settings.get('high_dpi_scaling')) # get the saved window geometry window_size = settings.get('MainWindow/size') if not isinstance(window_size, QSize): window_size = QSize(*window_size) window_pos = settings.get('MainWindow/position') if not isinstance(window_pos, QPoint): window_pos = QPoint(*window_pos) # make sure main window is smaller than the desktop desktop = QDesktopWidget() # this gives the maximum screen number if the position is off screen screen = desktop.screenNumber(window_pos) # recalculate the window size desktop_geom = desktop.screenGeometry(screen) w = min(desktop_geom.size().width(), window_size.width()) h = min(desktop_geom.size().height(), window_size.height()) window_size = QSize(w, h) # and position it on the supplied desktop screen x = max(window_pos.x(), desktop_geom.left()) y = max(window_pos.y(), desktop_geom.top()) window_pos = QPoint(x, y) # set the geometry self.resize(window_size) self.move(window_pos) # restore window state if settings.has('MainWindow/state'): self.restoreState(settings.get('MainWindow/state')) else: self.setWindowState(Qt.WindowMaximized) # read in settings for children AlgorithmInputHistory().readSettings(settings) for widget in self.widgets: if hasattr(widget, 'readSettings'): widget.readSettings(settings)
def imageFiles(self, new_files): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Parameters ---------- new_files : str """ self._state_images_string = str(new_files) try: new_file_dict = json.loads(self._state_images_string) except Exception: self._state_images = {} return self._sizeHint = QSize(0, 0) for (state, filename) in new_file_dict.items(): if is_pydm_app(): try: file_path = self.app.get_path(filename) except Exception as e: logger.exception("Couldn't get file with path %s", filename) file_path = filename else: file_path = filename # First, lets try SVG. We have to try SVG first, otherwise # QPixmap will happily load the SVG and turn it into a raster image. # Really annoying: We have to try to load the file as SVG, # and we expect it will fail often (because many images aren't SVG). # Qt prints a warning message to stdout any time SVG loading fails. # So we have to temporarily silence Qt warning messages here. qInstallMessageHandler(self.qt_message_handler) svg = QSvgRenderer() svg.repaintNeeded.connect(self.update) if svg.load(file_path): self._state_images[int(state)] = (filename, svg) self._sizeHint = self._sizeHint.expandedTo(svg.defaultSize()) qInstallMessageHandler(None) continue qInstallMessageHandler(None) # SVG didn't work, lets try QPixmap image = QPixmap(file_path) if not image.isNull(): self._state_images[int(state)] = (filename, image) self._sizeHint = self._sizeHint.expandedTo(image.size()) continue # If we get this far, the file specified could not be loaded at all. logger.error("Could not load image: {}".format(filename)) self._state_images[int(state)] = (filename, None)
def __init__(self, parent=None) -> None: super().__init__(parent) self._size = QSize(50, 50) self._max_id = 0
def sizeHint( self ): return QSize( 50, _TRACK_SIZE )
def sizeHint(self): """Override Qt method""" return QSize(self.WIDTH, 0)
class LSPServerEditor(QDialog): DEFAULT_HOST = '127.0.0.1' DEFAULT_PORT = 2084 DEFAULT_CMD = '' DEFAULT_ARGS = '' DEFAULT_CONFIGURATION = '{}' DEFAULT_EXTERNAL = False DEFAULT_STDIO = False HOST_REGEX = re.compile(r'^\w+([.]\w+)*$') NON_EMPTY_REGEX = re.compile(r'^\S+$') JSON_VALID = _('Valid JSON') JSON_INVALID = _('Invalid JSON') MIN_SIZE = QSize(850, 600) INVALID_CSS = "QLineEdit {border: 1px solid red;}" VALID_CSS = "QLineEdit {border: 1px solid green;}" def __init__(self, parent, language=None, cmd='', host='127.0.0.1', port=2084, args='', external=False, stdio=False, configurations={}, **kwargs): super(LSPServerEditor, self).__init__(parent) description = _( "To create a new server configuration, you need to select a " "programming language, set the command to start its associated " "server and enter any arguments that should be passed to it on " "startup. Additionally, you can set the server's hostname and " "port if connecting to an external server, " "or to a local one using TCP instead of stdio pipes." "<br><br>" "<i>Note</i>: You can use the placeholders <tt>{host}</tt> and " "<tt>{port}</tt> in the server arguments field to automatically " "fill in the respective values.<br>") self.parent = parent self.external = external # Widgets self.server_settings_description = QLabel(description) self.lang_cb = QComboBox(self) self.external_cb = QCheckBox(_('External server'), self) self.host_label = QLabel(_('Host:')) self.host_input = QLineEdit(self) self.port_label = QLabel(_('Port:')) self.port_spinner = QSpinBox(self) self.cmd_label = QLabel(_('Command:')) self.cmd_input = QLineEdit(self) self.args_label = QLabel(_('Arguments:')) self.args_input = QLineEdit(self) self.json_label = QLabel(self.JSON_VALID, self) self.conf_label = QLabel(_('<b>Server Configuration:</b>')) self.conf_input = CodeEditor(None) self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel) # Widget setup self.setMinimumSize(self.MIN_SIZE) self.setWindowTitle(_('LSP server editor')) self.server_settings_description.setWordWrap(True) self.lang_cb.setToolTip( _('Programming language provided by the LSP server')) self.lang_cb.addItem(_('Select a language')) self.lang_cb.addItems(LSP_LANGUAGES) self.button_ok.setEnabled(False) if language is not None: idx = LSP_LANGUAGES.index(language) self.lang_cb.setCurrentIndex(idx + 1) self.button_ok.setEnabled(True) self.host_input.setPlaceholderText('127.0.0.1') self.host_input.setText(host) self.host_input.textChanged.connect(lambda x: self.validate()) self.port_spinner.setToolTip(_('TCP port number of the server')) self.port_spinner.setMinimum(1) self.port_spinner.setMaximum(60000) self.port_spinner.setValue(port) self.cmd_input.setText(cmd) self.cmd_input.setPlaceholderText('/absolute/path/to/command') self.args_input.setToolTip( _('Additional arguments required to start the server')) self.args_input.setText(args) self.args_input.setPlaceholderText(r'--host {host} --port {port}') self.conf_input.setup_editor(language='json', color_scheme=CONF.get( 'appearance', 'selected'), wrap=False, edge_line=True, highlight_current_line=True, highlight_current_cell=True, occurrence_highlighting=True, auto_unindent=True, font=get_font(), filename='config.json', folding=False) self.conf_input.set_language('json', 'config.json') self.conf_input.setToolTip( _('Additional LSP server configuration ' 'set at runtime. JSON required')) try: conf_text = json.dumps(configurations, indent=4, sort_keys=True) except Exception: conf_text = '{}' self.conf_input.set_text(conf_text) self.external_cb.setToolTip( _('Check if the server runs on a remote location')) self.external_cb.setChecked(external) self.stdio_cb = QCheckBox(_('Use stdio pipes for communication'), self) self.stdio_cb.setToolTip( _('Check if the server communicates ' 'using stdin/out pipes')) self.stdio_cb.setChecked(stdio) # Layout setup hlayout = QHBoxLayout() general_vlayout = QVBoxLayout() general_vlayout.addWidget(self.server_settings_description) vlayout = QVBoxLayout() lang_group = QGroupBox(_('Language')) lang_layout = QVBoxLayout() lang_layout.addWidget(self.lang_cb) lang_group.setLayout(lang_layout) vlayout.addWidget(lang_group) server_group = QGroupBox(_('Language server')) server_layout = QGridLayout() server_layout.addWidget(self.cmd_label, 0, 0) server_layout.addWidget(self.cmd_input, 0, 1) server_layout.addWidget(self.args_label, 1, 0) server_layout.addWidget(self.args_input, 1, 1) server_group.setLayout(server_layout) vlayout.addWidget(server_group) address_group = QGroupBox(_('Server address')) host_layout = QVBoxLayout() host_layout.addWidget(self.host_label) host_layout.addWidget(self.host_input) port_layout = QVBoxLayout() port_layout.addWidget(self.port_label) port_layout.addWidget(self.port_spinner) conn_info_layout = QHBoxLayout() conn_info_layout.addLayout(host_layout) conn_info_layout.addLayout(port_layout) address_group.setLayout(conn_info_layout) vlayout.addWidget(address_group) advanced_group = QGroupBox(_('Advanced')) advanced_layout = QVBoxLayout() advanced_layout.addWidget(self.external_cb) advanced_layout.addWidget(self.stdio_cb) advanced_group.setLayout(advanced_layout) vlayout.addWidget(advanced_group) conf_layout = QVBoxLayout() conf_layout.addWidget(self.conf_label) conf_layout.addWidget(self.conf_input) conf_layout.addWidget(self.json_label) vlayout.addStretch() hlayout.addLayout(vlayout, 2) hlayout.addLayout(conf_layout, 3) general_vlayout.addLayout(hlayout) general_vlayout.addWidget(self.bbox) self.setLayout(general_vlayout) self.form_status(False) # Signals if not external: self.cmd_input.textChanged.connect(lambda x: self.validate()) self.external_cb.stateChanged.connect(self.set_local_options) self.stdio_cb.stateChanged.connect(self.set_stdio_options) self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed) self.conf_input.textChanged.connect(self.validate) self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.reject) # Final setup if language is not None: self.form_status(True) self.validate() if stdio: self.set_stdio_options(True) if external: self.set_local_options(True) @Slot() def validate(self): host_text = self.host_input.text() cmd_text = self.cmd_input.text() if not self.HOST_REGEX.match(host_text): self.button_ok.setEnabled(False) self.host_input.setStyleSheet(self.INVALID_CSS) if bool(host_text): self.host_input.setToolTip(_('Hostname must be valid')) else: self.host_input.setToolTip( _('Hostname or IP address of the host on which the server ' 'is running. Must be non empty.')) else: self.host_input.setStyleSheet(self.VALID_CSS) self.host_input.setToolTip(_('Hostname is valid')) self.button_ok.setEnabled(True) if not self.external: if not self.NON_EMPTY_REGEX.match(cmd_text): self.button_ok.setEnabled(False) self.cmd_input.setStyleSheet(self.INVALID_CSS) self.cmd_input.setToolTip( _('Command used to start the LSP server locally. Must be ' 'non empty')) return if find_program(cmd_text) is None: self.button_ok.setEnabled(False) self.cmd_input.setStyleSheet(self.INVALID_CSS) self.cmd_input.setToolTip( _('Program was not found ' 'on your system')) else: self.cmd_input.setStyleSheet(self.VALID_CSS) self.cmd_input.setToolTip( _('Program was found on your ' 'system')) self.button_ok.setEnabled(True) try: json.loads(self.conf_input.toPlainText()) try: self.json_label.setText(self.JSON_VALID) except Exception: pass except ValueError: try: self.json_label.setText(self.JSON_INVALID) self.button_ok.setEnabled(False) except Exception: pass def form_status(self, status): self.host_input.setEnabled(status) self.port_spinner.setEnabled(status) self.external_cb.setEnabled(status) self.stdio_cb.setEnabled(status) self.cmd_input.setEnabled(status) self.args_input.setEnabled(status) self.conf_input.setEnabled(status) self.json_label.setVisible(status) @Slot() def lang_selection_changed(self): idx = self.lang_cb.currentIndex() if idx == 0: self.set_defaults() self.form_status(False) self.button_ok.setEnabled(False) else: server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1]) self.form_status(True) if server is not None: self.host_input.setText(server.host) self.port_spinner.setValue(server.port) self.external_cb.setChecked(server.external) self.stdio_cb.setChecked(server.stdio) self.cmd_input.setText(server.cmd) self.args_input.setText(server.args) self.conf_input.set_text(json.dumps(server.configurations)) self.json_label.setText(self.JSON_VALID) self.button_ok.setEnabled(True) else: self.set_defaults() def set_defaults(self): self.cmd_input.setStyleSheet('') self.host_input.setStyleSheet('') self.host_input.setText(self.DEFAULT_HOST) self.port_spinner.setValue(self.DEFAULT_PORT) self.external_cb.setChecked(self.DEFAULT_EXTERNAL) self.stdio_cb.setChecked(self.DEFAULT_STDIO) self.cmd_input.setText(self.DEFAULT_CMD) self.args_input.setText(self.DEFAULT_ARGS) self.conf_input.set_text(self.DEFAULT_CONFIGURATION) self.json_label.setText(self.JSON_VALID) @Slot(bool) @Slot(int) def set_local_options(self, enabled): self.external = enabled self.cmd_input.setEnabled(True) self.args_input.setEnabled(True) if enabled: self.cmd_input.setEnabled(False) self.cmd_input.setStyleSheet('') self.args_input.setEnabled(False) self.stdio_cb.stateChanged.disconnect() self.stdio_cb.setChecked(False) self.stdio_cb.setEnabled(False) else: self.cmd_input.setEnabled(True) self.args_input.setEnabled(True) self.stdio_cb.setEnabled(True) self.stdio_cb.setChecked(False) self.stdio_cb.stateChanged.connect(self.set_stdio_options) try: self.validate() except Exception: pass @Slot(bool) @Slot(int) def set_stdio_options(self, enabled): self.stdio = enabled if enabled: self.cmd_input.setEnabled(True) self.args_input.setEnabled(True) self.external_cb.stateChanged.disconnect() self.external_cb.setChecked(False) self.external_cb.setEnabled(False) self.host_input.setStyleSheet('') self.host_input.setEnabled(False) self.port_spinner.setEnabled(False) else: self.cmd_input.setEnabled(True) self.args_input.setEnabled(True) self.external_cb.setChecked(False) self.external_cb.setEnabled(True) self.external_cb.stateChanged.connect(self.set_local_options) self.host_input.setEnabled(True) self.port_spinner.setEnabled(True) try: self.validate() except Exception: pass def get_options(self): language_idx = self.lang_cb.currentIndex() language = LSP_LANGUAGES[language_idx - 1] host = self.host_input.text() port = int(self.port_spinner.value()) external = self.external_cb.isChecked() stdio = self.stdio_cb.isChecked() args = self.args_input.text() cmd = self.cmd_input.text() configurations = json.loads(self.conf_input.toPlainText()) server = LSPServer(language=language.lower(), cmd=cmd, args=args, host=host, port=port, external=external, stdio=stdio, configurations=configurations) return server
def sizeHint( self ): return QSize( 100, 100 )
def __init__(self, latest_version=None, prefix=None): """Main dialog for the anaconda navgator updater.""" super(MainDialog, self).__init__() # Variables self.api = CondaAPI() self.prefix = prefix or os.environ.get('CONDA_PREFIX', self.api.ROOT_PREFIX) self.info = {} self.first_run = True self.setup_ready = False self.busy = False self.up_to_date = False self.error = False self.success = False self.status = '' self.current_version = None self.latest_version = latest_version self.style_sheet = load_style_sheet() self.timer = QTimer() self.timer_2 = QTimer() # Widgets self.message_box = None # For testing self.label_icon = QSvgWidget() self.label_message = LabelBase( "There's a new version of Anaconda Navigator available. " "We strongly recommend you to update.") self.label_status = LabelBase('') self.progress_bar = QProgressBar() self.button_cancel = ButtonNormal('Dismiss') self.button_update = ButtonPrimary('Update now') self.button_launch = ButtonPrimary('Launch Navigator') # Widgets setup self.label_message.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.label_message.setWordWrap(True) self.label_status.setWordWrap(True) self.button_update.setAutoDefault(True) self.button_launch.setAutoDefault(True) self.button_cancel.setFocusPolicy(Qt.NoFocus) self.timer.setInterval(1000) self.timer_2.setInterval(5000) self.progress_bar.setTextVisible(False) self.progress_bar.setStyleSheet(self.style_sheet) self.label_icon.load(images.ANACONDA_LOGO) self.label_icon.setMaximumSize(QSize(64, 64)) self.label_icon.setMinimumSize(QSize(64, 64)) self.setWindowTitle('Anaconda Navigator Updater') self.progress_bar.setMaximumWidth(self.WIDTH / 3) self.setMinimumWidth(self.WIDTH) self.setMaximumWidth(self.WIDTH) self.setMinimumHeight(self.HEIGHT) # Layouts layout_status = QHBoxLayout() layout_status.addWidget(self.label_status) layout_status.addWidget(SpacerHorizontal()) layout_status.addWidget(self.progress_bar) layout_text = QVBoxLayout() layout_text.addWidget(self.label_message) layout_text.addStretch() layout_text.addWidget(SpacerVertical()) layout_text.addLayout(layout_status) layout_icon = QVBoxLayout() layout_icon.addWidget(self.label_icon) layout_icon.addStretch() layout_top = QHBoxLayout() layout_top.addLayout(layout_icon) layout_top.addWidget(SpacerHorizontal()) layout_top.addLayout(layout_text) layout_buttons = QHBoxLayout() layout_buttons.addStretch() layout_buttons.addWidget(self.button_cancel) layout_buttons.addWidget(SpacerHorizontal()) layout_buttons.addWidget(self.button_update) layout_buttons.addWidget(self.button_launch) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addWidget(SpacerVertical()) layout.addWidget(SpacerVertical()) layout.addStretch() layout.addLayout(layout_buttons) self.setLayout(layout) # Signals self.button_update.clicked.connect(self.install_update) self.button_cancel.clicked.connect(self.reject) self.button_launch.clicked.connect(self.launch) self.timer.timeout.connect(self.refresh) self.timer_2.timeout.connect(self.check_conditions) # Setup self.timer.start() self.timer_2.start() self.check_conditions() self.refresh()
def sizeHint(self): """Override Qt method.""" return QSize(self.compute_width(), 0)
def __init__(self, parent, names, order, active): super(LayoutSettingsDialog, self).__init__(parent) # variables self._parent = parent self._selection_model = None self.names = names self.order = order self.active = active # widgets self.button_move_up = QPushButton(_('Move Up')) self.button_move_down = QPushButton(_('Move Down')) self.button_delete = QPushButton(_('Delete Layout')) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.group_box = QGroupBox(_("Layout Display and Order")) self.table = QTableView(self) self.ok_button = self.button_box.button(QDialogButtonBox.Ok) self.cancel_button = self.button_box.button(QDialogButtonBox.Cancel) self.cancel_button.setDefault(True) self.cancel_button.setAutoDefault(True) # widget setup self.dialog_size = QSize(300, 200) self.setMinimumSize(self.dialog_size) self.setFixedSize(self.dialog_size) self.setWindowTitle('Layout Settings') self.table.setModel(LayoutModel(self.table, order, active)) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSelectionMode(QAbstractItemView.SingleSelection) self.table.verticalHeader().hide() self.table.horizontalHeader().hide() self.table.setAlternatingRowColors(True) self.table.setShowGrid(False) self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.table.horizontalHeader().setStretchLastSection(True) self.table.setColumnHidden(1, True) # need to keep a reference for pyside not to segfault! self._selection_model = self.table.selectionModel() # layout buttons_layout = QVBoxLayout() buttons_layout.addWidget(self.button_move_up) buttons_layout.addWidget(self.button_move_down) buttons_layout.addStretch() buttons_layout.addWidget(self.button_delete) group_layout = QHBoxLayout() group_layout.addWidget(self.table) group_layout.addLayout(buttons_layout) self.group_box.setLayout(group_layout) layout = QVBoxLayout() layout.addWidget(self.group_box) layout.addWidget(self.button_box) self.setLayout(layout) # signals and slots self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.close) self.button_delete.clicked.connect(self.delete_layout) self.button_move_up.clicked.connect(lambda: self.move_layout(True)) self.button_move_down.clicked.connect(lambda: self.move_layout(False)) self.table.model().dataChanged.connect( lambda: self.selection_changed(None, None)) self._selection_model.selectionChanged.connect( lambda: self.selection_changed(None, None)) # focus table index = self.table.model().index(0, 0) self.table.setCurrentIndex(index) self.table.setFocus()
def widget_size(): """Return the size defined in the SASS file.""" return QSize(SASS_VARIABLES.WIDGET_ENVIRONMENT_TOTAL_WIDTH, SASS_VARIABLES.WIDGET_ENVIRONMENT_TOTAL_HEIGHT)
def __init__(self, parent=None, hide_nav_bar=False, hide_menu_bar=False, hide_status_bar=False): super(PyDMMainWindow, self).__init__(parent) self.app = QApplication.instance() self.font_factor = 1 self.iconFont = IconFont() self._display_widget = None self._showing_file_path_in_title_bar = False self._saved_menu_geometry = None self._saved_menu_height = None self._new_widget_size = None self.default_font_size = QApplication.instance().font().pointSizeF() self.home_file = None self.home_widget = None self.designer_path = None self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.navbar.setIconSize(QSize(24, 24)) self.ui.navbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.ui.actionHome.triggered.connect(self.home_triggered) self.ui.actionHome.setIcon(self.iconFont.icon("home")) self.ui.actionBack.triggered.connect(self.back_triggered) self.ui.actionBack.setIcon(self.iconFont.icon("angle-left")) self.ui.actionForward.triggered.connect(self.forward_triggered) self.ui.actionForward.setIcon(self.iconFont.icon("angle-right")) self.ui.actionEdit_in_Designer.triggered.connect(self.edit_in_designer) self.ui.actionOpen_File.triggered.connect(self.open_file_action) self.ui.actionReload_Display.triggered.connect(self.reload_display) self.ui.actionIncrease_Font_Size.triggered.connect( self.increase_font_size) self.ui.actionDecrease_Font_Size.triggered.connect( self.decrease_font_size) self.ui.actionDefault_Font_Size.triggered.connect(self.reset_font_size) self.ui.actionEnter_Fullscreen.triggered.connect(self.enter_fullscreen) self.ui.actionShow_File_Path_in_Title_Bar.triggered.connect( self.toggle_file_path_in_title_bar) self.ui.actionShow_Navigation_Bar.triggered.connect( self.toggle_nav_bar) self.ui.actionShow_Menu_Bar.triggered.connect(self.toggle_menu_bar) self.ui.actionShow_Status_Bar.triggered.connect(self.toggle_status_bar) self.ui.actionShow_Connections.triggered.connect(self.show_connections) self.ui.actionAbout_PyDM.triggered.connect(self.show_about_window) self.ui.actionLoadTool.triggered.connect(self.load_tool) self.ui.actionLoadTool.setIcon(self.iconFont.icon("rocket")) self.ui.actionQuit.triggered.connect(self.quit_main_window) if hide_nav_bar: self.toggle_nav_bar(False) if hide_menu_bar: # Toggle the menu bar via the QAction so that the menu item # stays in sync with menu visibility. self.ui.actionShow_Menu_Bar.activate(QAction.Trigger) if hide_status_bar: self.toggle_status_bar(False) #Try to find the designer binary. self.ui.actionEdit_in_Designer.setEnabled(False) possible_designer_bin_paths = ( QLibraryInfo.location(QLibraryInfo.BinariesPath), QLibraryInfo.location(QLibraryInfo.LibraryExecutablesPath)) for bin_path in possible_designer_bin_paths: if platform.system() == 'Darwin': designer_path = os.path.join( bin_path, 'Designer.app/Contents/MacOS/Designer') elif platform.system() == 'Linux': designer_path = os.path.join(bin_path, 'designer') else: designer_path = os.path.join(bin_path, 'designer.exe') if os.path.isfile(designer_path): self.designer_path = designer_path break self.update_tools_menu() self.enable_disable_navigation()
def minimumSizeHint(self): return QSize(30, 30)
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(), )
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 test_mainwindow_init(mainwindow): """Test that the mainwindow is initialized correctly.""" assert mainwindow assert mainwindow.size() == QSize(*INIT_MAINWINDOW_SIZE) assert mainwindow._workdir == get_home_dir()
def sizeHint(self): w, h = self.get_width_height() return QSize(w, h)
class PyDMSymbol(QWidget, PyDMWidget): """ PyDMSymbol will render an image (symbol) for each value of a channel. Parameters ---------- parent : QWidget The parent widget for the Label init_channel : str, optional The channel to be used by the widget. """ def __init__(self, parent=None, init_channel=None): QWidget.__init__(self, parent) PyDMWidget.__init__(self, init_channel=init_channel) if 'Index' not in PyDMSymbol.RULE_PROPERTIES: PyDMSymbol.RULE_PROPERTIES = PyDMWidget.RULE_PROPERTIES.copy() PyDMSymbol.RULE_PROPERTIES.update( {'Index': ['set_current_key', object]}) self.app = QApplication.instance() self._current_key = 0 self._state_images_string = "" self._state_images = {} # Keyed on state values (ints), values are (filename, qpixmap or qsvgrenderer) tuples. self._aspect_ratio_mode = Qt.KeepAspectRatio self._sizeHint = self.minimumSizeHint() self._painter = QPainter() def init_for_designer(self): """ Method called after the constructor to tweak configurations for when using the widget with the Qt Designer """ self.value = 0 self._current_key = 0 def set_current_key(self, current_key): """ Change the image being displayed for the one given by `current_key`. Parameters ---------- current_key : object The current_key parameter can be of any type as long as it matches the type used as key for the imageFiles dictionary. """ if self._current_key != current_key: self._current_key = current_key self.update() @Property(str) def imageFiles(self): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Returns ------- str """ if not self._state_images: return self._state_images_string return json.dumps({str(state): val[0] for (state, val) in self._state_images.items()}) @imageFiles.setter def imageFiles(self, new_files): """ JSON-formatted dictionary keyed on states (integers), with filenames of the image file to display for the state. Parameters ---------- new_files : str """ self._state_images_string = str(new_files) try: new_file_dict = json.loads(self._state_images_string) except Exception: self._state_images = {} return self._sizeHint = QSize(0, 0) for (state, filename) in new_file_dict.items(): if is_pydm_app(): try: file_path = self.app.get_path(filename) except Exception as e: logger.exception("Couldn't get file with path %s", filename) file_path = filename else: file_path = filename # First, lets try SVG. We have to try SVG first, otherwise # QPixmap will happily load the SVG and turn it into a raster image. # Really annoying: We have to try to load the file as SVG, # and we expect it will fail often (because many images aren't SVG). # Qt prints a warning message to stdout any time SVG loading fails. # So we have to temporarily silence Qt warning messages here. qInstallMessageHandler(self.qt_message_handler) svg = QSvgRenderer() svg.repaintNeeded.connect(self.update) if svg.load(file_path): self._state_images[int(state)] = (filename, svg) self._sizeHint = self._sizeHint.expandedTo(svg.defaultSize()) qInstallMessageHandler(None) continue qInstallMessageHandler(None) # SVG didn't work, lets try QPixmap image = QPixmap(file_path) if not image.isNull(): self._state_images[int(state)] = (filename, image) self._sizeHint = self._sizeHint.expandedTo(image.size()) continue # If we get this far, the file specified could not be loaded at all. logger.error("Could not load image: {}".format(filename)) self._state_images[int(state)] = (filename, None) @Property(Qt.AspectRatioMode) def aspectRatioMode(self): """ Which aspect ratio mode to use. Returns ------- Qt.AspectRatioMode """ return self._aspect_ratio_mode @aspectRatioMode.setter def aspectRatioMode(self, new_mode): """ Which aspect ratio mode to use. Parameters ----------- new_mode : Qt.AspectRatioMode """ if new_mode != self._aspect_ratio_mode: self._aspect_ratio_mode = new_mode self.update() def connection_changed(self, connected): """ Callback invoked when the connection state of the Channel is changed. This callback acts on the connection state to enable/disable the widget and also trigger the change on alarm severity to ALARM_DISCONNECTED. Parameters ---------- connected : int When this value is 0 the channel is disconnected, 1 otherwise. """ super(PyDMSymbol, self).connection_changed(connected) self.update() def value_changed(self, new_val): """ Callback invoked when the Channel value is changed. Parameters ---------- new_val : int The new value from the channel. """ super(PyDMSymbol, self).value_changed(new_val) self._current_key = new_val self.update() def sizeHint(self): """ This property holds the recommended size for the widget. Returns ------- QSize """ return self._sizeHint def minimumSizeHint(self): """ This property holds the recommended minimum size for the widget. Returns ------- QSize """ return QSize(10, 10) # This is totally arbitrary, I just want *some* visible nonzero size def paintEvent(self, event): """ Paint events are sent to widgets that need to update themselves, for instance when part of a widget is exposed because a covering widget was moved. At PyDMSymbol this method handles the alarm painting with parameters from the stylesheet and draws the proper image. Parameters ---------- event : QPaintEvent """ self._painter.begin(self) opt = QStyleOption() opt.initFrom(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, self._painter, self) # self._painter.setRenderHint(QPainter.Antialiasing) if self._current_key is None: self._painter.end() return image_to_draw = self._state_images.get(self._current_key, (None, None))[1] if image_to_draw is None: self._painter.end() return if isinstance(image_to_draw, QPixmap): w = float(image_to_draw.width()) h = float(image_to_draw.height()) if self._aspect_ratio_mode == Qt.IgnoreAspectRatio: scale = (event.rect().width() / w, event.rect().height() / h) elif self._aspect_ratio_mode == Qt.KeepAspectRatio: sf = min(event.rect().width() / w, event.rect().height() / h) scale = (sf, sf) elif self._aspect_ratio_mode == Qt.KeepAspectRatioByExpanding: sf = max(event.rect().width() / w, event.rect().height() / h) scale = (sf, sf) self._painter.scale(scale[0], scale[1]) self._painter.drawPixmap(event.rect().x(), event.rect().y(), image_to_draw) elif isinstance(image_to_draw, QSvgRenderer): draw_size = QSizeF(image_to_draw.defaultSize()) draw_size.scale(QSizeF(event.rect().size()), self._aspect_ratio_mode) image_to_draw.render(self._painter, QRectF(0.0, 0.0, draw_size.width(), draw_size.height())) self._painter.end() def qt_message_handler(self, msg_type, *args): # Intentionally suppress all qt messages. Make sure not to leave this handler installed. pass
def __init__(self, parent, prefix, name, action, version, versions, packages_sizes, active_channels): super(CondaPackageActionDialog, self).__init__(parent) self._parent = parent self._prefix = prefix self._version_text = None self._name = name self._dependencies_dic = {} self._active_channels = active_channels self._packages_sizes = packages_sizes self.api = ManagerAPI() # Widgets self.label = QLabel(self) self.combobox_version = QComboBox() self.label_version = QLabel(self) self.widget_version = None self.table_dependencies = None self.checkbox = QCheckBox(_("Install dependencies (recommended)")) self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel) self.button_cancel.setDefault(True) self.button_cancel.setAutoDefault(True) dialog_size = QSize(300, 90) # Helper variable values action_title = { C.ACTION_UPGRADE: _("Upgrade package"), C.ACTION_DOWNGRADE: _("Downgrade package"), C.ACTION_REMOVE: _("Remove package"), C.ACTION_INSTALL: _("Install package"), } # FIXME: There is a bug, a package installed by anaconda has version # astropy 0.4 and the linked list 0.4 but the available versions # in the json file do not include 0.4 but 0.4rc1... so... # temporal fix is to check if inside list otherwise show full list if action == C.ACTION_UPGRADE: if version in versions: index = versions.index(version) combo_versions = versions[index + 1 :] else: versions = versions elif action == C.ACTION_DOWNGRADE: if version in versions: index = versions.index(version) combo_versions = versions[:index] else: versions = versions elif action == C.ACTION_REMOVE: combo_versions = [version] self.combobox_version.setEnabled(False) elif action == C.ACTION_INSTALL: combo_versions = versions # Reverse order for combobox combo_versions = list(reversed(combo_versions)) if len(versions) == 1: if action == C.ACTION_REMOVE: labeltext = _("Package version to remove:") else: labeltext = _("Package version available:") self.label_version.setText(combo_versions[0]) self.widget_version = self.label_version else: labeltext = _("Select package version:") self.combobox_version.addItems(combo_versions) self.widget_version = self.combobox_version self.label.setText(labeltext) self.label_version.setAlignment(Qt.AlignLeft) self.table_dependencies = QWidget(self) layout = QVBoxLayout() version_layout = QHBoxLayout() version_layout.addWidget(self.label) version_layout.addStretch() version_layout.addWidget(self.widget_version) layout.addLayout(version_layout) self.widgets = [self.checkbox, self.button_ok, self.widget_version, self.table_dependencies] # Create a Table if action in [C.ACTION_INSTALL, C.ACTION_UPGRADE, C.ACTION_DOWNGRADE]: table = QTableView(self) dialog_size = QSize(dialog_size.width() + 40, 300) self.table_dependencies = table layout.addWidget(self.checkbox) self.checkbox.setChecked(True) self._changed_version(versions[0]) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.verticalHeader().hide() table.horizontalHeader().hide() table.setAlternatingRowColors(True) table.setShowGrid(False) table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.horizontalHeader().setStretchLastSection(True) layout.addWidget(self.table_dependencies) layout.addWidget(self.bbox) title = "{0}: {1}".format(action_title[action], name) self.setLayout(layout) self.setMinimumSize(dialog_size) self.setFixedSize(dialog_size) self.setWindowTitle(title) self.setModal(True) # Signals and slots self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.close) self.combobox_version.currentIndexChanged.connect(self._changed_version) self.checkbox.stateChanged.connect(self._changed_checkbox)
def paintEvent(self, event): """Override Qt method. Painting line number area """ painter = QPainter(self) painter.fillRect(event.rect(), self.editor.sideareas_color) # This is needed to make that the font size of line numbers # be the same as the text one when zooming # See spyder-ide/spyder#2296 and spyder-ide/spyder#4811. font = self.editor.font() font_height = self.editor.fontMetrics().height() active_block = self.editor.textCursor().block() active_line_number = active_block.blockNumber() + 1 def draw_pixmap(xleft, ytop, pixmap): if not QT55_VERSION: pixmap_height = pixmap.height() else: # scale pixmap height to device independent pixels pixmap_height = pixmap.height() / pixmap.devicePixelRatio() painter.drawPixmap(xleft, ytop + (font_height - pixmap_height) / 2, pixmap) for top, line_number, block in self.editor.visible_blocks: if self._margin: if line_number == active_line_number: font.setWeight(font.Bold) painter.setFont(font) painter.setPen(self.editor.normal_color) else: font.setWeight(font.Normal) painter.setFont(font) painter.setPen(self.linenumbers_color) painter.drawText(0, top, self.width(), font_height, Qt.AlignRight | Qt.AlignBottom, to_text_string(line_number)) size = self.get_markers_margin() - 2 icon_size = QSize(size, size) data = block.userData() if self._markers_margin and data: if data.code_analysis: errors = 0 warnings = 0 infos = 0 hints = 0 for _, _, sev, _ in data.code_analysis: errors += sev == DiagnosticSeverity.ERROR warnings += sev == DiagnosticSeverity.WARNING infos += sev == DiagnosticSeverity.INFORMATION hints += sev == DiagnosticSeverity.HINT if errors: draw_pixmap(1, top, self.error_icon.pixmap(icon_size)) elif warnings: draw_pixmap(1, top, self.warning_icon.pixmap(icon_size)) elif infos: draw_pixmap(1, top, self.info_icon.pixmap(icon_size)) elif hints: draw_pixmap(1, top, self.hint_icon.pixmap(icon_size)) if data.todo: draw_pixmap(1, top, self.todo_icon.pixmap(icon_size))
def setup(self): """Setup window parameters""" self.setWindowIcon(get_icon("python.png")) self.setWindowTitle(APP_NAME) self.resize(QSize(600, 800)) # Welcome message in statusbar: status = self.statusBar() status.showMessage(_("Welcome to guiqwt application example!"), 5000) # File menu file_menu = self.menuBar().addMenu(_("File")) new_action = create_action( self, _("New..."), shortcut="Ctrl+N", icon=get_icon("filenew.png"), tip=_("Create a new image"), triggered=self.new_image, ) open_action = create_action( self, _("Open..."), shortcut="Ctrl+O", icon=get_icon("fileopen.png"), tip=_("Open an image"), triggered=self.open_image, ) quit_action = create_action( self, _("Quit"), shortcut="Ctrl+Q", icon=get_std_icon("DialogCloseButton"), tip=_("Quit application"), triggered=self.close, ) add_actions(file_menu, (new_action, open_action, None, quit_action)) # Help menu help_menu = self.menuBar().addMenu("?") about_action = create_action( self, _("About..."), icon=get_std_icon("MessageBoxInformation"), triggered=self.about, ) add_actions(help_menu, (about_action, )) main_toolbar = self.addToolBar("Main") add_actions( main_toolbar, ( new_action, open_action, ), ) # Set central widget: toolbar = self.addToolBar("Image") self.mainwidget = CentralWidget(self, toolbar) self.setCentralWidget(self.mainwidget)
class SnippetEditor(QDialog): SNIPPET_VALID = _('Valid snippet') SNIPPET_INVALID = _('Invalid snippet') INVALID_CB_CSS = "QComboBox {border: 1px solid red;}" VALID_CB_CSS = "QComboBox {border: 1px solid green;}" INVALID_LINE_CSS = "QLineEdit {border: 1px solid red;}" VALID_LINE_CSS = "QLineEdit {border: 1px solid green;}" MIN_SIZE = QSize(850, 600) def __init__(self, parent, language=None, trigger_text='', description='', snippet_text='', remove_trigger=False, trigger_texts=[], descriptions=[]): super(SnippetEditor, self).__init__(parent) snippet_description = _( "To add a new text snippet, you need to define the text " "that triggers it, a short description (two words maximum) " "of the snippet and if it should delete the trigger text when " "inserted. Finally, you need to define the snippet body to insert." ) self.parent = parent self.trigger_text = trigger_text self.description = description self.remove_trigger = remove_trigger self.snippet_text = snippet_text self.descriptions = descriptions self.base_snippet = Snippet(language=language, trigger_text=trigger_text, snippet_text=snippet_text, description=description, remove_trigger=remove_trigger) # Widgets self.snippet_settings_description = QLabel(snippet_description) self.snippet_settings_description.setFixedWidth(450) # Trigger text self.trigger_text_label = QLabel(_('Trigger text:')) self.trigger_text_cb = QComboBox(self) self.trigger_text_cb.setEditable(True) # Description self.description_label = QLabel(_('Description:')) self.description_input = QLineEdit(self) # Remove trigger self.remove_trigger_cb = QCheckBox( _('Remove trigger text on insertion'), self) self.remove_trigger_cb.setToolTip( _('Check if the text that triggers ' 'this snippet should be removed ' 'when inserting it')) self.remove_trigger_cb.setChecked(self.remove_trigger) # Snippet body input self.snippet_label = QLabel(_('<b>Snippet text:</b>')) self.snippet_valid_label = QLabel(self.SNIPPET_INVALID, self) self.snippet_input = SimpleCodeEditor(None) # Dialog buttons self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel) # Widget setup self.setWindowTitle(_('Snippet editor')) self.snippet_settings_description.setWordWrap(True) self.trigger_text_cb.setToolTip( _('Trigger text for the current snippet')) self.trigger_text_cb.addItems(trigger_texts) if self.trigger_text != '': idx = trigger_texts.index(self.trigger_text) self.trigger_text_cb.setCurrentIndex(idx) self.description_input.setText(self.description) self.description_input.textChanged.connect(lambda _x: self.validate()) text_inputs = (self.trigger_text, self.description, self.snippet_text) non_empty_text = all([x != '' for x in text_inputs]) if non_empty_text: self.button_ok.setEnabled(True) self.snippet_input.setup_editor(language=language, color_scheme=CONF.get( 'appearance', 'selected'), wrap=False, highlight_current_line=True, font=get_font()) self.snippet_input.set_language(language) self.snippet_input.setToolTip(_('Snippet text completion to insert')) self.snippet_input.set_text(snippet_text) # Layout setup general_layout = QVBoxLayout() general_layout.addWidget(self.snippet_settings_description) snippet_settings_group = QGroupBox(_('Trigger information')) settings_layout = QGridLayout() settings_layout.addWidget(self.trigger_text_label, 0, 0) settings_layout.addWidget(self.trigger_text_cb, 0, 1) settings_layout.addWidget(self.description_label, 1, 0) settings_layout.addWidget(self.description_input, 1, 1) all_settings_layout = QVBoxLayout() all_settings_layout.addLayout(settings_layout) all_settings_layout.addWidget(self.remove_trigger_cb) snippet_settings_group.setLayout(all_settings_layout) general_layout.addWidget(snippet_settings_group) text_layout = QVBoxLayout() text_layout.addWidget(self.snippet_label) text_layout.addWidget(self.snippet_input) text_layout.addWidget(self.snippet_valid_label) general_layout.addLayout(text_layout) general_layout.addWidget(self.bbox) self.setLayout(general_layout) # Signals self.trigger_text_cb.editTextChanged.connect(self.validate) self.description_input.textChanged.connect(self.validate) self.snippet_input.textChanged.connect(self.validate) self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.reject) # Final setup if trigger_text != '' or snippet_text != '': self.validate() @Slot() def validate(self): trigger_text = self.trigger_text_cb.currentText() description_text = self.description_input.text() snippet_text = self.snippet_input.toPlainText() invalid = False try: build_snippet_ast(snippet_text) self.snippet_valid_label.setText(self.SNIPPET_VALID) except SyntaxError: invalid = True self.snippet_valid_label.setText(self.SNIPPET_INVALID) if trigger_text == '': invalid = True self.trigger_text_cb.setStyleSheet(self.INVALID_CB_CSS) else: self.trigger_text_cb.setStyleSheet(self.VALID_CB_CSS) if trigger_text in self.descriptions: if self.trigger_text != trigger_text: if description_text in self.descriptions[trigger_text]: invalid = True self.description_input.setStyleSheet(self.INVALID_LINE_CSS) else: self.description_input.setStyleSheet(self.VALID_LINE_CSS) else: if description_text != self.description: if description_text in self.descriptions[trigger_text]: invalid = True self.description_input.setStyleSheet( self.INVALID_LINE_CSS) else: self.description_input.setStyleSheet( self.VALID_LINE_CSS) else: self.description_input.setStyleSheet(self.VALID_LINE_CSS) self.button_ok.setEnabled(not invalid) def get_options(self): trigger_text = self.trigger_text_cb.currentText() description_text = self.description_input.text() snippet_text = self.snippet_input.toPlainText() remove_trigger = self.remove_trigger_cb.isChecked() self.base_snippet.update(trigger_text, description_text, snippet_text, remove_trigger) return self.base_snippet
def __init__(self, parent, env, name, action, version, versions): super(CondaPackageActionDialog, self).__init__(parent) self._parent = parent self._env = env self._version_text = None self._name = name self._dependencies_dic = {} self._conda_process = \ conda_api_q.CondaProcess(self, self._on_process_finished) # widgets self.label = QLabel(self) self.combobox_version = QComboBox() self.label_version = QLabel(self) self.widget_version = None self.table_dependencies = None self.checkbox = QCheckBox(_('Install dependencies (recommended)')) self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel) self.button_cancel.setDefault(True) self.button_cancel.setAutoDefault(True) dialog_size = QSize(300, 90) # helper variable values action_title = {const.UPGRADE: _("Upgrade package"), const.DOWNGRADE: _("Downgrade package"), const.REMOVE: _("Remove package"), const.INSTALL: _("Install package")} # Versions might have duplicates from different builds versions = sort_versions(list(set(versions)), reverse=True) # FIXME: There is a bug, a package installed by anaconda has version # astropy 0.4 and the linked list 0.4 but the available versions # in the json file do not include 0.4 but 0.4rc1... so... # temporal fix is to check if inside list otherwise show full list if action == const.UPGRADE: if version in versions: index = versions.index(version) versions = versions[:index] else: versions = versions elif action == const.DOWNGRADE: if version in versions: index = versions.index(version) versions = versions[index+1:] else: versions = versions elif action == const.REMOVE: versions = [version] self.combobox_version.setEnabled(False) if len(versions) == 1: if action == const.REMOVE: labeltext = _('Package version to remove:') else: labeltext = _('Package version available:') self.label_version.setText(versions[0]) self.widget_version = self.label_version else: labeltext = _("Select package version:") self.combobox_version.addItems(versions) self.widget_version = self.combobox_version self.label.setText(labeltext) self.label_version.setAlignment(Qt.AlignLeft) self.table_dependencies = QWidget(self) self._layout = QGridLayout() self._layout.addWidget(self.label, 0, 0, Qt.AlignVCenter | Qt.AlignLeft) self._layout.addWidget(self.widget_version, 0, 1, Qt.AlignVCenter | Qt.AlignRight) self.widgets = [self.checkbox, self.button_ok, self.widget_version, self.table_dependencies] row_index = 1 # Create a Table if action in [const.INSTALL, const.UPGRADE, const.DOWNGRADE]: table = QTableView(self) dialog_size = QSize(dialog_size.width() + 40, 300) self.table_dependencies = table row_index = 1 self._layout.addItem(QSpacerItem(10, 5), row_index, 0) self._layout.addWidget(self.checkbox, row_index + 1, 0, 1, 2) self.checkbox.setChecked(True) self._changed_version(versions[0]) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.verticalHeader().hide() table.horizontalHeader().hide() table.setAlternatingRowColors(True) table.setShowGrid(False) table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.horizontalHeader().setStretchLastSection(True) self._layout.addWidget(self.table_dependencies, row_index + 2, 0, 1, 2, Qt.AlignHCenter) self._layout.addItem(QSpacerItem(10, 5), row_index + 3, 0) self._layout.addWidget(self.bbox, row_index + 6, 0, 1, 2, Qt.AlignHCenter) title = "{0}: {1}".format(action_title[action], name) self.setLayout(self._layout) self.setMinimumSize(dialog_size) self.setFixedSize(dialog_size) self.setWindowTitle(title) self.setModal(True) # signals and slots self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.close) self.combobox_version.currentIndexChanged.connect( self._changed_version) self.checkbox.stateChanged.connect(self._changed_checkbox)
def createSpace(self, size=5): """Creates a widget that can be used as spacing on a panel.""" qw = QWidget() qw.setMinimumSize(QSize(size, size)) return qw
def __init__(self, parent, data=None, readonly=False, bg_value=None, bg_gradient='blue-red', minvalue=None, maxvalue=None, digits=None): QWidget.__init__(self, parent) assert bg_gradient in gradient_map if data is not None and np.isscalar(data): readonly = True self.readonly = readonly # prepare internal views and models self.model_axes = AxesArrayModel(parent=self, readonly=readonly) self.view_axes = AxesView(parent=self, model=self.model_axes) self.model_hlabels = LabelsArrayModel(parent=self, readonly=readonly) self.view_hlabels = LabelsView(parent=self, model=self.model_hlabels, hpos=RIGHT, vpos=TOP) self.model_vlabels = LabelsArrayModel(parent=self, readonly=readonly) self.view_vlabels = LabelsView(parent=self, model=self.model_vlabels, hpos=LEFT, vpos=BOTTOM) self.model_data = DataArrayModel(parent=self, readonly=readonly, minvalue=minvalue, maxvalue=maxvalue) self.view_data = DataView(parent=self, model=self.model_data) # in case data is None self.data_adapter = None # Create vertical and horizontal scrollbars self.vscrollbar = ScrollBar(self, self.view_data.verticalScrollBar()) self.hscrollbar = ScrollBar(self, self.view_data.horizontalScrollBar()) # Synchronize resizing self.view_axes.horizontalHeader().sectionResized.connect( self.view_vlabels.updateSectionWidth) self.view_axes.verticalHeader().sectionResized.connect( self.view_hlabels.updateSectionHeight) self.view_hlabels.horizontalHeader().sectionResized.connect( self.view_data.updateSectionWidth) self.view_vlabels.verticalHeader().sectionResized.connect( self.view_data.updateSectionHeight) # Synchronize auto-resizing self.view_axes.horizontalHeader().sectionHandleDoubleClicked.connect( self.resize_axes_column_to_contents) self.view_hlabels.horizontalHeader( ).sectionHandleDoubleClicked.connect( self.resize_hlabels_column_to_contents) self.view_axes.verticalHeader().sectionHandleDoubleClicked.connect( self.resize_axes_row_to_contents) self.view_vlabels.verticalHeader().sectionHandleDoubleClicked.connect( self.resize_vlabels_row_to_contents) # synchronize specific methods self.view_axes.allSelected.connect(self.view_data.selectAll) self.view_data.signal_copy.connect(self.copy) self.view_data.signal_excel.connect(self.to_excel) self.view_data.signal_paste.connect(self.paste) self.view_data.signal_plot.connect(self.plot) # propagate changes (add new items in the QUndoStack attribute of MappingEditor) self.model_data.newChanges.connect(self.data_changed) # Synchronize scrolling # data <--> hlabels self.view_data.horizontalScrollBar().valueChanged.connect( self.view_hlabels.horizontalScrollBar().setValue) self.view_hlabels.horizontalScrollBar().valueChanged.connect( self.view_data.horizontalScrollBar().setValue) # data <--> vlabels self.view_data.verticalScrollBar().valueChanged.connect( self.view_vlabels.verticalScrollBar().setValue) self.view_vlabels.verticalScrollBar().valueChanged.connect( self.view_data.verticalScrollBar().setValue) # Synchronize selecting columns(rows) via hor.(vert.) header of x(y)labels view self.view_hlabels.horizontalHeader().sectionPressed.connect( self.view_data.selectColumn) self.view_hlabels.horizontalHeader().sectionEntered.connect( self.view_data.selectNewColumn) self.view_vlabels.verticalHeader().sectionPressed.connect( self.view_data.selectRow) self.view_vlabels.verticalHeader().sectionEntered.connect( self.view_data.selectNewRow) # following lines are required to keep usual selection color # when selecting rows/columns via headers of label views. # Otherwise, selected rows/columns appear in grey. self.view_data.setStyleSheet("""QTableView { selection-background-color: palette(highlight); selection-color: white; }""") # set external borders array_frame = QFrame(self) array_frame.setFrameStyle(QFrame.StyledPanel) # remove borders of internal tables self.view_axes.setFrameStyle(QFrame.NoFrame) self.view_hlabels.setFrameStyle(QFrame.NoFrame) self.view_vlabels.setFrameStyle(QFrame.NoFrame) self.view_data.setFrameStyle(QFrame.NoFrame) # Set layout of table views: # [ axes ][hlabels]|V| # [vlabels][ data ]|s| # | H. scrollbar | array_layout = QGridLayout() array_layout.addWidget(self.view_axes, 0, 0) array_layout.addWidget(self.view_hlabels, 0, 1) array_layout.addWidget(self.view_vlabels, 1, 0) self.view_data.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) array_layout.addWidget(self.view_data, 1, 1) array_layout.addWidget(self.vscrollbar, 0, 2, 2, 1) array_layout.addWidget(self.hscrollbar, 2, 0, 1, 2) array_layout.setSpacing(0) array_layout.setContentsMargins(0, 0, 0, 0) array_frame.setLayout(array_layout) # Set filters and buttons layout self.filters_layout = QHBoxLayout() self.btn_layout = QHBoxLayout() self.btn_layout.setAlignment(Qt.AlignLeft) label = QLabel("Digits") self.btn_layout.addWidget(label) spin = QSpinBox(self) spin.valueChanged.connect(self.digits_changed) self.digits_spinbox = spin self.btn_layout.addWidget(spin) self.digits = 0 scientific = QCheckBox(_('Scientific')) scientific.stateChanged.connect(self.scientific_changed) self.scientific_checkbox = scientific self.btn_layout.addWidget(scientific) self.use_scientific = False gradient_chooser = QComboBox() gradient_chooser.setMaximumSize(120, 20) gradient_chooser.setIconSize(QSize(100, 20)) pixmap = QPixmap(100, 15) pixmap.fill(Qt.white) gradient_chooser.addItem(QIcon(pixmap), " ") pixmap.fill(Qt.transparent) painter = QPainter(pixmap) for name, gradient in available_gradients[1:]: qgradient = gradient.as_qgradient() # * fill with white because gradient can be transparent and if we do not "start from whilte", it skews the # colors. # * 1 and 13 instead of 0 and 15 to have a transparent border around/between the gradients painter.fillRect(0, 1, 100, 13, Qt.white) painter.fillRect(0, 1, 100, 13, qgradient) gradient_chooser.addItem(QIcon(pixmap), name, gradient) # without this, we can crash python :) del painter, pixmap # select default gradient # requires Qt5+ # gradient_chooser.setCurrentText(bg_gradient) gradient_chooser.setCurrentIndex( gradient_chooser.findText(bg_gradient)) gradient_chooser.currentIndexChanged.connect(self.gradient_changed) self.btn_layout.addWidget(gradient_chooser) self.gradient_chooser = gradient_chooser # Set widget layout layout = QVBoxLayout() layout.addLayout(self.filters_layout) layout.addWidget(array_frame) layout.addLayout(self.btn_layout) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) # set gradient self.model_data.set_bg_gradient(gradient_map[bg_gradient]) # set data if data is not None: self.set_data(data, bg_value=bg_value, digits=digits) # See http://doc.qt.io/qt-4.8/qt-draganddrop-fridgemagnets-dragwidget-cpp.html for an example self.setAcceptDrops(True)
def sizeHint(self): return QSize(self.prefixwidth, 0)