def __init__(self, parent=None): super().__init__(parent) self.launcher = Launcher() self.launcher.standard_output_signal.connect(self.handle_stdout) self.launcher.standard_error_signal.connect(self.handle_stderr) self.log_edit = QPlainTextEdit(readOnly=True) self.launcher_view = QTreeView() splitter = QSplitter(orientation=Qt.Vertical) splitter.addWidget(self.launcher_view) splitter.addWidget(self.log_edit) splitter.setSizes([10, 1]) self.setCentralWidget(splitter) self.resize(640, 480) filename = os.path.join(CURRENT_DIR, "quickcontrols2/gallery/main.py") self.start(filename, "PySide2")
class CSSEditor: """ Make sure to instanciate *after* creating the top level widgets of your QApplication """ def __init__(self, project_name): self.project_name = project_name self._app = QApplication.instance() self._css_filepath = None self.main_window = QWidget() self.main_window.setWindowFlags(Qt.Tool) self.main_window.setWindowTitle("CSS Editor - " + self.project_name) self.variables = Variables() self.variables.changed.connect(self._variables_changed) self.variables.changed.connect(self._render_and_apply) self.template = CSSTextEdit() self.template.changed.connect(self._template_changed) self.template.changed.connect(self._render_and_apply) self.save = QPushButton('Save stylesheet to') self.save.clicked.connect(self._save_stylesheet) self.save_destination = QLineEdit() self.save_destination.textChanged.connect(self._destination_changed) self.splitter = QSplitter() self.splitter.setOrientation(Qt.Vertical) self.splitter.addWidget(self.variables) self.splitter.addWidget(self.template) layout = QGridLayout(self.main_window) layout.addWidget(self.splitter, 0, 0, 1, 2) layout.addWidget(self.save, 1, 0) layout.addWidget(self.save_destination, 1, 1) self.main_window.resize(800, 600) self._project_dir = self._ensure_project_dir() self._top_level_widgets = [ widget for widget in QApplication.topLevelWidgets() if widget.windowTitle() != self.main_window.windowTitle() ] self._variables = dict() self._template = None self._stylesheet = "" self._app.aboutToQuit.connect(self._save_editor_state) self._open() self.save_destination.setText(self.css_filepath) self.main_window.show() @property def css_filepath(self): if self._css_filepath is None: return self._project_dir + self.project_name + '.css' return self._css_filepath def _ensure_project_dir(self): dir_ = os.path.expanduser('~/CSSEditor/' + self.project_name + '/') if not os.path.isdir(dir_): os.makedirs(dir_) return dir_ def _open(self): self.variables.blockSignals(True) self.template.blockSignals(True) try: with open(self._project_dir + EDITOR_STATE, 'r') as qsseditor_file: qsseditor = json.load(qsseditor_file) WindowPosition.restore(self.main_window, qsseditor['window']) self.splitter.setSizes(qsseditor['splitter']) self._css_filepath = qsseditor.get('save_destination', self.css_filepath) self.save_destination.setText(self._css_filepath) with open(self._project_dir + THEME_VARIABLES, 'r') as f_variables: self.variables.variables = json.load(f_variables) with open(self._project_dir + THEME_TEMPLATE, 'r') as f_template: self.template.set_plain_text(f_template.read()) except Exception as e: pass self.variables.blockSignals(False) self.template.blockSignals(False) self._template_changed() self._variables_changed() self._render_and_apply() def _destination_changed(self): self._css_filepath = self.save_destination.text() self._save_editor_state() def _save_editor_state(self): with open(self._project_dir + EDITOR_STATE, 'w+') as f_qsseditor: json.dump({ 'window': WindowPosition.save(self.main_window), 'splitter': self.splitter.sizes(), 'save_destination': self.css_filepath }, f_qsseditor) def _template_changed(self): template = self.template.plain_text() with open(self._project_dir + THEME_TEMPLATE, 'w+') as f_template: f_template.write(template) try: self._template = jinja2.Template(template) except TemplateSyntaxError: pass def _variables_changed(self): with open(self._project_dir + THEME_VARIABLES, 'w+') as f_variables: f_variables.write(json.dumps(self.variables.variables, indent=2)) self._variables = dict() for variable_name, variable_value in self.variables.variables.items(): if isinstance(variable_value, list) and len(variable_value) == 3: self._variables[variable_name] = 'rgb({})'.format(', '.join([str(channel) for channel in variable_value])) for variant in COLOR_VARIANTS: channels = [str(int(channel * variant * 0.01)) for channel in variable_value] self._variables['{}{:02d}'.format(variable_name, variant)] = 'rgb({})'.format(', '.join(channels)) else: self._variables[variable_name] = variable_value def _apply_style(self, style): for widget in self._top_level_widgets: widget.setStyleSheet(style) def _render_and_apply(self): self._apply_style("") if self._template is None: return self._stylesheet = self._template.render(**self._variables) self._apply_style(self._stylesheet) def _save_stylesheet(self): stylesheet = [ "/* GUI Bedos - CSS Template */", "/****************************/", "", "/* VARIABLES", json.dumps(self.variables.variables, indent=2), "/****************************/", "", "/* TEMPLATE", self.template.plain_text().replace('*/', '*|'), "/****************************/", "", "/* ACTUAL CSS */", "", self._stylesheet ] with open(self.css_filepath, 'w+') as f_stylesheet: f_stylesheet.write('\n'.join(stylesheet))
class PreferencesWidget(base.BaseWidget, object): closed = Signal(bool, dict) def __init__(self, settings=None, parent=None): self._settings = settings super(PreferencesWidget, self).__init__(parent=parent) self._indexes = dict() self._category_buttons = dict() self._settings = settings self._try_create_defaults() def ui(self): super(PreferencesWidget, self).ui() self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._splitter = QSplitter() self._splitter.setOrientation(Qt.Horizontal) self._splitter.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self._scroll_area = QScrollArea() self._scroll_area.setWidgetResizable(True) self._scroll_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # self._scroll_area.setMinimumWidth(200) self._scroll_area_widget_contents = QWidget() # self._scroll_area_widget_contents.setGeometry(QRect(0, 0, 480, 595)) self._scroll_area_layout = layouts.VerticalLayout(spacing=2, margins=(1, 1, 1, 1)) self._scroll_area_layout.setAlignment(Qt.AlignTop) self._scroll_area_widget_contents.setLayout(self._scroll_area_layout) self._categories_layout = layouts.VerticalLayout() self._stack = stack.SlidingStackedWidget() self._stack.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._stack.set_vertical_mode() self._buttons_layout = layouts.HorizontalLayout(spacing=1, margins=(0, 0, 0, 0)) self._save_prefs_close_btn = buttons.BaseButton( 'Save and Close', icon=resources.icon('save'), parent=self) self._close_btn = buttons.BaseButton('Close', icon=resources.icon('cancel'), parent=self) self._buttons_layout.addStretch() self._buttons_layout.addWidget(self._save_prefs_close_btn) self._buttons_layout.addWidget(self._close_btn) self._scroll_area_layout.addLayout(self._categories_layout) self._scroll_area.setWidget(self._scroll_area_widget_contents) self._splitter.addWidget(self._scroll_area) self._splitter.addWidget(self._stack) self._splitter.setSizes([150, 450]) self.main_layout.addWidget(self._splitter) self.main_layout.addWidget(dividers.Divider(parent=self)) self.main_layout.addLayout(self._buttons_layout) def setup_signals(self): self._save_prefs_close_btn.clicked.connect( self._on_save_and_close_prefs) self._close_btn.clicked.connect(self._on_close) def showEvent(self, event): settings = self.settings() if not settings: return groups = settings.childGroups() for name, index_widget in self._indexes.items(): index, widget = index_widget settings.beginGroup(name) if name not in groups: widget.init_defaults(settings) widget.show_widget(settings) settings.endGroup() def settings(self): return self._settings def set_settings(self, settings): if not settings: return self._settings = settings self._try_create_defaults() def add_category(self, name, widget): category_button = CategoryButton(text=name, parent=self) self._categories_layout.insertWidget( self._categories_layout.count() - 2, category_button) widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) index = self._stack.addWidget(widget) self._indexes[name] = (index, widget) self._category_buttons[index] = category_button category_button.clicked.connect(lambda checked=False, idx=index: self. _on_switch_category_content(idx)) widget.init_defaults(settings=self.settings()) self.closed.connect(widget._on_reset) def select_by_name(self, name): if name not in self._indexes: return index = self._indexes[name][0] self._stack.setCurrentIndex(index) self._category_buttons[index].setChecked(True) def _try_create_defaults(self): settings = self.settings() if not settings: return groups = settings.childGroups() for name, index_widget in self._indexes.items(): index, widget = index_widget init_defaults = False if name not in groups: init_defaults = True settings.beginGroup(name) if init_defaults: widget.init_defaults(settings) settings.endGroup() settings.sync() def _on_switch_category_content(self, index): self._stack.slide_in_index(index) self._category_buttons[index].toggle() def _on_save_prefs(self): settings = self.settings() if not settings: return stored_data = dict() for name, index_widget in self._indexes.items(): index, widget = index_widget settings.beginGroup(name) data = widget.serialize(settings) if data: stored_data[name] = data settings.endGroup() settings.sync() return stored_data def _on_save_and_close_prefs(self): stored_data = self._on_save_prefs() self.closed.emit(True, stored_data) def _on_close(self): self.closed.emit(False, None)