def populate_fields(self, fields): for field, hidden in fields: item = QCheckBox(self.fieldScrollArea) item.setObjectName(field) item.setText(field) item.setChecked(not hidden) self.fieldLayout.addWidget(item)
def __init__(self, *args, **kwargs ): QWidget.__init__( self, *args, **kwargs ) mainLayout = QHBoxLayout( self ) mainLayout.setContentsMargins(0,0,0,0) label = QLabel( "Aim Direction : " ) lineEdit1 = QLineEdit() lineEdit2 = QLineEdit() lineEdit3 = QLineEdit() verticalSeparator = Widget_verticalSeparator() checkBox = QCheckBox( "Set Auto" ) mainLayout.addWidget( label ) mainLayout.addWidget( lineEdit1 ) mainLayout.addWidget( lineEdit2 ) mainLayout.addWidget( lineEdit3 ) mainLayout.addWidget( verticalSeparator ) mainLayout.addWidget( checkBox ) validator = QDoubleValidator( -10000.0, 10000.0, 2 ) lineEdit1.setValidator( validator ) lineEdit2.setValidator( validator ) lineEdit3.setValidator( validator ) lineEdit1.setText( "0.0" ) lineEdit2.setText( "1.0" ) lineEdit3.setText( "0.0" ) checkBox.setChecked( True ) self.label = label; self.lineEdit1 = lineEdit1; self.lineEdit2 = lineEdit2; self.lineEdit3 = lineEdit3; self.checkBox = checkBox self.setVectorEnabled() QtCore.QObject.connect( checkBox, QtCore.SIGNAL( 'clicked()' ), self.setVectorEnabled )
def addCamerasToStackedWidget(self, names): for name in names: btn = QCheckBox(name, self) btn.clicked.connect(self.toggleSelectedAllButton3) btn.setChecked(True) self.cameraLayout.addWidget(btn) self.cameraButtons.append(btn)
class qLabeledCheck(QWidget): def __init__(self, name, arg_dict, pos = "side", max_size = 200): QWidget.__init__(self) self.setContentsMargins(1, 1, 1, 1) if pos == "side": self.layout1=QHBoxLayout() else: self.layout1 = QVBoxLayout() self.layout1.setContentsMargins(1, 1, 1, 1) self.layout1.setSpacing(1) self.setLayout(self.layout1) self.cbox = QCheckBox() # self.efield.setMaximumWidth(max_size) self.cbox.setFont(QFont('SansSerif', 12)) self.label = QLabel(name) # self.label.setAlignment(Qt.AlignLeft) self.label.setFont(QFont('SansSerif', 12)) self.layout1.addWidget(self.label) self.layout1.addWidget(self.cbox) self.arg_dict = arg_dict self.name = name self.mytype = type(self.arg_dict[name]) if self.mytype != bool: self.cbox.setChecked(bool(self.arg_dict[name])) else: self.cbox.setChecked(self.arg_dict[name]) self.cbox.toggled.connect(self.when_modified) self.when_modified() def when_modified(self): self.arg_dict[self.name] = self.cbox.isChecked() def hide(self): QWidget.hide(self)
def __init__(self, *args, **kwargs): self.attr_name = "" self.type_node = "" if kwargs.has_key("attr_name"): self.attr_name = kwargs.pop("attr_name") if kwargs.has_key('type_node'): self.type_node = kwargs.pop('type_node') self.path_uiInfo = path_basedir + "/attr_name_%s.json" % self.attr_name super(Widget_TypeAttribute, self).__init__(*args, **kwargs) self.installEventFilter(self) mainLayout = QHBoxLayout(self) mainLayout.setContentsMargins(0, 0, 0, 0) checkBox = QCheckBox() checkBox.setFixedWidth(10) checkBox.setChecked(True) label = QLabel('%s ( *.%s )' % (self.type_node, self.attr_name)) mainLayout.addWidget(checkBox) mainLayout.addWidget(label) self.setFixedHeight(25) self.checkBox = checkBox self.cmds_checkEvent = [] self.load_check() QtCore.QObject.connect(checkBox, QtCore.SIGNAL("stateChanged(int)"), self.save_check)
def _init_load_options_tab(self, tab): # auto load libs auto_load_libs = QCheckBox(self) auto_load_libs.setText("Automatically load all libraries") auto_load_libs.setChecked(False) self.option_widgets['auto_load_libs'] = auto_load_libs # dependencies list dep_group = QGroupBox("Dependencies") dep_list = QListWidget(self) self.option_widgets['dep_list'] = dep_list sublayout = QVBoxLayout() sublayout.addWidget(dep_list) dep_group.setLayout(sublayout) layout = QVBoxLayout() layout.addWidget(auto_load_libs) layout.addWidget(dep_group) layout.addStretch(0) frame = QFrame(self) frame.setLayout(layout) tab.addTab(frame, "Loading Options")
def testSignalMapper(self): checkboxMapper = QSignalMapper() box = QCheckBox('check me') box.stateChanged.connect(checkboxMapper.map) checkboxMapper.setMapping(box, box.text()) checkboxMapper.mapped[str].connect(self.cb_changed) self._changed = False box.setChecked(True) self.assert_(self._changed)
def addLayers(self): for layer in PlayListUtils.getDisplayLayers(): btn = QCheckBox(layer.name(), self) btn.setChecked(layer.visibility.get()) self.layerLayout.addWidget(btn) self.layerButtons.append(btn) self.setSelectAllButton() map(lambda btn: btn.clicked.connect(self.setSelectAllButton), self.layerButtons)
class EditPreferencesDlg(QDialog): def __init__(self, parent=None): super(EditPreferencesDlg, self).__init__(parent) self.setWindowTitle("Preferences") # define widgets pref_list = QListWidget() pref_list.addItem("General") pref_list.addItem("Display") pref_list.setMaximumWidth(150) pref_list.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) general_page = QWidget() general_layout = QGridLayout() general_layout.setAlignment(Qt.AlignTop) general_layout.addWidget(QLabel("<b>General</b>"), 0, 0) general_page.setLayout(general_layout) display_page = QWidget() display_layout = QGridLayout() display_layout.setAlignment(Qt.AlignTop) display_layout.addWidget(QLabel("<b>Display Options</b>"), 0, 0) self.multitabs_checkbox = QCheckBox("Limit the display of tabs to one relief device (and the device's scenarios) at a time") if parent.limit_tabs is True: self.multitabs_checkbox.setChecked(True) display_layout.addWidget(self.multitabs_checkbox, 1, 0) display_page.setLayout(display_layout) stacked_widget = QStackedWidget() for page in general_page, display_page: stacked_widget.addWidget(page) main_layout = QVBoxLayout() widgets_layout = QHBoxLayout() widgets_layout.addWidget(pref_list) widgets_layout.addWidget(stacked_widget) buttons_layout = QHBoxLayout() buttons_layout.addStretch() buttons_layout.addWidget(button_box) main_layout.addLayout(widgets_layout) main_layout.addLayout(buttons_layout) self.setLayout(main_layout) pref_list.currentRowChanged.connect(stacked_widget.setCurrentIndex) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) def sizeHint(self): return QSize(400, 400) def returnVals(self): return self.multitabs_checkbox.isChecked()
class ColorPickerExt(QWidget): """An extended color picker widget. This widget provides a color picker, and also a checkbox that allows to specify to use object color in lieu of color selected in the picker. """ def __init__(self, color=QColor(127, 127, 127), use_object_color=False): """Initialize widget. Args: color -- RGB color used to initialize the color picker use_object_color -- boolean used to initialize the 'use object color' checkbox """ super().__init__() self.use_object_color = use_object_color self.colorpicker = ColorPicker(color) self.checkbox = QCheckBox() self.checkbox.setText(translate("Render", "Use object color")) self.setLayout(QHBoxLayout()) self.layout().addWidget(self.colorpicker) self.layout().addWidget(self.checkbox) self.layout().setContentsMargins(0, 0, 0, 0) QObject.connect( self.checkbox, SIGNAL("stateChanged(int)"), self.on_object_color_change, ) self.checkbox.setChecked(use_object_color) def get_color_text(self): """Get color picker value, in text format.""" return self.colorpicker.get_color_text() def get_use_object_color(self): """Get 'use object color' checkbox value.""" return self.checkbox.isChecked() def get_value(self): """Get widget output value.""" res = ["Object"] if self.get_use_object_color() else [] res += [self.get_color_text()] return ";".join(res) def setToolTip(self, desc): """Set widget tooltip.""" self.colorpicker.setToolTip(desc) def on_object_color_change(self, state): """Respond to checkbox change event.""" self.colorpicker.setEnabled(not state)
def _init_settings_tab(self, tab): oneactive_checkbox = QCheckBox("Keep at most one active path") oneactive_checkbox.setChecked(False) self._oneactive_checkbox = oneactive_checkbox settings_layout = QVBoxLayout() settings_layout.addWidget(oneactive_checkbox) settings_layout.addStretch(0) frame = QFrame() frame.setLayout(settings_layout) tab.addTab(frame, 'Settings')
class CheckinConfirmation(QDialog): def __init__(self, parent, venue): super(CheckinConfirmation, self).__init__(parent) self.setWindowTitle("Checkin") self.centralWidget = QWidget() #Main Layout layout = QGridLayout() #layout.setSpacing(0) self.setLayout(layout) text = "You're checking in @<b>" + venue['name'] + "</b>" if 'address' in venue['location']: text += ", " + venue['location']['address'] text += "." textLabel = QLabel(text, self) textLabel.setWordWrap(True) okButton = QPushButton("Ok") self.connect(okButton, SIGNAL("clicked()"), self.accept) cancelButton = QPushButton("Cancel") self.connect(cancelButton, SIGNAL("clicked()"), self.reject) # TODO: make this a separate widget #---- self.tw = QCheckBox("Twitter") self.fb = QCheckBox("Facebook") broadcast = foursquare.config_get("broadcast") if broadcast: if not ", " in broadcast: self.tw.setChecked("twitter" in broadcast) self.fb.setChecked("facebook" in broadcast) #---- layout.addWidget(textLabel, 0, 0, 1, 3) layout.addWidget(self.tw, 1, 0) layout.addWidget(self.fb, 1, 1) layout.addWidget(okButton, 1, 2) #layout.addWidget(cancelButton, 1, 1) def broadcast(self): broadcast = "public" if self.tw.isChecked(): broadcast += ",twitter" if self.fb.isChecked(): broadcast += ",facebook"
class _ChannelsResultOptionsToolItem(_ResultToolItem): def _initUI(self): # Widgets self._chk_errorbar = QCheckBox("Show error bars") self._chk_errorbar.setChecked(True) # Layouts layout = _ResultToolItem._initUI(self) layout.addRow(self._chk_errorbar) # Signals self._chk_errorbar.stateChanged.connect(self.stateChanged) return layout def showErrorbar(self): return self._chk_errorbar.isChecked()
def __init__(self, *args, **kwargs): super(Widget_referenceFiles, self).__init__(*args, **kwargs) self.installEventFilter(self) mainLayout = QVBoxLayout(self) mainLayout.setContentsMargins(0, 0, 0, 0) mainLayout.setSpacing(8) treeWidget = QTreeWidget() headerItem = treeWidget.headerItem() checkBox_allItems = QCheckBox(treeWidget) checkBox_allItems.setFixedWidth(20) checkBox_allItems.setChecked(True) checkBox_allItems.setStyleSheet("margin: 6px 6px") treeWidget.setItemWidget(headerItem, 0, checkBox_allItems) headerItem.setText(0, "") headerItem.setText(1, "Reference File Name") treeWidget.setRootIsDecorated(False) treeWidget.setStyleSheet( "QTreeWidget::item { border-left: 1px solid gray;border-bottom: 1px solid gray; padding: 3px}\ QTreeWidget{ font-size:13px;}") treeWidget.header().setStyleSheet("font-size:12px;") treeWidget.setColumnWidth(0, 22) w_buttons = QWidget() lay_buttons = QHBoxLayout(w_buttons) lay_buttons.setContentsMargins(0, 0, 0, 0) buttonReference = QPushButton("REFERENCE") buttonCleanExceptSelected = QPushButton("CLEAN EXCEPT SELECTED") lay_buttons.addWidget(buttonCleanExceptSelected) lay_buttons.addWidget(buttonReference) mainLayout.addWidget(treeWidget) mainLayout.addWidget(w_buttons) self.treeWidget = treeWidget self.treeWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.treeWidget.checkBox_allItems = checkBox_allItems checkBox_allItems.stateChanged.connect(self.cmd_setCheckAsset) treeWidget.itemPressed.connect(self.cmd_selectItems) buttonReference.clicked.connect(self.referenceFiles) buttonCleanExceptSelected.clicked.connect(self.cmd_cleanScene) self.cmd_loadList()
def addLine(self): baseLayout = self.currentWidget().children()[0] lineLayout = QHBoxLayout() lineLayout.setContentsMargins(1,1,1,1) checkBox = QCheckBox(); checkBox.setChecked(True); checkBox.setContentsMargins(1,1,1,1) lineEdit = QLineEdit(); lineEdit.setContentsMargins(1,1,1,1) lineEdit.installEventFilter( self.lineEditEventFilter ) button = QPushButton( " - " ); button.setContentsMargins(1,1,1,1) lineLayout.addWidget( checkBox ) lineLayout.addWidget( lineEdit ) lineLayout.addWidget( button ) baseLayout.insertLayout( baseLayout.count()-2, lineLayout ) QtCore.QObject.connect( button, QtCore.SIGNAL( "clicked()" ), partial( self.removeLine, lineLayout ) ) self.lineLayouts.append( lineLayout )
def update_programs(self): selected_programs = self.selected_programs() for checkbox_program in self.checkboxes_programs: self.layout_programs.removeWidget(checkbox_program) checkbox_program.deleteLater() self.checkboxes_programs = list() for i, program_name in enumerate( sorted(self.current_fixture.programs.keys())): column = i // 4 row = i % 4 new_checkbox = QCheckBox(program_name) new_checkbox.setChecked(program_name in selected_programs) self.layout_programs.addWidget(new_checkbox, row, column) self.checkboxes_programs.append(new_checkbox)
def _init_cfg_options_tab(self, tab): resolve_indirect_jumps = QCheckBox(self) resolve_indirect_jumps.setText('Resolve indirect jumps') resolve_indirect_jumps.setChecked(True) self.option_widgets['resolve_indirect_jumps'] = resolve_indirect_jumps collect_data_refs = QCheckBox(self) collect_data_refs.setText( 'Collect cross-references and infer data types') collect_data_refs.setChecked(True) self.option_widgets['collect_data_refs'] = collect_data_refs layout = QVBoxLayout() layout.addWidget(resolve_indirect_jumps) layout.addWidget(collect_data_refs) layout.addStretch(0) frame = QFrame(self) frame.setLayout(layout) tab.addTab(frame, 'CFG Options')
class TreeWidgetItem_file(QTreeWidgetItem, Cmds_file_control): def __init__(self, *args, **kwargs): super(TreeWidgetItem_file, self).__init__(*args, **kwargs) def setCheckState(self): allChecked = True originalCheckValues = [] for checkBox in [ self.treeWidget().topLevelItem(i).checkBox for i in range(self.treeWidget().topLevelItemCount()) ]: if not checkBox.isChecked(): allChecked = False originalCheckValues.append(checkBox.isChecked()) if allChecked: self.treeWidget().checkBox_allItems.setChecked(True) else: self.treeWidget().checkBox_allItems.setChecked(False) for i in range(self.treeWidget().topLevelItemCount()): checkBox = self.treeWidget().topLevelItem(i).checkBox checkBox.setChecked(originalCheckValues[i]) def addFilePath(self, fileName, enableValue=True): self.checkBox = QCheckBox() self.checkBox.setFixedWidth(20) self.checkBox.setChecked(True) self.lineEdit = QLineEdit() self.lineEdit.setText(fileName) self.lineEdit.setReadOnly(True) self.treeWidget().setItemWidget(self, 0, self.checkBox) self.treeWidget().setItemWidget(self, 1, self.lineEdit) self.checkBox.stateChanged.connect(self.setCheckState) self.checkBox.setEnabled(enableValue) self.lineEdit.setEnabled(enableValue)
class _PhotonSpectrumResultOptionsToolItem(_ResultToolItem): def _initUI(self): # Widgets self._chk_total = QCheckBox("Show total intensity") self._chk_total.setChecked(True) self._chk_background = QCheckBox("Show background intensity") self._chk_background.setChecked(False) self._chk_errorbar = QCheckBox("Show error bars") self._chk_errorbar.setChecked(True) # Layouts layout = _ResultToolItem._initUI(self) layout.addRow(self._chk_total) layout.addRow(self._chk_background) layout.addRow(self._chk_errorbar) # Signals self._chk_total.stateChanged.connect(self.stateChanged) self._chk_background.stateChanged.connect(self.stateChanged) self._chk_errorbar.stateChanged.connect(self.stateChanged) return layout def isTotal(self): return self._chk_total.isChecked() def isBackground(self): return self._chk_background.isChecked() def isErrorbar(self): return self._chk_errorbar.isChecked()
class TrajectoryDetectorWidget(_DetectorWidget): def __init__(self, parent=None): _DetectorWidget.__init__(self, parent) self.setAccessibleName("Trajectory") def _initUI(self): # Widgets self._chk_secondary = QCheckBox("Simulation secondary electrons") self._chk_secondary.setChecked(True) # Layouts layout = _DetectorWidget._initUI(self) layout.addRow(self._chk_secondary) return layout def value(self): secondary = self._chk_secondary.isChecked() return TrajectoryDetector(secondary) def setValue(self, value): self._chk_secondary.setChecked(value.secondary)
def __loadUsers(self): """Loads user's data from DB""" users = self.parentWidget().app.getUsers() self.user_table.clearContents() self.user_table.setRowCount(len(users)) for i in range(len(users)): username_item = QTableWidgetItem(users[i].username) username_item.setFlags(username_item.flags() ^ Qt.ItemIsEditable) blocked_checkbox = QCheckBox() if users[i].blocked: blocked_checkbox.setChecked(True) def create_blocked_toggle(checkbox, user): def blocked_toggle(): user.blocked = (1 if checkbox.isChecked() else 0) self.parentWidget().app.updateUser(user) self.__loadUsers() return blocked_toggle blocked_checkbox.toggled.connect(create_blocked_toggle(blocked_checkbox, users[i])) password_restrict_checkbox = QCheckBox() if users[i].restrictions: password_restrict_checkbox.setChecked(True) def create_password_restrict_toggle(checkbox, user): def password_restrict_toggle(): user.restrictions = (1 if checkbox.isChecked() else 0) self.parentWidget().app.updateUser(user) self.__loadUsers() return password_restrict_toggle password_restrict_checkbox.toggled.connect( create_password_restrict_toggle(password_restrict_checkbox, users[i])) self.user_table.setItem(i, 0, username_item) self.user_table.setCellWidget(i, 1, blocked_checkbox) self.user_table.setCellWidget(i, 2, password_restrict_checkbox)
class RunnerDialog(QDialog): options_added = Signal(Options) options_running = Signal(Options) options_simulated = Signal(Options) options_error = Signal(Options, Exception) results_saved = Signal(Results, str) results_error = Signal(Results, Exception) def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Runner') self.setMinimumWidth(750) # Runner self._runner = None self._running_timer = QTimer() self._running_timer.setInterval(500) # Widgets self._dlg_progress = QProgressDialog() self._dlg_progress.setRange(0, 100) self._dlg_progress.setModal(True) self._dlg_progress.hide() lbl_outputdir = QLabel("Output directory") self._txt_outputdir = DirBrowseWidget() max_workers = cpu_count() #@UndefinedVariable lbl_workers = QLabel('Number of workers') self._spn_workers = QSpinBox() self._spn_workers.setRange(1, max_workers) self._spn_workers.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) lbl_max_workers = QLabel('(max: %i)' % max_workers) self._chk_overwrite = QCheckBox("Overwrite existing results in output directory") self._chk_overwrite.setChecked(True) self._lbl_available = QLabel('Available') self._lst_available = QListView() self._lst_available.setModel(_AvailableOptionsListModel()) self._lst_available.setSelectionMode(QListView.SelectionMode.MultiSelection) tlb_available = QToolBar() spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) tlb_available.addWidget(spacer) act_open = tlb_available.addAction(getIcon("document-open"), "Open") act_open.setShortcut(QKeySequence.Open) tlb_available.addSeparator() act_remove = tlb_available.addAction(getIcon("list-remove"), "Remove") act_clear = tlb_available.addAction(getIcon("edit-clear"), "Clear") self._btn_addtoqueue = QPushButton(getIcon("go-next"), "") self._btn_addtoqueue.setToolTip("Add to queue") self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue = QPushButton(getIcon("go-last"), "") self._btn_addalltoqueue.setToolTip("Add all to queue") self._btn_addalltoqueue.setEnabled(False) self._lbl_options = QLabel('Queued/Running/Completed') self._tbl_options = QTableView() self._tbl_options.setModel(_StateOptionsTableModel()) self._tbl_options.setItemDelegate(_StateOptionsItemDelegate()) self._tbl_options.setSelectionMode(QListView.SelectionMode.NoSelection) self._tbl_options.setColumnWidth(1, 60) self._tbl_options.setColumnWidth(2, 80) header = self._tbl_options.horizontalHeader() header.setResizeMode(0, QHeaderView.Interactive) header.setResizeMode(1, QHeaderView.Fixed) header.setResizeMode(2, QHeaderView.Fixed) header.setResizeMode(3, QHeaderView.Stretch) self._btn_start = QPushButton(getIcon("media-playback-start"), "Start") self._btn_cancel = QPushButton("Cancel") self._btn_cancel.setEnabled(False) self._btn_close = QPushButton("Close") self._btn_import = QPushButton("Import") self._btn_import.setEnabled(False) # Layouts layout = QVBoxLayout() sublayout = QGridLayout() sublayout.addWidget(lbl_outputdir, 0, 0) sublayout.addWidget(self._txt_outputdir, 0, 1) sublayout.addWidget(lbl_workers, 1, 0) subsublayout = QHBoxLayout() subsublayout.addWidget(self._spn_workers) subsublayout.addWidget(lbl_max_workers) sublayout.addLayout(subsublayout, 1, 1) layout.addLayout(sublayout) sublayout.addWidget(self._chk_overwrite, 2, 0, 1, 3) sublayout = QGridLayout() sublayout.setColumnStretch(0, 1) sublayout.setColumnStretch(2, 3) sublayout.addWidget(self._lbl_available, 0, 0) sublayout.addWidget(self._lst_available, 1, 0) sublayout.addWidget(tlb_available, 2, 0) subsublayout = QVBoxLayout() subsublayout.addStretch() subsublayout.addWidget(self._btn_addtoqueue) subsublayout.addWidget(self._btn_addalltoqueue) subsublayout.addStretch() sublayout.addLayout(subsublayout, 1, 1) sublayout.addWidget(self._lbl_options, 0, 2) sublayout.addWidget(self._tbl_options, 1, 2) layout.addLayout(sublayout) sublayout = QHBoxLayout() sublayout.addStretch() sublayout.addWidget(self._btn_import) sublayout.addWidget(self._btn_start) sublayout.addWidget(self._btn_cancel) sublayout.addWidget(self._btn_close) layout.addLayout(sublayout) self.setLayout(layout) # Signal self._running_timer.timeout.connect(self._onRunningTimer) act_open.triggered.connect(self._onOpen) act_remove.triggered.connect(self._onRemove) act_clear.triggered.connect(self._onClear) self._btn_addtoqueue.released.connect(self._onAddToQueue) self._btn_addalltoqueue.released.connect(self._onAddAllToQueue) self._btn_start.released.connect(self._onStart) self._btn_cancel.released.connect(self._onCancel) self._btn_close.released.connect(self._onClose) self._btn_import.released.connect(self._onImport) self.options_added.connect(self._onOptionsAdded) self.options_running.connect(self._onOptionsRunning) self.options_simulated.connect(self._onOptionsSimulated) self.options_error.connect(self._onOptionsError) self.results_error.connect(self._onResultsError) # Defaults settings = get_settings() section = settings.add_section('gui') if hasattr(section, 'outputdir'): self._txt_outputdir.setPath(section.outputdir) if hasattr(section, 'maxworkers'): self._spn_workers.setValue(int(section.maxworkers)) if hasattr(section, 'overwrite'): state = True if section.overwrite.lower() == 'true' else False self._chk_overwrite.setChecked(state) def _onDialogProgressProgress(self, progress, status): self._dlg_progress.setValue(progress * 100) self._dlg_progress.setLabelText(status) def _onDialogProgressCancel(self): self._dlg_progress.hide() if self._options_reader_thread is None: return self._options_reader_thread.cancel() self._options_reader_thread.quit() self._options_reader_thread.wait() def _onDialogProgressException(self, ex): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() messagebox.exception(self, ex) def _onRunningTimer(self): self._tbl_options.model().reset() def _onOpen(self): settings = get_settings() curdir = getattr(settings.gui, 'opendir', os.getcwd()) filepath, namefilter = \ QFileDialog.getOpenFileName(self, "Open", curdir, 'Options [*.xml] (*.xml)') if not filepath or not namefilter: return settings.gui.opendir = os.path.dirname(filepath) if not filepath.endswith('.xml'): filepath += '.xml' self._options_reader_thread = _OptionsReaderWrapperThread(filepath) self._dlg_progress.canceled.connect(self._onDialogProgressCancel) self._options_reader_thread.resultReady.connect(self._onOpened) self._options_reader_thread.progressUpdated.connect(self._onDialogProgressProgress) self._options_reader_thread.exceptionRaised.connect(self._onDialogProgressException) self._options_reader_thread.start() self._dlg_progress.reset() self._dlg_progress.show() def _onOpened(self, options): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() self._options_reader_thread = None try: self._lst_available.model().addOptions(options) except Exception as ex: messagebox.exception(self, ex) def _onRemove(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.popOptions(row) def _onClear(self): self._lst_available.model().clearOptions() def _onAddToQueue(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onAddAllToQueue(self): model = self._lst_available.model() for row in reversed(range(0, model.rowCount())): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onStart(self): outputdir = self._txt_outputdir.path() if not outputdir: QMessageBox.critical(self, 'Start', 'Missing output directory') return max_workers = self._spn_workers.value() overwrite = self._chk_overwrite.isChecked() self.start(outputdir, overwrite, max_workers) def _onCancel(self): self.cancel() def _onClose(self): if self._runner is not None: self._runner.close() self._running_timer.stop() self.close() def _onImport(self): list_options = self._lst_available.model().listOptions() if not list_options: return # Select options dialog = _OptionsSelector(list_options) if not dialog.exec_(): return options = dialog.options() # Start importer outputdir = self._runner.outputdir max_workers = self._runner.max_workers importer = LocalImporter(outputdir, max_workers) importer.start() importer.put(options) self._dlg_progress.show() try: while importer.is_alive(): if self._dlg_progress.wasCanceled(): importer.cancel() break self._dlg_progress.setValue(importer.progress * 100) finally: self._dlg_progress.hide() def _onOptionsAdded(self, options): logging.debug('runner: optionsAdded') self._tbl_options.model().addOptions(options) def _onOptionsRunning(self, options): logging.debug('runner: optionsRunning') self._tbl_options.model().resetOptions(options) def _onOptionsSimulated(self, options): logging.debug('runner: optionsSimulated') self._tbl_options.model().resetOptions(options) def _onOptionsError(self, options, ex): logging.debug('runner: optionsError') self._tbl_options.model().resetOptions(options) def _onResultsError(self, results, ex): logging.debug('runner: resultsError') self._tbl_options.model().reset() def closeEvent(self, event): if self.is_running(): message = 'Runner is running. Do you want to continue?' answer = QMessageBox.question(self, 'Runner', message, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: event.ignore() return self.cancel() self._dlg_progress.close() settings = get_settings() section = settings.add_section('gui') path = self._txt_outputdir.path() if path: section.outputdir = path section.maxworkers = str(self._spn_workers.value()) section.overwrite = str(self._chk_overwrite.isChecked()) settings.write() event.accept() def addAvailableOptions(self, options): self._lst_available.model().addOptions(options) def removeAvailableOptions(self, options): self._lst_available.model().removeOptions(options) def clearAvailableOptions(self): self._lbl_available.model().clearOptions() def start(self, outputdir, overwrite, max_workers): self._runner = LocalRunner(outputdir=outputdir, overwrite=overwrite, max_workers=max_workers) self._tbl_options.setModel(_StateOptionsTableModel(self._runner)) self._spn_workers.setEnabled(False) self._txt_outputdir.setEnabled(False) self._chk_overwrite.setEnabled(False) self._btn_addtoqueue.setEnabled(True) self._btn_addalltoqueue.setEnabled(True) self._btn_start.setEnabled(False) self._btn_cancel.setEnabled(True) self._btn_close.setEnabled(False) self._btn_import.setEnabled(True) self._runner.options_added.connect(self.options_added.emit) self._runner.options_running.connect(self.options_running.emit) self._runner.options_simulated.connect(self.options_simulated.emit) self._runner.options_error.connect(self.options_error.emit) self._runner.results_saved.connect(self.results_saved.emit) self._runner.results_error.connect(self.results_error.emit) self._running_timer.start() self._runner.start() def cancel(self): if self._runner is None: return self._runner.cancel() self._running_timer.stop() self._runner.options_added.disconnect(self.options_added.emit) self._runner.options_running.disconnect(self.options_running.emit) self._runner.options_simulated.disconnect(self.options_simulated.emit) self._runner.options_error.disconnect(self.options_error.emit) self._runner.results_saved.disconnect(self.results_saved.emit) self._runner.results_error.disconnect(self.results_error.emit) self._runner = None self._spn_workers.setEnabled(True) self._txt_outputdir.setEnabled(True) self._chk_overwrite.setEnabled(True) self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue.setEnabled(False) self._btn_start.setEnabled(True) self._btn_cancel.setEnabled(False) self._btn_close.setEnabled(True) self._btn_import.setEnabled(False) def is_running(self): return self._runner is not None and self._runner.is_alive()
class ConfigDialog(QtGui.QDialog): pressedclosebutton = False moreToggling = False def moreToggled(self): if self.moreToggling == False: self.moreToggling = True if self.showmoreCheckbox.isChecked() and self.showmoreCheckbox.isVisible(): self.showmoreCheckbox.setChecked(False) self.moreSettingsGroup.setChecked(True) self.moreSettingsGroup.show() self.showmoreCheckbox.hide() self.saveMoreState(True) else: self.moreSettingsGroup.setChecked(False) self.moreSettingsGroup.hide() self.showmoreCheckbox.show() self.saveMoreState(False) self.moreToggling = False self.adjustSize() self.setFixedSize(self.sizeHint()) def runButtonTextUpdate(self): if (self.donotstoreCheckbox.isChecked()): self.runButton.setText(getMessage("en", "run-label")) else: self.runButton.setText(getMessage("en", "storeandrun-label")) def openHelp(self): self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/client/") def _tryToFillPlayerPath(self, playerpath, playerpathlist): settings = QSettings("Syncplay", "PlayerList") settings.beginGroup("PlayerList") savedPlayers = settings.value("PlayerList", []) if(not isinstance(savedPlayers, list)): savedPlayers = [] playerpathlist = list(set(os.path.normcase(os.path.normpath(path)) for path in set(playerpathlist + savedPlayers))) settings.endGroup() foundpath = "" if playerpath != None and playerpath != "": if not os.path.isfile(playerpath): expandedpath = PlayerFactory().getExpandedPlayerPathByPath(playerpath) if expandedpath != None and os.path.isfile(expandedpath): playerpath = expandedpath if os.path.isfile(playerpath): foundpath = playerpath self.executablepathCombobox.addItem(foundpath) for path in playerpathlist: if(os.path.isfile(path) and os.path.normcase(os.path.normpath(path)) != os.path.normcase(os.path.normpath(foundpath))): self.executablepathCombobox.addItem(path) if foundpath == "": foundpath = path if foundpath != "": settings.beginGroup("PlayerList") playerpathlist.append(os.path.normcase(os.path.normpath(foundpath))) settings.setValue("PlayerList", list(set(os.path.normcase(os.path.normpath(path)) for path in set(playerpathlist)))) settings.endGroup() return(foundpath) def updateExecutableIcon(self): currentplayerpath = unicode(self.executablepathCombobox.currentText()) iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) if iconpath != None and iconpath != "": self.executableiconImage.load(self.resourcespath + iconpath) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) else: self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) def browsePlayerpath(self): options = QtGui.QFileDialog.Options() defaultdirectory = "" browserfilter = "All files (*)" if os.name == 'nt': browserfilter = "Executable files (*.exe);;All files (*)" if "PROGRAMFILES(X86)" in os.environ: defaultdirectory = os.environ["ProgramFiles(x86)"] elif "PROGRAMFILES" in os.environ: defaultdirectory = os.environ["ProgramFiles"] elif "PROGRAMW6432" in os.environ: defaultdirectory = os.environ["ProgramW6432"] elif sys.platform.startswith('linux'): defaultdirectory = "/usr/bin" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media player executable", defaultdirectory, browserfilter, "", options) if fileName: self.executablepathCombobox.setEditText(os.path.normpath(fileName)) def loadMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") self.mediadirectory = settings.value("mediadir", "") settings.endGroup() def saveMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") settings.setValue("mediadir", self.mediadirectory) settings.endGroup() def getMoreState(self): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") morestate = unicode.lower(unicode(settings.value("ShowMoreSettings", "false"))) settings.endGroup() if morestate == "true": return(True) else: return(False) def saveMoreState(self, morestate): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") settings.setValue("ShowMoreSettings", morestate) settings.endGroup() def browseMediapath(self): self.loadMediaBrowseSettings() options = QtGui.QFileDialog.Options() if (os.path.isdir(self.mediadirectory)): defaultdirectory = self.mediadirectory elif (os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.MoviesLocation))): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.MoviesLocation) elif (os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.HomeLocation))): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) else: defaultdirectory = "" browserfilter = "All files (*)" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory, browserfilter, "", options) if fileName: self.mediapathTextbox.setText(os.path.normpath(fileName)) self.mediadirectory = os.path.dirname(fileName) self.saveMediaBrowseSettings() def _saveDataAndLeave(self): self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT) self.config['name'] = self.usernameTextbox.text() self.config['room'] = self.defaultroomTextbox.text() self.config['password'] = self.serverpassTextbox.text() self.config['playerPath'] = unicode(self.executablepathCombobox.currentText()) if self.mediapathTextbox.text() == "": self.config['file'] = None elif os.path.isfile(os.path.abspath(self.mediapathTextbox.text())): self.config['file'] = os.path.abspath(self.mediapathTextbox.text()) else: self.config['file'] = unicode(self.mediapathTextbox.text()) if self.alwaysshowCheckbox.isChecked() == True: self.config['forceGuiPrompt'] = True else: self.config['forceGuiPrompt'] = False if self.donotstoreCheckbox.isChecked() == True: self.config['noStore'] = True else: self.config['noStore'] = False if self.slowdownCheckbox.isChecked() == True: self.config['slowOnDesync'] = True else: self.config['slowOnDesync'] = False if self.dontslowwithmeCheckbox.isChecked() == True: self.config['dontSlowDownWithMe'] = True else: self.config['dontSlowDownWithMe'] = False if self.pauseonleaveCheckbox.isChecked() == True: self.config['pauseOnLeave'] = True else: self.config['pauseOnLeave'] = False if constants.SHOW_REWIND_ON_DESYNC_CHECKBOX == True: if self.rewindCheckbox.isChecked() == True: self.config['rewindOnDesync'] = True else: self.config['rewindOnDesync'] = False if self.filenameprivacySendRawOption.isChecked() == True: self.config['filenamePrivacyMode'] = constants.PRIVACY_SENDRAW_MODE elif self.filenameprivacySendHashedOption.isChecked() == True: self.config['filenamePrivacyMode'] = constants.PRIVACY_SENDHASHED_MODE elif self.filenameprivacyDontSendOption.isChecked() == True: self.config['filenamePrivacyMode'] = constants.PRIVACY_DONTSEND_MODE if self.filesizeprivacySendRawOption.isChecked() == True: self.config['filesizePrivacyMode'] = constants.PRIVACY_SENDRAW_MODE elif self.filesizeprivacySendHashedOption.isChecked() == True: self.config['filesizePrivacyMode'] = constants.PRIVACY_SENDHASHED_MODE elif self.filesizeprivacyDontSendOption.isChecked() == True: self.config['filesizePrivacyMode'] = constants.PRIVACY_DONTSEND_MODE self.pressedclosebutton = True self.close() return def closeEvent(self, event): if self.pressedclosebutton == False: sys.exit() raise GuiConfiguration.WindowClosed event.accept() def dragEnterEvent(self, event): data = event.mimeData() urls = data.urls() if (urls and urls[0].scheme() == 'file'): event.acceptProposedAction() def dropEvent(self, event): data = event.mimeData() urls = data.urls() if (urls and urls[0].scheme() == 'file'): if sys.platform.startswith('linux'): dropfilepath = unicode(urls[0].path()) else: dropfilepath = unicode(urls[0].path())[1:] # Removes starting slash if dropfilepath[-4:].lower() == ".exe": self.executablepathCombobox.setEditText(dropfilepath) else: self.mediapathTextbox.setText(dropfilepath) def __init__(self, config, playerpaths, error): from syncplay import utils self.config = config self.datacleared = False if config['clearGUIData'] == True: settings = QSettings("Syncplay", "PlayerList") settings.clear() settings = QSettings("Syncplay", "MediaBrowseDialog") settings.clear() settings = QSettings("Syncplay", "MainWindow") settings.clear() settings = QSettings("Syncplay", "MoreSettings") settings.clear() self.datacleared = True self.QtGui = QtGui self.error = error if sys.platform.startswith('linux'): resourcespath = utils.findWorkingDir() + "/resources/" else: resourcespath = utils.findWorkingDir() + "\\resources\\" self.resourcespath = resourcespath super(ConfigDialog, self).__init__() self.setWindowTitle(getMessage("en", "config-window-title")) self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png")) if(config['host'] == None): host = "" elif(":" in config['host']): host = config['host'] else: host = config['host'] + ":" + str(config['port']) self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("en", "connection-group-title")) self.hostTextbox = QLineEdit(host, self) self.hostLabel = QLabel(getMessage("en", "host-label"), self) self.usernameTextbox = QLineEdit(config['name'], self) self.serverpassLabel = QLabel(getMessage("en", "password-label"), self) self.defaultroomTextbox = QLineEdit(config['room'], self) self.usernameLabel = QLabel(getMessage("en", "username-label"), self) self.serverpassTextbox = QLineEdit(config['password'], self) self.defaultroomLabel = QLabel(getMessage("en", "room-label"), self) if (constants.SHOW_TOOLTIPS == True): self.hostLabel.setToolTip(getMessage("en", "host-tooltip")) self.hostTextbox.setToolTip(getMessage("en", "host-tooltip")) self.usernameLabel.setToolTip(getMessage("en", "username-tooltip")) self.usernameTextbox.setToolTip(getMessage("en", "username-tooltip")) self.serverpassLabel.setToolTip(getMessage("en", "password-tooltip")) self.serverpassTextbox.setToolTip(getMessage("en", "password-tooltip")) self.defaultroomLabel.setToolTip(getMessage("en", "room-tooltip")) self.defaultroomTextbox.setToolTip(getMessage("en", "room-tooltip")) self.connectionSettingsLayout = QtGui.QGridLayout() self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) self.connectionSettingsLayout.addWidget(self.hostTextbox, 0, 1) self.connectionSettingsLayout.addWidget(self.serverpassLabel, 1, 0) self.connectionSettingsLayout.addWidget(self.serverpassTextbox, 1, 1) self.connectionSettingsLayout.addWidget(self.usernameLabel, 2, 0) self.connectionSettingsLayout.addWidget(self.usernameTextbox, 2, 1) self.connectionSettingsLayout.addWidget(self.defaultroomLabel, 3, 0) self.connectionSettingsLayout.addWidget(self.defaultroomTextbox, 3, 1) self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) self.mediaplayerSettingsGroup = QtGui.QGroupBox(getMessage("en", "media-setting-title")) self.executableiconImage = QtGui.QImage() self.executableiconLabel = QLabel(self) self.executableiconLabel.setMinimumWidth(16) self.executablepathCombobox = QtGui.QComboBox(self) self.executablepathCombobox.setEditable(True) self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths)) self.executablepathCombobox.setMinimumWidth(200) self.executablepathCombobox.setMaximumWidth(200) self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon) self.executablepathLabel = QLabel(getMessage("en", "executable-path-label"), self) self.executablebrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("en", "browse-label")) self.executablebrowseButton.clicked.connect(self.browsePlayerpath) self.mediapathTextbox = QLineEdit(config['file'], self) self.mediapathLabel = QLabel(getMessage("en", "media-path-label"), self) self.mediabrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("en", "browse-label")) self.mediabrowseButton.clicked.connect(self.browseMediapath) if (constants.SHOW_TOOLTIPS == True): self.executablepathLabel.setToolTip(getMessage("en", "executable-path-tooltip")) self.executablepathCombobox.setToolTip(getMessage("en", "executable-path-tooltip")) self.mediapathLabel.setToolTip(getMessage("en", "media-path-tooltip")) self.mediapathTextbox.setToolTip(getMessage("en", "media-path-tooltip")) if constants.SHOW_REWIND_ON_DESYNC_CHECKBOX == True: self.rewindCheckbox = QCheckBox(getMessage("en", "rewind-label")) if (constants.SHOW_TOOLTIPS == True): self.rewindCheckbox.setToolTip(getMessage("en", "rewind-tooltip")) self.mediaplayerSettingsLayout = QtGui.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) self.mediaplayerSettingsLayout.addWidget(self.executableiconLabel, 0, 1) self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox, 0, 2) self.mediaplayerSettingsLayout.addWidget(self.executablebrowseButton, 0, 3) self.mediaplayerSettingsLayout.addWidget(self.mediapathLabel, 1, 0) self.mediaplayerSettingsLayout.addWidget(self.mediapathTextbox , 1, 2) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) self.moreSettingsGroup = QtGui.QGroupBox(getMessage("en", "more-title")) self.moreSettingsGroup.setCheckable(True) self.filenameprivacyLabel = QLabel(getMessage("en", "filename-privacy-label"), self) self.filenameprivacyButtonGroup = QButtonGroup() self.filenameprivacySendRawOption = QRadioButton(getMessage("en", "privacy-sendraw-option")) self.filenameprivacySendHashedOption = QRadioButton(getMessage("en", "privacy-sendhashed-option")) self.filenameprivacyDontSendOption = QRadioButton(getMessage("en", "privacy-dontsend-option")) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendRawOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendHashedOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacyDontSendOption) self.filesizeprivacyLabel = QLabel(getMessage("en", "filesize-privacy-label"), self) self.filesizeprivacyButtonGroup = QButtonGroup() self.filesizeprivacySendRawOption = QRadioButton(getMessage("en", "privacy-sendraw-option")) self.filesizeprivacySendHashedOption = QRadioButton(getMessage("en", "privacy-sendhashed-option")) self.filesizeprivacyDontSendOption = QRadioButton(getMessage("en", "privacy-dontsend-option")) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendRawOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendHashedOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacyDontSendOption) self.slowdownCheckbox = QCheckBox(getMessage("en", "slowdown-label")) self.dontslowwithmeCheckbox = QCheckBox(getMessage("en", "dontslowwithme-label")) self.pauseonleaveCheckbox = QCheckBox(getMessage("en", "pauseonleave-label")) self.alwaysshowCheckbox = QCheckBox(getMessage("en", "alwayshow-label")) self.donotstoreCheckbox = QCheckBox(getMessage("en", "donotstore-label")) filenamePrivacyMode = config['filenamePrivacyMode'] if filenamePrivacyMode == constants.PRIVACY_DONTSEND_MODE: self.filenameprivacyDontSendOption.setChecked(True) elif filenamePrivacyMode == constants.PRIVACY_SENDHASHED_MODE: self.filenameprivacySendHashedOption.setChecked(True) else: self.filenameprivacySendRawOption.setChecked(True) filesizePrivacyMode = config['filesizePrivacyMode'] if filesizePrivacyMode == constants.PRIVACY_DONTSEND_MODE: self.filesizeprivacyDontSendOption.setChecked(True) elif filesizePrivacyMode == constants.PRIVACY_SENDHASHED_MODE: self.filesizeprivacySendHashedOption.setChecked(True) else: self.filesizeprivacySendRawOption.setChecked(True) if config['slowOnDesync'] == True: self.slowdownCheckbox.setChecked(True) if config['dontSlowDownWithMe'] == True: self.dontslowwithmeCheckbox.setChecked(True) if constants.SHOW_REWIND_ON_DESYNC_CHECKBOX == True and config['rewindOnDesync'] == True: self.rewindCheckbox.setChecked(True) if config['pauseOnLeave'] == True: self.pauseonleaveCheckbox.setChecked(True) if (constants.SHOW_TOOLTIPS == True): self.filenameprivacyLabel.setToolTip(getMessage("en", "filename-privacy-tooltip")) self.filenameprivacySendRawOption.setToolTip(getMessage("en", "privacy-sendraw-tooltip")) self.filenameprivacySendHashedOption.setToolTip(getMessage("en", "privacy-sendhashed-tooltip")) self.filenameprivacyDontSendOption.setToolTip(getMessage("en", "privacy-dontsend-tooltip")) self.filesizeprivacyLabel.setToolTip(getMessage("en", "filesize-privacy-tooltip")) self.filesizeprivacySendRawOption.setToolTip(getMessage("en", "privacy-sendraw-tooltip")) self.filesizeprivacySendHashedOption.setToolTip(getMessage("en", "privacy-sendhashed-tooltip")) self.filesizeprivacyDontSendOption.setToolTip(getMessage("en", "privacy-dontsend-tooltip")) self.slowdownCheckbox.setToolTip(getMessage("en", "slowdown-tooltip")) self.dontslowwithmeCheckbox.setToolTip(getMessage("en", "dontslowwithme-tooltip")) self.pauseonleaveCheckbox.setToolTip(getMessage("en", "pauseonleave-tooltip")) self.alwaysshowCheckbox.setToolTip(getMessage("en", "alwayshow-tooltip")) self.donotstoreCheckbox.setToolTip(getMessage("en", "donotstore-tooltip")) self.slowdownCheckbox.setToolTip(getMessage("en", "slowdown-tooltip")) self.moreSettingsLayout = QtGui.QGridLayout() self.privacySettingsLayout = QtGui.QGridLayout() self.privacyFrame = QtGui.QFrame() self.privacyFrame.setLineWidth(0) self.privacyFrame.setMidLineWidth(0) self.privacySettingsLayout.setContentsMargins(0, 0, 0, 0) self.privacySettingsLayout.addWidget(self.filenameprivacyLabel, 0, 0) self.privacySettingsLayout.addWidget(self.filenameprivacySendRawOption, 0, 1, Qt.AlignRight) self.privacySettingsLayout.addWidget(self.filenameprivacySendHashedOption, 0, 2, Qt.AlignRight) self.privacySettingsLayout.addWidget(self.filenameprivacyDontSendOption, 0, 3, Qt.AlignRight) self.privacySettingsLayout.addWidget(self.filesizeprivacyLabel, 1, 0) self.privacySettingsLayout.addWidget(self.filesizeprivacySendRawOption, 1, 1, Qt.AlignRight) self.privacySettingsLayout.addWidget(self.filesizeprivacySendHashedOption, 1, 2, Qt.AlignRight) self.privacySettingsLayout.addWidget(self.filesizeprivacyDontSendOption, 1, 3, Qt.AlignRight) self.privacyFrame.setLayout(self.privacySettingsLayout) self.moreSettingsLayout.addWidget(self.privacyFrame, 0, 0, 1, 4) self.moreSettingsLayout.addWidget(self.slowdownCheckbox, 2, 0, 1, 4) self.moreSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 3, 0, 1, 4) if constants.SHOW_REWIND_ON_DESYNC_CHECKBOX == True: self.moreSettingsLayout.addWidget(self.rewindCheckbox, 4, 0, 1, 4) self.moreSettingsLayout.addWidget(self.pauseonleaveCheckbox, 5, 0, 1, 4) self.moreSettingsLayout.addWidget(self.alwaysshowCheckbox, 6, 0, 1, 4) self.moreSettingsLayout.addWidget(self.donotstoreCheckbox, 7, 0, 1, 4) self.moreSettingsGroup.setLayout(self.moreSettingsLayout) self.showmoreCheckbox = QCheckBox(getMessage("en", "more-title")) if self.getMoreState() == False: self.showmoreCheckbox.setChecked(False) self.moreSettingsGroup.hide() else: self.showmoreCheckbox.hide() self.showmoreCheckbox.toggled.connect(self.moreToggled) self.moreSettingsGroup.toggled.connect(self.moreToggled) if config['forceGuiPrompt'] == True: self.alwaysshowCheckbox.setChecked(True) if (constants.SHOW_TOOLTIPS == True): self.showmoreCheckbox.setToolTip(getMessage("en", "more-tooltip")) self.donotstoreCheckbox.toggled.connect(self.runButtonTextUpdate) self.mainLayout = QtGui.QVBoxLayout() if error: self.errorLabel = QLabel(error, self) self.errorLabel.setAlignment(Qt.AlignCenter) self.errorLabel.setStyleSheet("QLabel { color : red; }") self.mainLayout.addWidget(self.errorLabel) self.mainLayout.addWidget(self.connectionSettingsGroup) self.mainLayout.addSpacing(12) self.mainLayout.addWidget(self.mediaplayerSettingsGroup) self.mainLayout.addSpacing(12) self.mainLayout.addWidget(self.showmoreCheckbox) self.mainLayout.addWidget(self.moreSettingsGroup) self.mainLayout.addSpacing(12) self.topLayout = QtGui.QHBoxLayout() self.helpButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'help.png'), getMessage("en", "help-label")) if (constants.SHOW_TOOLTIPS == True): self.helpButton.setToolTip(getMessage("en", "help-tooltip")) self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.pressed.connect(self.openHelp) self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("en", "storeandrun-label")) self.runButton.pressed.connect(self._saveDataAndLeave) if config['noStore'] == True: self.donotstoreCheckbox.setChecked(True) self.runButton.setText(getMessage("en", "run-label")) self.topLayout.addWidget(self.helpButton, Qt.AlignLeft) self.topLayout.addWidget(self.runButton, Qt.AlignRight) self.mainLayout.addLayout(self.topLayout) self.mainLayout.addStretch(1) self.setLayout(self.mainLayout) self.runButton.setFocus() self.setFixedSize(self.sizeHint()) self.setAcceptDrops(True) if self.datacleared == True: QtGui.QMessageBox.information(self, "Syncplay", getMessage("en", "gui-data-cleared-notification"))
class SettingsWindow(QDialog): def __init__(self, parent): super(self.__class__, self).__init__(parent) self.parent = parent self.lib = libserial.InitApp(self) if self.parent.receive is not None: self.boolean_config_is_ok = True else: self.boolean_config_is_ok = False self.config_parser = ConfigParser.ConfigParser() self.config_parser.read("config/profiles/profiles.ini") self.settings_parser = ConfigParser.ConfigParser() self.settings_parser.read('config/settings.ini') self.setWindowTitle(SERIAL_CHAT_SETTINGS_TITLE) self.button_box_dialog = QDialogButtonBox(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.button_box_dialog.button(QDialogButtonBox.Ok).setText(CONNECT) self.button_box_dialog.button(QDialogButtonBox.Cancel).setText(CANCEL) self.button_box_dialog.accepted.connect(self.accept) self.accepted.connect(self.apply_setting_changes) self.button_box_dialog.rejected.connect(self.reject) self.serial_dropdown = QComboBox() self.lib.init__serial() self.serial_values = self.lib.get_serials() for serials in self.serial_values: self.serial_dropdown.addItem(serials) if self.parent.serial_port is not None: self.serial_dropdown.setCurrentIndex( self.serial_dropdown.findText(self.parent.serial_port.name)) self.profiles_combobox = QComboBox() self.profiles_combobox.addItem("None") if self.parent.choosen_profile == "Custom": self.profiles_combobox.addItem("Custom") for profile in self.config_parser.sections(): self.profiles_combobox.addItem(profile) if self.parent.custom_settings: self.profiles_combobox.setCurrentIndex( self.profiles_combobox.findText('Custom')) elif self.parent.choosen_profile != 'None': self.profiles_combobox.setCurrentIndex( self.profiles_combobox.findText(self.parent.choosen_profile)) else: self.profiles_combobox.setCurrentIndex( self.profiles_combobox.findText('None')) self.profiles_combobox.currentIndexChanged.connect( self.change_custom_settings_on_profile) self.custom_settings_checkbox = QCheckBox() self.custom_settings_checkbox.stateChanged.connect( self.custom_settings_enable_disable) self.interval_time_lineedit = QLineEdit(str(self.parent.interval_time)) self.interval_time_lineedit.editingFinished.connect( self.check_if_digit) self.interval_time_lineedit.setDisabled(True) self.serial_speed_combobox = QComboBox() for sp in serial_speeds: self.serial_speed_combobox.addItem(str(sp)) if self.boolean_config_is_ok: self.serial_speed_combobox.setCurrentIndex( self.serial_speed_combobox.findText( str(self.parent.serial_port.baudrate))) else: self.serial_speed_combobox.setCurrentIndex( self.serial_speed_combobox.findText('9600')) self.serial_speed_combobox.setDisabled(True) self.databits_combobox = QComboBox() for db in bytesize_values: self.databits_combobox.addItem(str(db)) if self.boolean_config_is_ok: self.databits_combobox.setCurrentIndex( self.databits_combobox.findText( str(self.parent.serial_port.bytesize))) else: self.databits_combobox.setCurrentIndex( self.databits_combobox.findText('8')) self.databits_combobox.setDisabled(True) self.stopbits_combobox = QComboBox() for sb in stop_values: self.stopbits_combobox.addItem(str(sb)) if self.boolean_config_is_ok: sb = str(self.parent.serial_port.stopbits).replace('.', ',') self.stopbits_combobox.setCurrentIndex( self.stopbits_combobox.findText(str(sb))) else: self.stopbits_combobox.setCurrentIndex( self.stopbits_combobox.findText('1')) self.stopbits_combobox.setDisabled(True) self.parity_combobox = QComboBox() for par in parity_values: self.parity_combobox.addItem(str(par)) if self.boolean_config_is_ok: table = {'O': 'Odd', 'E': 'Even', 'N': 'None'} xxx = [ item for key, item in table.items() if self.parent.serial_port.parity == key ] self.parity_combobox.setCurrentIndex(parity_values.index(xxx[0])) else: self.parity_combobox.setCurrentIndex( self.parity_combobox.findText("None")) self.parity_combobox.setDisabled(True) self.flowcontrol_combobox = QComboBox() for fc in flow_control_values: self.flowcontrol_combobox.addItem(str(fc)) if self.boolean_config_is_ok: if self.parent.serial_port.xonxoff: self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("XON/XOFF")) elif self.parent.serial_port.rtscts: self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("RTS/CTS")) else: self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("None")) else: self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("None")) self.flowcontrol_combobox.setDisabled(True) self.nickname_lineedit = QLineEdit() if self.settings_parser.has_option('default', 'nickname'): nickname = self.settings_parser.get('default', 'nickname') if type(nickname) == str: nickname = nickname.decode('utf-8') self.nickname_lineedit.setText( self.settings_parser.get('default', 'nickname')) else: if self.parent.nickname is None: self.nickname_lineedit.setText("Guest_" + MD5.new( str(datetime.datetime.now())).digest().encode('hex')[:5]) else: self.nickname_lineedit.setText(self.parent.nickname) self.save_folder_editline = QLineEdit(self.parent.default_save_folder) self.save_folder_editline.editingFinished.connect( self.check_if_folder_exists) if self.settings_parser.has_option('default', 'default_save_folder'): folder = self.settings_parser.get('default', 'default_save_folder') if type(folder) == str: folder = folder.decode('utf-8') self.save_folder_editline.setText(folder) self.check_if_folder_exists() self.dir_browser_button = QPushButton() self.dir_browser_button.setIcon(QIcon(icons_folder + 'folder.png')) self.dir_browser_button.clicked.connect(self.choose_save_dir) self.horizontal_box_hboxlayout = QHBoxLayout() self.horizontal_box_hboxlayout.addWidget(self.save_folder_editline) self.horizontal_box_hboxlayout.addWidget(self.dir_browser_button) self.horizontal_box_container_widget = QWidget() self.horizontal_box_container_widget.setLayout( self.horizontal_box_hboxlayout) self.enable_ACP127 = QCheckBox() self.enable_ACP127.stateChanged.connect( self.enable_functionality_ACP127) if self.parent.acp127: self.enable_ACP127.setChecked(True) self.encryption_password_lineedit = QLineEdit() self.enable_encryption_checkbox = QCheckBox() self.enable_encryption_checkbox.stateChanged.connect( self.enable_functionality_encryption) if self.parent.isEncryptionEnabled: self.enable_encryption_checkbox.setChecked(True) self.encryption_password_lineedit.setEchoMode( QLineEdit.EchoMode.PasswordEchoOnEdit) if self.parent.encryption_key is not None: self.encryption_password_lineedit.setText( self.parent.encryption_key) if self.enable_encryption_checkbox.isChecked(): self.encryption_password_lineedit.setDisabled(False) else: self.encryption_password_lineedit.setDisabled(True) self.grid_form_layout = QFormLayout() self.grid_form_layout.addRow(FORMLAYOUT_SERIAL_TITLE + ":", self.serial_dropdown) self.grid_form_layout.addRow(FORMLAYOUT_PROFILE_TITLE + ":", self.profiles_combobox) self.grid_form_layout.addRow(FORMLAYOUT_CUSTOM_SERIAL_SETTINGS_TITLE, self.custom_settings_checkbox) self.grid_form_layout.addRow(FORMLAYOUT_INTERVAL_TIME_TITLE + ":", self.interval_time_lineedit) self.grid_form_layout.addRow(FORMLAYOUT_SERIAL_SPEED_TITLE + "(baud):", self.serial_speed_combobox) self.grid_form_layout.addRow(FORMLAYOUT_DATA_BITS_TITLE + ":", self.databits_combobox) self.grid_form_layout.addRow(FORMLAYOUT_STOP_BITS_TITLE + ":", self.stopbits_combobox) self.grid_form_layout.addRow(FORMLAYOUT_PARITY_TITLE + ":", self.parity_combobox) self.grid_form_layout.addRow(FORMLAYOUT_FLOWCONTROL_TITLE + ":", self.flowcontrol_combobox) self.grid_form_layout.addRow( FORMLAYOUT_ENABLE_ACP127_TITLE + " ACP-127", self.enable_ACP127) self.grid_form_layout.addRow(FORMLAYOUT_ENABLE_ENCRYPTION_TITLE, self.enable_encryption_checkbox) self.grid_form_layout.addRow(FORMLAYOUT_ENCRYPTION_KEY_TITLE, self.encryption_password_lineedit) self.grid_form_layout.addRow(FORMLAYOUT_NICKNAME_TITLE + ":", self.nickname_lineedit) self.grid_form_layout.addRow(FORMLAYOUT_SAVE_FOLDER_FILE_TITLE + ":", self.horizontal_box_container_widget) self.grid_form_layout.addRow("", self.button_box_dialog) self.setLayout(self.grid_form_layout) self.show() def enable_functionality_encryption(self): if self.enable_encryption_checkbox.isChecked(): self.encryption_password_lineedit.setDisabled(False) else: self.encryption_password_lineedit.setDisabled(True) def check_if_folder_exists(self): if not os.path.isdir(self.save_folder_editline.text()): msgBox = QMessageBox(icon=QMessageBox.Warning, text=ERROR_NO_DIR_MESSAGE) msgBox.setWindowTitle(ERROR_NO_DIR_TITLE) msgBox.exec_() self.save_folder_editline.setText(self.parent.default_save_folder) def check_if_digit(self): try: int(self.interval_time_lineedit.text()) except: msgBox = QMessageBox(icon=QMessageBox.Warning, text=ERROR_NO_INT_MESSAGE) msgBox.setWindowTitle(ERROR_NO_INT_TITLE) msgBox.exec_() self.interval_time_lineedit.setText(str(self.parent.interval_time)) def choose_save_dir(self): fname = QFileDialog(self, FILEBROWSER_SAVE_FOLDER_TITLE) fname.setFileMode(QFileDialog.Directory) looking_label = QFileDialog.DialogLabel(QFileDialog.LookIn) filename_label = QFileDialog.DialogLabel(QFileDialog.FileName) filetype_label = QFileDialog.DialogLabel(QFileDialog.FileType) fname.setLabelText(looking_label, FILEBROWSER_SAVE_FOLDER_LOOKIN) fname.setLabelText(filename_label, FILEBROWSER_SAVE_FOLDER_FOLDERNAME) fname.setLabelText(filetype_label, FILEBROWSER_SAVE_FOLDER_FOLDERTYPE) fname.setOption(QFileDialog.ShowDirsOnly) if fname.exec_(): filename = fname.selectedFiles()[0] self.save_folder_editline.setText(filename) def enable_functionality_ACP127(self): if self.enable_ACP127.isChecked(): self.parent.acp127 = True else: self.parent.acp127 = False def apply_setting_changes(self): res = None self.parent.custom_settings_enable_disable = self.custom_settings_checkbox.isChecked( ) self.parent.choosen_profile = self.profiles_combobox.currentText() if self.parent.custom_settings_enable_disable: self.parent.choosen_profile = "Custom" if self.enable_encryption_checkbox.isChecked(): self.parent.isEncryptionEnabled = True self.parent.encryption_key = self.encryption_password_lineedit.text( ) else: self.parent.isEncryptionEnabled = False self.parent.encryption_key = None if self.nickname_lineedit.text() != "": nick = self.nickname_lineedit.text().rstrip() nick = nick.replace(" ", "_") self.parent.nickname = nick if self.save_folder_editline.text() != "": if os.path.isdir(self.save_folder_editline.text()): self.parent.default_save_folder = self.save_folder_editline.text( ) self.parent.interval_time = int(self.interval_time_lineedit.text()) if self.flowcontrol_combobox.currentText() == "XON/XOFF": x_control = True else: x_control = False if self.flowcontrol_combobox.currentText() == "RTS/CTS": r_control = True else: r_control = False if self.parent.receive is None: res = self.lib.set_serial( port=self.serial_dropdown.currentText(), baudrate=self.serial_speed_combobox.currentText(), bytesize=self.databits_combobox.currentText(), stopbits=self.stopbits_combobox.currentText(), parity=self.parity_combobox.currentText(), xonxoff=x_control, rtscts=r_control) else: self.parent.receive.loop_run = False self.parent.receive.wait() self.parent.receive = None res = self.lib.set_serial( port=self.serial_dropdown.currentText(), baudrate=self.serial_speed_combobox.currentText(), bytesize=self.databits_combobox.currentText(), stopbits=self.stopbits_combobox.currentText(), parity=self.parity_combobox.currentText(), xonxoff=x_control, rtscts=r_control) if type(res) == OSError: self.parent.status_bar_widget.showMessage(str(res), 5000) msgBox = QMessageBox(icon=QMessageBox.Critical, text=str(res)) msgBox.setWindowTitle(ERROR_INTERFACE_TITLE) msgBox.exec_() if type(res) is not None and type(res) != OSError: self.parent.serial_port = res self.parent.start_threads() self.parent.status_bar_widget.showMessage( MSG_SERIAL_INT_STARTED % self.parent.serial_port.port) def change_custom_settings_on_profile(self): if self.profiles_combobox.currentText() != 'None': section = self.profiles_combobox.currentText() self.interval_time_lineedit.setText( self.config_parser.get(section, "interval")) self.serial_speed_combobox.setCurrentIndex( self.serial_speed_combobox.findText( self.config_parser.get(section, "serialspeed"))) self.databits_combobox.setCurrentIndex( self.databits_combobox.findText( self.config_parser.get(section, "bytesize"))) self.stopbits_combobox.setCurrentIndex( self.stopbits_combobox.findText( self.config_parser.get(section, "stopbits"))) self.parity_combobox.setCurrentIndex( self.parity_combobox.findText( self.config_parser.get(section, "parity"))) if self.config_parser.get(section, "xonxoff") == 'True': self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("XON/XOFF")) elif self.config_parser.get(section, "rtscts") == 'True': self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("RTS/CTS")) else: self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText("None")) if self.config_parser.get(section, "acp127") == "True": self.enable_ACP127.setChecked(True) else: self.enable_ACP127.setChecked(False) elif self.profiles_combobox.currentText() == "None": self.serial_speed_combobox.setCurrentIndex( self.serial_speed_combobox.findText('9600')) self.interval_time_lineedit.setText(str(self.parent.intervaltime)) self.databits_combobox.setCurrentIndex( self.databits_combobox.findText('8')) self.stopbits_combobox.setCurrentIndex( self.stopbits_combobox.findText('1')) self.parity_combobox.setCurrentIndex( self.parity_combobox.findText('None')) self.flowcontrol_combobox.setCurrentIndex( self.flowcontrol_combobox.findText('None')) self.enable_ACP127.setChecked(False) def custom_settings_enable_disable(self): if self.custom_settings_checkbox.isChecked(): self.interval_time_lineedit.setDisabled(False) self.serial_speed_combobox.setDisabled(False) self.databits_combobox.setDisabled(False) self.stopbits_combobox.setDisabled(False) self.parity_combobox.setDisabled(False) self.flowcontrol_combobox.setDisabled(False) else: self.interval_time_lineedit.setDisabled(True) self.serial_speed_combobox.setDisabled(True) self.databits_combobox.setDisabled(True) self.stopbits_combobox.setDisabled(True) self.parity_combobox.setDisabled(True) self.flowcontrol_combobox.setDisabled(True)
class ExportOrthoWin(QDialog ): #новый класс как приложение с интерфейсом и кодом def __init__(self, parent): #_____________Пременные уровня класса___________ self.OUT_dir = '' #выходная дирректория self.orthoBounds = [] # ВЫХОДНАЯ ПРОЕКЦИЯ по умолчанию #out_crs='PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' self.out_crs = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) #out_crs=PhotoScan.CoordinateSystem('PROJCS["WGS 84 / UTM zone 38N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",45],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32638"]]') self.crsShapes = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) self.DATA_OK = 0 #print ('orthoBounds=',len(self.orthoBounds)) #формат массива:0-имя ортофото, 1-Xmin, 2-Ymin, 3-sizeX, 4-sizeY, 5-ID полигона #__________________________________________________ QDialog.__init__(self, parent) self.setWindowTitle("Экспорт Орто по разграфке") #Заголвок окна self.resize(500, 250) #размер окна self.txt_comment = QLabel( " Модуль экспортирует ортофото и DEM из фотоскана по нарезке. \ Нарезка в текстовом файле: название листа, координаты нижнего левого угла, размеры. \n Проекция нарезки должна совпадать с проекцией выходного ортофотоплана.\ Листы делятся по нарезке, а внутри нарезки по блокам, размеры задаются. ФОРМАТ JPG \n При импорте SHP должно быть текстовое поле NAME \n \ Адрес сервера: " + ServerIP + " меняем в теле программы. Ваша версия фотоскана: " + PH_version + " \n") self.txt_comment.setWordWrap(True) self.now_prj = QLabel(str(self.out_crs)) self.select_prj = QPushButton("Выберете проекцию") #(" открыть ") self.select_prj.setFixedSize(170, 26) self.TXT_dif_pix = QLabel("<B>Размер пикселя: </B>") self.TXT_dif_pix.setFixedSize(170, 26) self.dif_pix = QLineEdit() self.dif_pix.setText('0.1') # Задает размер пикселя по умолчанию self.dif_pix.setFixedSize(100, 26) items_bloksize = ('5000', '8192', '10000', '15000', '20000', '25000', '29999', 'Full') # список с размерами тайлов #items_bloksize = {5000:5000, 8192:8192, 10000:10000, 15000:15000, 20000:20000, 25000:25000, 29999:29999} self.TXT_block_size = QLabel("<B>Размер блока: </B>", ) self.TXT_block_size.setFixedSize(170, 26) self.block_size = QComboBox() self.block_size.setFixedSize(100, 26) self.block_size.addItems(items_bloksize) self.block_size.setCurrentIndex( 1) #Устанавливает по умолчанию второе значение из списка - 8192 self.TXT_SHPname = QLabel("Файл разграфки SHP (NAME,poligons)") self.SHPname = QPushButton( "Выберете файл разграфки SHP") #(" открыть ") self.SHPname.setFixedSize(170, 26) self.TXT_filename = QLabel( "Файл разграфки TXT(имя; X0; Y0; sizeX; SizeY)") self.filename = QPushButton("Выберете Файл разграфки") #(" открыть ") self.filename.setFixedSize(170, 26) self.TXT_CheckOrthoDem = QLabel("Вид выходной продукции") self.TXT_CheckOrthoDem.setFixedSize(170, 26) self.CheckOrtho_Radio = QRadioButton("Ортофото") self.CheckOrtho_Radio.setChecked(True) self.CheckDem_Radio = QRadioButton("ДЕМ") self.TXT_OUTFOLDER = QLabel("Выходная дирректория") self.OUTFOLDER = QPushButton("Выберете дирректорию") #(" открыть ") self.OUTFOLDER.setFixedSize(170, 26) items_format = ( 'JPG', 'TIF' ) # список форматов, ПРИ выборе ДЕМ будет выбран второй формат - внимательно при изменении списка!!! self.file_format = QComboBox() self.file_format.setFixedSize(50, 26) self.file_format.addItems(items_format) self.file_format.setCurrentIndex( 0) #Устанавливает по умолчанию первое значение self.TXT_checkExportOrtho = QLabel("Построить ортофото:") # Ортофото self.TXT_checkExportOrtho.setFixedSize(170, 26) self.checkExportOrtho = QCheckBox() self.checkExportOrtho.setChecked(False) self.GoGo = QPushButton("Экспорт локально") #(" Экспорт локально ") self.GoGo.setFixedSize(170, 26) self.GoGo.setDisabled(True) self.GoGoNet = QPushButton("Экспорт по сети") #(" Экспорт по сети ") self.GoGoNet.setFixedSize(170, 26) self.GoGoNet.setDisabled(True) hbox0 = QHBoxLayout() hbox0.addWidget(self.txt_comment, alignment=0) hbox1 = QHBoxLayout() hbox1.addWidget(self.select_prj, alignment=0) hbox1.addWidget(self.now_prj, alignment=0) hbox2 = QHBoxLayout() hbox2.addWidget(self.TXT_block_size, alignment=1) hbox2.addWidget(self.block_size, alignment=1) hbox3 = QHBoxLayout() hbox3.addWidget(self.TXT_dif_pix, alignment=1) hbox3.addWidget(self.dif_pix, alignment=1) hbox4 = QHBoxLayout() #hbox4.addStretch(1) hbox4.addWidget(self.SHPname, alignment=0) hbox4.addWidget(self.TXT_SHPname, alignment=0) hbox5 = QHBoxLayout() #hbox5.addStretch(1) hbox5.addWidget(self.filename, alignment=0) hbox5.addWidget(self.TXT_filename, alignment=0) hbox51 = QHBoxLayout() hbox51.addWidget(self.TXT_CheckOrthoDem, alignment=0) hbox51.addWidget(self.CheckOrtho_Radio, alignment=0) hbox51.addWidget(self.CheckDem_Radio, alignment=0) hbox6 = QHBoxLayout() #hbox5.addStretch(1) hbox6.addWidget(self.OUTFOLDER, alignment=0) hbox6.addWidget(self.TXT_OUTFOLDER, alignment=0) hbox6.addWidget(self.file_format, alignment=0) hbox7 = QHBoxLayout() #build ortho hbox7.addWidget(self.TXT_checkExportOrtho, alignment=0) hbox7.addWidget(self.checkExportOrtho, alignment=0) hbox8 = QHBoxLayout() hbox8.addWidget(self.GoGo, stretch=0, alignment=0) hbox8.addWidget(self.GoGoNet, stretch=0, alignment=0) vbox = QVBoxLayout() #Определяем вбокс и забиваем его Нбоксами #vbox.addStretch(1) vbox.addLayout(hbox0) vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) vbox.addLayout(hbox4) vbox.addLayout(hbox5) vbox.addLayout(hbox51) #выбор, что строить орто или дем vbox.addLayout(hbox6) #Функция построения ортофото спрятана, поскольку работает не стабильно и построение ортофото для каждого листа в сумме занимает очень много времени, #гораздо больше, чем один раз построить ортофото для всех #vbox.addLayout(hbox7) #build ortho vbox.addLayout(hbox8) self.setLayout(vbox) self.select_prj.clicked.connect(self.set_projection) self.SHPname.clicked.connect(self.input_razgr_SHPname) self.filename.clicked.connect(self.input_razgr_name) self.OUTFOLDER.clicked.connect(self.input_out_dir) self.GoGo.clicked.connect(self.ortho_local) self.GoGoNet.clicked.connect(self.ortho_net) #Организация блокировки интерфейса для радио кнопок self.CheckOrtho_Radio.clicked.connect(self.CheckOrtho_Radio_DO) self.CheckDem_Radio.clicked.connect(self.CheckDem_Radio_DO) #____________ self.checkExportOrtho.clicked.connect( self.PrintChkStat) #Функция для проверки работы чека #self.WindowContextHelpButtonHint.clicked.connect(self.prog_hint) #self.WindowTitleHint.clicked.connect(self.prog_hint) self.exec() #____________________________________________________________________________ def PrintChkStat( self ): #Эта функция работает в принте с подстановкой и получение значения чека if self.checkExportOrtho.isChecked() == True: stat = 'ДА' else: stat = 'НЕТ' print('Строить орто %s здесь' % stat) def CheckOrtho_Radio_DO( self): #Если выбран Ортоф - формат Джипег и свободен!!! print("Орто") self.file_format.setCurrentIndex(0) self.file_format.setDisabled(False) def CheckDem_Radio_DO( self): #Если выбран ДЕМ - формат тифф и блокируется!!! print("DEM") self.file_format.setCurrentIndex(1) self.file_format.setDisabled(True) def ortho_local(self): self.export_ortho('local') def ortho_net(self): self.export_ortho('net') def prog_hint(self): print("OK") def unlock_export(self, sel): #Переменная нужна для разблокирования кнопки Экспорт. Два критических параметра:Файл разграфки и выходная дирректория, каждый добавляет по еденице. #Sel=5 блокирует кнопки при запуске сетевой обработки ''' DATA_OK логика работы: Для экспорта нужно задать выходную директорию и файл разграфки, текстовый или векторный при запуске сетевой обработки кнопки опять блокируются DATA_OK меняет только эта процедура!!! 0-ничего не задано экспорт заблокирован 1-выбран файл разграфки проверяем выбран ли путь, да, разблокируем 3 2-выбран путь проверяем выбран ли файл разграфки, да, разблокируем 3 ''' if sel == 5 and self.DATA_OK == 1: self.DATA_OK = 0 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if sel == 5 and self.DATA_OK == 2: self.DATA_OK = 2 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if sel == 5 and self.DATA_OK == 3: self.DATA_OK = 2 self.GoGo.setDisabled(True) self.GoGoNet.setDisabled(True) if self.DATA_OK == 1 and sel == 2: self.DATA_OK = 3 if self.DATA_OK == 2 and sel == 1: self.DATA_OK = 3 if self.DATA_OK == 0 and sel != 5: self.DATA_OK = sel if self.DATA_OK == 3 and sel != 5: self.GoGo.setDisabled(False) self.GoGoNet.setDisabled(False) print('unlock') print(sel, self.DATA_OK) def OrthoBoundCalc(self, Xn, Yn, XS, YS): # изменить под сетевую обработку с тайлами DifPix = float(self.dif_pix.text()) ''' Округление начала Если надо Xnround=floor(Xn/DifPix)*DifPix # Ynround=floor(Yn/DifPix)*DifPix ''' ''' if self.block_size.currentText()=='Full' or CommandStack==5 : #Экспорт целикового фрагмента print('границы целиковые') Xnround=Xn Ynround=Yn-DifPix XSround=ceil(XS/DifPix+1)*DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround=ceil(YS/DifPix+1)*DifPix XSround=Xnround+XSround YSround=Ynround+YSround elif CommandStack==1 and self.block_size.currentText()!='Full': # Экспорт по тайлам print("Границы со сдвигом") BlockSize=float(self.block_size.currentText()) Xnround=Xn Ynround=Yn #-DifPix XSround=ceil(XS/DifPix+1)*DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround=ceil(YS/DifPix+1)*DifPix YBlockSize=BlockSize*DifPix TileShift=YBlockSize-YSround Ynround=Ynround+TileShift XSround=Xnround+XSround YSround=Ynround+YSround+TileShift else: Print("Bound version error, OrthoBoundCalc") pass ''' Xnround = Xn Ynround = Yn - DifPix XSround = ceil( XS / DifPix + 1 ) * DifPix #Границы округляем в большую сторону и расширяем на пиксель YSround = ceil(YS / DifPix + 1) * DifPix XSround = Xnround + XSround YSround = Ynround + YSround point = [ ] #"Эта конструкция нужна для поиска максимальных координат квадрата при переходе из системы в систему print("точки") point.append(PhotoScan.Vector((Xnround, Ynround))) point.append(PhotoScan.Vector((Xnround, YSround))) point.append(PhotoScan.Vector((XSround, YSround))) point.append(PhotoScan.Vector((XSround, Ynround))) print("точки2") point_trans = [] point_trans.append( PhotoScan.CoordinateSystem.transform(point[0], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[1], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[2], self.crsShapes, self.out_crs)) point_trans.append( PhotoScan.CoordinateSystem.transform(point[3], self.crsShapes, self.out_crs)) x = [] y = [] for i in range(4): print(i) x.append(point_trans[i][0]) y.append(point_trans[i][1]) xMin = min(x) yMin = min(y) xMax = max(x) yMax = max(y) #OrthoBound=(Xnround,Ynround,XSround,YSround) OrthoBound = (Xnround, Ynround, XSround, YSround) print(OrthoBound) OrthoBound = (xMin, yMin, xMax, yMax) print(OrthoBound) return OrthoBound def input_razgr_SHPname(self): #global listShapes SHPname = '' #Векторный файл разграфки DataDir = os.path.dirname( __file__) # Дирректория по умолчанию - дирректория скрипта!! shpfilename = QFileDialog.getOpenFileName( self, 'выберете векторный файл разграфки', DataDir, filter='*.shp') #Координаты в выходной проекции #проверка на пустоту if not shpfilename[0] == '': SHP_name = shpfilename[0] else: return sname = os.path.basename(SHP_name) file_sname = os.path.splitext(sname)[0] print('Путь до шейпа: ', SHP_name) print('Имя шейпа: ', file_sname) chunk.importShapes(SHP_name, True) # Импорт шейпфайла с заменой shapes = chunk.shapes #Сделать проверку на ИМЯ ПОЛИГОНА #shapes=PhotoScan.app.document.chunk.shapes listShapes = shapes.items() #Массив (список) шейпов в проекте self.crsShapes = shapes.crs #Проекция шейпа print(self.crsShapes) PhotoScan.app.messageBox('Импортированы объекты: ' + str(shapes) + '\n Старые объекты удалены') #Получили список векторных объектов, загруженных в проект, теперь проходим по каждому объекту и определяем его минимум и максимум по коориднатам if len(listShapes) != 0: poligon_ID = 0 self.orthoBounds = [] for shape in listShapes: # ЗДЕСЬ определяются координаты минимум и максимум в текущей проекции в другой все по другому - Могут быть дыры # в OrthoBoundCalc стоит заглушка - имщет максимальные коориднаты углов прямоугольника после перепроецирования - можно но не совсем корректно x = [] y = [] vertices = shape.vertices for vertex in vertices: x.append(vertex[0]) y.append(vertex[1]) # Если есть NAME - это будет имя, если нет - имя шейпа и номер фичи if str(shape.label) == '': poligonName = str(file_sname) + '_' + str(poligon_ID) else: poligonName = str(shape.label) xMin = min(x) yMin = min(y) xSize = max(x) - min(x) ySize = max(y) - min(y) element = [poligonName, xMin, yMin, xSize, ySize, poligon_ID] self.orthoBounds.append( element) #ЭТО МАССИВ с ГРАНИЦАМИ ОРТОФОТО #формат массива:0-имя ортофото, 1-Xmin, 2-Ymin, 3-sizeX, 4-sizeY poligon_ID += 1 #Увеличение на единицу print(len(self.orthoBounds), poligon_ID) if len(self.orthoBounds) != 0: self.unlock_export(1) self.TXT_SHPname.setText(str(sname)) self.TXT_filename.setText( "Файл разграфки TXT(имя; X0; Y0; sizeX; SizeY)") else: PhotoScan.app.messageBox('Пустой SHP файл') self.unlock_export(5) print('orthoBounds=', len(self.orthoBounds)) # Шейп засосали, минимум максимум нашли, с обрезкой дальше разберемся #_____________________________________________________________________________ def input_razgr_name(self): TXT_name = '' #имя файла с разграфкой # КООРДИАНТЫ ДОЛЖНЫ БЫТЬ В ВЫХОДНОЙ ПРОЕКЦИИ!!!!! DataDir = os.path.dirname( __file__) # Дирректория по умолчанию - дирректория скрипта!! textfilename = QFileDialog.getOpenFileName( self, 'выберете файл разграфки', DataDir, filter='*.txt') #Координаты в выходной проекции #проверка текстфайлнайм на пустоту if not textfilename[0] == '': with open(textfilename[0]) as f: for line in f: znach = line.split(";") try: if not (isinstance(znach[0], str)): PhotoScan.app.messageBox('Неверный форматS') self.unlock_export(5) return if not (isinstance(float(znach[1]), (float, int))): PhotoScan.app.messageBox('Неверный формат1i') self.unlock_export(5) return if not (isinstance(float(znach[2]), (float, int))): PhotoScan.app.messageBox('Неверный формат2i') self.unlock_export(5) return if not (isinstance(float(znach[3]), (float, int))): PhotoScan.app.messageBox('Неверный формат3i') self.unlock_export(5) return if not (isinstance(float(znach[4]), (float, int))): PhotoScan.app.messageBox('Неверный формат4i') self.unlock_export(5) return except: PhotoScan.app.messageBox('Неверный формат_;') self.unlock_export(5) return else: return if not (textfilename[0] == ''): #Если все нормально заполняем orthoBounds TXT_name = textfilename self.orthoBounds = [] with open(TXT_name[0]) as f: count = 0 for line in f: znach = line.split(";") element = [ znach[0], znach[1], znach[2], znach[3], znach[4], count ] self.orthoBounds.append( element) #ЭТО МАССИВ с ГРАНИЦАМИ ОРТОФОТО count += 1 print('orthoBounds=', len(self.orthoBounds)) self.unlock_export( 1) #разблокирует экспорт, если заданы разграфка и дирректория self.TXT_filename.setText(str(TXT_name[0])) self.TXT_SHPname.setText("Файл разграфки SHP (NAME,poligons)") def set_projection(self): self.out_crs = PhotoScan.app.getCoordinateSystem( 'Система координат', self.out_crs) #Специальная форма для задания системы координат self.now_prj.setText(str(self.out_crs)) def input_out_dir(self): DataDir = os.path.dirname(__file__) outputdir = QFileDialog.getExistingDirectory(self, 'выберете дирректорию', DataDir) if not outputdir == '': self.OUT_dir = outputdir self.TXT_OUTFOLDER.setText(str(self.OUT_dir)) self.unlock_export( 2) #разблокирует экспорт, если заданы разграфка и дирректория else: return print('orthoBounds=', len(self.orthoBounds)) def export_ortho( self, proc_type ): # универсальная процедура экспорта для локлаьной и для сетевой обработки #global chunk ''' ЭТО ПРОВЕРКА ДЛЯ ПОСТРОЕНИЯ ОРТО ПЕРЕД РАБОТОЙ В ТЕКУЩЕЙ ВЕРСИИ ФУНКЦИЯ ОТКЛЮЧЕНА!! if self.checkExportOrtho.isChecked()==True: statOrthoBuild=True else: statOrthoBuild=False # 000000 Проверка на наличие ортофото или дем перед работой if (doc.chunk.orthomosaic==None and statOrthoBuild==False): PhotoScan.app.messageBox('Нет орто!!') return elif (doc.chunk.elevation==None and statOrthoBuild==True): PhotoScan.app.messageBox('Нет ДЕМ!!') return ''' #Определение вида экспорта - орто или дем if self.CheckOrtho_Radio.isChecked() == True: ExportType = 'ORTHO' elif self.CheckDem_Radio.isChecked() == True: ExportType = 'DEM' else: AssertionError("Какой процесс экспорта?") #ПРОВЕРКИ НАЛИЧИЯ ДЕМ И ОРТО if (doc.chunk.orthomosaic == None and ExportType == 'ORTHO'): PhotoScan.app.messageBox('Нет орто!!') return elif (doc.chunk.elevation == None and ExportType == 'DEM'): PhotoScan.app.messageBox('Нет ДЕМ!!') return file_format = self.file_format.currentText() print('orthoBounds=', len(self.orthoBounds)) task = [] #Это СПИСОК тасков DifPix = float(self.dif_pix.text()) if self.block_size.currentText() == 'Full': BlockSize = 0 else: BlockSize = int(self.block_size.currentText()) # Цикл для запуска ортофото локально или для забивания стека на сеть из массива try: for cu_string in self.orthoBounds: OName = cu_string[0] XMLeft = float(cu_string[1]) YMDown = float(cu_string[2]) sizeXM = float(cu_string[3]) sizeYM = float(cu_string[4]) shapeNumber = int(cu_string[5]) cu_Region = self.OrthoBoundCalc( XMLeft, YMDown, sizeXM, sizeYM ) #Функция вычисления границ # изменить под сетевую обработку с тайлами if file_format == 'JPG' and ExportType == 'ORTHO': fileoutname = self.OUT_dir + "\\ortho_" + OName + ".jpg" elif file_format == 'TIF' and ExportType == 'ORTHO': fileoutname = self.OUT_dir + "\\ortho_" + OName + ".tif" elif file_format == 'TIF' and ExportType == 'DEM': fileoutname = self.OUT_dir + "\\dem_" + OName + ".tif" else: print("Формат файла?") if proc_type == 'local': #КОММАНДЫ для локальной обработки print('Обработка локально') ''' ПОСТРОЕНИЕ ОРТОФОТО В ЭТОЙ ВЕРСИИ ОТКЛЮЧЕНО if statOrthoBuild==True: #chunk.buildOrthomosaic(surface=PhotoScan.ElevationData, blending=PhotoScan.MosaicBlending, color_correction=False, projection=self.out_crs, region=cu_Region,dx=DifPix, dy=DifPix) chunk.buildOrthomosaic(surface=PhotoScan.ElevationData, blending=PhotoScan.MosaicBlending, projection=self.out_crs, region=cu_Region,dx=DifPix, dy=DifPix) ''' if CommandStack == 1 and ExportType == 'ORTHO': if file_format == 'JPG': chunk.exportOrthomosaic(fileoutname, format="jpg", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True) elif file_format == 'TIF': chunk.exportOrthomosaic(fileoutname, format="tif", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression="jpeg", tiff_big=False) #сжатие LZW #elif file_format=='TIF': chunk.exportOrthomosaic(fileoutname, format="tif", region=cu_Region, projection=self.out_crs,dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression="lzw", tiff_big=False) else: print("Формат файла?") elif CommandStack == 5 and ExportType == 'ORTHO': if file_format == 'JPG': chunk.exportOrthomosaic( fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatJPEG, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True) elif file_format == 'TIF': chunk.exportOrthomosaic( fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression=PhotoScan.TiffCompressionJPEG, tiff_big=False) #сжатие LZW #elif file_format=='TIF': chunk.exportOrthomosaic(fileoutname, PhotoScan.RasterFormatTiles,PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs,dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_compression=PhotoScan.TiffCompressionLZW, tiff_big=False) else: print("Формат файла?") elif CommandStack == 1 and ExportType == 'DEM': print("Экспорт ДЕМ локально") if file_format == 'TIF': chunk.exportDem(fileoutname, format="tif", projection=self.out_crs, region=cu_Region, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_big=False) elif CommandStack == 5 and ExportType == 'DEM': print("Экспорт ДЕМ локально") if file_format == 'TIF': chunk.exportDem(fileoutname, PhotoScan.RasterFormatTiles, PhotoScan.ImageFormatTIFF, region=cu_Region, projection=self.out_crs, dx=DifPix, dy=DifPix, blockw=BlockSize, blockh=BlockSize, write_kml=False, write_world=True, tiff_big=False) elif proc_type == 'net': print('Обработка по сети') ''' ПОСТРОЕНИЕ ОРТОФОТО В ЭТОЙ ВЕРСИИ ОТКЛЮЧЕНО #Построить ортофото if statOrthoBuild==True: workBuild = PhotoScan.NetworkTask() # СОздаем ворк и забиваем его параметрами #Версионность if CommandStack==1: workBuild.params['ortho_surface'] = 0 workBuild.params['resolution_x'] = DifPix workBuild.params['resolution_y'] = DifPix elif CommandStack==5: workBuild.params['ortho_surface'] = 4 workBuild.params['resolution'] = DifPix else: return workBuild.name = "BuildOrthomosaic" workBuild.frames.append((chunk.key,0)) workBuild.params['network_distribute'] = True task.append(workBuild) #Добавляем задачу построения в таск ''' #Экспортировать ортофото workExport = PhotoScan.NetworkTask( ) # СОздаем ворк и забиваем его параметрами #ВЕРСИОННОСТЬ if CommandStack == 1 and ExportType == 'ORTHO': workExport.name = "ExportOrthomosaic" workExport.params['resolution_x'] = DifPix workExport.params['resolution_y'] = DifPix if file_format == 'JPG': workExport.params['raster_format'] = 2 elif file_format == 'TIF': workExport.params['raster_format'] = 1 else: print("Формат файла?") elif CommandStack == 5 and ExportType == 'ORTHO': workExport.name = "ExportRaster" workExport.params['resolution'] = DifPix if file_format == 'JPG': workExport.params['image_format'] = 1 elif file_format == 'TIF': workExport.params[ 'image_format'] = 2 #Значение на шару!!! ПРОВЕРИТЬ else: print("Формат файла?") elif CommandStack == 1 and ExportType == 'DEM': print("Экспорт ДЕМ по сети") workExport.name = "ExportDem" workExport.params['resolution_x'] = DifPix workExport.params['resolution_y'] = DifPix elif CommandStack == 5 and ExportType == 'DEM': #НЕ ОТЛАЖЕНО ПАРАМЕТРЫ НА ШАРУ print("Экспорт ДЕМ по сети") workExport.name = "ExportOrthomosaic" workExport.params['resolution'] = DifPix pass else: return workExport.frames.append((chunk.key, 0)) workExport.params['write_world'] = 1 if self.block_size.currentText( ) == 'Full': # Условие на запись тайлов workExport.params['write_tiles'] = 0 else: workExport.params['write_tiles'] = 1 workExport.params['tile_width'] = BlockSize workExport.params['tile_height'] = BlockSize workExport.params[ 'path'] = fileoutname #выходная дирректория с именем файла workExport.params['region'] = cu_Region # ВНИМАНИЕ! По сети нельзя экспортировать в пользовательской проекции ИЛИ проекция должна быть НА ВСЕХ НОДАХ workExport.params[ 'projection'] = self.out_crs.authority #Из объекта проекция берется только ее номер EPSG::32637 #ВНИМАНИЕ ЭКСПОРТ ОТКЛЮЧЕН!!!! task.append(workExport) #Добавляем задачу в таск else: print('Пока не задано') PhotoScan.app.messageBox('Обработка закончена') except Exception as e: print(e) PhotoScan.app.messageBox('Что-то пошло не так ((') return #break #Запуск сетевого стека, таска в обработку if proc_type == 'net': print(ProjectLocalPath_auto) print(ProjectPath) client.connect(ServerIP) batch_id = client.createBatch(ProjectPath, task) if batch_id == None: #Проверка наличия проекта в сети PhotoScan.app.messageBox( '<B>Этот проект уже запущен в обработку!!!<B>') self.unlock_export(5) else: print('Проект работает под номером ', batch_id) client.resumeBatch(batch_id) self.unlock_export(5) PhotoScan.app.messageBox( 'Проект поставлен в очередь сетевой обработки') client.disconnect() pass
class LoginView(View): """`View` derived class. Defines the log in widget""" login = Signal((str, str, str, bool,)) def __init__(self, parent=None): """ Init method. Initializes parent classes :param parent: Reference to a `QWidget` object to be used as parent """ super(LoginView, self).__init__(parent) self.createWidgets() self.createLayouts() self.setFixedSize(250, 340) def createLayouts(self): """Put widgets into layouts, thus creating the widget""" mainLayout = QHBoxLayout() fieldsLayout = QVBoxLayout() ftpInfoLayout = QHBoxLayout() buttonLayout = QHBoxLayout() mainLayout.addStretch(20) fieldsLayout.addStretch(80) fieldsLayout.addWidget(self.linkLabel) fieldsLayout.addWidget(self.line) fieldsLayout.addStretch(20) ftpInfoLayout.addWidget(self.hostLabel, 50, Qt.AlignLeft) ftpInfoLayout.addStretch(20) ftpInfoLayout.addWidget(self.sslLabel, 20, Qt.AlignRight) ftpInfoLayout.addWidget(self.sslCheck, 10, Qt.AlignRight) fieldsLayout.addLayout(ftpInfoLayout) fieldsLayout.addWidget(self.hostEdit) fieldsLayout.addWidget(self.usernameLabel) fieldsLayout.addWidget(self.usernameEdit) fieldsLayout.addWidget(self.passwdLabel) fieldsLayout.addWidget(self.passwdEdit) fieldsLayout.addStretch(30) buttonLayout.addStretch(50) buttonLayout.addWidget(self.loginButton, 50, Qt.AlignRight) fieldsLayout.addLayout(buttonLayout) fieldsLayout.addStretch(20) mainLayout.addLayout(fieldsLayout, 30) mainLayout.addStretch(20) self.setLayout(mainLayout) def createWidgets(self): """Create children widgets needed by this view""" fieldsWidth = 200 labelsFont = View.labelsFont() editsFont = View.editsFont() self.setLogo() self.hostLabel = QLabel(self) self.hostEdit = QLineEdit(self) self.sslLabel = QLabel(self) self.sslCheck = QCheckBox(self) self.hostLabel.setText('FTP Location') self.hostLabel.setFont(labelsFont) self.hostEdit.setFixedWidth(fieldsWidth) self.hostEdit.setFont(editsFont) self.sslLabel.setText('SSL') self.sslLabel.setFont(labelsFont) self.usernameLabel = QLabel(self) self.usernameEdit = QLineEdit(self) self.usernameLabel.setText('Username') self.usernameLabel.setFont(labelsFont) self.usernameEdit.setFixedWidth(fieldsWidth) self.usernameEdit.setFont(editsFont) self.passwdLabel = QLabel(self) self.passwdEdit = QLineEdit(self) self.passwdLabel.setText('Password') self.passwdLabel.setFont(labelsFont) self.passwdEdit.setFixedWidth(fieldsWidth) self.passwdEdit.setEchoMode(QLineEdit.Password) self.passwdEdit.setFont(editsFont) self.passwdEdit.returnPressed.connect(self.onLoginClicked) self.loginButton = QPushButton(self) self.loginButton.setText('Login') self.loginButton.setFont(labelsFont) self.loginButton.setFixedWidth(fieldsWidth / 2) self.loginButton.clicked.connect(self.onLoginClicked) # Sets previously stored values into the fields, if any settings = get_settings() self.hostEdit.setText(settings.value(SettingsKeys['host'], '')) self.usernameEdit.setText(settings.value(SettingsKeys['username'], '')) self.passwdEdit.setText(crypt.decrypt(settings.value(SettingsKeys['passwd'], ''))) # Unicode to boolean conversion ssl = settings.value(SettingsKeys['ssl'], u'true') ssl = True if ssl == u'true' else False self.sslCheck.setChecked(ssl) @Slot() def onLoginClicked(self): """ Slot. Called on the user clicks on the `loginButton` button """ # Takes out the user input from the fields host = self.hostEdit.text() username = self.usernameEdit.text() passwd = self.passwdEdit.text() ssl = self.sslCheck.isChecked() print 'Logging in: %s, %s, %s' % (host, username, '*' * len(passwd)) if len(host) > 0: # If the fields are valid, store them using a `QSettings` object # and triggers a log in request settings = get_settings() settings.setValue(SettingsKeys['host'], host) settings.setValue(SettingsKeys['username'], username) settings.setValue(SettingsKeys['passwd'], crypt.encrypt(passwd)) settings.setValue(SettingsKeys['ssl'], ssl) self.setEnabled(False) self.login.emit(host.strip(), username, passwd, ssl) @Slot() def onFailedLogIn(self): """ Slot. Called when the log in request fails """ # Enables the fields again for user input self.setEnabled(True)
class SceneTab(QWidget): #FIXME I'm Ugly. """This widget is for changing the Scene propagation policies of the module. """ def __init__(self, parent, agent): """Construct the SceneTab with the given parent (TabDialog) and ModuleAgent. """ super(SceneTab, self).__init__(parent) self.agent = agent self.layout = QVBoxLayout() self.layout.setAlignment(Qt.AlignCenter) self.layout.addWidget(self.buildHighlightGroupBox()) self.layout.addItem(QSpacerItem(5, 5)) self.layout.addWidget(self.buildModuleGroupBox()) self.layout.addItem(QSpacerItem(5, 5)) self.layout.addWidget(self.buildAttributeGroupBox()) self.setLayout(self.layout) def buildHighlightGroupBox(self): """Layout/construct the highlight UI for this tab.""" groupBox = QGroupBox("Highlight Policy") layout = QVBoxLayout() # agent.propagate_highlights self.highlights_propagate = QCheckBox("Propagate highlights to " + "other modules.") self.highlights_propagate.setChecked(self.agent.propagate_highlights) self.highlights_propagate.stateChanged.connect( self.highlightsPropagateChanged) # We only allow this change if the parent does not propagate if self.agent.parent().propagate_highlights: self.highlights_propagate.setDisabled(True) # agent.apply_highlights self.applyHighlights = QCheckBox("Apply highlights from " + "other modules.") self.applyHighlights.setChecked(self.agent.apply_highlights) self.applyHighlights.stateChanged.connect(self.applyHighlightsChanged) layout.addWidget(self.applyHighlights) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.highlights_propagate) groupBox.setLayout(layout) return groupBox def highlightsPropagateChanged(self): """Called when highlight propagtion is changed to update the Agent. """ self.agent.propagate_highlights = self.highlights_propagate.isChecked() def applyHighlightsChanged(self): """Called when highlight application is changed to update the Agent. """ self.agent.apply_highlights = self.applyHighlights.isChecked() def buildModuleGroupBox(self): """Layout/construct the ModuleScene UI for this tab.""" groupBox = QGroupBox("Module Policy") layout = QVBoxLayout() # agent.propagate_module_scenes self.module_propagate = QCheckBox( "Propagate module scene information " + "to other modules.") self.module_propagate.setChecked(self.agent.propagate_module_scenes) self.module_propagate.stateChanged.connect(self.modulePropagateChanged) # We only allow this change if the parent does not propagate if self.agent.parent().propagate_module_scenes: self.module_propagate.setDisabled(True) # agent.apply_module_scenes self.module_applyScene = QCheckBox("Apply module scene information " + "from other modules.") self.module_applyScene.setChecked(self.agent.apply_module_scenes) self.module_applyScene.stateChanged.connect(self.moduleApplyChanged) layout.addWidget(self.module_applyScene) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.module_propagate) groupBox.setLayout(layout) return groupBox def modulePropagateChanged(self): """Called when ModuleScene propagtion is changed to update the Agent. """ self.agent.propagate_module_scenes = self.module_propagate.isChecked() def moduleApplyChanged(self): """Called when ModuleScene application is changed to update the Agent. """ self.agent.apply_module_scenes = self.module_applyScene.isChecked() def buildAttributeGroupBox(self): """Layout/construct the AttributeScene UI for this tab.""" groupBox = QGroupBox("Attribute Policy (Colors)") layout = QVBoxLayout() # agent.propagate_attribute_scenes self.attr_propagate = QCheckBox( "Propagate attribute scene " + "information (e.g. color maps) to other modules.") self.attr_propagate.setChecked(self.agent.propagate_attribute_scenes) self.attr_propagate.stateChanged.connect(self.attrPropagateChanged) # We only allow this change if the parent does not propagate if self.agent.parent().propagate_attribute_scenes: self.attr_propagate.setDisabled(True) # agent.apply_attribute_scenes self.attr_applyScene = QCheckBox("Apply attribute scene information " + "from other modules.") self.attr_applyScene.setChecked(self.agent.apply_attribute_scenes) self.attr_applyScene.stateChanged.connect(self.attrApplyChanged) layout.addWidget(self.attr_applyScene) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.attr_propagate) groupBox.setLayout(layout) return groupBox def attrPropagateChanged(self): """Called when AttributeScene propagtion is changed to update the Agent. """ self.agent.propagate_attribute_scenes = self.attr_propagate.isChecked() def attrApplyChanged(self): """Called when AttributeScene application is changed to update the Agent. """ self.agent.apply_attribute_scenes = self.attr_applyScene.isChecked()
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): settings = QSettings() self.sortRulesGroupBox = QGroupBox("Calculate &Sort As Rules") defaultSortAsRules = settings.value(Gconf.Key.SortAsRules, Gopt.Default.SortAsRules) self.thisSortAsRules = self.config.get(Gopt.Key.SortAsRules, defaultSortAsRules) self.defaultSortAsRulesBox = QComboBox() self.form.tooltips.append((self.defaultSortAsRulesBox, """\ <p><b>Calculate Sort As Rules, Default</b></p> <p>The default setting for the <b>Calculate Sort As Rules, For This Index</b> combobox for new indexes.</p>""")) self.thisSortAsRulesBox = QComboBox() self.form.tooltips.append((self.thisSortAsRulesBox, """\ <p><b>Calculate Sort As Rules, For This Index</b></p> <p>The rules to use for calculating each entry's sort as text for this index.</p> <p>If the rules are changed, when the dialog is closed, the new rules will be applied to every entry in the index.</p>""")) self.populateSortAsRulesBox(self.defaultSortAsRulesBox, defaultSortAsRules) self.populateSortAsRulesBox(self.thisSortAsRulesBox, self.thisSortAsRules) self.pageRangeRulesBox = QGroupBox("&Page Range Rules") defaultPageRangeRules = settings.value(Gconf.Key.PageRangeRules, Gopt.Default.PageRangeRules) self.thisPageRangeRules = self.config.get(Gopt.Key.PageRangeRules, defaultPageRangeRules) self.defaultPageRangeRulesBox = QComboBox() self.form.tooltips.append((self.defaultPageRangeRulesBox, """\ <p><b>Page Range Rules, Default</b></p> <p>The default setting for the <b>Page Range Rules, For This Index</b> combobox for new indexes.</p>""")) self.thisPageRangeRulesBox = QComboBox() self.form.tooltips.append((self.thisPageRangeRulesBox, """\ <p><b>Page Range Rules, For This Index</b></p> <p>The rules to use for handling page ranges, e.g., whether in full such as 120–124, or somehow compressed, e.g., 120–4, for this index.</p> <p>If the rules are changed, when the dialog is closed, the new rules will be applied to every entry in the index.</p>""")) self.populatePageRangeRulesBox(self.defaultPageRangeRulesBox, defaultPageRangeRules) self.populatePageRangeRulesBox(self.thisPageRangeRulesBox, self.thisPageRangeRules) self.padDigitsGroupBox = QGroupBox("Pad &Digits") defaultPadDigits = int( settings.value(Gconf.Key.PadDigits, Gopt.Default.PadDigits)) self.thisPadDigits = int( self.config.get(Gopt.Key.PadDigits, defaultPadDigits)) self.thisPadDigitsLabel = QLabel("For This Index") self.thisPadDigitsSpinBox = QSpinBox() self.thisPadDigitsSpinBox.setAlignment(Qt.AlignRight) self.thisPadDigitsSpinBox.setRange(0, 12) self.thisPadDigitsSpinBox.setValue(self.thisPadDigits) self.form.tooltips.append((self.thisPadDigitsSpinBox, """\ <p><b>Pad Digits, For This Index</b></p> <p>Sort as texts are compared textually, so if a term contains a number (or text which is converted to a number), the number must be padded by leading zeros to ensure correct ordering. This is the number of digits to pad for, for this index. For example, if set to 4, the numbers 1, 23, and 400 would be set to 0001, 0023, and 0400, in the sort as text.</p>""")) self.defaultPadDigitsLabel = QLabel("Default") self.defaultPadDigitsSpinBox = QSpinBox() self.defaultPadDigitsSpinBox.setAlignment(Qt.AlignRight) self.defaultPadDigitsSpinBox.setRange(0, 12) self.defaultPadDigitsSpinBox.setValue(defaultPadDigits) self.form.tooltips.append((self.defaultPadDigitsSpinBox, """\ <p><b>Pad Digits, Default</b></p> <p>The default setting for the <b>Pad Digits, For This Index</b> spinbox for new indexes.</p>""")) self.ignoreSubFirstsGroupBox = QGroupBox( "&Ignore Subentry Function Words") defaultIgnoreSubFirsts = bool( int( settings.value(Gconf.Key.IgnoreSubFirsts, Gopt.Default.IgnoreSubFirsts))) thisIgnoreSubFirsts = bool( int( self.config.get(Gopt.Key.IgnoreSubFirsts, defaultIgnoreSubFirsts))) self.thisIgnoreSubFirstsCheckBox = QCheckBox("For This Index") self.thisIgnoreSubFirstsCheckBox.setChecked(thisIgnoreSubFirsts) self.form.tooltips.append((self.thisIgnoreSubFirstsCheckBox, """\ <p><b>Ignore Subentry Function Words, For This Index</b></p> <p>This setting applies to this index.</p> <p>If checked, words listed in the <b>Index→Ignore Subentry Function Words</b> list are ignored for sorting purposes when the first word of a subentry, i.e., ignored when the first word of an entry's sort as text.</p> <p>This should normally be checked for Chicago Manual of Style Sort As Rules, and unchecked for NISO Rules.</p>""")) self.defaultIgnoreSubFirstsCheckBox = QCheckBox("Default") self.defaultIgnoreSubFirstsCheckBox.setChecked(defaultIgnoreSubFirsts) self.form.tooltips.append((self.defaultIgnoreSubFirstsCheckBox, """\ <p><b>Ignore Subentry Function Words, Default</b></p> <p>The default setting for the <b>Ignore Subentry Function Words, For This Index</b> checkbox for new indexes</p>""")) self.suggestSpelledGroupBox = QGroupBox( "&Suggest Spelled Out Numbers when Appropriate") defaultSuggestSpelled = bool( int( settings.value(Gconf.Key.SuggestSpelled, Gopt.Default.SuggestSpelled))) thisSuggestSpelled = bool( int(self.config.get(Gopt.Key.SuggestSpelled, defaultSuggestSpelled))) self.thisSuggestSpelledCheckBox = QCheckBox("For This Index") self.thisSuggestSpelledCheckBox.setChecked(thisSuggestSpelled) self.form.tooltips.append((self.thisSuggestSpelledCheckBox, """\ <p><b>Suggest Spelled Out Numbers when Appropriate, For This Index</b></p> <p>When checked (and providing the Sort As rules in force are not NISO rules), when adding or editing a term when the <b>Automatically Calculate Sort As</b> checkbox is checked, and when the term contains a number, the choice of sort as texts will include the number spelled out.</p>""")) self.defaultSuggestSpelledCheckBox = QCheckBox("Default") self.defaultSuggestSpelledCheckBox.setChecked(defaultSuggestSpelled) self.form.tooltips.append((self.defaultSuggestSpelledCheckBox, """\ <p><b>Suggest Spelled Out Numbers when Appropriate, Default</b></p> <p>The default setting for the <b>Suggest Spelled Out Numbers when Appropriate, For This Index</b> checkbox for new indexes.</p>""")) def layoutWidgets(self): layout = QVBoxLayout() form = QFormLayout() form.addRow("For This Index", self.thisSortAsRulesBox) form.addRow("Default", self.defaultSortAsRulesBox) self.sortRulesGroupBox.setLayout(form) layout.addWidget(self.sortRulesGroupBox) form = QFormLayout() form.addRow("For This Index", self.thisPageRangeRulesBox) form.addRow("Default", self.defaultPageRangeRulesBox) self.pageRangeRulesBox.setLayout(form) layout.addWidget(self.pageRangeRulesBox) hbox = QHBoxLayout() hbox.addWidget(self.thisPadDigitsLabel) hbox.addWidget(self.thisPadDigitsSpinBox) hbox.addStretch(1) hbox.addWidget(self.defaultPadDigitsLabel) hbox.addWidget(self.defaultPadDigitsSpinBox) hbox.addStretch(3) self.padDigitsGroupBox.setLayout(hbox) layout.addWidget(self.padDigitsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.thisIgnoreSubFirstsCheckBox) hbox.addWidget(self.defaultIgnoreSubFirstsCheckBox) hbox.addStretch() self.ignoreSubFirstsGroupBox.setLayout(hbox) layout.addWidget(self.ignoreSubFirstsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.thisSuggestSpelledCheckBox) hbox.addWidget(self.defaultSuggestSpelledCheckBox) hbox.addStretch() self.suggestSpelledGroupBox.setLayout(hbox) layout.addWidget(self.suggestSpelledGroupBox) layout.addStretch() self.setLayout(layout) def createConnections(self): self.defaultSortAsRulesBox.currentIndexChanged.connect( self.setDefaultSortAsRules) self.defaultPageRangeRulesBox.currentIndexChanged.connect( self.setDefaultPageRangeRules) self.defaultPadDigitsSpinBox.valueChanged.connect( self.setDefaultPadDigits) self.defaultIgnoreSubFirstsCheckBox.toggled.connect( self.setDefaultIgnoreSubFirsts) self.defaultSuggestSpelledCheckBox.toggled.connect( self.setDefaultSuggestSpelled) def populateSortAsRulesBox(self, combobox, rules): index = -1 for i, name in enumerate(SortAs.RulesForName): displayName = SortAs.RulesForName[name].name combobox.addItem(displayName, name) if name == rules: index = i combobox.setCurrentIndex(index) def setDefaultSortAsRules(self, index): index = self.defaultSortAsRulesBox.currentIndex() name = self.defaultSortAsRulesBox.itemData(index) settings = QSettings() settings.setValue(Gopt.Key.SortAsRules, name) def populatePageRangeRulesBox(self, combobox, rules): index = -1 for i, name in enumerate(Pages.RulesForName): displayName = Pages.RulesForName[name].name combobox.addItem(displayName, name) if name == rules: index = i combobox.setCurrentIndex(index) def setDefaultPageRangeRules(self, index): index = self.defaultPageRangeRulesBox.currentIndex() name = self.defaultPageRangeRulesBox.itemData(index) settings = QSettings() settings.setValue(Gopt.Key.PageRangeRules, name) def setDefaultPadDigits(self): value = self.defaultPadDigitsSpinBox.value() settings = QSettings() settings.setValue(Gopt.Key.PadDigits, value) def setDefaultIgnoreSubFirsts(self): value = int(self.defaultIgnoreSubFirstsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.IgnoreSubFirsts, value) def setDefaultSuggestSpelled(self): value = int(self.defaultSuggestSpelledCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.SuggestSpelled, value)
class EditConfigurationDialog(QDialog): def __init__(self, parent): global configuration super(EditConfigurationDialog, self).__init__(parent) title = _("Preferences") self.setWindowTitle(title) self.title_widget = TitleWidget(title, self) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.Ok) self.buttons.addButton(QDialogButtonBox.Cancel) self.font_select = QCheckBox() self.server_address = QLineEdit() form_layout = QFormLayout() form_layout.addRow(_("Fonts"), self.font_select) form_layout.addRow(_("Server's IP address"), self.server_address) top_layout = QVBoxLayout() top_layout.addWidget(self.title_widget) top_layout.addLayout(form_layout) top_layout.addWidget(self.buttons) self.setLayout(top_layout) # QWidget takes ownership of the layout self.buttons.accepted.connect(self.save_and_accept) self.buttons.rejected.connect(self.cancel) self._load_configuration(configuration) def _load_configuration(self, config): host_or_ip = "" if config: if config.get("DownloadSite", "base_url"): r = re.compile('https?://([^:]+):.*') host_or_ip = r.match(config.get("DownloadSite", "base_url")).groups()[0] elif config.database_url: r = re.compile('.*@([^:]+):.*') host_or_ip = r.match(config.database_url).groups()[0] self.server_address.setText(host_or_ip) self.font_select.setChecked(config.font_select) @Slot() def cancel(self): return super(EditConfigurationDialog, self).reject() @Slot() def save_and_accept(self): super(EditConfigurationDialog, self).accept() configuration.font_select = self.font_select.isChecked() configuration.set_server_network_address( self.server_address.text().strip(), overwrite=True) configuration.save() showWarningBox( _("Restart needed"), _("The modifications you have requested needs a restart of the application to be applied. They will take effect when you restart the application." )) self.deleteLater()
class EegCarDashboardWindow(QWidget): def setSliderMaxThrottle(self, x): self.setMaxThrottle(x) # self.dashboard.set_throttle(x) # self.dashboard.wheel.forward(x) def setSteeringValue(self, x): # x range is 1-9 need to scale (10-90) x = x*10 self.dashboard.set_steering(x) # self.dashboard.steering.turn_by_position(x) pot = 1.5 self.dashboard.steering.turn_by_position(x, pot) def setSteeringTurnRangeValue(self, x): ticks = int(100000 * (x/10.0)) # max is 100000 # print "STEERING TURN TICKS %d" % ticks self.dashboard.set_steering_eeg_turn_ticks(ticks) def steering_update_current_pos(self): # x = int(self.steering_current_pos.text()) + delta_x # while check busy ## read position ## print 'current pos %d' % x ticks = int(self.steering_move_ticks.text()) seconds = int(ticks/(DEFAULT_STEERING_SPEED*7)) seconds = seconds + 1 # at least one second ending_time = time.time() + seconds while time.time() < ending_time: # print "ENDNIG: %d" % ending_time # print "CURRENT: %d" % time.time() self.steering_set_current_pos(self.dashboard.steering.get_current_location()) def steering_set_current_pos(self, x): self.steering_current_pos.setText(str(x)) def steering_move_left(self): ticks = int(self.steering_move_ticks.text()) # Stepping Motor MOVE! self.dashboard.steering.stepping_driver.forward(ticks) self.setMessage('Steering left') self.steering_update_current_pos() def steering_move_right(self): ticks = int(self.steering_move_ticks.text()) # Stepping Motor MOVE! self.dashboard.steering.stepping_driver.backward(ticks) self.setMessage('Steering right') self.steering_update_current_pos() def set_steering_move_ticks_value(self): self.steering_move_ticks.blockSignals(True) # update line edit ticks = int(self.steering_move_ticks.text()) self.steering_move_ticks.setText(str(ticks)) self.steering_move_ticks.blockSignals(False) self.steering_move_ticks.setModified(True) if self.steering_move_ticks.isModified(): self.steering_move_ticks.clearFocus() self.maxThrottle.setModified(False) def steering_reset_position(self): # RESET self.setMessage('Steering Controller Reset') self.dashboard.steering.stepping_driver.reset() # reset self.dashboard.steering.stepping_driver.set_speed(DEFAULT_STEERING_SPEED) # set speed self.steering_update_current_pos() def setMessage(self, msg): self.statusBar.showMessage(msg, 2000) def remote_control(self, state): if state == QtCore.Qt.Checked: self.dashboard.set_rc_mode(True) self.setMessage('SET RC MODE') else: self.dashboard.set_rc_mode(False) self.setMessage('CLEAR RC MODE') def keep_mode_control(self, state): if state == QtCore.Qt.Checked: self.keep_mode = True self.setMessage('Keep Mode (EEG)') else: self.keep_mode = False self.setMessage('Keyboard Mode') def power_handle_mode_control(self, state): if state == QtCore.Qt.Checked: self.dashboard.set_power_handle_mode(True) self.setMessage('Power Handle (Auto Steering Middle)') else: self.dashboard.set_power_handle_mode(False) self.setMessage('Turn Off Power Handle') def ignore_eeg_input_control(self, state): if state == QtCore.Qt.Checked: self.dashboard.set_ignore_eeg_input(True) self.setMessage('Ignore EEG Input') else: self.dashboard.set_ignore_eeg_input(False) self.setMessage('Access EEG Input') def stright_control(self, state): if state == QtCore.Qt.Checked: self.dashboard.set_rc_stright_mode(True) self.setMessage('RC STRIGHT Mode') else: self.dashboard.set_rc_stright_mode(False) self.setMessage('RC FREE L/R Mode') def __init__(self): QWidget.__init__(self) self.setWindowTitle("EEG Pilot Dashboard") self.setGeometry(0, 0, 750, 800) # self.setGeometry(300, 300, 750, 800) self.dashboard = EegCarDashboard() self.dashboard.set_max_throttle(DEFAULT_MAX_THROTTLE) self.dashboard.set_backward_max_throttle(DEFAULT_MAX_BACK_THROTTLE) self.layout = QVBoxLayout(self) # Drive Setting self.rc_mode = QCheckBox('Remote Control', self) self.rc_mode.stateChanged.connect(self.remote_control) self.rc_stright_mode = QCheckBox('RC Stright', self) self.rc_stright_mode.stateChanged.connect(self.stright_control) self.keep_mode_checkbox = QCheckBox('Keep Mode', self) self.keep_mode_checkbox.stateChanged.connect(self.keep_mode_control) self.power_handle_mode_checkbox = QCheckBox('Power Handle', self) self.power_handle_mode_checkbox.stateChanged.connect(self.power_handle_mode_control) self.ignore_eeg_input = QCheckBox('Ignore Eeg Input', self) self.ignore_eeg_input.stateChanged.connect(self.ignore_eeg_input_control) drive_layout = QHBoxLayout(self) drive_layout.addWidget(self.rc_mode) drive_layout.addWidget(self.rc_stright_mode) drive_layout.addWidget(self.keep_mode_checkbox) drive_layout.addWidget(self.power_handle_mode_checkbox) drive_layout.addWidget(self.ignore_eeg_input) drive_groupbox = QtGui.QGroupBox("Drive Status & Setting") drive_groupbox.setLayout(drive_layout) # Throttle Setting self.throttle_slider = QSlider(Qt.Horizontal) self.throttle_slider.setFocusPolicy(Qt.StrongFocus) self.throttle_slider.setTickPosition(QSlider.TicksBothSides) self.throttle_slider.setTickInterval(10) self.throttle_slider.setSingleStep(10) self.throttle_slider.setValue(DEFAULT_MAX_THROTTLE) self.throttle_slider.valueChanged.connect(self.throttle_slider.setValue) self.connect(self.throttle_slider, SIGNAL("valueChanged(int)"), self.setSliderMaxThrottle) self.throttle_label = QLabel('Max Throttle (%): ', self) self.maxThrottle = QLineEdit(str(DEFAULT_MAX_THROTTLE)) # self.maxThrottle.textChanged[str].connect(self.setMaxThrottle) self.maxThrottle.editingFinished.connect(self.setMaxThrottle) self.maxThrottle.setMaxLength(2) self.maxThrottle.setMaximumWidth(40) self.backwardMaxThrottle = QLineEdit(str(DEFAULT_MAX_BACK_THROTTLE)) # self.maxThrottle.textChanged[str].connect(self.setMaxThrottle) self.backwardMaxThrottle.editingFinished.connect(self.setBackwardMaxThrottle) self.backwardMaxThrottle.setMaxLength(2) self.backwardMaxThrottle.setMaximumWidth(40) throttle_layout = QHBoxLayout(self) throttle_layout.addWidget(self.throttle_label) throttle_layout.addWidget(self.throttle_slider) throttle_layout.addWidget(QLabel("Forward Max:")) throttle_layout.addWidget(self.maxThrottle) throttle_layout.addWidget(QLabel("Backward Max:")) throttle_layout.addWidget(self.backwardMaxThrottle) throttle_groupbox = QtGui.QGroupBox("Max Throttle Setting (30-99)") throttle_groupbox.setLayout(throttle_layout) # Steering self.steering_label = QLabel('Turn Range', self) self.steering_turn_range_slider = QSlider(Qt.Horizontal) self.steering_turn_range_slider.setFocusPolicy(Qt.StrongFocus) self.steering_turn_range_slider.setTickPosition(QSlider.TicksBothSides) self.steering_turn_range_slider.setRange(1, 9) # self.steering_slider.setMinimum(2) # self.steering_slider.setMaximum(8) self.steering_turn_range_slider.setMinimum(4) self.steering_turn_range_slider.setMaximum(8) self.steering_turn_range_slider.setTickInterval(1) self.steering_turn_range_slider.setSingleStep(1) self.steering_turn_range_slider.setValue(6) self.steering_turn_range_slider.valueChanged.connect(self.steering_turn_range_slider.setValue) self.connect(self.steering_turn_range_slider, SIGNAL("valueChanged(int)"), self.setSteeringTurnRangeValue) self.steering_adjust_label = QLabel(' Home Adjust ', self) self.steering_move_left_button = QPushButton('<Left+', self) self.steering_current_pos = QLabel('0', self) self.steering_move_right_button = QPushButton('-Right>', self) self.steering_move_ticks = QLineEdit(str(5000)) self.steering_move_ticks.editingFinished.connect(self.set_steering_move_ticks_value) self.steering_move_ticks.setMaxLength(5) self.steering_move_ticks.setMaximumWidth(50) self.steering_reset = QPushButton('Reset', self) self.steering_move_left_button.clicked.connect(self.steering_move_left) self.steering_move_right_button.clicked.connect(self.steering_move_right) self.steering_reset.clicked.connect(self.steering_reset_position) steering_layout = QHBoxLayout(self) steering_layout.addWidget(self.steering_label) # steering_layout.addWidget(self.steering_slider) steering_layout.addWidget(self.steering_turn_range_slider) steering_layout.addWidget(self.steering_adjust_label) steering_layout.addWidget(self.steering_move_left_button) steering_layout.addWidget(self.steering_current_pos) steering_layout.addWidget(self.steering_move_right_button) steering_layout.addWidget(self.steering_move_ticks) steering_layout.addWidget(self.steering_reset) steering_groupbox = QtGui.QGroupBox("Steering Setting") steering_groupbox.setLayout(steering_layout) self.layout.addWidget(self.dashboard, 2) self.layout.addWidget(drive_groupbox) self.layout.addWidget(throttle_groupbox) self.layout.addWidget(steering_groupbox) self.statusBar = QStatusBar() self.statusBar.showMessage('Ready', 2000) self.layout.addWidget(self.statusBar) self.setIcon() self.show() # save the state self.default_backgroundcolor = self.palette().color(QtGui.QPalette.Background) self.previos_steering = 50 self.init_keep_mode() self.init_power_handle_mode() # Timer For reading current steering position # self.timer = QtCore.QTimer() # self.timer.timeout.connect(self.readSteeringPos) # # check every second # self.timer.start(1000) # Timer For Powerhandle # self.power_handle_timer = QtCore.QTimer() # self.power_handle_timer.timeout.connect(self.update_power_handle) # # check every half second # self.power_handle_timer.start(500) # # Timer For Start Accel # self.start_accel_timer = QtCore.QTimer() # # self.start_accel_timer.singleShot(5000, self.end_start_accel_handle) # self.can_start_accel = True # def set_start_accel(self, value): # self.can_start_accel = value # def get_start_accel(self): # return self.can_start_accel # def end_start_accel_handle(self): # self.dashboard.end_start_accel() # def update_power_handle(self): # if self.power_handle_mode: # self.dashboard.update_power_handle() def readSteeringPos(self): # self.setMessage(str(self.dashboard.steering.get_current_steering())) # TODO: is it thread safe? # self.steering_set_current_pos(self.dashboard.steering.get_current_location()) return def getMaxThrottle(self): return int(self.maxThrottle.text()) def getBackwardMaxThrottle(self): return int(self.backwardMaxThrottle.text()) def setMaxThrottle(self, _throttle=None): if _throttle is None: # from line textbox throttle = self.getMaxThrottle() self.throttle_slider.blockSignals(True); # update slider self.throttle_slider.setValue(throttle); self.throttle_slider.blockSignals(False); else: # from slider throttle = _throttle self.maxThrottle.blockSignals(True); # update line edit self.maxThrottle.setText(str(throttle)) self.maxThrottle.blockSignals(False); self.maxThrottle.setModified(True) if self.maxThrottle.isModified(): if throttle >= FORWARD_THROTTLE_THRESHOLD: # forward throttle threshold is 20 self.dashboard.set_max_throttle(throttle) self.setMessage("Forward Max Throttle: %d" % throttle) self.maxThrottle.clearFocus() self.maxThrottle.setModified(False) def setBackwardMaxThrottle(self): throttle = self.getBackwardMaxThrottle() if self.backwardMaxThrottle.isModified(): if throttle >= BACKWARD_THROTTLE_THRESHOLD: # backward throttle threshold is 20 self.dashboard.set_backward_max_throttle(throttle) self.backwardMaxThrottle.clearFocus() self.backwardMaxThrottle.setModified(False) def setIcon(self): self.appIcon = QIcon('logo.png') self.setWindowIcon(self.appIcon) def init_keep_mode(self): self.w_keep_countdown = 0 self.x_keep_countdown = 0 self.a_keep_countdown = 0 self.d_keep_countdown = 0 self.default_keep_countdown = DEFAULT_KEEP_COUNT # self.default_keep_countdown = 28 # self.default_keep_countdown = 38 self.keep_mode = False def init_power_handle_mode(self): self.power_handle_mode = False def is_keep_mode(self, ignore_key): # if key is 'w' -> w_keep_countdown # if key is 'x' -> x_keep_countdown # ignore several 's' key while chountdown number to zero if self.keep_mode: if ignore_key == Qt.Key_S: if self.dashboard.power_handle_mode == True: self.dashboard.update_power_handle() if self.w_keep_countdown > 0: self.w_keep_countdown = self.w_keep_countdown - 1 # print "w keep countdown %d" % self.w_keep_countdown self.setMessage("w keep countdown %d" % self.w_keep_countdown) self.x_keep_countdown = 0 return True if self.x_keep_countdown > 0: self.x_keep_countdown = self.x_keep_countdown - 1 # print "x keep countdown %d" % self.x_keep_countdown self.setMessage("x keep countdown %d" % self.x_keep_countdown) self.w_keep_countdown = 0 return True if ignore_key == Qt.Key_X: if self.w_keep_countdown > 0: self.w_keep_countdown = self.w_keep_countdown - 1 self.setMessage("w keep countdown %d" % self.w_keep_countdown) if self.w_keep_countdown < DEFAULT_KEEP_COUNT - 10: # self.stop() self.dashboard.set_key_input('s') self.dashboard.stop() self.dashboard.set_start_accel(True) return True if ignore_key == Qt.Key_W: if self.x_keep_countdown > 0: self.x_keep_countdown = self.x_keep_countdown - 1 self.setMessage("x keep countdown %d" % self.x_keep_countdown) if self.x_keep_countdown < DEFAULT_KEEP_COUNT - 10: # self.stop() self.dashboard.set_key_input('s') self.dashboard.stop() self.dashboard.set_start_accel(True) return True return False def go_to_keep_mode(self, key): if key == Qt.Key_W: self.w_keep_countdown = self.default_keep_countdown if key == Qt.Key_X: self.x_keep_countdown = self.default_keep_countdown # A, D make a w_keep_countdown FOR powerhandle if key == Qt.Key_A: self.w_keep_countdown = self.default_keep_countdown if key == Qt.Key_D: self.w_keep_countdown = self.default_keep_countdown def keyPressEvent(self, event): if self.dashboard.rc_mode == True : if self.dashboard.ignore_eeg_input == True: self.ignore_eeg_input.setChecked(True) if event.key(): self.dashboard.set_key_input('Ignore') return else: self.ignore_eeg_input.setChecked(False) # self.update_power_handle(event.key()) if self.is_keep_mode(event.key()): return if event.key() == Qt.Key_S: self.dashboard.set_key_input('s') self.dashboard.stop() self.dashboard.set_start_accel(True) if event.key() == Qt.Key_W: self.dashboard.set_key_input('w') if self.dashboard.get_start_accel() == True: self.dashboard.start_accel_forward() else: self.dashboard.forward() if event.key() == Qt.Key_A: self.dashboard.set_key_input('a') if self.dashboard.get_start_accel() == True: self.dashboard.start_accel_turn_left() else: self.dashboard.turn_left() if event.key() == Qt.Key_X: self.dashboard.set_key_input('x') if self.dashboard.get_start_accel() == True: self.dashboard.start_accel_backward() else: self.dashboard.backward() if event.key() == Qt.Key_D: self.dashboard.set_key_input('d') if self.dashboard.get_start_accel() == True: self.dashboard.start_accel_turn_right() else: self.dashboard.turn_right() if event.key() == Qt.Key_B: self.dashboard.set_key_input('b') self.dashboard.brake() if event.key() == Qt.Key_R: self.dashboard.set_key_input('r') # TODO: Make Inspection Mode # self.dashboard.steering.position_clear() #pot = self.dashboard.wheel.get_steering_pot() #self.dashboard.steering.middle_position(pot) if event.key() == Qt.Key_F: if self.dashboard.isFullScreen(): for i in range(self.layout.count()): w = self.layout.itemAt(i).widget() w.show() self.dashboard.showNormal() self.change_backgroundcolor(self.default_backgroundcolor); self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowTitleHint) self.showNormal() else: for i in range(self.layout.count()): w = self.layout.itemAt(i).widget() if w == self.dashboard: continue w.hide() self.change_backgroundcolor(Qt.black); self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) self.showMaximized() self.dashboard.showFullScreen() self.dashboard.reset_label_position() if event.key() == Qt.Key_Escape: self.dashboard.close() self.close() self.go_to_keep_mode(event.key()) def change_backgroundcolor(self, color): p = self.palette() p.setColor(self.backgroundRole(), color) self.setPalette(p)
class optdlg(QDialog): def __init__(self, parent=None): super(optdlg, self).__init__(parent) self.setFixedSize(484, 399) appicom = QIcon(":/icons/njnlogo.png") self.setWindowIcon(appicom) self.setWindowTitle("Nigandu English to Tamil Dictionary | OPTIONS") self.buttonBox = QDialogButtonBox(self) self.buttonBox.setEnabled(True) self.buttonBox.setGeometry(QRect(350, 20, 121, 200)) self.buttonBox.setOrientation(Qt.Vertical) self.buttonBox.setStandardButtons(QDialogButtonBox.Apply|QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.setCenterButtons(True) self.restorebtn = QPushButton(self) self.restorebtn.setGeometry(QRect(354, 360, 121, 23)) self.restorebtn.setText("&RestoreDefults") self.fontbox = QGroupBox(self) self.fontbox.setGeometry(QRect(10, 10, 331, 141)) self.spinBox = QSpinBox(self.fontbox) self.spinBox.setGeometry(QRect(100, 20, 81, 21)) self.spinBox.setMinimum(10) self.spinBox.setMaximum(24) self.label = QLabel(self.fontbox) self.label.setGeometry(QRect(20, 20, 71, 21)) self.label.setText("Font Size:") self.fontbox.setTitle("Font") self.samplefontbox = QGroupBox(self) self.samplefontbox.setGeometry(QRect(20, 50, 291, 91)) self.samplefontbox.setTitle("Sample Text") self.sampletxt = QLabel(self.samplefontbox) self.sampletxt.setGeometry(QRect(20, 20, 251, 61)) self.sampletxt.setText("AaBbCcDdEeFfGgHhIiJjKkLlYyZz") self.clipbox = QGroupBox(self) self.clipbox.setGeometry(QRect(10, 160, 331, 61)) self.clipbox.setTitle("ClipBoard Options") self.checkclip = QCheckBox(self.clipbox) self.checkclip.setGeometry(QRect(20, 20, 301, 31)) self.checkclip.setText("Allow copy from clipboard on start-up") self.histbox = QGroupBox(self) self.histbox.setGeometry(QRect(10, 230, 331, 91)) self.histbox.setTitle("History") self.checkshowhistdock = QCheckBox(self.histbox) self.checkshowhistdock.setGeometry(QRect(20, 60, 301, 17)) self.checkshowhistdock.setText("Show History Dock on the right side") self.checkdelhist = QCheckBox(self.histbox) self.checkdelhist.setGeometry(QRect(20, 30, 301, 17)) self.checkdelhist.setText("Clear all the past history records") self.bkmbox = QGroupBox(self) self.bkmbox.setGeometry(QRect(10, 330, 331, 61)) self.bkmbox.setTitle("Book Marks") self.checkshowbkmdock = QCheckBox(self.bkmbox) self.checkshowbkmdock.setGeometry(QRect(20, 30, 301, 17)) self.checkshowbkmdock.setText("Show Book Marks Dock on the right side.") self.spinBox.valueChanged[int].connect(self.setsampletxt) self.restorebtn.clicked.connect(self.setdeafults) self.buttonBox.rejected.connect(self.close) def setdeafults(self): self.spinBox.setValue(13) self.checkshowhistdock.setChecked(True) self.checkshowbkmdock.setChecked(True) self.checkclip.setChecked(True) self.checkdelhist.setChecked(False) def setsampletxt(self, i): font = QFont() font.setPixelSize(i) self.sampletxt.setFont(font)
class RangeWidget(QWidget): """Interface for changing Range information. It shows the current range and range policy. This widget was designed for use with the tab dialog. It can be used by itself or it can be used as part of a bigger color tab. Changes to this widget are emitted via a changeSignal as a boolean on policy, range tuple and this widget's tag. """ changeSignal = Signal(bool, float, float, str) def __init__(self, parent, use_max, current_range, max_range, tag): """Creates a ColorMap widget. parent The Qt parent of this widget. use_max Whether the policy is to use max possible or set range. current_range The min and max range on creation. tag A name for this widget, will be emitted on change. """ super(RangeWidget, self).__init__(parent) self.edit_range = (current_range[0], current_range[1]) self.max_range = max_range self.use_max = use_max self.tag = tag layout = QVBoxLayout() self.range_check = QCheckBox("Use maximum range across applicable " + "modules.") layout.addWidget(self.range_check) if self.use_max: self.range_check.setChecked(True) else: self.range_check.setChecked(False) self.range_check.stateChanged.connect(self.checkChanged) layout.addItem(QSpacerItem(3, 3)) hlayout = QHBoxLayout() hlayout.addWidget(QLabel("Set range: ")) self.range_min = QLineEdit(str(current_range[0]), self) self.range_min.editingFinished.connect(self.rangeChanged) hlayout.addWidget(self.range_min) hlayout.addWidget(QLabel(" to ")) self.range_max = QLineEdit(str(current_range[1]), self) self.range_max.editingFinished.connect(self.rangeChanged) hlayout.addWidget(self.range_max) layout.addLayout(hlayout) self.setStates() self.setLayout(layout) def setStates(self): if self.use_max: self.range_min.setDisabled(True) self.range_max.setDisabled(True) else: self.range_min.setDisabled(False) self.range_max.setDisabled(False) @Slot() def checkChanged(self): """Handles check/uncheck of use max.""" self.use_max = self.range_check.isChecked() self.setStates() if self.use_max: self.changeSignal.emit(self.use_max, self.max_range[0], self.max_range[1], self.tag) else: self.changeSignal.emit(self.use_max, self.edit_range[0], self.edit_range[1], self.tag) @Slot() def rangeChanged(self): self.edit_range = (float(self.range_min.text()), float(self.range_max.text())) self.changeSignal.emit(self.use_max, self.edit_range[0], self.edit_range[1], self.tag)
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.slicesLabel = QLabel("Show slices for directions:") self.sliceLabelTexts = ["x:", "y:", "z:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 3) layout.addWidget(self.slicesLabel, 0, 0, 1, -1) for index in range(3): layout.addWidget(self.sliceLabels[index], index + 1, 0) layout.addWidget(self.sliceCheckBoxes[index], index + 1, 1) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingLabel = QLabel("Clipping box:") self.clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.clippingLabel, 5, 0) layout.addWidget(self.clippingCheckBox, 5, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState( ) == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox( self.clippingCheckBox.checkState() == Qt.Checked) @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show)
class ConfigDialog(QtGui.QDialog): pressedclosebutton = False moreToggling = False def automaticUpdatePromptCheck(self): if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked and not self.nostoreCheckbox.isChecked(): reply = QtGui.QMessageBox.question(self, "Syncplay", getMessage("promptforupdate-label"), QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No) if reply == QtGui.QMessageBox.Yes: self.automaticupdatesCheckbox.setChecked(True) else: self.automaticupdatesCheckbox.setChecked(False) def moreToggled(self): if self.moreToggling == False: self.moreToggling = True if self.showmoreCheckbox.isChecked(): self.tabListFrame.show() self.resetButton.show() self.nostoreCheckbox.show() self.saveMoreState(True) self.tabListWidget.setCurrentRow(0) self.ensureTabListIsVisible() else: self.tabListFrame.hide() self.resetButton.hide() self.nostoreCheckbox.hide() self.saveMoreState(False) self.stackedLayout.setCurrentIndex(0) self.adjustSize() self.setFixedSize(self.sizeHint()) self.moreToggling = False self.setFixedWidth(self.minimumSizeHint().width()) self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width()) def runButtonTextUpdate(self): if self.nostoreCheckbox.isChecked(): self.runButton.setText(getMessage("run-label")) else: self.runButton.setText(getMessage("storeandrun-label")) def openHelp(self): self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/client/")) def _isURL(self, path): if path is None: return False if "http://" in path: return True def safenormcaseandpath(self, path): if self._isURL(path): return path else: return os.path.normcase(os.path.normpath(path)) def _tryToFillPlayerPath(self, playerpath, playerpathlist): settings = QSettings("Syncplay", "PlayerList") settings.beginGroup("PlayerList") savedPlayers = settings.value("PlayerList", []) if not isinstance(savedPlayers, list): savedPlayers = [] else: for i, savedPlayer in enumerate(savedPlayers): savedPlayers[i] = self.safenormcaseandpath(savedPlayer) playerpathlist = list(set(playerpathlist + savedPlayers)) settings.endGroup() foundpath = "" if playerpath != None and playerpath != "": if self._isURL(playerpath): foundpath = playerpath self.executablepathCombobox.addItem(foundpath) else: if not os.path.isfile(playerpath): expandedpath = PlayerFactory().getExpandedPlayerPathByPath(playerpath) if expandedpath != None and os.path.isfile(expandedpath): playerpath = expandedpath if os.path.isfile(playerpath): foundpath = playerpath self.executablepathCombobox.addItem(foundpath) for path in playerpathlist: if self._isURL(path): if foundpath == "": foundpath = path if path != playerpath: self.executablepathCombobox.addItem(path) elif os.path.isfile(path) and os.path.normcase(os.path.normpath(path)) != os.path.normcase(os.path.normpath(foundpath)): self.executablepathCombobox.addItem(path) if foundpath == "": foundpath = path if foundpath != "": settings.beginGroup("PlayerList") playerpathlist.append(self.safenormcaseandpath(foundpath)) settings.setValue("PlayerList", list(set(playerpathlist))) settings.endGroup() return foundpath def updateExecutableIcon(self): currentplayerpath = unicode(self.executablepathCombobox.currentText()) iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) if iconpath != None and iconpath != "": self.executableiconImage.load(self.resourcespath + iconpath) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) else: self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) def languageChanged(self): setLanguage(unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex()))) QtGui.QMessageBox.information(self, "Syncplay", getMessage("language-changed-msgbox-label")) def browsePlayerpath(self): options = QtGui.QFileDialog.Options() defaultdirectory = "" browserfilter = "All files (*)" if os.name == 'nt': browserfilter = "Executable files (*.exe);;All files (*)" if "PROGRAMFILES(X86)" in os.environ: defaultdirectory = os.environ["ProgramFiles(x86)"] elif "PROGRAMFILES" in os.environ: defaultdirectory = os.environ["ProgramFiles"] elif "PROGRAMW6432" in os.environ: defaultdirectory = os.environ["ProgramW6432"] elif sys.platform.startswith('linux'): defaultdirectory = "/usr/bin" elif sys.platform.startswith('darwin'): defaultdirectory = "/Applications/" elif "bsd" in sys.platform or sys.platform.startswith('dragonfly'): defaultdirectory = "/usr/local/bin" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media player executable", defaultdirectory, browserfilter, "", options) if fileName: self.executablepathCombobox.setEditText(os.path.normpath(fileName)) def loadLastUpdateCheckDate(self): settings = QSettings("Syncplay", "Interface") settings.beginGroup("Update") self.lastCheckedForUpdates = settings.value("lastChecked", None) if self.lastCheckedForUpdates: if self.config["lastCheckedForUpdates"] is not None and self.config["lastCheckedForUpdates"] is not "": if self.lastCheckedForUpdates > datetime.strptime(self.config["lastCheckedForUpdates"], "%Y-%m-%d %H:%M:%S.%f"): self.config["lastCheckedForUpdates"] = str(self.lastCheckedForUpdates) else: self.config["lastCheckedForUpdates"] = str(self.lastCheckedForUpdates) def loadMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") self.mediadirectory = settings.value("mediadir", "") settings.endGroup() def saveMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") settings.setValue("mediadir", self.mediadirectory) settings.endGroup() def getMoreState(self): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") morestate = unicode.lower(unicode(settings.value("ShowMoreSettings", "false"))) settings.endGroup() if morestate == "true": return True else: return False def saveMoreState(self, morestate): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") settings.setValue("ShowMoreSettings", morestate) settings.endGroup() def browseMediapath(self): self.loadMediaBrowseSettings() options = QtGui.QFileDialog.Options() if os.path.isdir(self.mediadirectory): defaultdirectory = self.mediadirectory elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.MoviesLocation)): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.MoviesLocation) elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.HomeLocation)): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) else: defaultdirectory = "" browserfilter = "All files (*)" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory, browserfilter, "", options) if fileName: self.mediapathTextbox.setText(os.path.normpath(fileName)) self.mediadirectory = os.path.dirname(fileName) self.saveMediaBrowseSettings() def _saveDataAndLeave(self): self.automaticUpdatePromptCheck() self.loadLastUpdateCheckDate() self.processWidget(self, lambda w: self.saveValues(w)) if self.hostTextbox.text(): self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT) else: self.config['host'] = None self.config['playerPath'] = unicode(self.safenormcaseandpath(self.executablepathCombobox.currentText())) self.config['language'] = unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex())) if self.mediapathTextbox.text() == "": self.config['file'] = None elif os.path.isfile(os.path.abspath(self.mediapathTextbox.text())): self.config['file'] = os.path.abspath(self.mediapathTextbox.text()) else: self.config['file'] = unicode(self.mediapathTextbox.text()) self.pressedclosebutton = True self.close() return def closeEvent(self, event): if self.pressedclosebutton == False: sys.exit() def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: sys.exit() def dragEnterEvent(self, event): data = event.mimeData() urls = data.urls() if urls and urls[0].scheme() == 'file': event.acceptProposedAction() def dropEvent(self, event): data = event.mimeData() urls = data.urls() if urls and urls[0].scheme() == 'file': dropfilepath = os.path.abspath(unicode(event.mimeData().urls()[0].toLocalFile())) if dropfilepath[-4:].lower() == ".exe": self.executablepathCombobox.setEditText(dropfilepath) else: self.mediapathTextbox.setText(dropfilepath) def processWidget(self, container, torun): for widget in container.children(): self.processWidget(widget, torun) if hasattr(widget, 'objectName') and widget.objectName() and widget.objectName()[:3] != "qt_": torun(widget) def loadTooltips(self, widget): tooltipName = widget.objectName().lower().split(constants.CONFIG_NAME_MARKER)[0] + "-tooltip" if tooltipName[:1] == constants.INVERTED_STATE_MARKER or tooltipName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: tooltipName = tooltipName[1:] widget.setToolTip(getMessage(tooltipName)) def loadValues(self, widget): valueName = str(widget.objectName()) if valueName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: return if isinstance(widget, QCheckBox) and widget.objectName(): if valueName[:1] == constants.INVERTED_STATE_MARKER: valueName = valueName[1:] inverted = True else: inverted = False if self.config[valueName] is None: widget.setTristate(True) widget.setCheckState(Qt.PartiallyChecked) widget.stateChanged.connect(lambda: widget.setTristate(False)) else: widget.setChecked(self.config[valueName] != inverted) elif isinstance(widget, QRadioButton): radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER) if self.config[radioName] == radioValue: widget.setChecked(True) elif isinstance(widget, QLineEdit): widget.setText(self.config[valueName]) def saveValues(self, widget): valueName = str(widget.objectName()) if valueName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: return if isinstance(widget, QCheckBox) and widget.objectName(): if widget.checkState() == Qt.PartiallyChecked: self.config[valueName] = None else: if valueName[:1] == constants.INVERTED_STATE_MARKER: valueName = valueName[1:] inverted = True else: inverted = False self.config[valueName] = widget.isChecked() != inverted elif isinstance(widget, QRadioButton): radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER) if widget.isChecked(): self.config[radioName] = radioValue elif isinstance(widget, QLineEdit): self.config[valueName] = widget.text() def connectChildren(self, widget): widgetName = str(widget.objectName()) if self.subitems.has_key(widgetName) and isinstance(widget, QCheckBox): widget.stateChanged.connect(lambda: self.updateSubwidgets(self, widget)) self.updateSubwidgets(self, widget) def updateSubwidgets(self, container, parentwidget, subwidgets=None): widgetName = parentwidget.objectName() if not subwidgets: subwidgets = self.subitems[widgetName] for widget in container.children(): self.updateSubwidgets(widget, parentwidget, subwidgets) if hasattr(widget, 'objectName') and widget.objectName() and widget.objectName() in subwidgets: widget.setDisabled(not parentwidget.isChecked()) def addBasicTab(self): config = self.config playerpaths = self.playerpaths resourcespath = self.resourcespath error = self.error if self.datacleared == True: error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification")) if config['host'] == None: host = "" elif ":" in config['host']: host = config['host'] else: host = config['host'] + ":" + str(config['port']) self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("connection-group-title")) self.hostTextbox = QLineEdit(host, self) self.hostLabel = QLabel(getMessage("host-label"), self) self.usernameTextbox = QLineEdit(self) self.usernameTextbox.setObjectName("name") self.serverpassLabel = QLabel(getMessage("password-label"), self) self.defaultroomTextbox = QLineEdit(self) self.usernameLabel = QLabel(getMessage("name-label"), self) self.serverpassTextbox = QLineEdit(self) self.defaultroomLabel = QLabel(getMessage("room-label"), self) self.hostLabel.setObjectName("host") self.hostTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "host") self.usernameLabel.setObjectName("name") self.usernameTextbox.setObjectName("name") self.serverpassLabel.setObjectName("password") self.serverpassTextbox.setObjectName("password") self.defaultroomLabel.setObjectName("room") self.defaultroomTextbox.setObjectName("room") self.connectionSettingsLayout = QtGui.QGridLayout() self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) self.connectionSettingsLayout.addWidget(self.hostTextbox, 0, 1) self.connectionSettingsLayout.addWidget(self.serverpassLabel, 1, 0) self.connectionSettingsLayout.addWidget(self.serverpassTextbox, 1, 1) self.connectionSettingsLayout.addWidget(self.usernameLabel, 2, 0) self.connectionSettingsLayout.addWidget(self.usernameTextbox, 2, 1) self.connectionSettingsLayout.addWidget(self.defaultroomLabel, 3, 0) self.connectionSettingsLayout.addWidget(self.defaultroomTextbox, 3, 1) self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) self.connectionSettingsGroup.setMaximumHeight(self.connectionSettingsGroup.minimumSizeHint().height()) self.mediaplayerSettingsGroup = QtGui.QGroupBox(getMessage("media-setting-title")) self.executableiconImage = QtGui.QImage() self.executableiconLabel = QLabel(self) self.executableiconLabel.setMinimumWidth(16) self.executablepathCombobox = QtGui.QComboBox(self) self.executablepathCombobox.setEditable(True) self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths)) self.executablepathCombobox.setFixedWidth(165) self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon) self.executablepathLabel = QLabel(getMessage("executable-path-label"), self) self.executablebrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.executablebrowseButton.clicked.connect(self.browsePlayerpath) self.mediapathTextbox = QLineEdit(config['file'], self) self.mediapathLabel = QLabel(getMessage("media-path-label"), self) self.mediabrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.mediabrowseButton.clicked.connect(self.browseMediapath) self.executablepathLabel.setObjectName("executable-path") self.executablepathCombobox.setObjectName("executable-path") self.mediapathLabel.setObjectName("media-path") self.mediapathTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "media-path") self.mediaplayerSettingsLayout = QtGui.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) self.mediaplayerSettingsLayout.addWidget(self.executableiconLabel, 0, 1) self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox, 0, 2) self.mediaplayerSettingsLayout.addWidget(self.executablebrowseButton, 0, 3) self.mediaplayerSettingsLayout.addWidget(self.mediapathLabel, 1, 0) self.mediaplayerSettingsLayout.addWidget(self.mediapathTextbox , 1, 2) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) self.showmoreCheckbox = QCheckBox(getMessage("more-title")) self.showmoreCheckbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "more") self.basicOptionsFrame = QtGui.QFrame() self.basicOptionsLayout = QtGui.QVBoxLayout() if error: self.errorLabel = QLabel(self) if error[:1] != constants.ERROR_MESSAGE_MARKER: self.errorLabel.setStyleSheet(constants.STYLE_ERRORLABEL) else: error = error[1:] self.errorLabel.setStyleSheet(constants.STYLE_SUCCESSLABEL) self.errorLabel.setText(error) self.errorLabel.setAlignment(Qt.AlignCenter) self.basicOptionsLayout.addWidget(self.errorLabel, 0, 0) self.connectionSettingsGroup.setMaximumHeight(self.connectionSettingsGroup.minimumSizeHint().height()) self.basicOptionsLayout.setAlignment(Qt.AlignTop) self.basicOptionsLayout.addWidget(self.connectionSettingsGroup) self.basicOptionsLayout.addSpacing(5) self.mediaplayerSettingsGroup.setMaximumHeight(self.mediaplayerSettingsGroup.minimumSizeHint().height()) self.basicOptionsLayout.addWidget(self.mediaplayerSettingsGroup) self.basicOptionsFrame.setLayout(self.basicOptionsLayout) self.stackedLayout.addWidget(self.basicOptionsFrame) def addReadinessTab(self): self.readyFrame = QtGui.QFrame() self.readyLayout = QtGui.QVBoxLayout() self.readyFrame.setLayout(self.readyLayout) # Initial state self.readyInitialGroup = QtGui.QGroupBox(u"Initial readiness state") self.readyInitialLayout = QtGui.QVBoxLayout() self.readyInitialGroup.setLayout(self.readyInitialLayout) self.readyatstartCheckbox = QCheckBox(getMessage("readyatstart-label")) self.readyatstartCheckbox.setObjectName("readyAtStart") self.readyInitialLayout.addWidget(self.readyatstartCheckbox) self.readyLayout.addWidget(self.readyInitialGroup) # Automatically pausing self.readyPauseGroup = QtGui.QGroupBox(u"Pausing") self.readyPauseLayout = QtGui.QVBoxLayout() self.readyPauseGroup.setLayout(self.readyPauseLayout) self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label")) self.pauseonleaveCheckbox.setObjectName("pauseOnLeave") self.readyPauseLayout.addWidget(self.pauseonleaveCheckbox) self.readyLayout.addWidget(self.readyPauseGroup) # Unpausing self.readyUnpauseGroup = QtGui.QGroupBox(getMessage("unpause-title")) self.readyUnpauseLayout = QtGui.QVBoxLayout() self.readyUnpauseGroup.setLayout(self.readyUnpauseLayout) self.readyUnpauseButtonGroup = QButtonGroup() self.unpauseIfAlreadyReadyOption = QRadioButton(getMessage("unpause-ifalreadyready-option")) self.readyUnpauseButtonGroup.addButton(self.unpauseIfAlreadyReadyOption) self.unpauseIfAlreadyReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfAlreadyReadyOption.setObjectName("unpause-ifalreadyready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFALREADYREADY_MODE) self.readyUnpauseLayout.addWidget(self.unpauseIfAlreadyReadyOption) self.unpauseIfOthersReadyOption = QRadioButton(getMessage("unpause-ifothersready-option")) self.readyUnpauseButtonGroup.addButton(self.unpauseIfOthersReadyOption) self.unpauseIfOthersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfOthersReadyOption.setObjectName("unpause-ifothersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFOTHERSREADY_MODE) self.readyUnpauseLayout.addWidget(self.unpauseIfOthersReadyOption) self.unpauseIfMinUsersReadyOption = QRadioButton(getMessage("unpause-ifminusersready-option")) self.readyUnpauseButtonGroup.addButton(self.unpauseIfMinUsersReadyOption) self.unpauseIfMinUsersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfMinUsersReadyOption.setObjectName("unpause-ifminusersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFMINUSERSREADY_MODE) self.readyUnpauseLayout.addWidget(self.unpauseIfMinUsersReadyOption) self.unpauseAlwaysUnpauseOption = QRadioButton(getMessage("unpause-always")) self.readyUnpauseButtonGroup.addButton(self.unpauseAlwaysUnpauseOption) self.unpauseAlwaysUnpauseOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseAlwaysUnpauseOption.setObjectName("unpause-always" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_ALWAYS_MODE) self.readyUnpauseLayout.addWidget(self.unpauseAlwaysUnpauseOption) self.readyLayout.addWidget(self.readyUnpauseGroup) self.readyLayout.setAlignment(Qt.AlignTop) self.stackedLayout.addWidget(self.readyFrame) def addMiscTab(self): self.miscFrame = QtGui.QFrame() self.miscLayout = QtGui.QVBoxLayout() self.miscFrame.setLayout(self.miscLayout) self.coreSettingsGroup = QtGui.QGroupBox(getMessage("core-behaviour-title")) self.coreSettingsLayout = QtGui.QGridLayout() self.coreSettingsGroup.setLayout(self.coreSettingsLayout) ### Privacy: self.filenameprivacyLabel = QLabel(getMessage("filename-privacy-label"), self) self.filenameprivacyButtonGroup = QButtonGroup() self.filenameprivacySendRawOption = QRadioButton(getMessage("privacy-sendraw-option")) self.filenameprivacySendHashedOption = QRadioButton(getMessage("privacy-sendhashed-option")) self.filenameprivacyDontSendOption = QRadioButton(getMessage("privacy-dontsend-option")) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendRawOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendHashedOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacyDontSendOption) self.filesizeprivacyLabel = QLabel(getMessage("filesize-privacy-label"), self) self.filesizeprivacyButtonGroup = QButtonGroup() self.filesizeprivacySendRawOption = QRadioButton(getMessage("privacy-sendraw-option")) self.filesizeprivacySendHashedOption = QRadioButton(getMessage("privacy-sendhashed-option")) self.filesizeprivacyDontSendOption = QRadioButton(getMessage("privacy-dontsend-option")) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendRawOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendHashedOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacyDontSendOption) self.filenameprivacyLabel.setObjectName("filename-privacy") self.filenameprivacySendRawOption.setObjectName("privacy-sendraw" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDRAW_MODE) self.filenameprivacySendHashedOption.setObjectName("privacy-sendhashed" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDHASHED_MODE) self.filenameprivacyDontSendOption.setObjectName("privacy-dontsend" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_DONTSEND_MODE) self.filesizeprivacyLabel.setObjectName("filesize-privacy") self.filesizeprivacySendRawOption.setObjectName("privacy-sendraw" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDRAW_MODE) self.filesizeprivacySendHashedOption.setObjectName("privacy-sendhashed" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDHASHED_MODE) self.filesizeprivacyDontSendOption.setObjectName("privacy-dontsend" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_DONTSEND_MODE) self.coreSettingsLayout.addWidget(self.filenameprivacyLabel, 3, 0) self.coreSettingsLayout.addWidget(self.filenameprivacySendRawOption, 3, 1, Qt.AlignLeft) self.coreSettingsLayout.addWidget(self.filenameprivacySendHashedOption, 3, 2, Qt.AlignLeft) self.coreSettingsLayout.addWidget(self.filenameprivacyDontSendOption, 3, 3, Qt.AlignLeft) self.coreSettingsLayout.addWidget(self.filesizeprivacyLabel, 4, 0) self.coreSettingsLayout.addWidget(self.filesizeprivacySendRawOption, 4, 1, Qt.AlignLeft) self.coreSettingsLayout.addWidget(self.filesizeprivacySendHashedOption, 4, 2, Qt.AlignLeft) self.coreSettingsLayout.addWidget(self.filesizeprivacyDontSendOption, 4, 3, Qt.AlignLeft) ## Syncplay internals self.internalSettingsGroup = QtGui.QGroupBox(getMessage("syncplay-internals-title")) self.internalSettingsLayout = QtGui.QVBoxLayout() self.internalSettingsGroup.setLayout(self.internalSettingsLayout) self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label")) self.alwaysshowCheckbox.setObjectName(constants.INVERTED_STATE_MARKER + "forceGuiPrompt") self.internalSettingsLayout.addWidget(self.alwaysshowCheckbox) self.automaticupdatesCheckbox = QCheckBox(getMessage("checkforupdatesautomatically-label")) self.automaticupdatesCheckbox.setObjectName("checkForUpdatesAutomatically") self.internalSettingsLayout.addWidget(self.automaticupdatesCheckbox) self.miscLayout.addWidget(self.coreSettingsGroup) self.miscLayout.addWidget(self.internalSettingsGroup) self.miscLayout.setAlignment(Qt.AlignTop) self.stackedLayout.addWidget(self.miscFrame) def addSyncTab(self): self.syncSettingsFrame = QtGui.QFrame() self.syncSettingsLayout = QtGui.QVBoxLayout() self.desyncSettingsGroup = QtGui.QGroupBox(getMessage("sync-otherslagging-title")) self.desyncOptionsFrame = QtGui.QFrame() self.desyncSettingsOptionsLayout = QtGui.QHBoxLayout() config = self.config self.slowdownCheckbox = QCheckBox(getMessage("slowondesync-label")) self.slowdownCheckbox.setObjectName("slowOnDesync") self.rewindCheckbox = QCheckBox(getMessage("rewindondesync-label")) self.rewindCheckbox.setObjectName("rewindOnDesync") self.fastforwardCheckbox = QCheckBox(getMessage("fastforwardondesync-label")) self.fastforwardCheckbox.setObjectName("fastforwardOnDesync") self.desyncSettingsLayout = QtGui.QGridLayout() self.desyncSettingsLayout.setSpacing(2) self.desyncFrame = QtGui.QFrame() self.desyncFrame.setLineWidth(0) self.desyncFrame.setMidLineWidth(0) self.desyncSettingsLayout.addWidget(self.slowdownCheckbox, 0, 0, 1, 2, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.rewindCheckbox, 1, 0,1,2, Qt.AlignLeft) self.desyncSettingsLayout.setAlignment(Qt.AlignLeft) self.desyncSettingsGroup.setLayout(self.desyncSettingsLayout) self.desyncSettingsOptionsLayout.addWidget(self.desyncFrame) self.desyncFrame.setLayout(self.syncSettingsLayout) self.othersyncSettingsGroup = QtGui.QGroupBox(getMessage("sync-youlaggging-title")) self.othersyncOptionsFrame = QtGui.QFrame() self.othersyncSettingsLayout = QtGui.QGridLayout() self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label")) self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe") self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 2, 0, 1, 2, Qt.AlignLeft) self.othersyncSettingsLayout.setAlignment(Qt.AlignLeft) self.othersyncSettingsLayout.addWidget(self.fastforwardCheckbox, 3, 0,1,2, Qt.AlignLeft) self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout) self.othersyncSettingsGroup.setMaximumHeight(self.othersyncSettingsGroup.minimumSizeHint().height()) self.syncSettingsLayout.addWidget(self.othersyncSettingsGroup) self.syncSettingsLayout.addWidget(self.desyncSettingsGroup) self.syncSettingsFrame.setLayout(self.syncSettingsLayout) self.desyncSettingsGroup.setMaximumHeight(self.desyncSettingsGroup.minimumSizeHint().height()) self.syncSettingsLayout.setAlignment(Qt.AlignTop) self.stackedLayout.addWidget(self.syncSettingsFrame) def addMessageTab(self): self.messageFrame = QtGui.QFrame() self.messageLayout = QtGui.QVBoxLayout() self.messageLayout.setAlignment(Qt.AlignTop) # OSD self.osdSettingsGroup = QtGui.QGroupBox(getMessage("messages-osd-title")) self.osdSettingsLayout = QtGui.QVBoxLayout() self.osdSettingsFrame = QtGui.QFrame() self.showOSDCheckbox = QCheckBox(getMessage("showosd-label")) self.showOSDCheckbox.setObjectName("showOSD") self.osdSettingsLayout.addWidget(self.showOSDCheckbox) self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label")) self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD") self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox) self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label")) self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD") self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox) self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label")) self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD") self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox) self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label")) self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD") self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox) self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label")) self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings") self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox) self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"] self.osdSettingsGroup.setLayout(self.osdSettingsLayout) self.osdSettingsGroup.setMaximumHeight(self.osdSettingsGroup.minimumSizeHint().height()) self.osdSettingsLayout.setAlignment(Qt.AlignTop) self.messageLayout.addWidget(self.osdSettingsGroup) # Other display self.displaySettingsGroup = QtGui.QGroupBox(getMessage("messages-other-title")) self.displaySettingsLayout = QtGui.QVBoxLayout() self.displaySettingsLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.displaySettingsFrame = QtGui.QFrame() self.showDurationNotificationCheckbox = QCheckBox(getMessage("showdurationnotification-label")) self.showDurationNotificationCheckbox.setObjectName("showDurationNotification") self.displaySettingsLayout.addWidget(self.showDurationNotificationCheckbox) self.languageFrame = QtGui.QFrame() self.languageLayout = QtGui.QHBoxLayout() self.languageLayout.setContentsMargins(0, 0, 0, 0) self.languageFrame.setLayout(self.languageLayout) self.languageFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) self.languageLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.languageLabel = QLabel(getMessage("language-label"), self) self.languageCombobox = QtGui.QComboBox(self) self.languageCombobox.addItem(getMessage("automatic-language").format(getMessage("LANGUAGE", getInitialLanguage()))) self.languages = getLanguages() for lang in self.languages: self.languageCombobox.addItem(self.languages[lang], lang) if lang == self.config['language']: self.languageCombobox.setCurrentIndex(self.languageCombobox.count()-1) self.languageCombobox.currentIndexChanged.connect(self.languageChanged) self.languageLayout.addWidget(self.languageLabel, 1, 0) self.languageLayout.addWidget(self.languageCombobox, 1, 1) self.displaySettingsLayout.addWidget(self.languageFrame) self.languageLabel.setObjectName("language") self.languageCombobox.setObjectName("language") self.languageFrame.setMaximumWidth(self.languageFrame.minimumSizeHint().width()) self.displaySettingsGroup.setLayout(self.displaySettingsLayout) self.displaySettingsGroup.setMaximumHeight(self.displaySettingsGroup.minimumSizeHint().height()) self.displaySettingsLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.messageLayout.addWidget(self.displaySettingsGroup) # messageFrame self.messageFrame.setLayout(self.messageLayout) self.stackedLayout.addWidget(self.messageFrame) def addBottomLayout(self): config = self.config resourcespath = self.resourcespath self.bottomButtonFrame = QtGui.QFrame() self.bottomButtonLayout = QtGui.QHBoxLayout() self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'help.png'), getMessage("help-label")) self.helpButton.setObjectName("help") self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.pressed.connect(self.openHelp) self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'cog_delete.png'),getMessage("reset-label")) self.resetButton.setMaximumSize(self.resetButton.sizeHint()) self.resetButton.setObjectName("reset") self.resetButton.pressed.connect(self.resetSettings) self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label")) self.runButton.pressed.connect(self._saveDataAndLeave) self.bottomButtonLayout.addWidget(self.helpButton) self.bottomButtonLayout.addWidget(self.resetButton) self.bottomButtonLayout.addWidget(self.runButton) self.bottomButtonFrame.setLayout(self.bottomButtonLayout) if config['noStore'] == True: self.runButton.setText(getMessage("run-label")) self.bottomButtonLayout.setContentsMargins(5,0,5,0) self.mainLayout.addWidget(self.bottomButtonFrame, 1, 0, 1, 2) self.bottomCheckboxFrame = QtGui.QFrame() self.bottomCheckboxFrame.setContentsMargins(0,0,0,0) self.bottomCheckboxLayout = QtGui.QGridLayout() self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label")) self.nostoreCheckbox = QCheckBox(getMessage("nostore-label")) self.bottomCheckboxLayout.addWidget(self.showmoreCheckbox) self.bottomCheckboxLayout.addWidget(self.nostoreCheckbox, 0, 2, Qt.AlignRight) self.alwaysshowCheckbox.setObjectName(constants.INVERTED_STATE_MARKER + "forceGuiPrompt") self.nostoreCheckbox.setObjectName("noStore") self.nostoreCheckbox.toggled.connect(self.runButtonTextUpdate) self.bottomCheckboxFrame.setLayout(self.bottomCheckboxLayout) self.mainLayout.addWidget(self.bottomCheckboxFrame, 2, 0, 1, 2) def tabList(self): self.tabListLayout = QtGui.QHBoxLayout() self.tabListFrame = QtGui.QFrame() self.tabListWidget = QtGui.QListWidget() self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "house.png"),getMessage("basics-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "control_pause_blue.png"),getMessage("readiness-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "film_link.png"),getMessage("sync-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "comments.png"),getMessage("messages-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "cog.png"),getMessage("misc-label"))) self.tabListLayout.addWidget(self.tabListWidget) self.tabListFrame.setLayout(self.tabListLayout) self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width()) self.tabListWidget.setStyleSheet(constants.STYLE_TABLIST) self.tabListWidget.currentItemChanged.connect(self.tabChange) self.tabListWidget.itemClicked.connect(self.tabChange) self.tabListWidget.itemPressed.connect(self.tabChange) self.mainLayout.addWidget(self.tabListFrame, 0, 0, 1, 1) def ensureTabListIsVisible(self): self.stackedFrame.setFixedWidth(self.stackedFrame.width()) while self.tabListWidget.horizontalScrollBar().isVisible() and self.tabListFrame.width() < 200: self.tabListFrame.setFixedWidth(self.tabListFrame.width()+1) def tabChange(self): self.setFocus() self.stackedLayout.setCurrentIndex(self.tabListWidget.currentRow()) def resetSettings(self): self.clearGUIData(leaveMore=True) self.config['resetConfig'] = True self.pressedclosebutton = True self.close() def showEvent(self, *args, **kwargs): self.ensureTabListIsVisible() self.setFixedWidth(self.minimumSizeHint().width()) self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width()) def clearGUIData(self, leaveMore=False): settings = QSettings("Syncplay", "PlayerList") settings.clear() settings = QSettings("Syncplay", "MediaBrowseDialog") settings.clear() settings = QSettings("Syncplay", "MainWindow") settings.clear() settings = QSettings("Syncplay", "Interface") settings.beginGroup("Update") settings.setValue("lastChecked", None) settings.endGroup() if not leaveMore: settings = QSettings("Syncplay", "MoreSettings") settings.clear() self.datacleared = True def __init__(self, config, playerpaths, error, defaultConfig): from syncplay import utils self.config = config self.defaultConfig = defaultConfig self.playerpaths = playerpaths self.datacleared = False self.config['resetConfig'] = False self.subitems = {} if self.config['clearGUIData'] == True: self.config['clearGUIData'] = False self.clearGUIData() self.QtGui = QtGui self.error = error if sys.platform.startswith('win'): resourcespath = utils.findWorkingDir() + "\\resources\\" else: resourcespath = utils.findWorkingDir() + "/resources/" self.posixresourcespath = utils.findWorkingDir().replace("\\","/") + "/resources/" self.resourcespath = resourcespath super(ConfigDialog, self).__init__() self.setWindowTitle(getMessage("config-window-title")) self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png")) self.stackedLayout = QtGui.QStackedLayout() self.stackedFrame = QtGui.QFrame() self.stackedFrame.setLayout(self.stackedLayout) self.mainLayout = QtGui.QGridLayout() self.mainLayout.setSpacing(0) self.mainLayout.setContentsMargins(0,0,0,0) self.addBasicTab() self.addReadinessTab() self.addSyncTab() self.addMessageTab() self.addMiscTab() self.tabList() self.mainLayout.addWidget(self.stackedFrame, 0, 1) self.addBottomLayout() if self.getMoreState() == False: self.tabListFrame.hide() self.nostoreCheckbox.hide() self.resetButton.hide() else: self.showmoreCheckbox.setChecked(True) self.tabListWidget.setCurrentRow(0) self.showmoreCheckbox.toggled.connect(self.moreToggled) self.setLayout(self.mainLayout) self.runButton.setFocus() self.setFixedSize(self.sizeHint()) self.setAcceptDrops(True) if constants.SHOW_TOOLTIPS: self.processWidget(self, lambda w: self.loadTooltips(w)) self.processWidget(self, lambda w: self.loadValues(w)) self.processWidget(self, lambda w: self.connectChildren(w))
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.renderController.clippingPlanesChanged.connect( self.showsClippingPlanes) self.sliceLabelTexts = ["Axial:", "Coronal:", "Sagittal:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) slicesLayout = QGridLayout() slicesLayout.setAlignment(Qt.AlignTop) for index in range(3): slicesLayout.addWidget(self.sliceLabels[index], index + 1, 0) slicesLayout.addWidget(self.sliceCheckBoxes[index], index + 1, 1) self.slicesGroupBox = QGroupBox() self.slicesGroupBox.setTitle("Visible slices") self.slicesGroupBox.setLayout(slicesLayout) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.setChecked(self.renderController.clippingBox) self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingPlanesCheckBox = QCheckBox() self.clippingPlanesCheckBox.setChecked( self.renderController.clippingPlanes) self.clippingPlanesCheckBox.clicked.connect( self.clippingPlanesCheckBoxChanged) self.resetButton = QPushButton("Reset") self.resetButton.clicked.connect(self.resetClippingBox) clippingLabel = QLabel("Clipping box:") clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clippingPlanesLabel = QLabel("Clipping planes:") clippingPlanesLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clipLayout = QGridLayout() clipLayout.addWidget(clippingLabel, 0, 0) clipLayout.addWidget(self.clippingCheckBox, 0, 1) clipLayout.addWidget(clippingPlanesLabel, 1, 0) clipLayout.addWidget(self.clippingPlanesCheckBox, 1, 1) clipLayout.addWidget(self.resetButton, 2, 0) self.clippingGroupBox = QGroupBox() self.clippingGroupBox.setTitle("Clipping box") self.clippingGroupBox.setLayout(clipLayout) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.slicesGroupBox, 0, 0) layout.addWidget(self.clippingGroupBox, 0, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState( ) == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox( self.clippingCheckBox.checkState() == Qt.Checked) @Slot() def clippingPlanesCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingPlanes( self.clippingPlanesCheckBox.checkState() == Qt.Checked) @Slot() def resetClippingBox(self): self.renderController.resetClippingBox() @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show) @Slot(bool) def showsClippingPlanes(self, show): self.clippingPlanesCheckBox.setChecked(show)
class ExchangeView(QGroupBox): '''The box containing the rate value''' def __init__(self, title = 'Peak Exchange Matrix', parent = None): '''Initialize''' super(ExchangeView, self).__init__(parent) self.setTitle(title) self._createWidgets() def _createWidgets(self): '''Create the widgets contained in this box''' # Peak number chooser self.numpeaks = [QRadioButton("2"), QRadioButton("3"), QRadioButton("4")] self.numpeaks[0].setToolTip(ttt('Model the exchange of 2 peaks')) self.numpeaks[1].setToolTip(ttt('Model the exchange of 3 peaks')) self.numpeaks[2].setToolTip(ttt('Model the exchange of 4 peaks')) # Make 4x4 matrix of QLabels self.exview = [[QLabel(self) for i in xrange(4)] for j in xrange(4)] for i in xrange(4): for e in self.exview[i]: e.setToolTip(ttt('The current exchange matrix')) # Enforce symmetry button self.symmetry = QCheckBox("Enforce Symmetry", self) self.symmetry.setToolTip(ttt('If symmetry is on then you only need to ' 'manually set the upper triangle of the ' 'exchange matrix. Thse values are ' 'mirrored ' 'in the lower triangle and the diagonals ' 'are automatically set so that each row ' 'sums to 1. ' 'Otherwise you must set every element')) # Exchange picker self.exchooser = QComboBox(self) self.exchooser.setToolTip(ttt('Choose between which two peaks to set ' 'the exchange (relative) rate')) # Exchange value self.exvalue = QLineEdit(self) self.exvalue.setToolTip(ttt('The exchange (relative) rate')) self.exvalue.setValidator(QDoubleValidator(0.0, 1.0, 3, self.exvalue)) def makeConnections(self): '''Connect the widgets together''' # When the table has been resized, tidy it up self.matrix.matrixChanged.connect(self.resetMatrix) # If the check state changed, change the data model self.symmetry.stateChanged.connect(self.changeDataModel) self.numpeaks[0].clicked.connect(self.changeDataModel) self.numpeaks[1].clicked.connect(self.changeDataModel) self.numpeaks[2].clicked.connect(self.changeDataModel) # Attach the chooser to an exchange rate self.exchooser.currentIndexChanged.connect(self.attachExchange) # If the exchange rate is changed, update the matrix self.exvalue.editingFinished.connect(self.newExchange) def initUI(self): '''Lays out the widgets''' nums = QHBoxLayout() nums.addWidget(QLabel("Number of Peaks: ")) nums.addWidget(self.numpeaks[0]) nums.addWidget(self.numpeaks[1]) nums.addWidget(self.numpeaks[2]) val = QHBoxLayout() val.addWidget(QLabel("Exchange: ")) val.addStretch() val.addWidget(self.exchooser) self.exvalue.setMaximumWidth(50) val.addWidget(self.exvalue) ex = QGridLayout() for i in xrange(4): for j in xrange(4): ex.addWidget(self.exview[i][j], i+1, j+1) lo = QVBoxLayout() lo.addLayout(nums) lo.addWidget(self.symmetry) lo.addLayout(val) lo.addLayout(ex) self.setLayout(lo) def setModel(self, model, npmodel): '''Attaches models to the views.''' self.matrix = model self.npmodel = npmodel def setNumPeaks(self, npeaks): '''Manually set the number of peaks''' if npeaks == 2: self.numpeaks[0].click() elif npeaks == 3: self.numpeaks[1].click() elif npeaks == 4: self.numpeaks[2].click() else: error.showMessage('Only valid number of peaks is 2, 3, or 4') def setMatrixSymmetry(self, sym): '''Manually set the matrix symmetry''' self.symmetry.setChecked(sym) def setMatrix(self, Z): '''Manually set the matrix elements with a numpy matrix''' npeaks = self.npmodel.getNumPeaks() self.matrix.matrix = Z[0:npeaks,0:npeaks] self.matrix.updateInternalModel(npeaks) self.resetMatrix() ####### # SLOTS ####### def newExchange(self): '''Prepares an exchange value to be broadcasted''' try: value = round(float(self.exvalue.text()), 3) except ValueError: value = 0.0 indx = self.exchooser.currentIndex() if self.numpeaks[0].isChecked(): npeaks = 2 elif self.numpeaks[1].isChecked(): npeaks = 3 elif self.numpeaks[2].isChecked(): npeaks = 4 self.matrix.updateExchange(value, indx, npeaks) def resetMatrix(self): '''Reset the matrix values''' # Iterate over the matrix and fill the values for index, num in ndenumerate(self.matrix.matrix): self.exview[index[0]][index[1]].setText('{0:.3f}'.format(num)) # Set all other values to two dashes if len(self.matrix.matrix) == 2: for i in xrange(4): for j in xrange(4): if not (i < 2 and j < 2): self.exview[i][j].setText('--') elif len(self.matrix.matrix) == 3: for i in xrange(4): for j in xrange(4): if not (i < 3 and j < 3): self.exview[i][j].setText('--') def changeDataModel(self): '''Change the matrix from symmetric to not or vice versa''' # Change the model for the combo box if self.numpeaks[0].isChecked(): npeaks = 2 elif self.numpeaks[1].isChecked(): npeaks = 3 elif self.numpeaks[2].isChecked(): npeaks = 4 self.npmodel.setNumPeaks(npeaks) self.matrix.sym = self.symmetry.isChecked() if self.matrix.sym: self.exchooser.setModel(self.matrix.symex[npeaks]) else: self.exchooser.setModel(self.matrix.unsymex[npeaks]) # Reset the matrix self.matrix.setMatrix(npeaks) def attachExchange(self, indx): '''Attach a new exchange rate to the chooser''' r = self.matrix.symrate if self.matrix.sym else self.matrix.unsymrate self.exvalue.setText('{0:.3f}'.format(r[self.npmodel.numPeaks][indx]))
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.renderController.clippingPlanesChanged.connect(self.showsClippingPlanes) self.sliceLabelTexts = ["Axial:", "Coronal:", "Sagittal:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) slicesLayout = QGridLayout() slicesLayout.setAlignment(Qt.AlignTop) for index in range(3): slicesLayout.addWidget(self.sliceLabels[index], index+1, 0) slicesLayout.addWidget(self.sliceCheckBoxes[index], index+1, 1) self.slicesGroupBox = QGroupBox() self.slicesGroupBox.setTitle("Visible slices") self.slicesGroupBox.setLayout(slicesLayout) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.setChecked(self.renderController.clippingBox) self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingPlanesCheckBox = QCheckBox() self.clippingPlanesCheckBox.setChecked(self.renderController.clippingPlanes) self.clippingPlanesCheckBox.clicked.connect(self.clippingPlanesCheckBoxChanged) self.resetButton = QPushButton("Reset") self.resetButton.clicked.connect(self.resetClippingBox) clippingLabel = QLabel("Clipping box:") clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clippingPlanesLabel = QLabel("Clipping planes:") clippingPlanesLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clipLayout = QGridLayout() clipLayout.addWidget(clippingLabel, 0, 0) clipLayout.addWidget(self.clippingCheckBox, 0, 1) clipLayout.addWidget(clippingPlanesLabel, 1, 0) clipLayout.addWidget(self.clippingPlanesCheckBox, 1, 1) clipLayout.addWidget(self.resetButton, 2, 0) self.clippingGroupBox = QGroupBox() self.clippingGroupBox.setTitle("Clipping box") self.clippingGroupBox.setLayout(clipLayout) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.slicesGroupBox, 0, 0) layout.addWidget(self.clippingGroupBox, 0, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState() == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox(self.clippingCheckBox.checkState() == Qt.Checked) @Slot() def clippingPlanesCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingPlanes(self.clippingPlanesCheckBox.checkState() == Qt.Checked) @Slot() def resetClippingBox(self): self.renderController.resetClippingBox() @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show) @Slot(bool) def showsClippingPlanes(self, show): self.clippingPlanesCheckBox.setChecked(show)
class ConfigDialog(QtGui.QDialog): pressedclosebutton = False moreToggling = False def moreToggled(self): if self.moreToggling == False: self.moreToggling = True if self.showmoreCheckbox.isChecked(): self.tabListFrame.show() self.resetButton.show() self.nostoreCheckbox.show() self.alwaysshowCheckbox.show() self.saveMoreState(True) self.tabListWidget.setCurrentRow(0) self.ensureTabListIsVisible() else: self.tabListFrame.hide() self.resetButton.hide() self.nostoreCheckbox.hide() self.alwaysshowCheckbox.hide() self.saveMoreState(False) self.stackedLayout.setCurrentIndex(0) self.adjustSize() self.setFixedSize(self.sizeHint()) self.moreToggling = False self.setFixedWidth(self.minimumSizeHint().width()) self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width()) def runButtonTextUpdate(self): if self.nostoreCheckbox.isChecked(): self.runButton.setText(getMessage("run-label")) else: self.runButton.setText(getMessage("storeandrun-label")) def openHelp(self): self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/client/") def _tryToFillPlayerPath(self, playerpath, playerpathlist): settings = QSettings("Syncplay", "PlayerList") settings.beginGroup("PlayerList") savedPlayers = settings.value("PlayerList", []) if not isinstance(savedPlayers, list): savedPlayers = [] playerpathlist = list(set(os.path.normcase(os.path.normpath(path)) for path in set(playerpathlist + savedPlayers))) settings.endGroup() foundpath = "" if playerpath != None and playerpath != "": if not os.path.isfile(playerpath): expandedpath = PlayerFactory().getExpandedPlayerPathByPath(playerpath) if expandedpath != None and os.path.isfile(expandedpath): playerpath = expandedpath if os.path.isfile(playerpath): foundpath = playerpath self.executablepathCombobox.addItem(foundpath) for path in playerpathlist: if os.path.isfile(path) and os.path.normcase(os.path.normpath(path)) != os.path.normcase(os.path.normpath(foundpath)): self.executablepathCombobox.addItem(path) if foundpath == "": foundpath = path if foundpath != "": settings.beginGroup("PlayerList") playerpathlist.append(os.path.normcase(os.path.normpath(foundpath))) settings.setValue("PlayerList", list(set(os.path.normcase(os.path.normpath(path)) for path in set(playerpathlist)))) settings.endGroup() return foundpath def updateExecutableIcon(self): currentplayerpath = unicode(self.executablepathCombobox.currentText()) iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) if iconpath != None and iconpath != "": self.executableiconImage.load(self.resourcespath + iconpath) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) else: self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) def browsePlayerpath(self): options = QtGui.QFileDialog.Options() defaultdirectory = "" browserfilter = "All files (*)" if os.name == 'nt': browserfilter = "Executable files (*.exe);;All files (*)" if "PROGRAMFILES(X86)" in os.environ: defaultdirectory = os.environ["ProgramFiles(x86)"] elif "PROGRAMFILES" in os.environ: defaultdirectory = os.environ["ProgramFiles"] elif "PROGRAMW6432" in os.environ: defaultdirectory = os.environ["ProgramW6432"] elif sys.platform.startswith('linux'): defaultdirectory = "/usr/bin" elif sys.platform.startswith('darwin'): defaultdirectory = "/Applications/" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media player executable", defaultdirectory, browserfilter, "", options) if fileName: self.executablepathCombobox.setEditText(os.path.normpath(fileName)) def loadMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") self.mediadirectory = settings.value("mediadir", "") settings.endGroup() def saveMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") settings.setValue("mediadir", self.mediadirectory) settings.endGroup() def getMoreState(self): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") morestate = unicode.lower(unicode(settings.value("ShowMoreSettings", "false"))) settings.endGroup() if morestate == "true": return True else: return False def saveMoreState(self, morestate): settings = QSettings("Syncplay", "MoreSettings") settings.beginGroup("MoreSettings") settings.setValue("ShowMoreSettings", morestate) settings.endGroup() def browseMediapath(self): self.loadMediaBrowseSettings() options = QtGui.QFileDialog.Options() if os.path.isdir(self.mediadirectory): defaultdirectory = self.mediadirectory elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.MoviesLocation)): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.MoviesLocation) elif os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.HomeLocation)): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) else: defaultdirectory = "" browserfilter = "All files (*)" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory, browserfilter, "", options) if fileName: self.mediapathTextbox.setText(os.path.normpath(fileName)) self.mediadirectory = os.path.dirname(fileName) self.saveMediaBrowseSettings() def _saveDataAndLeave(self): self.processWidget(self, lambda w: self.saveValues(w)) if self.hostTextbox.text(): self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT) else: self.config['host'] = None self.config['playerPath'] = unicode(self.executablepathCombobox.currentText()) if self.mediapathTextbox.text() == "": self.config['file'] = None elif os.path.isfile(os.path.abspath(self.mediapathTextbox.text())): self.config['file'] = os.path.abspath(self.mediapathTextbox.text()) else: self.config['file'] = unicode(self.mediapathTextbox.text()) if not self.slowdownThresholdSpinbox.text: self.slowdownThresholdSpinbox.value = constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD if not self.rewindThresholdSpinbox.text: self.rewindThresholdSpinbox.value = constants.DEFAULT_REWIND_THRESHOLD self.config['slowdownThreshold'] = self.slowdownThresholdSpinbox.value() self.config['rewindThreshold'] = self.rewindThresholdSpinbox.value() self.pressedclosebutton = True self.close() return def closeEvent(self, event): if self.pressedclosebutton == False: sys.exit() raise GuiConfiguration.WindowClosed event.accept() def dragEnterEvent(self, event): data = event.mimeData() urls = data.urls() if urls and urls[0].scheme() == 'file': event.acceptProposedAction() def dropEvent(self, event): data = event.mimeData() urls = data.urls() if urls and urls[0].scheme() == 'file': if sys.platform.startswith('win'): dropfilepath = unicode(urls[0].path())[1:] # Removes starting slash else: dropfilepath = unicode(urls[0].path()) if dropfilepath[-4:].lower() == ".exe": self.executablepathCombobox.setEditText(dropfilepath) else: self.mediapathTextbox.setText(dropfilepath) def processWidget(self, container, torun): for widget in container.children(): self.processWidget(widget, torun) if hasattr(widget, 'objectName') and widget.objectName() and widget.objectName()[:3] != "qt_": torun(widget) def loadTooltips(self, widget): tooltipName = widget.objectName().lower().split(constants.CONFIG_NAME_MARKER)[0] + "-tooltip" if tooltipName[:1] == constants.INVERTED_STATE_MARKER or tooltipName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: tooltipName = tooltipName[1:] widget.setToolTip(getMessage(tooltipName)) def loadValues(self, widget): valueName = str(widget.objectName()) if valueName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: return if isinstance(widget, QCheckBox) and widget.objectName(): if valueName[:1] == constants.INVERTED_STATE_MARKER: valueName = valueName[1:] inverted = True else: inverted = False widget.setChecked(self.config[valueName] != inverted) elif isinstance(widget, QRadioButton): radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER) if self.config[radioName] == radioValue: widget.setChecked(True) elif isinstance(widget, QLineEdit): widget.setText(self.config[valueName]) def saveValues(self, widget): valueName = str(widget.objectName()) if valueName[:1] == constants.LOAD_SAVE_MANUALLY_MARKER: return if isinstance(widget, QCheckBox) and widget.objectName(): if valueName[:1] == constants.INVERTED_STATE_MARKER: valueName = valueName[1:] inverted = True else: inverted = False self.config[valueName] = widget.isChecked() != inverted elif isinstance(widget, QRadioButton): radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER) if widget.isChecked(): self.config[radioName] = radioValue elif isinstance(widget, QLineEdit): self.config[valueName] = widget.text() def connectChildren(self, widget): widgetName = str(widget.objectName()) if self.subitems.has_key(widgetName) and isinstance(widget, QCheckBox): widget.stateChanged.connect(lambda: self.updateSubwidgets(self, widget)) self.updateSubwidgets(self, widget) def updateSubwidgets(self, container, parentwidget, subwidgets=None): widgetName = parentwidget.objectName() if not subwidgets: subwidgets = self.subitems[widgetName] for widget in container.children(): self.updateSubwidgets(widget, parentwidget, subwidgets) if hasattr(widget, 'objectName') and widget.objectName() and widget.objectName() in subwidgets: widget.setDisabled(not parentwidget.isChecked()) def addBasicTab(self): config = self.config playerpaths = self.playerpaths resourcespath = self.resourcespath error = self.error if self.datacleared == True: error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification")) if config['host'] == None: host = "" elif ":" in config['host']: host = config['host'] else: host = config['host'] + ":" + str(config['port']) self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("connection-group-title")) self.hostTextbox = QLineEdit(host, self) self.hostLabel = QLabel(getMessage("host-label"), self) self.usernameTextbox = QLineEdit(self) self.usernameTextbox.setObjectName("name") self.serverpassLabel = QLabel(getMessage("password-label"), self) self.defaultroomTextbox = QLineEdit(self) self.usernameLabel = QLabel(getMessage("name-label"), self) self.serverpassTextbox = QLineEdit(self) self.defaultroomLabel = QLabel(getMessage("room-label"), self) self.hostLabel.setObjectName("host") self.hostTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "host") self.usernameLabel.setObjectName("name") self.usernameTextbox.setObjectName("name") self.serverpassLabel.setObjectName("password") self.serverpassTextbox.setObjectName("password") self.defaultroomLabel.setObjectName("room") self.defaultroomTextbox.setObjectName("room") self.connectionSettingsLayout = QtGui.QGridLayout() self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) self.connectionSettingsLayout.addWidget(self.hostTextbox, 0, 1) self.connectionSettingsLayout.addWidget(self.serverpassLabel, 1, 0) self.connectionSettingsLayout.addWidget(self.serverpassTextbox, 1, 1) self.connectionSettingsLayout.addWidget(self.usernameLabel, 2, 0) self.connectionSettingsLayout.addWidget(self.usernameTextbox, 2, 1) self.connectionSettingsLayout.addWidget(self.defaultroomLabel, 3, 0) self.connectionSettingsLayout.addWidget(self.defaultroomTextbox, 3, 1) self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) self.mediaplayerSettingsGroup = QtGui.QGroupBox(getMessage("media-setting-title")) self.executableiconImage = QtGui.QImage() self.executableiconLabel = QLabel(self) self.executableiconLabel.setMinimumWidth(16) self.executablepathCombobox = QtGui.QComboBox(self) self.executablepathCombobox.setEditable(True) self.executablepathCombobox.currentIndexChanged.connect(self.updateExecutableIcon) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'], playerpaths)) self.executablepathCombobox.setFixedWidth(165) self.executablepathCombobox.editTextChanged.connect(self.updateExecutableIcon) self.executablepathLabel = QLabel(getMessage("executable-path-label"), self) self.executablebrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.executablebrowseButton.clicked.connect(self.browsePlayerpath) self.mediapathTextbox = QLineEdit(config['file'], self) self.mediapathLabel = QLabel(getMessage("media-path-label"), self) self.mediabrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'), getMessage("browse-label")) self.mediabrowseButton.clicked.connect(self.browseMediapath) self.executablepathLabel.setObjectName("executable-path") self.executablepathCombobox.setObjectName("executable-path") self.mediapathLabel.setObjectName("media-path") self.mediapathTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "media-path") self.mediaplayerSettingsLayout = QtGui.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) self.mediaplayerSettingsLayout.addWidget(self.executableiconLabel, 0, 1) self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox, 0, 2) self.mediaplayerSettingsLayout.addWidget(self.executablebrowseButton, 0, 3) self.mediaplayerSettingsLayout.addWidget(self.mediapathLabel, 1, 0) self.mediaplayerSettingsLayout.addWidget(self.mediapathTextbox , 1, 2) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) self.showmoreCheckbox = QCheckBox(getMessage("more-title")) self.showmoreCheckbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "more") self.basicOptionsFrame = QtGui.QFrame() self.basicOptionsLayout = QtGui.QVBoxLayout() if error: self.errorLabel = QLabel(self) if error[:1] != constants.ERROR_MESSAGE_MARKER: self.errorLabel.setStyleSheet(constants.STYLE_ERRORLABEL) else: error = error[1:] self.errorLabel.setStyleSheet(constants.STYLE_SUCCESSLABEL) self.errorLabel.setText(error) self.errorLabel.setAlignment(Qt.AlignCenter) self.basicOptionsLayout.addWidget(self.errorLabel, 0, 0) self.basicOptionsLayout.addWidget(self.connectionSettingsGroup) self.basicOptionsLayout.addSpacing(12) self.basicOptionsLayout.addWidget(self.mediaplayerSettingsGroup) self.basicOptionsFrame.setLayout(self.basicOptionsLayout) self.stackedLayout.addWidget(self.basicOptionsFrame) def addSyncTab(self): self.syncSettingsFrame = QtGui.QFrame() self.syncSettingsLayout = QtGui.QVBoxLayout() self.desyncSettingsGroup = QtGui.QGroupBox("If others are lagging behind...") self.desyncOptionsFrame = QtGui.QFrame() self.desyncSettingsOptionsLayout = QtGui.QHBoxLayout() config = self.config self.slowdownCheckbox = QCheckBox(getMessage("slowondesync-label")) self.slowdownCheckbox.setObjectName("slowOnDesync") self.rewindCheckbox = QCheckBox(getMessage("rewindondesync-label")) self.rewindCheckbox.setObjectName("rewindOnDesync") self.spaceLabel = QLabel() self.spaceLabel.setFixedHeight(5) self.desyncSettingsLayout = QtGui.QGridLayout() self.desyncSettingsLayout.setSpacing(2) self.desyncFrame = QtGui.QFrame() self.desyncFrame.setLineWidth(0) self.desyncFrame.setMidLineWidth(0) self.slowdownThresholdLabel = QLabel(getMessage("slowdown-threshold-label"), self) self.slowdownThresholdLabel.setStyleSheet(constants.STYLE_SUBLABEL.format(self.posixresourcespath + "bullet_black.png")) self.slowdownThresholdSpinbox = QDoubleSpinBox() try: slowdownThreshold = float(config['slowdownThreshold']) self.slowdownThresholdSpinbox.setValue(slowdownThreshold) if slowdownThreshold < constants.MINIMUM_SLOWDOWN_THRESHOLD: constants.MINIMUM_SLOWDOWN_THRESHOLD = slowdownThreshold except ValueError: self.slowdownThresholdSpinbox.setValue(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD) self.slowdownThresholdSpinbox.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) self.slowdownThresholdSpinbox.setMinimum(constants.MINIMUM_SLOWDOWN_THRESHOLD) self.slowdownThresholdSpinbox.setSingleStep(0.1) self.slowdownThresholdSpinbox.setSuffix(getMessage("seconds-suffix")) self.slowdownThresholdSpinbox.adjustSize() self.rewindThresholdLabel = QLabel(getMessage("rewind-threshold-label"), self) self.rewindThresholdLabel.setStyleSheet(constants.STYLE_SUBLABEL.format(self.posixresourcespath + "bullet_black.png")) self.rewindThresholdSpinbox = QDoubleSpinBox() try: rewindThreshold = float(config['rewindThreshold']) self.rewindThresholdSpinbox.setValue(rewindThreshold) if rewindThreshold < constants.MINIMUM_REWIND_THRESHOLD: constants.MINIMUM_REWIND_THRESHOLD = rewindThreshold except ValueError: self.rewindThresholdSpinbox.setValue(constants.DEFAULT_REWIND_THRESHOLD) self.rewindThresholdSpinbox.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) self.rewindThresholdSpinbox.setMinimum(constants.MINIMUM_REWIND_THRESHOLD) self.rewindThresholdSpinbox.setSingleStep(0.1) self.rewindThresholdSpinbox.setSuffix(getMessage("seconds-suffix")) self.rewindThresholdSpinbox.adjustSize() self.slowdownThresholdLabel.setObjectName("slowdown-threshold") self.slowdownThresholdSpinbox.setObjectName("slowdown-threshold") self.rewindThresholdLabel.setObjectName("rewind-threshold") self.rewindThresholdSpinbox.setObjectName("rewind-threshold") self.desyncSettingsLayout.addWidget(self.slowdownCheckbox, 0, 0, 1, 2, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.slowdownThresholdLabel, 1, 0, 1, 1, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.slowdownThresholdSpinbox, 1, 1, 1, 1, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.spaceLabel, 2, 0,1,2, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.rewindCheckbox, 3, 0,1,2, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.rewindThresholdLabel, 4, 0, 1, 1, Qt.AlignLeft) self.desyncSettingsLayout.addWidget(self.rewindThresholdSpinbox, 4, 1, Qt.AlignLeft) self.subitems['slowOnDesync'] = ["slowdown-threshold"] self.subitems['rewindOnDesync'] = ["rewind-threshold"] self.desyncSettingsLayout.setAlignment(Qt.AlignLeft) self.desyncSettingsGroup.setLayout(self.desyncSettingsLayout) self.desyncSettingsOptionsLayout.addWidget(self.desyncFrame) self.syncSettingsLayout.addWidget(self.desyncSettingsGroup) self.desyncFrame.setLayout(self.syncSettingsLayout) self.othersyncSettingsGroup = QtGui.QGroupBox("Other sync options") self.othersyncOptionsFrame = QtGui.QFrame() self.othersyncSettingsLayout = QtGui.QGridLayout() self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label")) self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label")) self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox) self.othersyncSettingsLayout.addWidget(self.pauseonleaveCheckbox) self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe") self.pauseonleaveCheckbox.setObjectName("pauseOnLeave") self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout) self.syncSettingsLayout.addWidget(self.othersyncSettingsGroup) self.syncSettingsFrame.setLayout(self.syncSettingsLayout) self.desyncSettingsGroup.setMaximumHeight(self.desyncSettingsGroup.minimumSizeHint().height()) self.syncSettingsLayout.setAlignment(Qt.AlignTop) self.stackedLayout.addWidget(self.syncSettingsFrame) def addMessageTab(self): self.messageFrame = QtGui.QFrame() self.messageLayout = QtGui.QVBoxLayout() # OSD self.osdSettingsGroup = QtGui.QGroupBox("On-screen Display settings") self.osdSettingsLayout = QtGui.QVBoxLayout() self.osdSettingsFrame = QtGui.QFrame() self.showOSDCheckbox = QCheckBox(getMessage("showosd-label")) self.showOSDCheckbox.setObjectName("showOSD") self.osdSettingsLayout.addWidget(self.showOSDCheckbox) self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label")) self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD") self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png")) self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox) self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label")) self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD") self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png")) self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox) self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label")) self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD") self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png")) self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox) self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label")) self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings") self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "bullet_black.png")) self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox) self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings"] self.osdSettingsGroup.setLayout(self.osdSettingsLayout) self.osdSettingsLayout.setAlignment(Qt.AlignTop) self.messageLayout.addWidget(self.osdSettingsGroup) # Other display self.displaySettingsGroup = QtGui.QGroupBox("Other display settings") self.displaySettingsLayout = QtGui.QVBoxLayout() self.displaySettingsFrame = QtGui.QFrame() self.showDurationNotificationCheckbox = QCheckBox(getMessage("showdurationnotification-label")) self.showDurationNotificationCheckbox.setObjectName("showDurationNotification") self.displaySettingsLayout.addWidget(self.showDurationNotificationCheckbox) self.showcontactinfoCheckbox = QCheckBox(getMessage("showcontactinfo-label")) self.showcontactinfoCheckbox.setObjectName("showContactInfo") self.displaySettingsLayout.addWidget(self.showcontactinfoCheckbox) self.showButtonLabelsCheckbox = QCheckBox(getMessage("showbuttonlabels-label")) self.showButtonLabelsCheckbox.setObjectName("showButtonLabels") self.displaySettingsLayout.addWidget(self.showButtonLabelsCheckbox) self.showTooltipsCheckbox = QCheckBox(getMessage("showtooltips-label")) self.showTooltipsCheckbox.setObjectName("showTooltips") self.displaySettingsLayout.addWidget(self.showTooltipsCheckbox) self.displaySettingsGroup.setLayout(self.displaySettingsLayout) self.displaySettingsLayout.setAlignment(Qt.AlignTop) self.messageLayout.addWidget(self.displaySettingsGroup) # messageFrame self.messageFrame.setLayout(self.messageLayout) self.stackedLayout.addWidget(self.messageFrame) def addPrivacyTab(self): self.privacySettingsGroup = QtGui.QGroupBox("Privacy settings") self.privacySettingsLayout = QtGui.QVBoxLayout() self.privacySettingsFrame = QtGui.QFrame() self.privacyFrame = QtGui.QFrame() self.privacyLayout = QtGui.QGridLayout() self.filenameprivacyLabel = QLabel(getMessage("filename-privacy-label"), self) self.filenameprivacyButtonGroup = QButtonGroup() self.filenameprivacySendRawOption = QRadioButton(getMessage("privacy-sendraw-option")) self.filenameprivacySendHashedOption = QRadioButton(getMessage("privacy-sendhashed-option")) self.filenameprivacyDontSendOption = QRadioButton(getMessage("privacy-dontsend-option")) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendRawOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacySendHashedOption) self.filenameprivacyButtonGroup.addButton(self.filenameprivacyDontSendOption) self.filesizeprivacyLabel = QLabel(getMessage("filesize-privacy-label"), self) self.filesizeprivacyButtonGroup = QButtonGroup() self.filesizeprivacySendRawOption = QRadioButton(getMessage("privacy-sendraw-option")) self.filesizeprivacySendHashedOption = QRadioButton(getMessage("privacy-sendhashed-option")) self.filesizeprivacyDontSendOption = QRadioButton(getMessage("privacy-dontsend-option")) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendRawOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacySendHashedOption) self.filesizeprivacyButtonGroup.addButton(self.filesizeprivacyDontSendOption) self.filenameprivacyLabel.setObjectName("filename-privacy") self.filenameprivacySendRawOption.setObjectName("privacy-sendraw" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDRAW_MODE) self.filenameprivacySendHashedOption.setObjectName("privacy-sendhashed" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDHASHED_MODE) self.filenameprivacyDontSendOption.setObjectName("privacy-dontsend" + constants.CONFIG_NAME_MARKER + "filenamePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_DONTSEND_MODE) self.filesizeprivacyLabel.setObjectName("filesize-privacy") self.filesizeprivacySendRawOption.setObjectName("privacy-sendraw" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDRAW_MODE) self.filesizeprivacySendHashedOption.setObjectName("privacy-sendhashed" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDHASHED_MODE) self.filesizeprivacyDontSendOption.setObjectName("privacy-dontsend" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_DONTSEND_MODE) self.privacyLayout.addWidget(self.filenameprivacyLabel, 1, 0) self.privacyLayout.addWidget(self.filenameprivacySendRawOption, 1, 1, Qt.AlignLeft) self.privacyLayout.addWidget(self.filenameprivacySendHashedOption, 1, 2, Qt.AlignLeft) self.privacyLayout.addWidget(self.filenameprivacyDontSendOption, 1, 3, Qt.AlignLeft) self.privacyLayout.addWidget(self.filesizeprivacyLabel, 2, 0) self.privacyLayout.addWidget(self.filesizeprivacySendRawOption, 2, 1, Qt.AlignLeft) self.privacyLayout.addWidget(self.filesizeprivacySendHashedOption, 2, 2, Qt.AlignLeft) self.privacyLayout.addWidget(self.filesizeprivacyDontSendOption, 2, 3, Qt.AlignLeft) self.privacyFrame.setLayout(self.privacyLayout) self.privacySettingsGroup.setLayout(self.privacyLayout) self.privacySettingsGroup.setMaximumHeight(self.privacySettingsGroup.minimumSizeHint().height()) self.privacySettingsLayout.addWidget(self.privacySettingsGroup) self.privacySettingsLayout.setAlignment(Qt.AlignTop) self.privacyFrame.setLayout(self.privacySettingsLayout) self.stackedLayout.addWidget(self.privacyFrame) def addBottomLayout(self): config = self.config resourcespath = self.resourcespath self.bottomButtonFrame = QtGui.QFrame() self.bottomButtonLayout = QtGui.QHBoxLayout() self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'help.png'), getMessage("help-label")) self.helpButton.setObjectName("help") self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.pressed.connect(self.openHelp) self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'cog_delete.png'),getMessage("reset-label")) self.resetButton.setMaximumSize(self.resetButton.sizeHint()) self.resetButton.setObjectName("reset") self.resetButton.pressed.connect(self.resetSettings) self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label")) self.runButton.pressed.connect(self._saveDataAndLeave) self.bottomButtonLayout.addWidget(self.helpButton) self.bottomButtonLayout.addWidget(self.resetButton) self.bottomButtonLayout.addWidget(self.runButton) self.bottomButtonFrame.setLayout(self.bottomButtonLayout) if config['noStore'] == True: self.runButton.setText(getMessage("run-label")) self.bottomButtonLayout.setContentsMargins(5,0,5,0) self.mainLayout.addWidget(self.bottomButtonFrame, 1, 0, 1, 2) self.bottomCheckboxFrame = QtGui.QFrame() self.bottomCheckboxFrame.setContentsMargins(0,0,0,0) self.bottomCheckboxLayout = QtGui.QGridLayout() self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label")) self.nostoreCheckbox = QCheckBox(getMessage("nostore-label")) self.bottomCheckboxLayout.addWidget(self.showmoreCheckbox) self.bottomCheckboxLayout.addWidget(self.alwaysshowCheckbox, 0, 1, Qt.AlignLeft) self.bottomCheckboxLayout.addWidget(self.nostoreCheckbox, 0, 2, Qt.AlignRight) self.alwaysshowCheckbox.setObjectName(constants.INVERTED_STATE_MARKER + "forceGuiPrompt") self.nostoreCheckbox.setObjectName("noStore") self.nostoreCheckbox.toggled.connect(self.runButtonTextUpdate) self.bottomCheckboxFrame.setLayout(self.bottomCheckboxLayout) self.mainLayout.addWidget(self.bottomCheckboxFrame, 2, 0, 1, 2) def tabList(self): self.tabListLayout = QtGui.QHBoxLayout() self.tabListFrame = QtGui.QFrame() self.tabListWidget = QtGui.QListWidget() self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "house.png"),getMessage("basics-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "film_link.png"),getMessage("sync-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "comments.png"),getMessage("messages-label"))) self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "eye.png"),getMessage("privacy-label"))) self.tabListLayout.addWidget(self.tabListWidget) self.tabListFrame.setLayout(self.tabListLayout) self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width()) self.tabListWidget.setStyleSheet(constants.STYLE_TABLIST) self.tabListWidget.currentItemChanged.connect(self.tabChange) self.tabListWidget.itemClicked.connect(self.tabChange) self.tabListWidget.itemPressed.connect(self.tabChange) self.mainLayout.addWidget(self.tabListFrame, 0, 0, 1, 1) def ensureTabListIsVisible(self): self.stackedFrame.setFixedWidth(self.stackedFrame.width()) while self.tabListWidget.horizontalScrollBar().isVisible() and self.tabListFrame.width() < 200: self.tabListFrame.setFixedWidth(self.tabListFrame.width()+1) def tabChange(self): self.setFocus() self.stackedLayout.setCurrentIndex(self.tabListWidget.currentRow()) def resetSettings(self): self.clearGUIData(leaveMore=True) self.config['resetConfig'] = True self.pressedclosebutton = True self.close() def showEvent(self, *args, **kwargs): self.ensureTabListIsVisible() self.setFixedWidth(self.minimumSizeHint().width()) self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width()) def clearGUIData(self, leaveMore=False): settings = QSettings("Syncplay", "PlayerList") settings.clear() settings = QSettings("Syncplay", "MediaBrowseDialog") settings.clear() settings = QSettings("Syncplay", "MainWindow") settings.clear() if not leaveMore: settings = QSettings("Syncplay", "MoreSettings") settings.clear() self.datacleared = True def __init__(self, config, playerpaths, error, defaultConfig): from syncplay import utils self.config = config self.defaultConfig = defaultConfig self.playerpaths = playerpaths self.datacleared = False self.config['resetConfig'] = False self.subitems = {} if self.config['clearGUIData'] == True: self.config['clearGUIData'] = False self.clearGUIData() self.QtGui = QtGui self.error = error if sys.platform.startswith('win'): resourcespath = utils.findWorkingDir() + "\\resources\\" else: resourcespath = utils.findWorkingDir() + "/resources/" self.posixresourcespath = utils.findWorkingDir().replace("\\","/") + "/resources/" self.resourcespath = resourcespath super(ConfigDialog, self).__init__() self.setWindowTitle(getMessage("config-window-title")) self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png")) self.stackedLayout = QtGui.QStackedLayout() self.stackedFrame = QtGui.QFrame() self.stackedFrame.setLayout(self.stackedLayout) self.mainLayout = QtGui.QGridLayout() self.mainLayout.setSpacing(0) self.mainLayout.setContentsMargins(0,0,0,0) self.addBasicTab() self.addSyncTab() self.addMessageTab() self.addPrivacyTab() self.tabList() self.mainLayout.addWidget(self.stackedFrame, 0, 1) self.addBottomLayout() if self.getMoreState() == False: self.tabListFrame.hide() self.nostoreCheckbox.hide() self.alwaysshowCheckbox.hide() self.resetButton.hide() else: self.showmoreCheckbox.setChecked(True) self.tabListWidget.setCurrentRow(0) self.showmoreCheckbox.toggled.connect(self.moreToggled) self.setLayout(self.mainLayout) self.runButton.setFocus() self.setFixedSize(self.sizeHint()) self.setAcceptDrops(True) if constants.SHOW_TOOLTIPS: self.processWidget(self, lambda w: self.loadTooltips(w)) self.processWidget(self, lambda w: self.loadValues(w)) self.processWidget(self, lambda w: self.connectChildren(w))
class MainWindow(object): ''' Contains the implementation for building and displaying the application's main window. ''' def __init__(self, model, alg): ''' Constructs the GUI and initializes internal parameters. ''' self._window = QMainWindow() self._window.setWindowTitle("Reverse A*") self._worldWidget = WorldWidget(model, alg) self._model = model self._alg = alg self._spdSetting = 0 self._timer = QTimer() #Every time the timer times out, invoke the _onStep method. self._timer.timeout.connect(self._onStep) self._buildGUI() self._window.show() def _buildGUI(self): ''' Construct the GUI widgets and layouts. ''' centerWidget = QWidget() self._window.setCentralWidget(centerWidget) worldLayout = QHBoxLayout() worldLayout.addWidget(self._worldWidget) grpBx = QGroupBox("2D World") grpBx.setLayout(worldLayout) grpBx.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) ctrlPan = self._buildControlPanel() layout = QHBoxLayout() layout.addWidget(ctrlPan) layout.addWidget(grpBx) layout.setAlignment(ctrlPan, Qt.AlignLeft | Qt.AlignTop) centerWidget.setLayout(layout) def _buildControlPanel(self): ''' Create all buttons, labels, etc for the application control elements ''' layout = QVBoxLayout() layout.addWidget(self._buildSetupPanel()) layout.addWidget(self._buildSpeedPanel()) layout.addWidget(self._buildResultsPanel()) layout.addWidget(self._buildRenderingOptions()) layout.setAlignment(Qt.AlignLeft | Qt.AlignTop) ctrlWidget = QWidget(self._window) ctrlWidget.setLayout(layout) ctrlWidget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) return ctrlWidget def _buildSetupPanel(self): ''' Creates the sub-panel containing control widgets for re-initializing the world on demand. ''' self._percentLbl = QLabel("%") self._setupBtn = QPushButton("Setup", self._window) self._setupBtn.clicked.connect(self._onSetup) self._percentObstacleSldr = QSlider(Qt.Horizontal, self._window) self._percentObstacleSldr.setTickPosition(QSlider.TickPosition.TicksBelow) self._percentObstacleSldr.setTickInterval(10) self._percentObstacleSldr.setMinimum(0) self._percentObstacleSldr.setMaximum(100) self._percentObstacleSldr.valueChanged.connect(self._onPercentSlideChange) self._percentObstacleSldr.setValue(33) layout = QGridLayout() layout.addWidget(self._setupBtn, 0, 0, 1, 2) layout.addWidget(QLabel("Percent Occupied:"), 1, 0) layout.addWidget(self._percentLbl, 1, 1) layout.addWidget(self._percentObstacleSldr, 2, 0, 1, 2) grpBx = QGroupBox("Setup Controls") grpBx.setLayout(layout) grpBx.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) return grpBx def _buildSpeedPanel(self): ''' Creates the sub-panel containing control widgets for controlling the speed of execution of the algorithm. ''' self._runBtn = QPushButton("Run", self._window) self._stepBtn = QPushButton("Step Once", self._window) self._runBtn.clicked.connect(self._onRun) self._stepBtn.clicked.connect(self._onStep) slowRadio = QRadioButton('Slow', self._window) medRadio = QRadioButton('Medium', self._window) fastRadio = QRadioButton('Fast', self._window) notVisRadio = QRadioButton('Not visible', self._window) slowRadio.setChecked(True) self._speedGroup = QButtonGroup(self._window) self._speedGroup.addButton(slowRadio, 0) self._speedGroup.addButton(medRadio, 1) self._speedGroup.addButton(fastRadio, 2) self._speedGroup.addButton(notVisRadio, 3) self._speedGroup.buttonClicked.connect(self._onSpeedChange) layout = QVBoxLayout() layout.addWidget(self._runBtn) layout.addWidget(self._stepBtn) layout.addWidget(slowRadio) layout.addWidget(medRadio) layout.addWidget(fastRadio) layout.addWidget(notVisRadio) grpBx = QGroupBox("Run Controls") grpBx.setLayout(layout) grpBx.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) return grpBx def _buildResultsPanel(self): ''' Creates the sub-panel containing displays widgets for informing the user on the results of running the algorithm. ''' self._doneLbl = QLabel("No", self._window) self._solvableLbl = QLabel("Yes", self._window) #_doneLbl is highlighted green upon successful algorithm completion pal = self._doneLbl.palette() pal.setColor(QPalette.Window, Qt.green) self._doneLbl.setPalette(pal) #_solvableLbl is highlighted red if the world model isn't solvable pal = self._solvableLbl.palette() pal.setColor(QPalette.Window, Qt.red) self._solvableLbl.setPalette(pal) layout = QGridLayout() layout.addWidget(QLabel("Path Found:"), 0, 0) layout.addWidget(self._doneLbl, 0, 1) layout.addWidget(QLabel("Is Solvable:"), 1, 0) layout.addWidget(self._solvableLbl, 1, 1) grpBx = QGroupBox("Results") grpBx.setLayout(layout) grpBx.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) return grpBx def _buildRenderingOptions(self): ''' Creates the sub-panel containing control widgets for setting options in how the world is rendered on the GUI. ''' self._openChk = QCheckBox("Active Cells") self._visitedChk = QCheckBox("Visited Cells") self._pathChk = QCheckBox("Draw Path") self._costChk = QCheckBox("Draw Estimated Costs") pal = self._openChk.palette() pal.setColor(QPalette.WindowText, Qt.green) self._openChk.setPalette(pal) pal = self._visitedChk.palette() pal.setColor(QPalette.WindowText, Qt.cyan) self._visitedChk.setPalette(pal) pal = self._pathChk.palette() pal.setColor(QPalette.WindowText, Qt.red) self._pathChk.setPalette(pal) self._visitedChk.setChecked(True) self._pathChk.setChecked(True) self._costChk.setChecked(True) self._openChk.stateChanged.connect(self._renderingOptionChanged) self._visitedChk.stateChanged.connect(self._renderingOptionChanged) self._pathChk.stateChanged.connect(self._renderingOptionChanged) self._costChk.stateChanged.connect(self._renderingOptionChanged) layout = QVBoxLayout() layout.addWidget(self._openChk) layout.addWidget(self._visitedChk) layout.addWidget(self._pathChk) layout.addWidget(self._costChk) grpBx = QGroupBox("Rendering Options") grpBx.setLayout(layout) grpBx.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) return grpBx @Slot() def _renderingOptionChanged(self, value): ''' When any rendering option is changed this method is invoked. It polls the GUI for the selected setting values and passes them to the 2D world widget. ''' self._worldWidget.setDrawActiveCells(self._openChk.isChecked()) self._worldWidget.setDrawVisitedCells(self._visitedChk.isChecked()) self._worldWidget.setDrawPath(self._pathChk.isChecked()) self._worldWidget.setDrawCosts(self._costChk.isChecked()) self._worldWidget.repaint() @Slot() def _onPercentSlideChange(self, value): ''' Invoked every time the percent slider is changed. Displays the percent value on the GUI. ''' #Add extra padding to the front of the string to help prevent #gui layout resizing if value < 10: self._percentLbl.setText(" " + str(value) + "%") elif value < 100: self._percentLbl.setText(" " + str(value) + "%") else: self._percentLbl.setText(str(value) + "%") @Slot() def _onSpeedChange(self, value): ''' Invoked every time one of the speed setting radio buttons are selected. Resets the algorithm iterating callback timer if it's currently running. ''' self._spdSetting = self._speedGroup.checkedId() if self._timer.isActive(): self._resetTimer() @Slot() def _onSetup(self): ''' Invoked when the setup button is pushed. Re-initializes the world model and the algorithm. ''' self._timer.stop() self._runBtn.setText('Run') self._model.reset(self._percentObstacleSldr.value() / 100.0) self._alg.reset() self._doneLbl.setText("No") self._solvableLbl.setText("Yes") self._doneLbl.setAutoFillBackground(False) self._solvableLbl.setAutoFillBackground(False) self._worldWidget.repaint() @Slot() def _onRun(self): ''' Invoked when the run button is pushed. Toggles the algorithm iterating timer on and off. ''' if self._timer.isActive(): self._timer.stop() self._runBtn.setText("Run") else: self._resetTimer() self._runBtn.setText("Stop") @Slot() def _onStep(self): ''' Invoked on every 'step once' call and on every timer timeout. Iterates one step of the algorithm and then checks for termination conditions such as the algorithm being done or solvable. ''' self._alg.step() self._worldWidget.repaint() if self._alg.isDone() or not self._alg.isSolvable(): self._timer.stop() self._runBtn.setText('Run') self._checkTerminalConditions() def _checkTerminalConditions(self): ''' Sets the 'results' labels based on the algorithm results. ''' if self._alg.isDone(): self._doneLbl.setText("Yes") self._doneLbl.setAutoFillBackground(True) if not self._alg.isSolvable(): self._solvableLbl.setAutoFillBackground(True) self._solvableLbl.setText("No") def _resetTimer(self): ''' When the algorithm run speed is modified by the user this resets the algorithm timer. ''' if self._spdSetting == 3: while not self._alg.isDone() and self._alg.isSolvable(): self._alg.step() self._worldWidget.repaint() self._timer.stop() self._runBtn.setText("Run") self._checkTerminalConditions() else: timeOut = 1 if self._spdSetting == 0: timeOut = 500 elif self._spdSetting == 1: timeOut = 250 elif self._spdSetting == 2: timeOut = 1 self._timer.start(timeOut)
class MainWindow(QWidget): # noinspection PyUnresolvedReferences def __init__(self, clipboard): super().__init__() self.clipboard = clipboard self.setWindowIcon(QIcon('Logo_rendered_edited.png')) self.layout = QBoxLayout(QBoxLayout.TopToBottom, self) self.generator = CtSesam() self.iterations = 4096 # Master password self.master_password_label = QLabel("&Master-Passwort:") self.maser_password_edit = QLineEdit() self.maser_password_edit.setEchoMode(QLineEdit.EchoMode.Password) self.maser_password_edit.textChanged.connect(self.reset_iterations) self.maser_password_edit.returnPressed.connect(self.move_focus) self.maser_password_edit.setMaximumHeight(28) self.master_password_label.setBuddy(self.maser_password_edit) self.layout.addWidget(self.master_password_label) self.layout.addWidget(self.maser_password_edit) # Domain self.domain_label = QLabel("&Domain:") self.domain_edit = QLineEdit() self.domain_edit.textChanged.connect(self.reset_iterations) self.domain_edit.returnPressed.connect(self.move_focus) self.domain_edit.setMaximumHeight(28) self.domain_label.setBuddy(self.domain_edit) self.layout.addWidget(self.domain_label) self.layout.addWidget(self.domain_edit) # Username self.username_label = QLabel("&Username:"******"Sonderzeichen") self.special_characters_checkbox.setChecked(True) self.special_characters_checkbox.stateChanged.connect(self.reset_iterations) self.layout.addWidget(self.special_characters_checkbox) self.letters_checkbox = QCheckBox("Buchstaben") self.letters_checkbox.setChecked(True) self.letters_checkbox.stateChanged.connect(self.reset_iterations) self.layout.addWidget(self.letters_checkbox) self.digits_checkbox = QCheckBox("Zahlen") self.digits_checkbox.setChecked(True) self.digits_checkbox.stateChanged.connect(self.reset_iterations) self.layout.addWidget(self.digits_checkbox) # Length slider self.length_label = QLabel("&Länge:") self.length_display = QLabel() self.length_label_layout = QBoxLayout(QBoxLayout.LeftToRight) self.length_label_layout.addWidget(self.length_label) self.length_label_layout.addWidget(self.length_display) self.length_label_layout.addStretch() self.length_slider = QSlider(Qt.Horizontal) self.length_slider.setMinimum(4) self.length_slider.setMaximum(20) self.length_slider.setPageStep(1) self.length_slider.setValue(10) self.length_display.setText(str(self.length_slider.sliderPosition())) self.length_slider.valueChanged.connect(self.length_slider_changed) self.length_label.setBuddy(self.length_slider) self.layout.addLayout(self.length_label_layout) self.layout.addWidget(self.length_slider) # Button self.generate_button = QPushButton("Erzeugen") self.generate_button.clicked.connect(self.generate_password) self.generate_button.setAutoDefault(True) self.layout.addWidget(self.generate_button) # Password self.password_label = QLabel("&Passwort:") self.password = QLabel() self.password.setTextFormat(Qt.PlainText) self.password.setAlignment(Qt.AlignCenter) self.password.setFont(QFont("Helvetica", 18, QFont.Bold)) self.password_label.setBuddy(self.password) self.layout.addWidget(self.password_label) self.layout.addWidget(self.password) # Iteration display self.message_label = QLabel() self.message_label.setTextFormat(Qt.RichText) self.message_label.setVisible(False) self.layout.addWidget(self.message_label) # Window layout self.layout.addStretch() self.setGeometry(0, 30, 300, 400) self.setWindowTitle("c't SESAM") self.maser_password_edit.setFocus() self.show() def length_slider_changed(self): self.length_display.setText(str(self.length_slider.sliderPosition())) self.reset_iterations() def reset_iterations(self): self.iterations = 4096 self.message_label.setVisible(False) self.password.setText('') self.clipboard.setText('') def move_focus(self): line_edits = [self.maser_password_edit, self.domain_edit, self.username_edit] for i, edit in enumerate(line_edits): if edit.hasFocus() and i + 1 < len(line_edits): line_edits[i + 1].setFocus() return True self.generate_button.setFocus() def generate_password(self): if len(self.domain_edit.text()) <= 0: self.reset_iterations() self.message_label.setText( '<span style="font-size: 10px; color: #aa0000;">Bitte geben Sie eine Domain an.</span>') self.message_label.setVisible(True) return False if self.letters_checkbox.isChecked() or \ self.digits_checkbox.isChecked() or \ self.special_characters_checkbox.isChecked(): self.generator.set_password_characters( use_letters=self.letters_checkbox.isChecked(), use_digits=self.digits_checkbox.isChecked(), use_special_characters=self.special_characters_checkbox.isChecked()) else: self.reset_iterations() self.message_label.setText( '<span style="font-size: 10px; color: #aa0000;">Bei den aktuellen Einstellungen ' + 'kann kein Passwort berechnet werden.</span>') self.message_label.setVisible(True) return False password = self.generator.generate( master_password=self.maser_password_edit.text(), domain=self.domain_edit.text(), username=self.username_edit.text(), length=self.length_slider.sliderPosition(), iterations=self.iterations ) self.password.setText(password) self.password.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) self.clipboard.setText(password) self.message_label.setText( '<span style="font-size: 10px; color: #888888;">Das Passwort wurde ' + str(self.iterations) + ' mal gehasht <br />und in die Zwischenablage kopiert.</span>') self.message_label.setVisible(True) self.iterations += 1
def __init__(self, mainwindow, config): super(SettingsDialog, self).__init__() self.setWindowTitle(self.str_title) # Reference kept to set settings in MainWindow self.mainwindow = mainwindow """A reference to the top window of the app.""" self.config = config """The settings of our app.""" # Setting log handlers logHandlers = QGroupBox(self.str_logHandlers) logHandlersLayout = QVBoxLayout() logHandlers.setLayout(logHandlersLayout) logToGui = QCheckBox(self.str_logToGui) logToGui.setChecked(self.config.getboolean('LogHandlers', 'gui')) logToGui.stateChanged.connect( lambda: self.chooseHandler(logToGui, 'gui')) logHandlersLayout.addWidget(logToGui) logtoStdout = QCheckBox(self.str_logToStdout) logtoStdout.setChecked(self.config.getboolean('LogHandlers', 'stdout')) logtoStdout.stateChanged.connect( lambda: self.chooseHandler(logtoStdout, 'stdout')) logHandlersLayout.addWidget(logtoStdout) logToFile = QCheckBox(self.str_logToFile) logToFile.setChecked(self.config.getboolean('LogHandlers', 'file')) logToFile.stateChanged.connect( lambda: self.chooseHandler(logToFile, 'file')) logHandlersLayout.addWidget(logToFile) # Setting log verbosity logVerbosity = QGroupBox(self.str_logVerbosity) logVerbosityLayout = QHBoxLayout() logVerbosity.setLayout(logVerbosityLayout) self.verbosityOptions = QTreeWidget() self.verbosityOptions.header().setVisible(False) for k, v in self.str_treeItems.items(): node = QTreeWidgetItem(self.verbosityOptions, [k]) if isinstance(v, str): node.setText(1, v) node.setCheckState( 0, boolToCheckState( self.config.getboolean('LogVerbosity', v))) else: count = 0 for key, val in v.items(): item = QTreeWidgetItem(node, [key, val]) checked = self.config.getboolean('LogVerbosity', val) item.setCheckState(0, boolToCheckState(checked)) if checked: count += 1 if count == node.childCount(): node.setCheckState(0, Qt.Checked) elif count == 0: node.setCheckState(0, Qt.Unchecked) else: node.setCheckState(0, Qt.PartiallyChecked) self.verbosityOptions.itemChanged.connect(self.chooseVerbosity) logVerbosityLayout.addWidget(self.verbosityOptions) # Setting clock speed clock = QGroupBox(self.str_clock) clockLayout = QHBoxLayout() clock.setLayout(clockLayout) clockLayout.addWidget(QLabel(self.str_clockSpeed)) spin = QDoubleSpinBox() spin.setValue(self.config.getfloat('Clock', 'speed')) clockLayout.addWidget(spin) # Setting appearance appearance = QGroupBox(self.str_appearance) appearanceLayout = QHBoxLayout() appearance.setLayout(appearanceLayout) appearanceLayout.addWidget(QLabel(self.str_circBgColor)) circBgBtn = QPushButton(self.str_choose) circBgBtn.setPalette(QPalette( QColor(self.config.get('Appearance', 'circ_bg_color')))) circBgBtn.clicked.connect( lambda: self.chooseColor(circBgBtn, 'circ_bg_color')) appearanceLayout.addWidget(circBgBtn) appearanceLayout.addWidget(QLabel(self.str_logBgColor)) logBgBtn = QPushButton(self.str_choose) logBgBtn.setPalette(QPalette( QColor(self.config.get('Appearance', 'log_bg_color')))) logBgBtn.clicked.connect( lambda: self.chooseColor(logBgBtn, 'log_bg_color')) appearanceLayout.addWidget(logBgBtn) # Saving settings to file and effectively setting them close = QPushButton(self.str_close) close.clicked.connect(self.closeAndApply) layout = QGridLayout(self) layout.addWidget(logHandlers, 0, 0, 1, 1) layout.addWidget(logVerbosity, 0, 1, 1, 1) layout.addWidget(clock, 1, 0, 1, 2) layout.addWidget(appearance, 2, 0, 1, 2) layout.addWidget(close, 3, 1, 1, 1) self.setLayout(layout)
class Layer(object): def __init__(self): super(Layer, self).__init__() self.orientation = Quaternion() self.picked = None self.show = QCheckBox() self.show.setChecked(True) self.alpha_slider = QSlider(QtCore.Qt.Orientation.Horizontal) self.alpha_slider.setRange(0, 1024) self.alpha_slider.setValue(1024) self.alpha_number = QDoubleSpinBox() self.alpha_number.setDecimals(3) self.alpha_number.setSingleStep(0.01) self.alpha_number.setRange(0, 1) self.alpha_number.setValue(1) self.alpha_slider.valueChanged.connect(self._alphaSliderChanged) self.alpha_number.valueChanged.connect(self._alphaNumberChanged) self.move = QCheckBox() self.move.setChecked(True) self.quat = QLineEdit() font = QFont('monospace') font.setStyleHint(QFont.TypeWriter) self.quat.setFont(font) default_quat = '+0.000, +1.000, +0.000, +0.000' margins = self.quat.textMargins() self.quat.setFixedWidth( # HACK -------------------------------------------v QFontMetrics(self.quat.font()).width(default_quat + ' ') + margins.left() + margins.right() ) self.quat.setInputMask('#0.000, #0.000, #0.000, #0.000') self.quat.setMaxLength(30) self.quat.setText(default_quat) self.quat.editingFinished.connect(self._orientationChanged) self.nbytes = QLabel() self.nbytes.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.nbytes.setText('0') self.label = QLabel() self.label.setText('<empty>') def multiplyOrientation(self, quat): self.setOrientation(quat * self.orientation) def setOrientation(self, quat): self.orientation = quat self.quat.setText( '%+1.3f, %+1.3f, %+1.3f, %+1.3f' % ( self.orientation.w, self.orientation.x, self.orientation.y, self.orientation.z, ) ) def _orientationChanged(self): text = self.quat.text() def alpha(self): return self.alpha_number.value() if self.show.isChecked() else 0.0 def _alphaSliderChanged(self): self.alpha_number.setValue(self.alpha_slider.value() / 1024.0) def _alphaNumberChanged(self): self.alpha_slider.setValue(1024 * self.alpha_number.value()) def setup_ui(self, table, row): widgets = [ None, CenterH(self.show), self.alpha_slider, self.alpha_number, CenterH(self.move), self.quat, self.nbytes, self.label, ] for (column, widget) in enumerate(widgets): if widget is not None: table.setCellWidget(row, column, widget) def load_file(self, file_name, in_format): self.sphere = proj.load_sphere(file_name, projection=in_format) in_format = self.sphere.__class__ print('Loaded input %s from %s.' % (in_format.__name__, file_name)) self.texture_id = glGenTextures(1) self.sphere.to_gl(self.texture_id) self.shader = Shader( vert=VERTEX_SHADER, frag=FRAGMENT_SHADER + self.sphere.get_glsl_sampler(), ) self.label.setText(file_name) self.nbytes.setText(read_bsize(self.sphere.array.nbytes))
class _PhotonIntensityResultOptionsToolItem(_ResultToolItem): def _initUI(self): # Variables solidangle_sr = self.options().detectors[self.key()].solidangle_sr self._factors = { "counts / (s.A)": solidangle_sr / physics.e, "counts / (s.nA)": solidangle_sr / physics.e / 1e9, } # Widgets self._cb_unit = QComboBox() self._cb_unit.addItem("counts / (sr.electron)") self._cb_unit.addItem("counts / (s.A)") self._cb_unit.addItem("counts / (s.nA)") self._chk_uncertainty = QCheckBox("Show uncertainties") self._chk_uncertainty.setChecked(True) self._chk_pg = QCheckBox("No fluorescence") self._chk_pg.setChecked(True) self._chk_cg = QCheckBox("Characteristic fluorescence") self._chk_cg.setChecked(True) self._chk_bg = QCheckBox("Bremsstrahlung fluorescence") self._chk_bg.setChecked(True) self._chk_tg = QCheckBox("Total") self._chk_tg.setChecked(True) self._chk_pe = QCheckBox("No fluorescence") self._chk_pe.setChecked(True) self._chk_ce = QCheckBox("Characteristic fluorescence") self._chk_ce.setChecked(True) self._chk_be = QCheckBox("Bremsstrahlung fluorescence") self._chk_be.setChecked(True) self._chk_te = QCheckBox("Total") self._chk_te.setChecked(True) # Layouts layout = _ResultToolItem._initUI(self) layout.addRow("Unit", self._cb_unit) layout.addRow(self._chk_uncertainty) boxlayout = QVBoxLayout() boxlayout.addWidget(self._chk_pg) boxlayout.addWidget(self._chk_cg) boxlayout.addWidget(self._chk_bg) boxlayout.addWidget(self._chk_tg) box_generated = QGroupBox("Generated intensities (no absorption)") box_generated.setLayout(boxlayout) layout.addRow(box_generated) boxlayout = QVBoxLayout() boxlayout.addWidget(self._chk_pe) boxlayout.addWidget(self._chk_ce) boxlayout.addWidget(self._chk_be) boxlayout.addWidget(self._chk_te) box_emitted = QGroupBox("Emitted intensities (with absorption)") box_emitted.setLayout(boxlayout) layout.addRow(box_emitted) # Signals self._cb_unit.currentIndexChanged.connect(self.stateChanged) self._chk_uncertainty.stateChanged.connect(self.stateChanged) self._chk_pg.stateChanged.connect(self.stateChanged) self._chk_cg.stateChanged.connect(self.stateChanged) self._chk_bg.stateChanged.connect(self.stateChanged) self._chk_tg.stateChanged.connect(self.stateChanged) self._chk_pe.stateChanged.connect(self.stateChanged) self._chk_ce.stateChanged.connect(self.stateChanged) self._chk_be.stateChanged.connect(self.stateChanged) self._chk_te.stateChanged.connect(self.stateChanged) return layout def showUncertainty(self): return self._chk_uncertainty.isChecked() def showGenerated(self): return (self._chk_pg.isChecked(), self._chk_cg.isChecked(), self._chk_bg.isChecked(), self._chk_tg.isChecked()) def showEmitted(self): return (self._chk_pe.isChecked(), self._chk_ce.isChecked(), self._chk_be.isChecked(), self._chk_te.isChecked()) def factor(self): unit = self._cb_unit.currentText() return self._factors.get(unit, 1.0)
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): self.formatPanel = Widgets.FormatPanel.Panel(self.state, self, editableFontSize=True) formatActions = self.formatPanel.formatActions self.titleLabel = QLabel("&Index Title") self.titleTextEdit = Widgets.LineEdit.HtmlLineEdit( self.state, formatActions=formatActions) self.titleLabel.setBuddy(self.titleTextEdit) self.titleTextEdit.setHtml(self.config.get(Gconf.Key.Title)) self.form.tooltips.append((self.titleTextEdit, """\ <p><b>Index Title</b></p> <p>The index's title. Leave blank if the title is to be added directly in the output file.</p>""")) self.noteLabel = QLabel("Index &Note") self.noteTextEdit = Widgets.LineEdit.MultilineHtmlEdit( self.state, maxLines=8, formatActions=formatActions) self.noteLabel.setBuddy(self.noteTextEdit) self.noteTextEdit.setLineWrapMode(QTextEdit.FixedColumnWidth) self.noteTextEdit.setLineWrapColumnOrWidth(60) self.noteTextEdit.setWordWrapMode(QTextOption.WordWrap) self.noteTextEdit.setHtml(self.config.get(Gconf.Key.Note)) self.form.tooltips.append((self.noteTextEdit, """\ <p><b>Index Note</b></p> <p>The index's note. Leave blank if no note is required or if the note is to be added directly in the output file.</p>""")) self.sectionsGroupBox = QGroupBox("Sections") self.blankBeforeLabel = QLabel("&Blank Lines Before") self.blankBeforeSpinBox = QSpinBox() self.blankBeforeSpinBox.setAlignment(Qt.AlignRight) self.blankBeforeLabel.setBuddy(self.blankBeforeSpinBox) self.blankBeforeSpinBox.setRange(0, 3) self.blankBeforeSpinBox.setValue( self.config.get(Gconf.Key.SectionPreLines)) self.form.tooltips.append((self.blankBeforeSpinBox, """\ <p><b>Blank Lines Before</b></p> <p>How many blank lines to output before a section. (A section is a distinct part of the index, e.g., the ‘A’s.)</p>""")) self.blankAfterLabel = QLabel("Blank &Lines After") self.blankAfterSpinBox = QSpinBox() self.blankAfterSpinBox.setAlignment(Qt.AlignRight) self.blankAfterLabel.setBuddy(self.blankAfterSpinBox) self.blankAfterSpinBox.setRange(0, 3) self.blankAfterSpinBox.setValue( self.config.get(Gconf.Key.SectionPostLines)) self.form.tooltips.append((self.blankAfterSpinBox, """\ <p><b>Blank Lines After</b></p> <p>How many blank lines to output before after section's title. (A section is a distinct part of the index, e.g., the ‘A’s.)</p>""")) self.sectionTitlesCheckBox = QCheckBox("&Output Titles") self.sectionTitlesCheckBox.setChecked( self.config.get(Gconf.Key.SectionTitles)) self.form.tooltips.append((self.sectionTitlesCheckBox, """\ <p><b>Output Titles</b></p> <p>If checked, section titles are output before each section, e.g., ‘A’, before the As, ‘B’, before the Bs, and so on.</p>""")) self.sectionSpecialTitleLabel = QLabel("Special Section &Title") self.sectionSpecialTitleTextEdit = Widgets.LineEdit.HtmlLineEdit( self.state, formatActions=formatActions) self.sectionSpecialTitleLabel.setBuddy( self.sectionSpecialTitleTextEdit) self.sectionSpecialTitleTextEdit.setHtml( self.config.get(Gconf.Key.SectionSpecialTitle)) self.form.tooltips.append((self.sectionSpecialTitleTextEdit, """\ <p><b>Special Section Title</b></p> <p>If there are entries which precede the ‘A’ section, then this section title will be used for them.</p> <p>Note that even if this title isn't used, its font name and size will be used for all the other section titles.</p>""")) size = self.font().pointSize() + (1 if WIN else 2) family = self.config.get(Gconf.Key.StdFont) size = self.config.get(Gconf.Key.StdFontSize, size) Lib.createFontBoxesFor(self, "Std", family, size, tooltips=self.form.tooltips, which="Std.") self.onStdFontChange(False) family = self.config.get(Gconf.Key.AltFont) size = self.config.get(Gconf.Key.AltFontSize, size) Lib.createFontBoxesFor(self, "Alt", family, size, tooltips=self.form.tooltips, which="Alt.") self.onAltFontChange(False) family = self.config.get(Gconf.Key.MonoFont) size = self.config.get(Gconf.Key.MonoFontSize, size) Lib.createFontBoxesFor(self, "Mono", family, size, mono=True, tooltips=self.form.tooltips, which="Mono.") self.onMonoFontChange(False) self.monoFontAsStrikeoutCheckbox = QCheckBox( "Output Mono. &Font as Strikeout") self.form.tooltips.append((self.monoFontAsStrikeoutCheckbox, """\ <p><b>Output Mono. Font as Strikeout</b></p> <p>If checked, any text in the index that is styled as mono. font family will be output using the std. font family—but with <s>strikeout</s>.</p>""")) self.monoFontAsStrikeoutCheckbox.setChecked( self.config.get(Gconf.Key.MonoFontAsStrikeout)) self.styleLabel = QLabel("St&yle") self.styleComboBox = QComboBox() self.styleLabel.setBuddy(self.styleComboBox) oldStyle = self.config.get(Gconf.Key.Style) index = -1 for i, style in enumerate(StyleKind): self.styleComboBox.addItem(style.text, style.value) if style is oldStyle: index = i self.styleComboBox.setCurrentIndex(index) self.form.tooltips.append((self.styleComboBox, """\ <p><b>Style</b></p> <p>The style of index to output.</p>""")) self.termPagesSepLabel = QLabel("T&erm-Pages Separator") self.termPagesSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit( self.state, 3, formatActions=formatActions) self.termPagesSepLabel.setBuddy(self.termPagesSepTextEdit) self.termPagesSepTextEdit.setHtml( self.config.get(Gconf.Key.TermPagesSeparator)) self.form.tooltips.append((self.termPagesSepTextEdit, """\ <p><b>Term-Pages Separator</b></p> <p>The separator text to use between the end of an entry's term and its pages.</p>{}""".format(BLANK_SPACE_HTML))) self.runInSepLabel = QLabel("&Run-in Separator") self.runInSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit( self.state, 3, formatActions=formatActions) self.runInSepLabel.setBuddy(self.runInSepTextEdit) self.runInSepTextEdit.setHtml(self.config.get( Gconf.Key.RunInSeparator)) self.form.tooltips.append((self.runInSepTextEdit, """\ <p><b>Run-in Separator</b></p> <p>The separator text to use between run-in entries (for run-in style index output).</p>{}""".format(BLANK_SPACE_HTML))) self.formatPanel.state.editors = [ self.titleTextEdit, self.noteTextEdit, self.sectionSpecialTitleTextEdit, self.termPagesSepTextEdit, self.runInSepTextEdit ] def layoutWidgets(self): form = QFormLayout() hbox = QHBoxLayout() hbox.addStretch() hbox.addWidget(self.formatPanel) form.addRow(hbox) form.addRow(self.titleLabel, self.titleTextEdit) form.addRow(self.noteLabel, self.noteTextEdit) vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.blankBeforeLabel) hbox.addWidget(self.blankBeforeSpinBox) hbox.addWidget(self.blankAfterLabel) hbox.addWidget(self.blankAfterSpinBox) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.addWidget(self.sectionTitlesCheckBox) hbox.addStretch() hbox.addWidget(self.sectionSpecialTitleLabel) hbox.addWidget(self.sectionSpecialTitleTextEdit) vbox.addLayout(hbox) self.sectionsGroupBox.setLayout(vbox) form.addRow(self.sectionsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.stdFontComboBox, 1) hbox.addWidget(self.stdFontSizeSpinBox) hbox.addStretch() label = QLabel("&Std. Font") label.setBuddy(self.stdFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.altFontComboBox, 1) hbox.addWidget(self.altFontSizeSpinBox) hbox.addStretch() label = QLabel("&Alt. Font") label.setBuddy(self.altFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.monoFontComboBox, 1) hbox.addWidget(self.monoFontSizeSpinBox) hbox.addStretch() label = QLabel("&Mono. Font") label.setBuddy(self.monoFontComboBox) form.addRow(label, hbox) grid = QGridLayout() grid.addWidget(self.monoFontAsStrikeoutCheckbox, 0, 0, 1, 2) grid.addWidget(self.termPagesSepLabel, 0, 2) grid.addWidget(self.termPagesSepTextEdit, 0, 3) grid.addWidget(self.styleLabel, 1, 0) grid.addWidget(self.styleComboBox, 1, 1) grid.addWidget(self.runInSepLabel, 1, 2) grid.addWidget(self.runInSepTextEdit, 1, 3) form.addRow(grid) self.setLayout(form) def createConnections(self): self.stdFontComboBox.currentFontChanged.connect(self.onStdFontChange) self.stdFontSizeSpinBox.valueChanged[int].connect(self.onStdFontChange) self.altFontComboBox.currentFontChanged.connect(self.onAltFontChange) self.altFontSizeSpinBox.valueChanged[int].connect(self.onAltFontChange) self.monoFontComboBox.currentFontChanged.connect(self.onMonoFontChange) self.monoFontSizeSpinBox.valueChanged[int].connect( self.onMonoFontChange) def onStdFontChange(self, propagate=True): font = QFont(self.stdFontComboBox.currentFont()) font.setPointSize(self.stdFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.StdFont, font.family()) self.state.model.setConfig(Gconf.Key.StdFontSize, font.pointSize()) def onAltFontChange(self, propagate=True): font = QFont(self.altFontComboBox.currentFont()) font.setPointSize(self.altFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.AltFont, font.family()) self.state.model.setConfig(Gconf.Key.AltFontSize, font.pointSize()) def onMonoFontChange(self, propagate=True): font = QFont(self.monoFontComboBox.currentFont()) font.setPointSize(self.monoFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.MonoFont, font.family()) self.state.model.setConfig(Gconf.Key.MonoFontSize, font.pointSize())
class _PhotonDistributionResultOptionsToolItem(_ResultToolItem): def _initUI(self): # Variables result = self.result() transitions = sorted(result.iter_transitions()) transition0 = transitions[0] model = _TransitionListModel(transitions) # Widgets self._chk_errorbar = QCheckBox("Show error bars") self._chk_errorbar.setChecked(True) self._cb_transition = QComboBox() self._cb_transition.setModel(model) self._cb_transition.setCurrentIndex(0) self._chk_pg = QCheckBox("No absorption, no fluorescence") state = result.exists(transition0, True, False, False, False) self._chk_pg.setEnabled(state) self._chk_pg.setChecked(state) self._chk_eg = QCheckBox("With absorption, no fluorescence") state = result.exists(transition0, True, True, False, False) self._chk_eg.setEnabled(state) self._chk_eg.setChecked(state) self._chk_pt = QCheckBox("No absorption, with fluorescence") state = result.exists(transition0, True, False, True, True) self._chk_pt.setEnabled(state) self._chk_pt.setChecked(state) self._chk_et = QCheckBox("With absorption, with fluorescence") state = result.exists(transition0, True, True, True, True) self._chk_et.setEnabled(state) self._chk_et.setChecked(state) # Layouts layout = _ResultToolItem._initUI(self) layout.addRow(self._chk_errorbar) layout.addRow("Transition", self._cb_transition) boxlayout = QVBoxLayout() boxlayout.addWidget(self._chk_pg) boxlayout.addWidget(self._chk_eg) boxlayout.addWidget(self._chk_pt) boxlayout.addWidget(self._chk_et) box_generated = QGroupBox("Curves") box_generated.setLayout(boxlayout) layout.addRow(box_generated) # Signals self._cb_transition.currentIndexChanged.connect(self._onTransitionChanged) self._chk_pg.stateChanged.connect(self.stateChanged) self._chk_eg.stateChanged.connect(self.stateChanged) self._chk_pt.stateChanged.connect(self.stateChanged) self._chk_et.stateChanged.connect(self.stateChanged) self._chk_errorbar.stateChanged.connect(self.stateChanged) return layout def _onTransitionChanged(self): result = self.result() index = self._cb_transition.currentIndex() transition = self._cb_transition.model().transition(index) self._chk_pg.setEnabled(result.exists(transition, True, False, False, False)) self._chk_eg.setEnabled(result.exists(transition, True, True, False, False)) self._chk_pt.setEnabled(result.exists(transition, True, False, True, True)) self._chk_et.setEnabled(result.exists(transition, True, True, True, True)) self.stateChanged.emit() def transition(self): index = self._cb_transition.currentIndex() return self._cb_transition.model().transition(index) def showConditions(self): return ( self._chk_pg.isChecked() and self._chk_pg.isEnabled(), self._chk_eg.isChecked() and self._chk_eg.isEnabled(), self._chk_pt.isChecked() and self._chk_pt.isEnabled(), self._chk_et.isChecked() and self._chk_et.isEnabled(), ) def showErrorbar(self): return self._chk_errorbar.isChecked()
class Mixin: def createWidgets(self): settings = QSettings() self.searchLabel = QLabel("Search For") self.searchLineEdit = QLineEdit() self.tooltips.append((self.searchLineEdit, """\ <p><b>Search For editor</b></p> <p>The text or regular expression to search for.</p>""")) self.searchLabel.setBuddy(self.searchLineEdit) self.replaceLabel = QLabel("Replace With") self.replaceLineEdit = QLineEdit() self.tooltips.append((self.replaceLineEdit, """\ <p><b>Replace With editor</b></p> <p>The replacement text (which may include backreferences, \\1, \\2, etc., if a regular expression search is being made).</p>""")) self.replaceLabel.setBuddy(self.replaceLineEdit) self.allEntriesRadioButton = QRadioButton("All Entries") self.allEntriesRadioButton.setChecked( bool(int(settings.value("RP/All", 1)))) self.tooltips.append((self.allEntriesRadioButton, """\ <p><b>All Entries</b></p> <p>If checked, the search will consider every entry in the index.</p>""")) self.filteredEntriesRadioButton = QRadioButton("Filtered Entries") self.filteredEntriesRadioButton.setChecked( bool(int(settings.value("RP/Filtered", 0)))) self.tooltips.append((self.filteredEntriesRadioButton, """\ <p><b>Filtered Entries</b></p> <p>If checked, the search will consider only those entries that are in the current filtered view.</p>""")) self.considerLabel = QLabel("Consider") self.scopeGroup = QButtonGroup() self.scopeGroup.addButton(self.allEntriesRadioButton) self.scopeGroup.addButton(self.filteredEntriesRadioButton) self.literalRadioButton = QRadioButton("Literal") self.literalRadioButton.setChecked( bool(int(settings.value("RP/Literal", 1)))) self.tooltips.append((self.literalRadioButton, """<p><b>Literal</b></p> <p>If checked, the <b>Search For</b> text will be searched for literally.</p>""")) self.regexRadioButton = QRadioButton("Regex") self.regexRadioButton.setChecked( bool(int(settings.value("RP/Regex", 0)))) self.tooltips.append((self.regexRadioButton, """<p><b>Regex</b></p> <p>If checked, the <b>Search For</b> text will be searched for as a regular expression pattern.</p>""")) self.matchAsGroup = QButtonGroup() self.matchAsGroup.addButton(self.literalRadioButton) self.matchAsGroup.addButton(self.regexRadioButton) self.ignoreCaseCheckBox = QCheckBox("Ignore Case") self.ignoreCaseCheckBox.setChecked( bool(int(settings.value("RP/ICase", 0)))) self.tooltips.append((self.ignoreCaseCheckBox, """\ <p><b>Ignore Case</b></p> <p>If checked, the <b>Search For</b> text will be searched for case-insensitively.</p>""")) self.wholeWordsCheckBox = QCheckBox("Whole Words") self.wholeWordsCheckBox.setChecked( bool(int(settings.value("RP/WW", 0)))) self.tooltips.append((self.wholeWordsCheckBox, """\ <p><b>Whole Words</b></p> <p>If checked—and when <b>Literal</b> is checked—the <b>Search For</b> text will be matched as whole words.</p> <p>For example, “habit” will not match “habitat” when whole words is checked.</p> <p>(For regular expressions use \\b before and after each word to get whole word matches.)</p>""")) self.replaceInLabel = QLabel("Look In") self.replaceInTermsCheckBox = QCheckBox("Terms") self.replaceInTermsCheckBox.setChecked( bool(int(settings.value("RP/Terms", 1)))) self.tooltips.append((self.replaceInTermsCheckBox, """\ <p><b>Terms</b></p> <p>If checked, the search will look in term texts.</p>""")) self.replaceInPagesCheckBox = QCheckBox("Pages") self.replaceInPagesCheckBox.setChecked( bool(int(settings.value("RP/Pages", 0)))) self.tooltips.append((self.replaceInPagesCheckBox, """\ <p><b>Pages</b></p> <p>If checked, the search will look in pages texts.</p>""")) self.replaceInNotesCheckBox = QCheckBox("Notes") self.replaceInNotesCheckBox.setChecked( bool(int(settings.value("RP/Notes", 0)))) self.tooltips.append((self.replaceInNotesCheckBox, """\ <p><b>Notes</b></p> <p>If checked, the search will look in notes texts.</p>""")) self.startButton = QPushButton(QIcon(":/edit-find.svg"), "Start Search") self.tooltips.append((self.startButton, """<p><b>Start Search</b></p> <p>Start the search from the first entry in the index or the first entry in the filtered view's entries.</p>""")) self.replaceButton = QPushButton(QIcon(":/edit-find-replace.svg"), "Replace") self.tooltips.append((self.replaceButton, """<p><b>Replace</b></p> <p>Replace the highlighted text with the <b>Replace With</b> text (using backreferences if they are in the replacement text and a <b>Regex</b> search is underway), and then try to find the next matching text.</p>""")) self.skipButton = QPushButton(QIcon(":/skip.svg"), "S&kip") self.tooltips.append((self.skipButton, """<p><b>Skip</b></p> <p>Skip the highlighted text and try to find the next matching text.</p>""")) self.stopButton = QPushButton(QIcon(":/process-stop.svg"), "Stop Search") self.tooltips.append((self.stopButton, """<p><b>Stop Search</b></p> <p>Stop the current search. This allows the search options to be changed.</p>""")) self.closeButton = QToolButton() self.closeButton.setIcon(QIcon(":/hide.svg")) self.closeButton.setFocusPolicy(Qt.NoFocus) self.tooltips.append((self.closeButton, """<p><b>Hide</b></p> <p>Hide the Search and Replace panel.</p> <p>Press <b>Ctrl+H</b> or click <img src=":/edit-find-replace.svg" width={0} height={0}> or click <b>Edit→Search and Replace</b> to show it again.</p>""".format(TOOLTIP_IMAGE_SIZE))) self.helpButton = QToolButton() self.helpButton.setIcon(QIcon(":/help.svg")) self.helpButton.setFocusPolicy(Qt.NoFocus) self.tooltips.append( (self.helpButton, "Help on the Search and Replace panel.")) def layoutWidgets(self): form = QFormLayout() hbox = QHBoxLayout() hbox.addWidget(self.searchLineEdit) hbox.addWidget(self.closeButton) form.addRow(self.searchLabel, hbox) hbox = QHBoxLayout() hbox.addWidget(self.replaceLineEdit) hbox.addWidget(self.helpButton) form.addRow(self.replaceLabel, hbox) hbox = QHBoxLayout() hbox.addWidget(self.allEntriesRadioButton) hbox.addWidget(self.filteredEntriesRadioButton) hbox.addStretch() form.addRow(self.considerLabel, hbox) hbox = QHBoxLayout() hbox.addWidget(self.literalRadioButton) hbox.addWidget(self.regexRadioButton) hbox.addStretch(1) hbox.addWidget(self.ignoreCaseCheckBox) hbox.addWidget(self.wholeWordsCheckBox) hbox.addStretch(5) form.addRow(QLabel("Match"), hbox) hbox = QHBoxLayout() hbox.addWidget(self.replaceInTermsCheckBox) hbox.addWidget(self.replaceInPagesCheckBox) hbox.addWidget(self.replaceInNotesCheckBox) hbox.addStretch() form.addRow(self.replaceInLabel, hbox) hbox = QHBoxLayout() hbox.addWidget(self.startButton) hbox.addWidget(self.replaceButton) hbox.addWidget(self.skipButton) hbox.addWidget(self.stopButton) hbox.addStretch() form.addRow(hbox) self.setLayout(form) def createConnections(self): self.helpButton.clicked.connect(self.help) self.stopButton.clicked.connect(self.stop) self.startButton.clicked.connect(self.start) self.replaceButton.clicked.connect(self.replace) self.skipButton.clicked.connect(self.skip) self.searchLineEdit.textChanged.connect(self.updateUi) self.searchLineEdit.returnPressed.connect(self.doAction) self.replaceLineEdit.textChanged.connect(self.updateUi) self.replaceLineEdit.returnPressed.connect(self.doAction) for button in (self.literalRadioButton, self.regexRadioButton, self.ignoreCaseCheckBox, self.wholeWordsCheckBox, self.replaceInTermsCheckBox, self.replaceInPagesCheckBox, self.replaceInNotesCheckBox): button.clicked.connect(self.updateUi) def doAction(self): button = None if self.skipButton.isEnabled(): button = self.skipButton elif self.startButton.isEnabled(): button = self.startButton if button is not None: button.setFocus() button.click() if self.skipButton.isEnabled(): self.skipButton.setFocus() def help(self): self.state.help("xix_ref_panel_replace.html")
class MassAttribute_UI(QDialog): """ The main UI """ class Applikator(QObject): """ This is the core applier which toggle the display of the corresponding widget and handling events' connections """ def __init__(self, parent=None): super(MassAttribute_UI.Applikator, self).__init__() self.root = parent def widget_event(self, t): """ Return the correct widget's event depending on attribute's type :param t: the attribute's type :type t: str :return: the event :rtype : Signal """ return { 'float': self.root.W_EDI_float.valueChanged, 'enum': self.root.W_EDI_enum.currentIndexChanged, 'int': self.root.W_EDI_int.valueChanged, 'bool': self.root.W_EDI_bool.stateChanged, 'str': self.root.W_EDI_str.textChanged, 'd3': self.root.W_EDI_d3.valuesChanged, 'd4': self.root.W_EDI_d4.valuesChanged, 'color': self.root.W_EDI_color.colorChanged }[t] def unset_editors(self): """ Toggle off all editors and disconnect the current one """ for widget in (self.root.W_EDI_float, self.root.W_EDI_int, self.root.W_EDI_enum, self.root.W_EDI_bool, self.root.W_EDI_str, self.root.W_EDI_d3, self.root.W_EDI_d4, self.root.W_EDI_color): widget.setVisible(False) # trying to force disconnection try: self.widget_event(self.root.ctx).disconnect( self.root.apply_value) except (KeyError, RuntimeError): pass def prepare(applier_name): """ A decorator to prepare the attribute depending on type for the corresponding widget and getting the attribute's value :param applier_name: attribute's type :type applier_name: str """ def sub_wrapper(func): def wrapper(self, attr_path): self.unset_editors() self.root.ctx = applier_name self.root.__getattribute__('W_EDI_%s' % applier_name).setVisible(True) ret = func(self, cmds.getAttr(attr_path), attr_path) return ret return wrapper return sub_wrapper @staticmethod def get_bounds(obj, attr, min_default, max_default): """ Try to retrieve the range for the given attribute, if min or max fail it'll set default values :param obj: the object's name :type obj: str :param attr: attribute's name :type attr: str :param min_default: minimum default value :param max_default: max default value :type min_default: float | int :type max_default: float | int :return: minimum, maximum :rtype : tuple """ try: assert cmds.attributeQuery(attr, n=obj, mxe=True) maxi = cmds.attributeQuery(attr, n=obj, max=True)[0] except (RuntimeError, AssertionError): maxi = max_default try: assert cmds.attributeQuery(attr, n=obj, mne=True) mini = cmds.attributeQuery(attr, n=obj, min=True)[0] except (RuntimeError, AssertionError): mini = min_default return mini, maxi @prepare('float') def apply_float(self, value, path): """ Float attribute case :param value: attribute's value :param path: attribute's path = obj.attr """ obj, attr = path.split('.', 1) self.root.W_EDI_float.setRange( *self.get_bounds(obj, attr, -100.0, 100.0)) self.root.W_EDI_float.setValue(value) @prepare('enum') def apply_enum(self, value, path): """Enum case""" self.root.W_EDI_enum.clear() obj, attr = path.split('.', 1) try: enums = [ enum.split('=')[0] for enum in cmds.attributeQuery( attr, n=obj, listEnum=True)[0].split(':') ] except RuntimeError: self.apply_int(path) else: self.root.W_EDI_enum.addItems(enums) self.root.W_EDI_enum.setCurrentIndex( enums.index(cmds.getAttr(path, asString=True))) @prepare('int') def apply_int(self, value, path): """Integer case""" obj, attr = path.split('.', 1) self.root.W_EDI_int.setRange( *self.get_bounds(obj, attr, -1000, 1000)) self.root.W_EDI_int.setValue(value) @prepare('bool') def apply_bool(self, value, path): """Boolean case""" self.root.W_EDI_bool.setChecked(value) self.root.W_EDI_bool.setText(path.split('.', 1)[1]) @prepare('str') def apply_str(self, value, path): """String case""" self.root.W_EDI_str.setText(value) @prepare('d3') def apply_d3(self, value, path): """3D array case""" self.root.W_EDI_d3.setValues(value[0]) @prepare('d4') def apply_d4(self, value, path): """4D array case""" self.root.W_EDI_d4.setValues(value[0]) @prepare('color') def apply_color(self, value, path): """Color case""" try: colors = value[0] self.root.W_EDI_color.setColor([int(c * 255) for c in colors]) except TypeError: self.apply_int(value, path) class Attribute(str): """ A custom string attribute class to ship more information into the string variable """ def __new__(cls, path='', super_type=Object): obj, attr = path.split('.', 1) str_obj = str.__new__(cls, attr) str_obj.obj, str_obj.attr = obj, attr str_obj.path = path str_obj.super_type = super_type str_obj.type = None return str_obj # static variables to pre-load icons and attributes short names ctx_icons = { 'float': QIcon(':render_decomposeMatrix.png'), 'enum': QIcon(':showLineNumbers.png'), 'bool': QIcon(':out_decomposeMatrix.png'), 'time': QIcon(':time.svg'), 'byte': QIcon(':out_defaultTextureList.png'), 'angle': QIcon(':angleDim.png'), 'string': QIcon(':text.png'), 'float3': QIcon(':animCurveTA.svg'), 'float4': QIcon(':animCurveTA.svg'), 'color': QIcon(':clampColors.svg') } for ctx in ('doubleLinear', 'double', 'long', 'short'): ctx_icons[ctx] = ctx_icons['float'] ctx_icons['double3'] = ctx_icons['float3'] ctx_icons['double4'] = ctx_icons['float4'] ctx_wide = { 'float': ('float', 'doubleLinear', 'double', 'long', 'short'), 'enum': ('enum', ), 'bool': ('bool', ), 'time': ('time', ), 'byte': ('byte', ), 'angle': ('doubleAngle', ), 'string': ('string', ), 'float3': ('double3', 'float3'), 'float4': ('double4', 'float4'), 'color': ('color', ) } def __init__(self, parent=None): super(MassAttribute_UI, self).__init__(parent) # Abstract self.applier = self.Applikator(self) self.selection = [] self.callback = None self.ctx = None # storing found attributes' types to avoid double check self.solved = {} self.setLocale(QLocale.C) self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_QuitOnClose) self.setFixedWidth(300) self.setWindowTitle('Massive Attribute Modifier') # UI L_main = QVBoxLayout() self.WV_title = QLabel('') self.WV_title.setVisible(False) self.WV_title.setFont(QFont('Verdana', 10)) self.WV_title.setContentsMargins(0, 0, 0, 7) self.WB_select = QPushButton('Select') self.WB_select.setVisible(False) self.WB_select.setFixedWidth(50) self.WB_select.clicked.connect(lambda: cmds.select(self.selection)) self.WB_update = QPushButton('Update') self.WB_update.setFixedWidth(50) self.WB_update.clicked.connect( lambda: self.update_attributes(cmds.ls(sl=True))) self.WV_search = Filter() self.WV_search.textChanged.connect(self.filter) self.WC_cases = QCheckBox('Case sensitive') self.WC_cases.stateChanged.connect(self.filter) self.WC_types = QCheckBox('Type filtering') self.WL_attrtype = QComboBox() self.WL_attrtype.setEnabled(False) for i, ctx in enumerate(sorted(self.ctx_wide)): self.WL_attrtype.addItem(ctx.title()) self.WL_attrtype.setItemIcon(i, self.ctx_icons[ctx]) L_attrtype = line(self.WC_types, self.WL_attrtype) self.WC_types.stateChanged.connect( partial(self.update_attributes, self.selection)) self.WC_types.stateChanged.connect(self.WL_attrtype.setEnabled) self.WL_attrtype.currentIndexChanged.connect(self.filter) self.WC_liveu = QCheckBox('Live') self.WC_liveu.stateChanged.connect(self.WB_update.setDisabled) self.WC_liveu.stateChanged.connect(self.set_callback) self.WC_histo = QCheckBox('Load history') self.WC_histo.setChecked(True) self.WC_histo.stateChanged.connect( partial(self.update_attributes, self.selection)) self.WC_child = QCheckBox('Children') self.WC_child.stateChanged.connect( partial(self.update_attributes, self.selection)) options = group( 'Options', line(self.WC_cases, L_attrtype), line(self.WC_child, self.WC_histo, self.WC_liveu, self.WB_update)) options.layout().setSpacing(2) self.WL_attributes = QTreeWidget() self.WL_attributes.setStyleSheet( 'QTreeView {alternate-background-color: #1b1b1b;}') self.WL_attributes.setAlternatingRowColors(True) self.WL_attributes.setHeaderHidden(True) self.WL_attributes.setRootIsDecorated(False) self.objs_attr = set() self.shps_attr = set() self.W_EDI_float = FloatBox() self.W_EDI_int = IntBox() self.W_EDI_enum = QComboBox() self.W_EDI_bool = QCheckBox() self.W_EDI_str = QLineEdit() self.W_EDI_d3 = Double3() self.W_EDI_d4 = Double4() self.W_EDI_color = ColorPicker() # Final layout L_title = line(self.WV_title, self.WB_select) L_title.setStretch(0, 1) L_main.addLayout(L_title) L_main.setAlignment(Qt.AlignLeft) L_main.addWidget(self.WV_search) L_main.addWidget(options) L_main.addWidget(self.WL_attributes) L_edits = col(self.W_EDI_bool, self.W_EDI_int, self.W_EDI_float, self.W_EDI_enum, self.W_EDI_str, self.W_EDI_d3, self.W_EDI_d4, self.W_EDI_color) L_edits.setContentsMargins(0, 8, 0, 0) L_main.addLayout(L_edits) L_main.setStretch(3, 1) L_main.setSpacing(2) self.appliers = { 'float': self.applier.apply_float, 'enum': self.applier.apply_enum, 'bool': self.applier.apply_bool, 'time': self.applier.apply_float, 'byte': self.applier.apply_int, 'angle': self.applier.apply_float, 'string': self.applier.apply_str, 'float3': self.applier.apply_d3, 'float4': self.applier.apply_d4, 'color': self.applier.apply_color } self.setLayout(L_main) # final settings self.WL_attributes.itemSelectionChanged.connect(self.update_setter) self.applier.unset_editors() def closeEvent(self, *args, **kwargs): self.set_callback(False) def set_callback(self, state): """ Toggle selection event callback :param state: checkbox's state :type state: bool | int """ if state and not self.callback: self.callback = MEventMessage.addEventCallback( 'SelectionChanged', self.update_attributes) self.update_attributes(cmds.ls(sl=True)) elif not state and self.callback: MMessage.removeCallback(self.callback) self.callback = None @staticmethod def format_title(nodes): """ Extract the matching characters from a given nodes selection, if begin matches it will return "joint*" with a wildcard when names don't match :param nodes: objects' list :type nodes: list | tuple :return: the formatted name with the corresponding characters :rtype : str """ res = None if nodes: # we get the first node as a reference node = nodes[0] # and compare with the other nodes subs = [w for w in nodes if w != node] l = 1 valid = True # will continue until l (length) match the full name's length or until names don't match while l < len(node) and valid: for sub in subs: if not sub.startswith(node[:l]): valid = False break else: l += 1 # if matching characters isn't long enough we only display the number of nodes selected if l <= 3: res = '%i objects' % len(nodes) # otherwise showing matching pattern elif l < len(node) or len(nodes) > 1: res = node[:l - 1] + '* (%i objects)' % len(nodes) else: res = node return res @staticmethod def get_history(node): """ Extract history for the given node :rtype: list """ return cmds.listHistory(node, il=2, pdo=True) or [] @staticmethod def get_shapes(node): """ Extract shape(s) for the given node :rtype: list """ return cmds.listRelatives(node, s=True, ni=True, f=True) def get_attributes_type(self, attrs): """ For a given list of attributes of type Attribute, will loop through and fill the type parameter of the attribute with the corresponding type, if type is invalid or not handled, it'll remove it :param attrs: attributes' list :type attrs: [MassAttribute_UI.Attribute] :return: cleaned and filled attributes' list :rtype: [MassAttribute_UI.Attribute] """ attrs = list(attrs) # first we sort the attributes' list attrs.sort() # then we try to extract the attribute's type for i, attr in enumerate(attrs): try: if attr.attr in self.solved: attr.type = self.solved[attr.attr] raise RuntimeError tpe = cmds.getAttr(attr.path, typ=True) assert tpe attr.type = tpe self.solved[attr.attr] = tpe except (AssertionError, ValueError, RuntimeError): pass # defining a to-remove list rm_list = set() layers = {'3': 'XYZ', '4': 'XYZW'} for i, attr in enumerate(attrs): if i in rm_list: continue # we handle some special cases here, if ever the attribute list contains RGB and separate R, G and B we # assume it's a color, if it's a double3 or float3 and we find the corresponding XYZ, we remove then to # avoid duplicates if attr.endswith('RGB'): if '%sR' % attr[:-3] in attrs: attr.type = 'color' for chan in 'RGB': rm_list.add(attrs.index('%s%s' % (attr[:-3], chan))) # if the attribute's type isn't in the list, we remove elif attr.type not in MassAttribute_UI.ctx_icons: rm_list.add(i) elif attr.endswith('R'): if '%sG' % attr[:-1] in attrs and attr[:-1] in attrs: attr.type = 'color' for chan in 'RGB': rm_list.add(attrs.index('%s%s' % (attr[:-1], chan))) elif attr.type in ('double3', 'double4', 'float3', 'float4'): if '%sX' % attr in attrs: for chan in layers[attr.type[-1]]: rm_list.add(attrs.index('%s%s' % (attr, chan))) # finally cleaning the list for i in sorted(rm_list, reverse=True): attrs.pop(i) return attrs def apply_value(self, value): """ When the value is modified in the UI, we forward the given value and applies to the object's :param value: attribute's value, mixed type :type value: mixed """ # We get the only selected object in list and get it's super type (Shape, History or Object) and # type (float, int, string) item = self.WL_attributes.selectedItems()[0] attr = item.attribute shape = attr.super_type == Shape histo = attr.super_type == History tpe = item.attribute.type # eq dict for each context value = { 'bool': bool, 'int': int, 'float': float, 'enum': int, 'str': str, 'd3': list, 'd4': list, 'color': list }[self.ctx](value) # converting the selection into a set cmds.undoInfo(openChunk=True) targets = set(self.selection) # we propagate to children if 'Children' checkbox is on if self.WC_child.isChecked(): for obj in list(targets): targets |= set(cmds.listRelatives(obj, ad=True)) # if the target attribute is on the history, we add all selection's history to the list if histo: for obj in list(targets): targets.remove(obj) targets |= set(self.get_history(obj)) # then we loop through target objects for obj in targets: # if the target is on the shape we get object's shape if shape and not histo: shapes = self.get_shapes(obj) if obj in shapes: continue else: obj = shapes[0] # then we try to apply depending on attribute's type try: correct_path = attr.path.replace(attr.obj, obj) if tpe == 'string': cmds.setAttr(correct_path, value, type='string') elif tpe in ('double3', 'double4', 'float3', 'float4', 'color'): cmds.setAttr(correct_path, *value, type='double%d' % len(value)) else: cmds.setAttr(correct_path, value) except RuntimeError: pass cmds.undoInfo(closeChunk=True) def update_setter(self): """ When the list's selection changes we update the applier widget """ item = self.WL_attributes.selectedItems() # abort if no item is selected if not len(item): return # getting attribute's parameter attr = item[0].attribute if len(self.selection): try: # looping until we find a context having the current attribute's type for applier in self.ctx_wide: if attr.type in self.ctx_wide[applier]: break # then we apply for the given path (obj.attribute) self.appliers[applier](attr.path) # and connecting event to the self.apply_value function self.applier.widget_event(self.ctx).connect(self.apply_value) # otherwise selection or type is invalid except IndexError: self.ctx = None def update_attributes(self, selection=None, *args): """ Update the attributes for the given selection, looping through objects' attributes, finding attr in common between all objects then cleaning the lists, doing the same for shapes and / or histories :param selection: object's selection """ # redefining lists as set to intersect union etc self.objs_attr = set() self.shps_attr = set() # pre init self.WL_attributes.clear() self.applier.unset_editors() self.selection = selection or (cmds.ls( sl=True) if self.WC_liveu.isChecked() else self.selection) self.WV_title.setText(self.format_title(self.selection)) self.WV_title.setVisible(bool(len(self.selection))) self.WB_select.setVisible(bool(len(self.selection))) if not len(self.selection): return def get_usable_attrs(obj, super_type): """ Small internal function to get a compatible attributes' list for the given object and assign the given super_type to it (Object, Shape or History) :param obj: object's name :type obj: str :param super_type: attribute's main type :type super_type: Object | Shape | History :return: """ return set([ MassAttribute_UI.Attribute('%s.%s' % (obj, attr), super_type) for attr in cmds.listAttr( obj, se=True, ro=False, m=True, w=True) ]) if len(self.selection): self.objs_attr = get_usable_attrs(self.selection[0], Object) # if we also want the object's history we add it to the initial set if self.WC_histo.isChecked(): for histo in self.get_history(self.selection[0]): self.objs_attr |= get_usable_attrs(histo, History) # filling the shape's set for shape in (self.get_shapes(self.selection[0]) or []): self.shps_attr |= get_usable_attrs(shape, Shape) # if selection's length bigger than one we compare by intersection with the other sets if len(self.selection) > 1: for obj in self.selection: sub_attr = get_usable_attrs(obj, Object) if self.WC_histo.isChecked(): for histo in self.get_history(obj): sub_attr |= get_usable_attrs(histo, History) self.objs_attr.intersection_update(sub_attr) for shape in (self.get_shapes(self.selection[0]) or []): self.shps_attr.intersection_update( get_usable_attrs(shape, Shape)) # finally getting all intersecting attributes' types self.objs_attr = self.get_attributes_type(self.objs_attr) self.shps_attr = self.get_attributes_type(self.shps_attr) # and filtering the list self.filter() def add_set(self, iterable, title=None): """ Adding the given iterable to the list with a first Separator object with given title :param iterable: list of item's attributes :param title: Separator's name """ if len(iterable): # if title is given we first add a Separator item to indicate coming list title if title: self.WL_attributes.addTopLevelItem( QTreeWidget_Separator(title)) items = [] for attr in sorted(iterable): item = QTreeWidgetItem([attr]) # assigning the attribute itself inside a custom parameter item.attribute = attr items.append(item) # finally adding all the items to the list self.WL_attributes.addTopLevelItems(items) def filter(self): """ Filter the list with UI's parameters, such as name or type filtering, etc """ # pre cleaning self.WL_attributes.clear() # using regex compile to avoid re execution over many attributes mask = self.WV_search.text() case = 0 if self.WC_cases.isChecked() else re.IGNORECASE re_start = re.compile(r'^%s.*?' % mask, case) re_cont = re.compile(r'.*?%s.*?' % mask, case) # getting the four different lists obj_start = set([at for at in self.objs_attr if re_start.search(at)]) shp_start = set([at for at in self.shps_attr if re_start.search(at)]) # if type filtering is one we only extract the wanted attribute's type if self.WC_types.isChecked(): obj_start = set([ at for at in obj_start if at.type in self.ctx_wide[ self.WL_attrtype.currentText().lower()] ]) shp_start = set([ at for at in shp_start if at.type in self.ctx_wide[ self.WL_attrtype.currentText().lower()] ]) # finally adding the current sets if there is a mask we add the also the containing matches if mask: # getting contains filtering and type containers filtering obj_contains = obj_start.symmetric_difference( set([at for at in self.objs_attr if re_cont.search(at)])) shp_contains = shp_start.symmetric_difference( set([at for at in self.shps_attr if re_cont.search(at)])) if self.WC_types.isChecked(): obj_contains = set([ at for at in obj_contains if at.type in self.ctx_wide[ self.WL_attrtype.currentText().lower()] ]) shp_contains = set([ at for at in shp_contains if at.type in self.ctx_wide[ self.WL_attrtype.currentText().lower()] ]) # adding the sets self.add_set(obj_start, 'Obj attributes starting with') self.add_set(obj_contains, 'Obj attributes containing') self.add_set(shp_start, 'Shape attributes starting with') self.add_set(shp_contains, 'Shape attributes containing') else: self.add_set(obj_start, 'Object\'s attributes') self.add_set(shp_start, 'Shape\'s attributes') # and we select the first one if ever there is something in the list if self.WL_attributes.topLevelItemCount(): self.WL_attributes.setItemSelected( self.WL_attributes.topLevelItem(1), True)
class RangeWidget(QWidget): """Interface for changing Range information. It shows the current range and range policy. This widget was designed for use with the tab dialog. It can be used by itself or it can be used as part of a bigger color tab. Changes to this widget are emitted via a changeSignal as a boolean on policy, range tuple and this widget's tag. """ changeSignal = Signal(bool, float, float, str) def __init__(self, parent, use_max, current_range, max_range, tag): """Creates a ColorMap widget. parent The Qt parent of this widget. use_max Whether the policy is to use max possible or set range. current_range The min and max range on creation. tag A name for this widget, will be emitted on change. """ super(RangeWidget, self).__init__(parent) self.edit_range = (current_range[0], current_range[1]) self.max_range = max_range self.use_max = use_max self.tag = tag layout = QVBoxLayout() self.range_check = QCheckBox("Use maximum range across applicable " + "modules.") layout.addWidget(self.range_check) if self.use_max: self.range_check.setChecked(True) else: self.range_check.setChecked(False) self.range_check.stateChanged.connect(self.checkChanged) layout.addItem(QSpacerItem(3,3)) hlayout = QHBoxLayout() hlayout.addWidget(QLabel("Set range: ")) self.range_min = QLineEdit(str(current_range[0]), self) self.range_min.editingFinished.connect(self.rangeChanged) hlayout.addWidget(self.range_min) hlayout.addWidget(QLabel(" to ")) self.range_max = QLineEdit(str(current_range[1]), self) self.range_max.editingFinished.connect(self.rangeChanged) hlayout.addWidget(self.range_max) layout.addLayout(hlayout) self.setStates() self.setLayout(layout) def setStates(self): if self.use_max: self.range_min.setDisabled(True) self.range_max.setDisabled(True) else: self.range_min.setDisabled(False) self.range_max.setDisabled(False) @Slot() def checkChanged(self): """Handles check/uncheck of use max.""" self.use_max = self.range_check.isChecked() self.setStates() if self.use_max: self.changeSignal.emit(self.use_max, self.max_range[0], self.max_range[1], self.tag) else: self.changeSignal.emit(self.use_max, self.edit_range[0], self.edit_range[1], self.tag) @Slot() def rangeChanged(self): self.edit_range = (float(self.range_min.text()), float(self.range_max.text())) self.changeSignal.emit(self.use_max, self.edit_range[0], self.edit_range[1], self.tag)
class Form(QDialog): def __init__(self, state, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.setWindowTitle("Copy Entry — {}".format( QApplication.applicationName())) self.createWidgets() self.layoutWidgets() self.createConnections() self.updateUi() settings = QSettings() self.updateToolTips( bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): selectedEid = self.state.viewAllPanel.view.selectedEid self.selectedEntry = self.state.model.entry(selectedEid) self.entryLabel = QLabel("Copy ") termText = Lib.elidePatchHtml(self.selectedEntry.term, self.state) self.termLabel = Widgets.Label.HtmlLabel("“{}”".format(termText)) self.eidGroup = QGroupBox() self.copyToTopRadioButton = QRadioButton("to be a &Main Entry") self.tooltips.append((self.copyToTopRadioButton, """\ <p><b>to be a Main Entry</b></p> <p>Copy the original entry to be a Main Entry (even if it is already).</p>""")) self.subentryRadioButton = QRadioButton("to be a &Subentry of itself") self.tooltips.append((self.subentryRadioButton, """\ <p><b>to be a Subentry of itself</b></p> <p>Copy the original entry to be a subentry of the original entry.</p>""")) self.siblingRadioButton = QRadioButton("to be a Si&bling of itself") self.tooltips.append((self.subentryRadioButton, """\ <p><b>to be a Sibling of itself</b></p> <p>Copy the original entry to be a sibling of itself, i.e., to be a subentry of the original entry's parent.</p>""")) self.filteredEntry = self.circledEntry = None filteredEid = self.state.viewFilteredPanel.view.selectedEid if filteredEid is not None: self.filteredEntry = self.state.model.entry(filteredEid) circledEid = self.state.viewAllPanel.view.circledEid if circledEid is not None: self.circledEntry = self.state.model.entry(circledEid) self.filteredRadioButton = QRadioButton("under &Filtered") self.circledRadioButton = QRadioButton("under C&ircled") self.recentRadioButton = QRadioButton("under &Recent") self.tooltips.append( (self.recentRadioButton, """<p><b>under Recent</b></p> <p>Copy the current entry under a recently visited entry.</p>""")) self.filteredLabel = Widgets.Label.HtmlLabel() self.circledLabel = Widgets.Label.HtmlLabel() self.copyToTopRadioButton.setChecked(True) seen = {selectedEid} self.buttons = (self.copyToTopRadioButton, self.subentryRadioButton, self.filteredRadioButton, self.circledRadioButton, self.recentRadioButton) Forms.Util.setUpRadioButton( self, self.filteredEntry, self.filteredRadioButton, self.filteredLabel, self.buttons, seen, """<p><b>under Filtered</b></p> <p>Copy the current entry under the filtered entry “{}”.</p>""") Forms.Util.setUpRadioButton( self, self.circledEntry, self.circledRadioButton, self.circledLabel, self.buttons, seen, """<p><b>under Circled</b></p> <p>Copy the current entry under the circled entry “{}”.</p>""") self.recentComboBox = Forms.Util.createTermsComboBox( self.state, self.state.gotoEids, ignore=seen, maximum=MAX_RECENT) self.optionsGroup = QGroupBox() self.copyAllCheckBox = QCheckBox("Copy &All:") self.tooltips.append((self.copyAllCheckBox, """\ <p><b>Copy All</b></p> <p>If you check this checkbox, the other Copy checkboxes are checked in one go.</p>""")) self.copyXrefsCheckBox = QCheckBox("Cross-r&eferences") self.tooltips.append((self.copyXrefsCheckBox, """\ <p><b>Cross-references</b></p> <p>Copy cross-references from the original entry(ies) to the copied entry(ies).</p>""")) self.copyGroupsCheckBox = QCheckBox("&Groups") self.tooltips.append((self.copyGroupsCheckBox, """\ <p><b>Groups</b></p> <p>Copy groups from the original entry(ies) to the copied entry(ies).</p> <p>If you check the <b>Link Pages...</b> checkbox, this checkbox will be both checked and disabled, since linking is achieved by copying a linked group (creating one if necessary).</p>""")) self.copySubentriesCheckBox = QCheckBox("S&ubentries") self.tooltips.append((self.copySubentriesCheckBox, """\ <p><b>Subentries</b></p> <p>Copy the copied entry's subentries, subsubentries, and so on.</p>""")) self.linkPagesCheckBox = QCheckBox("&Link Pages between") self.linkLabel = Widgets.Label.HtmlLabel( "“{}” and its copy".format(termText)) self.tooltips.append((self.linkPagesCheckBox, """\ <p><b>Link Pages</b></p> <p>If the original entry belongs to a linked group, its copy is added to that linked group. If the original doesn't belong to a linked group, a new linked group is created with the name of the original's term, and both the original and its copy are added to this new linked group.</p> <p>If you check the this checkbox, the <b>Copy Groups</b> checkbox will be both checked and disabled, since linking is achieved by copying a linked group (creating one if necessary).</p>""")) self.withSeeCheckBox = QCheckBox("A&dd a") self.withSeeLabel1 = Widgets.Label.HtmlLabel( "<i>see</i> cross-reference from the copy to “{}”".format( termText)) self.withSeeLabel2 = Widgets.Label.HtmlLabel( "and <i>don't</i> copy the pages") self.withSeeLabel2.setIndent(self.fontMetrics().width("WW")) self.buttonBox = QDialogButtonBox() self.copyButton = QPushButton(QIcon(":/copy.svg"), "C&opy") self.tooltips.append((self.copyButton, """<p><b>Copy</b></p> <p>Copy the “{}” entry.</p>""".format(self.termLabel.text()))) self.buttonBox.addButton(self.copyButton, QDialogButtonBox.AcceptRole) self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel") self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p> <p>Close the dialog without making any changes to the index.</p>""")) self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append( (self.helpButton, "Help on the Copy Entry dialog")) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole) def layoutWidgets(self): layout = QVBoxLayout() entryLayout = QHBoxLayout() entryLayout.setSpacing(0) entryLayout.addWidget(self.entryLabel) entryLayout.addWidget(self.termLabel) entryLayout.addStretch() layout.addLayout(entryLayout) eidLayout = QVBoxLayout() eidLayout.addWidget(self.copyToTopRadioButton) eidLayout.addWidget(self.subentryRadioButton) eidLayout.addWidget(self.siblingRadioButton) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.filteredRadioButton) hbox.addWidget(self.filteredLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.circledRadioButton) hbox.addWidget(self.circledLabel, 1) eidLayout.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.recentRadioButton) hbox.addWidget(self.recentComboBox, 1) eidLayout.addLayout(hbox) eidLayout.addStretch() self.eidGroup.setLayout(eidLayout) layout.addWidget(self.eidGroup) vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.copyAllCheckBox) hbox.addWidget(self.copyXrefsCheckBox) hbox.addWidget(self.copyGroupsCheckBox) hbox.addWidget(self.copySubentriesCheckBox) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.linkPagesCheckBox) hbox.addWidget(self.linkLabel) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.setSpacing(0) hbox.addWidget(self.withSeeCheckBox) hbox.addWidget(self.withSeeLabel1) hbox.addStretch() vbox.addLayout(hbox) vbox.addWidget(self.withSeeLabel2) self.optionsGroup.setLayout(vbox) layout.addWidget(self.optionsGroup) layout.addWidget(self.buttonBox) self.setLayout(layout) def createConnections(self): self.buttonBox.accepted.connect(self.copy) self.buttonBox.rejected.connect(self.reject) self.helpButton.clicked.connect(self.help) self.copyXrefsCheckBox.toggled.connect(self.updateUi) self.copyGroupsCheckBox.toggled.connect(self.updateUi) self.copySubentriesCheckBox.toggled.connect(self.updateUi) self.linkPagesCheckBox.toggled.connect(self.updateUi) self.withSeeCheckBox.toggled.connect(self.updateUi) self.copyAllCheckBox.toggled.connect(self.copyAll) self.recentRadioButton.toggled.connect(self.moveFocus) self.recentComboBox.currentIndexChanged[int].connect( self.recentChanged) def recentChanged(self): self.recentRadioButton.setChecked(True) self.updateUi() def moveFocus(self): if self.recentRadioButton.isChecked(): self.recentComboBox.setFocus() def updateUi(self): self.recentRadioButton.setEnabled(self.recentComboBox.count()) self.recentComboBox.setEnabled(self.recentComboBox.count()) enable = not self.withSeeCheckBox.isChecked() for widget in (self.copyAllCheckBox, self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox, self.linkPagesCheckBox): if not enable: widget.setChecked(False) widget.setEnabled(enable) self.linkLabel.setEnabled(enable) if enable: if self.linkPagesCheckBox.isChecked(): self.copyGroupsCheckBox.setChecked(True) self.copyGroupsCheckBox.setEnabled(False) else: self.copyGroupsCheckBox.setEnabled(True) self.copyAllCheckBox.setChecked( all(widget.isChecked() for widget in (self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox))) def copyAll(self, checked): if checked: for widget in (self.copyXrefsCheckBox, self.copyGroupsCheckBox, self.copySubentriesCheckBox): widget.setChecked(True) def help(self): self.state.help("xix_ref_dlg_copy.html") def copy(self): self.state.maybeSave() eid = self.selectedEntry.eid peid = None if self.copyToTopRadioButton.isChecked(): peid = ROOT description = "copy “{}” to be main entry" elif self.subentryRadioButton.isChecked(): peid = eid description = "copy “{}” to be subentry of itself" elif self.siblingRadioButton.isChecked(): peid = self.selectedEntry.peid description = "copy “{}” to be sibling of itself" elif self.filteredRadioButton.isChecked(): peid = self.filteredEntry.eid description = "copy “{}” under filtered" elif self.circledRadioButton.isChecked(): peid = self.circledEntry.eid description = "copy “{}” under circled" elif self.recentRadioButton.isChecked(): peid = self.recentComboBox.itemData( self.recentComboBox.currentIndex()) description = "copy “{}” under recently visited" if peid is not None: # Should always be True description = description.format( Lib.elidePatchHtml(self.selectedEntry.term, self.state)) self.state.model.copyEntry( Lib.CopyInfo(eid, peid, self.copyXrefsCheckBox.isChecked(), self.copyGroupsCheckBox.isChecked(), self.copySubentriesCheckBox.isChecked(), self.linkPagesCheckBox.isChecked(), self.withSeeCheckBox.isChecked(), description)) say(re.sub(r"^copy", "Copied", Lib.htmlToPlainText(description)), SAY_TIMEOUT) self.accept()
class Panel(QWidget): def __init__(self, state, parent=None): super().__init__(parent) self.state = state self.entry = None self.saf = Saf.AUTO self.peid = ROOT self.createWidgets() self.layoutWidgets() self.createConnections() self.showOrHideNotes() self.showOrHideSortAs() self.termEdit.setFocus() def createWidgets(self): self.helpButton = QToolButton() self.helpButton.setIcon(QIcon(":/help.svg")) self.helpButton.setFocusPolicy(Qt.NoFocus) self.tooltips.append((self.helpButton, "Help on the Entry panel.")) self.addingLabel = Widgets.Label.HtmlLabel(CANCEL_ADD) self.addingLabel.hide() self.termLabel = QLabel("&Term") self.termEdit = Widgets.LineEdit.HtmlLineEdit(self.state) self.tooltips.append((self.termEdit, """\ <p><b>Term editor</b> (Alt+T)</p> <p>The entry's term text styled (e.g., <b>bold</b>, <i>italic</i>), as it should appear in the final index.</p>""")) self.spellHighlighter = Widgets.SpellHighlighter.Highlighter( self.state, self.termEdit.document()) self.termLabel.setBuddy(self.termEdit) self.pagesLabel = QLabel("&Pages") self.pagesEdit = Widgets.LineEdit.HtmlPagesLineEdit(self.state, maxLines=3) self.tooltips.append((self.pagesEdit, """\ <p><b>Pages editor</b> (Alt+P)</p> <p>The entry's pages styled (e.g., <b>bold</b>, <i>italic</i>), as they should appear in the final index.</p> <p>The pages are automatically sorted, and exact duplicates are automatically removed.</p> <p>See also <b>Index→Combine Overlapping Pages</b> and <b>Index→Renumber Pages</b>.</p>""")) self.pagesLabel.setBuddy(self.pagesEdit) self.calcSortAsCheckBox = QCheckBox("&Automatically Calculate Sort As") self.tooltips.append((self.calcSortAsCheckBox, """\ <p><b>Automatically Calculate Sort As</b> (Alt+A)</p> <p>This checkbox controls how the Sort As text is created.</p> <p>If checked, {} will either automatically create the sort as text, or will present some choices from which to choose the sort as text, depending on the term text.</p> <p>If unchecked, the sort as text should be entered manually.</p>""".format(QApplication.applicationName()))) self.calcSortAsCheckBox.setChecked(True) self.sortAsHelpButton = QToolButton() self.sortAsHelpButton.setIcon(QIcon(":/help.svg")) self.sortAsHelpButton.setFocusPolicy(Qt.NoFocus) self.tooltips.append( (self.sortAsHelpButton, "Help on the Sort As text.")) self.sortAsEdit = Widgets.LineEdit.LineEdit(self.state) self.tooltips.append((self.sortAsEdit, """\ <p><b>Sort As editor</b> (Alt+S)</p> <p>The entry's sort as text.</p> <p>If the <b>Automatically Calculate Sort As</b> checkbox is unchecked, manually enter the sort as text to use for sorting the entry.</p> <p>Main entry's are sorted using the sort as text, so it is easy to force a non-standard ordering by entering a custom sort as text.</p> <p>Subentries are also sorted using the sort as text, but the first word of a subentry will be ignored for sorting purposes if it is in the Ignore Subentry Function words list (see <b>Index→Ignore Subentry Function words</b>) <i>and</i> the <b>Index→Options, Rules, Ignore Subenty Function Words</b> checkbox is checked for this index.</p>""")) self.sortAsEdit.setEnabled(False) self.sortAsLabel = QLabel("&Sort As") self.sortAsLabel.setBuddy(self.sortAsEdit) self.sortAsLabel.setEnabled(False) self.xrefLabel = QLabel("&Cross-references") self.xrefList = Widgets.List.HtmlListWidget(self.state, minLines=4) self.tooltips.append((self.xrefList, """\ <p><b>Cross-references list</b> (Alt+C)</p> <p>The list of the entry's see and see also cross-references, both generic and to other entries.</p> <p>To add a cross-reference to an entry, circle the <i>to</i> entry (<b>Entry→Circle</b>), then go to the <i>from</i> entry and click <img src=":/xref-add.svg" width={0} height={0}> or press <b>Entry→Add Cross-reference</b> (See also the <b>Entry</b> menu.)</p>""".format(TOOLTIP_IMAGE_SIZE))) self.xrefLabel.setBuddy(self.xrefList) self.notesLabel = QLabel("&Notes") self.notesEdit = Widgets.LineEdit.MultilineHtmlEdit(self.state) self.tooltips.append((self.notesEdit, """\ <p><b>Notes editor</b> (Alt+N)</p> <p>The entry's notes.</p> <p>The notes shown here are never output as part of the index so may be freely used for any purpose.</p> <p>If the notes facility isn't wanted, the notes can be hidden by unchecking the <b>Index→Options, General, Show Notes</b> checkbox.</p>""")) self.notesLabel.setBuddy(self.notesEdit) def layoutWidgets(self): form = QFormLayout() form.addRow(self.addingLabel) hbox = QHBoxLayout() hbox.addWidget(self.termEdit, 1) hbox.addWidget(self.helpButton) form.addRow(self.termLabel, hbox) form.addRow(self.pagesLabel, self.pagesEdit) hbox = QHBoxLayout() hbox.addWidget(self.calcSortAsCheckBox, 1) hbox.addWidget(self.sortAsHelpButton) form.addRow(hbox) form.addRow(self.sortAsLabel, self.sortAsEdit) vbox = QVBoxLayout() vbox.addLayout(form) vbox.addWidget(self.xrefLabel) vbox.addWidget(self.xrefList, 1) vbox.addWidget(self.notesLabel) vbox.addWidget(self.notesEdit, 1) self.setLayout(vbox) def createConnections(self): self.helpButton.clicked.connect(self.help) self.sortAsHelpButton.clicked.connect( lambda: self.help("xix_ref_sortas.html")) self.termEdit.textChanged.connect(self.termChanged) self.termEdit.cursorPositionChanged.connect(self.maybeSetSuggestions) self.termEdit.textChanged.connect(self.updateMode) self.termEdit.lostFocus.connect(self.maybeSave) self.termEdit.enterPressed.connect( lambda: self.tabAndMaybeSave(self.pagesEdit)) self.pagesEdit.textChanged.connect(self.updateMode) self.pagesEdit.lostFocus.connect(self.maybeSave) self.pagesEdit.enterPressed.connect( lambda: self.tabAndMaybeSave(self.calcSortAsCheckBox)) self.calcSortAsCheckBox.toggled.connect(self.calcSortAsToggled) self.sortAsEdit.textChanged.connect(self.updateMode) self.sortAsEdit.lostFocus.connect(self.maybeSave) self.sortAsEdit.enterPressed.connect( lambda: self.tabAndMaybeSave(self.xrefList)) self.notesEdit.textChanged.connect(self.updateMode) self.notesEdit.lostFocus.connect(self.maybeSave) def help(self, page="xix_ref_panel_entry.html"): self.state.help(page) def tabAndMaybeSave(self, widget): self.maybeSave() widget.setFocus() def updateUi(self): enable = self.state.mode not in {ModeKind.NO_INDEX, ModeKind.CHANGE} self.setEnabled(enable) if enable: enable = (self.state.mode in {ModeKind.ADD, ModeKind.EDIT} or not self.termEdit.isEmpty()) for widget in (self.termEdit, self.pagesEdit, self.calcSortAsCheckBox, self.xrefList, self.notesEdit): widget.setEnabled(enable) self.sortAsEdit.setEnabled( enable and not self.calcSortAsCheckBox.isChecked()) if self.state.mode is ModeKind.ADD: self.state.window.modeLabel.setText( "<font color=green>Adding</font>") def updateDisplayFonts(self): for widget in (self.termEdit, self.sortAsEdit, self.pagesEdit, self.notesEdit, self.xrefList): widget.updateDisplayFonts() def populateEditors(self, editors): editors |= { self.termEdit, self.sortAsEdit, self.pagesEdit, self.notesEdit } def maybeSave(self): if self.hasChanged(): if not bool(self.sortAsEdit.toPlainText().strip()): sortas = self.state.model.sortBy(self.termEdit.toHtml(), self.saf, self.peid is not ROOT) self.sortAsEdit.setPlainText(sortas) self.state.save() def hasChanged(self): term = self.termEdit.toHtml() sortas = self.sortAsEdit.toPlainText().strip() pages = self.pagesEdit.toHtml() notes = self.notesEdit.toHtml() if self.entry is None: return bool(term or sortas or pages or notes) return (self.entry.term != term or self.entry.sortas != sortas or self.entry.pages != pages or self.entry.notes != notes or self.entry.saf != self.saf) def updateMode(self): if (self.state.mode not in { ModeKind.NO_INDEX, ModeKind.ADD, ModeKind.EDIT, ModeKind.CHANGE } and self.hasChanged()): self.state.setMode(ModeKind.EDIT) def clearForm(self): self.state.spellPanel.clearSuggestions() self.state.groupsPanel.clear() positions = Positions(self.termEdit.textCursor().position(), self.sortAsEdit.textCursor().position(), self.pagesEdit.textCursor().position(), self.notesEdit.textCursor().position()) self.termEdit.clear() self.calcSortAsCheckBox.setChecked(True) self.sortAsEdit.clear() self.pagesEdit.clear() self.xrefList.clear() self.notesEdit.clear() return positions def setEntry(self, entry): positions = self.clearForm() self.entry = entry if entry is not None: self.termEdit.setHtml(entry.term, positions.term) self.saf = entry.saf or Saf.AUTO self.calcSortAsCheckBox.setChecked(self.saf != Saf.CUSTOM) self.sortAsEdit.setPlainText(entry.sortas, positions.sortas) self.pagesEdit.setHtml(entry.pages, positions.pages) self.notesEdit.setHtml(entry.notes, positions.notes) for xref in list(self.state.model.xrefs(entry.eid)): kind = "See" if xref.kind is XrefKind.SEE else "See also" term = Lib.elidePatchHtml(self.state.model.termPath( xref.to_eid), self.state, maxlen=None) item = QListWidgetItem("{} <i>{}</i> {}".format( XREF_INDICATOR, kind, term)) item.setData(Qt.UserRole, xref) self.xrefList.addItem(item) for xref in list(self.state.model.generic_xrefs(entry.eid)): kind = ("See (generic)" if xref.kind is XrefKind.SEE_GENERIC else "See also (generic)") item = QListWidgetItem("{} <i>{}</i> {}".format( XREF_INDICATOR, kind, xref.term)) item.setData(Qt.UserRole, xref) self.xrefList.addItem(item) if self.xrefList.count(): self.xrefList.setCurrentRow(0) self.state.updateGotoEids(entry.eid) self.state.groupsPanel.updateGroups() self.state.updateNavigationStatus() self.state.setMode(ModeKind.VIEW) @property def unknownWords(self): return self.spellHighlighter.unknownWords def termChanged(self): if self.addingLabel.isVisible(): self.addingLabel.setText(CANCEL_ADD) text = self.termEdit.toPlainText() if bool(self.state.model): while text: eid = self.state.model.firstForPrefix(text) if eid is not None: term = Lib.elidePatchHtml(self.state.model.term(eid), self.state) self.addingLabel.setText(CANCEL_ADD + " and goto “{}”".format(term)) break text = text[:-1] self.maybeSetSuggestions() def maybeSetSuggestions(self): word, _ = self.termEdit.wordAndPosition() if word: if self.termEdit.hasFocus(): replacement = self.state.model.autoReplacementFor(word) if replacement is not None: self.termEdit.replaceWord(replacement) return self.state.spellPanel.populateSuggestions(word) else: self.state.spellPanel.clearSuggestions() def rememberWord(self): word = self.findNearestUnknownWord() if word: Spell.add(word, self.state.language.value) self.state.model.addSpellWord(word) self.spellHighlighter.rehighlight() def ignoreWord(self): word = self.findNearestUnknownWord() if word: self.spellHighlighter.wordsToIgnore.add(word) self.spellHighlighter.rehighlight() def findNearestUnknownWord(self): pos = self.termEdit.textCursor().position() where = -1 unknownWord = None unknownWords = sorted(self.unknownWords) for i, word in unknownWords: if i > where and i <= pos: where = i unknownWord = word if i > pos: break if unknownWord is None and unknownWords: unknownWord = unknownWords[-1][1] return unknownWord def completeWithSuggested(self): index = self.state.spellPanel.currentRow() self.complete(index) def complete(self, i): item = self.state.spellPanel.item(i) if item: word = self.state.spellPanel.item(i).text() self.completeWord(word) def completeWord(self, word): word = COMPLETE_WORD_RX.sub("", word) if word: self.termEdit.replaceWord(word) def showOrHideNotes(self): settings = QSettings() visible = bool( int(settings.value(Gopt.Key.ShowNotes, Gopt.Default.ShowNotes))) self.notesLabel.setVisible(visible) self.notesEdit.setVisible(visible) def showOrHideSortAs(self): settings = QSettings() alwaysShowSortAs = bool( int( settings.value(Gopt.Key.AlwaysShowSortAs, Gopt.Default.AlwaysShowSortAs))) editable = not self.calcSortAsCheckBox.isChecked() visible = alwaysShowSortAs or editable for widget in (self.sortAsLabel, self.sortAsEdit): widget.setVisible(visible) widget.setEnabled(editable) def calcSortAsToggled(self): self.showOrHideSortAs() self.updateMode() if self.calcSortAsCheckBox.isChecked(): saf = self.saf if self.saf != Saf.CUSTOM else Saf.AUTO self.state.calculateSortAs(saf, force=True) else: self.saf = Saf.CUSTOM
def testSimpleSignal(self): box = QCheckBox('check me') box.stateChanged[int].connect(self.cb_changedVoid) self._changed = False box.setChecked(True) self.assert_(self._changed)
class ConfigDialog(QtGui.QDialog): pressedclosebutton = False malToggling = False def malToggled(self): if self.malToggling == False: self.malToggling = True if self.malenabledCheckbox.isChecked() and self.malenabledCheckbox.isVisible(): self.malenabledCheckbox.setChecked(False) self.malSettingsGroup.setChecked(True) self.malSettingsGroup.show() self.malpasswordLabel.show() self.malpasswordTextbox.show() self.malusernameLabel.show() self.malusernameTextbox.show() self.malenabledCheckbox.hide() else: self.malSettingsGroup.setChecked(False) self.malSettingsGroup.hide() self.malpasswordLabel.hide() self.malpasswordTextbox.hide() self.malusernameLabel.hide() self.malusernameTextbox.hide() self.malenabledCheckbox.show() self.malToggling = False self.adjustSize() self.setFixedSize(self.sizeHint()) def runButtonTextUpdate(self): if (self.donotstoreCheckbox.isChecked()): self.runButton.setText("Run Syncplay") else: self.runButton.setText("Store configuration and run Syncplay") def openHelp(self): if sys.platform.startswith('linux'): self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/linux/") elif sys.platform.startswith('win'): self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/windows/") else: self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/") def _tryToFillPlayerPath(self, playerpath, playerpathlist): foundpath = "" if playerpath != None and playerpath != "" and os.path.isfile(playerpath): foundpath = playerpath self.executablepathCombobox.addItem(foundpath) for path in playerpathlist: if(os.path.isfile(path) and path.lower() != foundpath.lower()): self.executablepathCombobox.addItem(path) if foundpath == None: foundpath = path if foundpath: return(foundpath) else: return("") def browsePlayerpath(self): options = QtGui.QFileDialog.Options() defaultdirectory = "" browserfilter = "All Files (*)" if os.name == 'nt': browserfilter = "Executable files (*.exe);;All Files (*)" if "PROGRAMFILES(X86)" in os.environ: defaultdirectory = os.environ["ProgramFiles(x86)"] elif "PROGRAMFILES" in os.environ: defaultdirectory = os.environ["ProgramFiles"] elif "PROGRAMW6432" in os.environ: defaultdirectory = os.environ["ProgramW6432"] elif sys.platform.startswith('linux'): defaultdirectory = "/usr/bin" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self, "Browse for media player executable", defaultdirectory, browserfilter, "", options) if fileName: self.executablepathCombobox.setEditText(fileName) def loadMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") self.mediadirectory = settings.value("mediadir", "") settings.endGroup() def saveMediaBrowseSettings(self): settings = QSettings("Syncplay", "MediaBrowseDialog") settings.beginGroup("MediaBrowseDialog") settings.setValue("mediadir", self.mediadirectory) settings.endGroup() def browseMediapath(self): self.loadMediaBrowseSettings() options = QtGui.QFileDialog.Options() if (os.path.isdir(self.mediadirectory)): defaultdirectory = self.mediadirectory elif (os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.MoviesLocation))): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.MoviesLocation) elif (os.path.isdir(QDesktopServices.storageLocation(QDesktopServices.HomeLocation))): defaultdirectory = QDesktopServices.storageLocation(QDesktopServices.HomeLocation) else: defaultdirectory = "" browserfilter = "All Files (*)" fileName, filtr = QtGui.QFileDialog.getOpenFileName(self,"Browse for media files",defaultdirectory, browserfilter, "", options) if fileName: self.mediapathTextbox.setText(fileName) self.mediadirectory = os.path.dirname(fileName) self.saveMediaBrowseSettings() def _saveDataAndLeave(self): self.config['host'] = self.hostTextbox.text() self.config['name'] = self.usernameTextbox.text() self.config['room'] = self.defaultroomTextbox.text() self.config['password'] = self.serverpassTextbox.text() self.config['playerPath'] = unicode(self.executablepathCombobox.currentText()) self.config['file'] = os.path.abspath(self.mediapathTextbox.text()) if self.mediapathTextbox.text() != "" else None if self.alwaysshowCheckbox.isChecked() == True: self.config['forceGuiPrompt'] = True else: self.config['forceGuiPrompt'] = False if self.donotstoreCheckbox.isChecked() == True: self.config['noStore'] = True else: self.config['noStore'] = False if self.slowdownCheckbox.isChecked() == True: self.config['slowOnDesync'] = True else: self.config['slowOnDesync'] = False self.config['malUsername'] = self.malusernameTextbox.text() if self.malSettingsGroup.isChecked(): self.config['malPassword'] = self.malpasswordTextbox.text() else: self.config['malPassword'] = "" self.pressedclosebutton = True self.close() return def closeEvent(self, event): if self.pressedclosebutton == False: sys.exit() raise GuiConfiguration.WindowClosed event.accept() def dragEnterEvent(self, event): data = event.mimeData() urls = data.urls() if (urls and urls[0].scheme() == 'file'): event.acceptProposedAction() def dropEvent(self, event): data = event.mimeData() urls = data.urls() if (urls and urls[0].scheme() == 'file'): if sys.platform.startswith('linux'): dropfilepath = unicode(urls[0].path()) else: dropfilepath = unicode(urls[0].path())[1:] # Removes starting slash if dropfilepath[-4:].lower() == ".exe": self.executablepathCombobox.setEditText(dropfilepath) else: self.mediapathTextbox.setText(dropfilepath) def __init__(self, config, playerpaths, error): from syncplay import utils self.config = config self.QtGui = QtGui self.error = error if sys.platform.startswith('linux'): resourcespath = utils.findWorkingDir() + "/resources/" else: resourcespath = utils.findWorkingDir() + "\\resources\\" super(ConfigDialog, self).__init__() self.setWindowTitle(getMessage("en", "config-window-title")) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png")) if(config['host'] == None): host = "" elif(":" in config['host']): host = config['host'] else: host = config['host']+":"+str(config['port']) self.connectionSettingsGroup = QtGui.QGroupBox("Connection Settings") self.hostTextbox = QLineEdit(host, self) self.hostLabel = QLabel(getMessage("en", "host-label"), self) self.usernameTextbox = QLineEdit(config['name'],self) self.serverpassLabel = QLabel(getMessage("en", "password-label"), self) self.defaultroomTextbox = QLineEdit(config['room'],self) self.usernameLabel = QLabel(getMessage("en", "username-label"), self) self.serverpassTextbox = QLineEdit(config['password'],self) self.defaultroomLabel = QLabel(getMessage("en", "room-label"), self) self.connectionSettingsLayout = QtGui.QGridLayout() self.connectionSettingsLayout.addWidget(self.hostLabel, 0, 0) self.connectionSettingsLayout.addWidget(self.hostTextbox, 0, 1) self.connectionSettingsLayout.addWidget(self.serverpassLabel, 1, 0) self.connectionSettingsLayout.addWidget(self.serverpassTextbox, 1, 1) self.connectionSettingsLayout.addWidget(self.usernameLabel, 2, 0) self.connectionSettingsLayout.addWidget(self.usernameTextbox, 2, 1) self.connectionSettingsLayout.addWidget(self.defaultroomLabel, 3, 0) self.connectionSettingsLayout.addWidget(self.defaultroomTextbox, 3, 1) self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) self.mediaplayerSettingsGroup = QtGui.QGroupBox("Media Player Settings") self.executablepathCombobox = QtGui.QComboBox(self) self.executablepathCombobox.setEditable(True) self.executablepathCombobox.setEditText(self._tryToFillPlayerPath(config['playerPath'],playerpaths)) self.executablepathCombobox.setMinimumWidth(200) self.executablepathCombobox.setMaximumWidth(200) self.executablepathLabel = QLabel("Path to player executable:", self) self.executablebrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'),"Browse") self.executablebrowseButton.clicked.connect(self.browsePlayerpath) self.mediapathTextbox = QLineEdit(config['file'], self) self.mediapathLabel = QLabel("Path to media file:", self) self.mediabrowseButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'folder_explore.png'),"Browse") self.mediabrowseButton.clicked.connect(self.browseMediapath) self.slowdownCheckbox = QCheckBox("Slow down on desync") self.mediaplayerSettingsLayout = QtGui.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) self.mediaplayerSettingsLayout.addWidget(self.executablepathCombobox , 0, 1) self.mediaplayerSettingsLayout.addWidget(self.executablebrowseButton , 0, 2) self.mediaplayerSettingsLayout.addWidget(self.mediapathLabel, 1, 0) self.mediaplayerSettingsLayout.addWidget(self.mediapathTextbox , 1, 1) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 2) self.mediaplayerSettingsLayout.addWidget(self.slowdownCheckbox, 2, 0) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) if config['slowOnDesync'] == True: self.slowdownCheckbox.setChecked(True) self.malSettingsGroup = QtGui.QGroupBox("Enable MyAnimeList Updater (EXPERIMENTAL)") self.malSettingsGroup.setCheckable(True) self.malSettingsGroup.toggled.connect(self.malToggled) self.malSettingsSplit = QtGui.QSplitter(self) self.malusernameTextbox = QLineEdit(config['malUsername'],self) self.malusernameLabel = QLabel("MAL Username:"******"MAL Password:"******"Enable MyAnimeList Updater (EXPERIMENTAL)") self.malenabledCheckbox.toggled.connect(self.malToggled) if config['malPassword'] == None or config['malPassword'] == "": self.malenabledCheckbox.setChecked(False) self.malSettingsGroup.hide() else: self.malenabledCheckbox.hide() self.alwaysshowCheckbox = QCheckBox("Always Show This Dialog") if config['forceGuiPrompt'] == True: self.alwaysshowCheckbox.setChecked(True) self.donotstoreCheckbox = QCheckBox("Do Not Store This Configuration") self.donotstoreCheckbox.toggled.connect(self.runButtonTextUpdate) self.mainLayout = QtGui.QVBoxLayout() if error: self.errorLabel = QLabel(error, self) self.errorLabel.setAlignment(Qt.AlignCenter) self.errorLabel.setStyleSheet("QLabel { color : red; }") self.mainLayout.addWidget(self.errorLabel) self.mainLayout.addWidget(self.connectionSettingsGroup) self.mainLayout.addSpacing(12) self.mainLayout.addWidget(self.mediaplayerSettingsGroup) self.mainLayout.addSpacing(12) self.mainLayout.addWidget(self.malenabledCheckbox) self.mainLayout.addWidget(self.malSettingsGroup) self.topLayout = QtGui.QHBoxLayout() self.helpButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'help.png'),"Help") self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.pressed.connect(self.openHelp) self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'),"Store configuration and run Syncplay") self.runButton.pressed.connect(self._saveDataAndLeave) if config['noStore'] == True: self.donotstoreCheckbox.setChecked(True) self.runButton.setText("Run Syncplay") self.topLayout.addWidget(self.helpButton, Qt.AlignLeft) self.topLayout.addWidget(self.runButton, Qt.AlignRight) self.mainLayout.addWidget(self.alwaysshowCheckbox) self.mainLayout.addWidget(self.donotstoreCheckbox) self.mainLayout.addLayout(self.topLayout) self.mainLayout.addStretch(1) self.setLayout(self.mainLayout) self.runButton.setFocus() self.setFixedSize(self.sizeHint()) self.setAcceptDrops(True)
class DataBrowser(QWidget, Ui_DataBrowser): """ @since: 2011-08-24 """ __author__ = "Moritz Wade" __contact__ = "*****@*****.**" __copyright__ = "Zuse Institute Berlin 2011" def __init__(self, parent, id, dataSet): super(DataBrowser, self).__init__(parent) self.setupUi(self) self._simWorkbench = None self.dataService = None self.id = id self.data = dataSet self.optionsService = OptionsService() # create the custom selectable table header self.selectableHeader = SelectableTableHeader(Qt.Horizontal, self.tableView) self.selectableHeader.setNonSelectableIndexes([0]) self.selectableHeader.sectionSelectionChanged.connect( self.on_columnSelectionChanged) self.tableView.setHorizontalHeader(self.selectableHeader) # create the data model self.dataModel = DataBrowserModel(self, self.id, self.data) self.tableView.setModel(self.dataModel) self._setUpSelectionCheckBox() self._updateInfoPane() if not self.optionsService.getDebug(): self.groupBoxPerturbation.setVisible(False) def getId(self): return self.id def setSimulationWorkbench(self, simWorkbench): self._simWorkbench = simWorkbench def getSelectionCheckBox(self): return self._selectionCheckBox def isSelected(self): checkState = self._selectionCheckBox.checkState() return True if checkState == Qt.Checked else False def _setUpSelectionCheckBox(self): self._selectionCheckBox = QCheckBox() self._selectionCheckBox.setChecked(True) infoText = "Select or deselect this data (e.g. to be included in plots and computations)." self._selectionCheckBox.setStatusTip(infoText) self._selectionCheckBox.setToolTip(infoText) self._selectionCheckBox.stateChanged.connect(self._selectionChanged) def _updateInfoPane(self): """ Updates the info pane with basic info about the loaded data and the data file (if any). """ self.lineEditInfoSpecies.setText(str(self.data.getNumOfRealData())) self.lineEditInfoDataType.setText(self.data.type) # self.lineEditInfoFormat.setText(self.data.format) filepath = self.data.filename if filepath and os.path.exists(filepath): self.lineEditInfoPath.setText(filepath) filesize = os.path.getsize(filepath) filesize = filesize / 1024 # displaying kB self.lineEditInfoFilesize.setText("%s kB" % filesize) timeLastModifiedEpoch = os.path.getmtime(filepath) timeLastModified = time.strftime( "%a, %d %b %Y %H:%M:%S", time.localtime(timeLastModifiedEpoch)) self.lineEditInfoLastModified.setText(str(timeLastModified)) else: noFileText = "No File" self.lineEditInfoPath.setText(noFileText) self.lineEditInfoFilesize.setText(noFileText) self.lineEditInfoLastModified.setText(noFileText) def remove(self): """ Cleans up stuff then destroys self. It's not sure whether this is really needed but it might serve to close some memory holes (e.g. dangling references somewhere). """ del self.dataModel del self @Slot() def on_actionPlot_triggered(self): dataDict = {self.data.getId(): self.data} self._simWorkbench.plotExpData(dataDict) @Slot() def on_buttonPerturb_clicked(self): """ Perturbs the data by the % given in self.spinBoxPerturb. """ percentage = self.spinBoxPerturb.value() factor = percentage / 100.0 for entity, entityData in self.data.getData().items(): if not entityData.isSelected(): continue id = entity.getId() if type(entity) == EntityData else str(entity) logging.debug("Perturbing data of EntityData: %s" % id) for i in xrange(len(entityData.datapoints)): value = entityData.datapoints[i] if not value: # for None values continue fraction = value * factor # fraction of value that will be added or substracted #newValue = value + random.uniform(-1 * fraction, fraction) newValue = value + random.uniform(-1, 1) * fraction # newValue = value - fraction if random.random() < 0.5 else value + fraction entityData.setDatapoint(i, newValue) @Slot("") def on_buttonSaveAs_clicked(self): logging.debug("Saving data. Displaying file chooser...") file_choices = "Tab-Delimited Text File *.txt (*.txt)" path = unicode( QFileDialog.getSaveFileName(self, 'Save file', '', file_choices)[0]) if not path.endswith(".txt"): path += ".txt" if path: if not self.dataService: self.dataService = DataService() id = self.data.getId() self.dataService.save_data_as_csv(id, path) logging.info("Saved data to %s" % path) @Slot() def on_buttonTimeshift_clicked(self): """ Timeshift data within this DataBrowser (i.e. DataSet). Not only shift the global timepoints but also the timepoint lists within the individiual EntityData objects. """ try: shiftValue = float(self.lineEditTimeshift.text()) self.dataModel.doTimeshift(shiftValue) except Exception, e: logging.error( "DataBrowser.on_buttonTimeshift_clicked(): Error while timeshifting the data: %s" % e)
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): size = self.font().pointSize() + (1 if WIN else 2) Lib.createFontBoxesFor(self, "DisplayStd", *self.getFontFamilyAndSize( Gopt.Key.StdFont, Gopt.StdFont, Gopt.Key.StdFontSize, size), tooltips=self.form.tooltips, which="Std.") self.onDisplayStdFontChange(False) Lib.createFontBoxesFor(self, "DisplayAlt", *self.getFontFamilyAndSize( Gopt.Key.AltFont, Gopt.AltFont, Gopt.Key.AltFontSize, size), tooltips=self.form.tooltips, which="Alt.") self.onDisplayAltFontChange(False) Lib.createFontBoxesFor(self, "DisplayMono", *self.getFontFamilyAndSize( Gopt.Key.MonoFont, Gopt.MonoFont, Gopt.Key.MonoFontSize, size - 1), mono=True, tooltips=self.form.tooltips, which="Mono.") self.onDisplayMonoFontChange(False) settings = QSettings() index = int( settings.value(Gopt.Key.MainForm_IndexViewPosition, Gopt.Default.MainForm_IndexViewPosition)) self.indexViewOnLeft = QCheckBox("&Index View on Left") self.indexViewOnLeft.setChecked(not index) self.form.tooltips.append((self.indexViewOnLeft, """\ <p><b>Index View on Left</b></p> <p>If checked, the index view will appear on the left with the entry, suggestions, and filtered panels on the right.</p>""")) showNotes = bool( int(settings.value(Gopt.Key.ShowNotes, Gopt.Default.ShowNotes))) self.showNotesCheckBox = QCheckBox("Show &Notes") self.showNotesCheckBox.setChecked(showNotes) self.form.tooltips.append((self.showNotesCheckBox, """\ <p><b>Show Notes</b></p> <p>If checked, a notes edit—and any notes that have been entered— is visible in the entry panel.</p>""")) alwaysShowSortAs = bool( int( settings.value(Gopt.Key.AlwaysShowSortAs, Gopt.Default.AlwaysShowSortAs))) self.alwaysShowSortAsCheckBox = QCheckBox("A&lways Show Sort As") self.alwaysShowSortAsCheckBox.setChecked(alwaysShowSortAs) self.form.tooltips.append((self.alwaysShowSortAsCheckBox, """\ <p><b>Always Show Sort As</b></p> <p>If checked, every entry's sort as text is shown. If unchecked, the sort as text is only shown if it is entered manually, i.e., if the <b>Automatically Calculate Sort As</b> checkbox is checked.</p>""")) showMenuToolTips = bool( int( settings.value(Gopt.Key.ShowMenuToolTips, Gopt.Default.ShowMenuToolTips))) self.showMenuToolTipsCheckBox = QCheckBox("Show Menu &Tooltips") self.showMenuToolTipsCheckBox.setChecked(showMenuToolTips) self.form.tooltips.append((self.showMenuToolTipsCheckBox, """\ <p><b>Show Menu Tooltips</b></p> <p>If checked, menu tooltips are shown when menus are pulled down and navigated using the mouse or keyboard.</p>""")) showMainWindowToolTips = bool( int( settings.value(Gopt.Key.ShowMainWindowToolTips, Gopt.Default.ShowMainWindowToolTips))) self.showMainWindowToolTipsCheckBox = QCheckBox( "Show Main &Window Tooltips") self.showMainWindowToolTipsCheckBox.setChecked(showMainWindowToolTips) self.form.tooltips.append((self.showMainWindowToolTipsCheckBox, """\ <p><b>Show Main Window Tooltips</b></p> <p>If checked, tooltips are shown when the mouse hovers over controls in the main window.</p>""")) showDialogToolTips = bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips))) self.showDialogToolTipsCheckBox = QCheckBox("Show &Dialog Tooltips") self.showDialogToolTipsCheckBox.setChecked(showDialogToolTips) self.form.tooltips.append((self.showDialogToolTipsCheckBox, """\ <p><b>Show Dialog Tooltips</b></p> <p>If checked, tooltips are shown when the mouse hovers over controls in dialogs (such as this one).</p>""")) keepHelpOnTop = bool( int( settings.value(Gopt.Key.KeepHelpOnTop, Gopt.Default.KeepHelpOnTop))) self.keepHelpOnTopCheckBox = QCheckBox("Keep &Help on Top") self.keepHelpOnTopCheckBox.setChecked(keepHelpOnTop) self.form.tooltips.append((self.keepHelpOnTopCheckBox, """\ <p><b>Keep Help on Top</b></p> <p>If checked, when you pop up the help window it will stay above any other XindeX window, even if you click another XindeX window.</p>""")) showSplash = bool( int(settings.value(Gopt.Key.ShowSplash, Gopt.Default.ShowSplash))) self.showSplashCheckBox = QCheckBox("Show S&plash at Startup") self.showSplashCheckBox.setChecked(showSplash) self.form.tooltips.append((self.showSplashCheckBox, """\ <p><b>Show Splash at Startup</b></p> <p>If checked, a splash window showing the XindeX icon and name will appear while XindeX is starting.</p>""")) def layoutWidgets(self): form = QFormLayout() grid = QGridLayout() grid.addWidget(self.indexViewOnLeft, 0, 0) grid.addWidget(self.alwaysShowSortAsCheckBox, 1, 0) grid.addWidget(self.showNotesCheckBox, 2, 0) grid.addWidget(self.showMenuToolTipsCheckBox, 0, 1) grid.addWidget(self.showMainWindowToolTipsCheckBox, 1, 1) grid.addWidget(self.showDialogToolTipsCheckBox, 2, 1) grid.addWidget(self.keepHelpOnTopCheckBox, 3, 1) grid.addWidget(self.showSplashCheckBox, 4, 1) hbox = QHBoxLayout() hbox.addLayout(grid) hbox.addStretch() form.addRow(hbox) hbox = QHBoxLayout() hbox.addWidget(self.displaystdFontComboBox, 1) hbox.addWidget(self.displaystdFontSizeSpinBox) hbox.addStretch() label = QLabel("&Std. Font") label.setBuddy(self.displaystdFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.displayaltFontComboBox, 1) hbox.addWidget(self.displayaltFontSizeSpinBox) hbox.addStretch() label = QLabel("&Alt. Font") label.setBuddy(self.displayaltFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.displaymonoFontComboBox, 1) hbox.addWidget(self.displaymonoFontSizeSpinBox) hbox.addStretch() label = QLabel("&Mono. Font") label.setBuddy(self.displaymonoFontComboBox) form.addRow(label, hbox) self.setLayout(form) def createConnections(self): self.displaystdFontComboBox.currentFontChanged.connect( self.onDisplayStdFontChange) self.displaystdFontSizeSpinBox.valueChanged[int].connect( self.onDisplayStdFontChange) self.displayaltFontComboBox.currentFontChanged.connect( self.onDisplayAltFontChange) self.displayaltFontSizeSpinBox.valueChanged[int].connect( self.onDisplayAltFontChange) self.displaymonoFontComboBox.currentFontChanged.connect( self.onDisplayMonoFontChange) self.displaymonoFontSizeSpinBox.valueChanged[int].connect( self.onDisplayMonoFontChange) self.indexViewOnLeft.stateChanged.connect(self.setIndexViewOnLeft) self.showNotesCheckBox.stateChanged.connect(self.setShowNotes) self.alwaysShowSortAsCheckBox.stateChanged.connect( self.setAlwaysShowSortAs) self.showMenuToolTipsCheckBox.stateChanged.connect( self.setShowMenuToolTips) self.showMainWindowToolTipsCheckBox.stateChanged.connect( self.setShowMainWindowToolTips) self.showDialogToolTipsCheckBox.stateChanged.connect( self.setShowDialogToolTips) self.showSplashCheckBox.stateChanged.connect(self.setShowSplash) self.keepHelpOnTopCheckBox.stateChanged.connect(self.setKeepHelpOnTop) def getFontFamilyAndSize(self, familyOpt, familyDef, sizeOpt, sizeDef): settings = QSettings() family = settings.value(familyOpt, familyDef) size = int(settings.value(sizeOpt, sizeDef)) return family, size def onDisplayStdFontChange(self, propagate=True): font = QFont(self.displaystdFontComboBox.currentFont()) font.setPointSize(self.displaystdFontSizeSpinBox.value()) if propagate: settings = QSettings() settings.setValue(Gopt.Key.StdFont, font.family()) settings.setValue(Gopt.Key.StdFontSize, font.pointSize()) self.state.updateDisplayFonts() def onDisplayAltFontChange(self, propagate=True): font = QFont(self.displayaltFontComboBox.currentFont()) font.setPointSize(self.displayaltFontSizeSpinBox.value()) if propagate: settings = QSettings() settings.setValue(Gopt.Key.AltFont, font.family()) settings.setValue(Gopt.Key.AltFontSize, font.pointSize()) self.state.updateDisplayFonts() def onDisplayMonoFontChange(self, propagate=True): font = QFont(self.displaymonoFontComboBox.currentFont()) font.setPointSize(self.displaymonoFontSizeSpinBox.value()) if propagate: settings = QSettings() settings.setValue(Gopt.Key.MonoFont, font.family()) settings.setValue(Gopt.Key.MonoFontSize, font.pointSize()) self.state.updateDisplayFonts() def setIndexViewOnLeft(self): index = 0 if self.indexViewOnLeft.isChecked() else 1 settings = QSettings() settings.setValue(Gopt.Key.MainForm_IndexViewPosition, index) self.state.window.setIndexViewPosition() def setShowNotes(self): showNotes = int(self.showNotesCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.ShowNotes, showNotes) self.state.entryPanel.showOrHideNotes() def setAlwaysShowSortAs(self): alwaysShowSortAs = int(self.alwaysShowSortAsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.AlwaysShowSortAs, alwaysShowSortAs) self.state.entryPanel.showOrHideSortAs() def setShowMenuToolTips(self): showMenuToolTips = int(self.showMenuToolTipsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.ShowMenuToolTips, showMenuToolTips) def setShowMainWindowToolTips(self): showMainWindowToolTips = int( self.showMainWindowToolTipsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.ShowMainWindowToolTips, showMainWindowToolTips) self.state.window.updateToolTips() def setShowDialogToolTips(self): showDialogToolTips = int(self.showDialogToolTipsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.ShowDialogToolTips, showDialogToolTips) self.form.updateToolTips(showDialogToolTips) def setShowSplash(self): showSplash = int(self.showSplashCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.ShowSplash, showSplash) def setKeepHelpOnTop(self): keepHelpOnTop = int(self.keepHelpOnTopCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.KeepHelpOnTop, keepHelpOnTop)
class LoginView(View): """`View` derived class. Defines the log in widget""" login = Signal(( str, str, str, bool, )) def __init__(self, parent=None): """ Init method. Initializes parent classes :param parent: Reference to a `QWidget` object to be used as parent """ super(LoginView, self).__init__(parent) self.createWidgets() self.createLayouts() self.setFixedSize(250, 340) def createLayouts(self): """Put widgets into layouts, thus creating the widget""" mainLayout = QHBoxLayout() fieldsLayout = QVBoxLayout() ftpInfoLayout = QHBoxLayout() buttonLayout = QHBoxLayout() mainLayout.addStretch(20) fieldsLayout.addStretch(80) fieldsLayout.addWidget(self.linkLabel) fieldsLayout.addWidget(self.line) fieldsLayout.addStretch(20) ftpInfoLayout.addWidget(self.hostLabel, 50, Qt.AlignLeft) ftpInfoLayout.addStretch(20) ftpInfoLayout.addWidget(self.sslLabel, 20, Qt.AlignRight) ftpInfoLayout.addWidget(self.sslCheck, 10, Qt.AlignRight) fieldsLayout.addLayout(ftpInfoLayout) fieldsLayout.addWidget(self.hostEdit) fieldsLayout.addWidget(self.usernameLabel) fieldsLayout.addWidget(self.usernameEdit) fieldsLayout.addWidget(self.passwdLabel) fieldsLayout.addWidget(self.passwdEdit) fieldsLayout.addStretch(30) buttonLayout.addStretch(50) buttonLayout.addWidget(self.loginButton, 50, Qt.AlignRight) fieldsLayout.addLayout(buttonLayout) fieldsLayout.addStretch(20) mainLayout.addLayout(fieldsLayout, 30) mainLayout.addStretch(20) self.setLayout(mainLayout) def createWidgets(self): """Create children widgets needed by this view""" fieldsWidth = 200 labelsFont = View.labelsFont() editsFont = View.editsFont() self.setLogo() self.hostLabel = QLabel(self) self.hostEdit = QLineEdit(self) self.sslLabel = QLabel(self) self.sslCheck = QCheckBox(self) self.hostLabel.setText('FTP Location') self.hostLabel.setFont(labelsFont) self.hostEdit.setFixedWidth(fieldsWidth) self.hostEdit.setFont(editsFont) self.sslLabel.setText('SSL') self.sslLabel.setFont(labelsFont) self.usernameLabel = QLabel(self) self.usernameEdit = QLineEdit(self) self.usernameLabel.setText('Username') self.usernameLabel.setFont(labelsFont) self.usernameEdit.setFixedWidth(fieldsWidth) self.usernameEdit.setFont(editsFont) self.passwdLabel = QLabel(self) self.passwdEdit = QLineEdit(self) self.passwdLabel.setText('Password') self.passwdLabel.setFont(labelsFont) self.passwdEdit.setFixedWidth(fieldsWidth) self.passwdEdit.setEchoMode(QLineEdit.Password) self.passwdEdit.setFont(editsFont) self.passwdEdit.returnPressed.connect(self.onLoginClicked) self.loginButton = QPushButton(self) self.loginButton.setText('Login') self.loginButton.setFont(labelsFont) self.loginButton.setFixedWidth(fieldsWidth / 2) self.loginButton.clicked.connect(self.onLoginClicked) # Sets previously stored values into the fields, if any settings = get_settings() self.hostEdit.setText(settings.value(SettingsKeys['host'], '')) self.usernameEdit.setText(settings.value(SettingsKeys['username'], '')) self.passwdEdit.setText( crypt.decrypt(settings.value(SettingsKeys['passwd'], ''))) # Unicode to boolean conversion ssl = settings.value(SettingsKeys['ssl'], u'true') ssl = True if ssl == u'true' else False self.sslCheck.setChecked(ssl) @Slot() def onLoginClicked(self): """ Slot. Called on the user clicks on the `loginButton` button """ # Takes out the user input from the fields host = self.hostEdit.text() username = self.usernameEdit.text() passwd = self.passwdEdit.text() ssl = self.sslCheck.isChecked() print 'Logging in: %s, %s, %s' % (host, username, '*' * len(passwd)) if len(host) > 0: # If the fields are valid, store them using a `QSettings` object # and triggers a log in request settings = get_settings() settings.setValue(SettingsKeys['host'], host) settings.setValue(SettingsKeys['username'], username) settings.setValue(SettingsKeys['passwd'], crypt.encrypt(passwd)) settings.setValue(SettingsKeys['ssl'], ssl) self.setEnabled(False) self.login.emit(host.strip(), username, passwd, ssl) @Slot() def onFailedLogIn(self): """ Slot. Called when the log in request fails """ # Enables the fields again for user input self.setEnabled(True)
class qHotField(QWidget): def __init__(self, name, mytype, initial_value, value_list = None, pos = "left", help_text = None, help_instance = None, min_size = 0, max_size = None, handler = None, multiline=False): QWidget.__init__(self) if max_size == None: max_size = 300 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) # Let it expand horizontally but not vertically self.name = name self.mytype = mytype self.multiline = multiline self.setContentsMargins(1, 1, 1, 1) self.is_popup = (value_list != None) if self.is_popup: self.value_list = [str(v) for v in value_list] # It's possible the values won't be strings. if pos == "top": self.layout1 = QVBoxLayout() else: self.layout1=QHBoxLayout() self.layout1.setContentsMargins(1, 1, 1, 1) self.layout1.setSpacing(1) self.setLayout(self.layout1) if mytype == bool: self.cb = QCheckBox(name) self.cb.setFont(regular_small_font) self.layout1.addWidget(self.cb) self.cb.setChecked(initial_value) if handler != None: self.cb.toggled.connect(handler) else: if not self.is_popup: if multiline: self.efield=QPlainTextEdit("") self.efield.appendPlainText(str(initial_value)) else: self.efield = QLineEdit("Default Text") self.efield.setText(str(initial_value)) if handler != None: self.efield.textChanged.connect(handler) else: self.efield = QComboBox() self.efield.addItems(value_list) if len(value_list) != 0: self.efield.setCurrentIndex(value_list.index(initial_value)) self.efield.setSizeAdjustPolicy(QComboBox.AdjustToContents) if handler != None: self.efield.currentIndexChanged.connect(handler) self.layout1.setContentsMargins(5, 5, 5, 5) # Popups need a little more space self.layout1.setSpacing(2) self.efield.setFont(regular_small_font) self.label = QLabel(name) self.label.setFont(regular_small_font) if pos == "right": self.layout1.addWidget(self.efield) self.layout1.addWidget(self.label) else: self.layout1.addWidget(self.label) self.layout1.addWidget(self.efield) self.efield.setMaximumWidth(max_size) if min_size != 0: self.efield.setMinimumWidth(min_size) self.layout1.addStretch() if help_text != None: if (help_instance == None): print "No help instance specified." else: help_button_widget = help_instance.create_button(name, help_text) self.layout1.addWidget(help_button_widget) def repopulate_list(self, initial_value, value_list): if not self.is_popup: print "This qHotField is not a popup list. So it can't be repopulated" return self.value_list = [str(v) for v in value_list] # It's possible the values won't be strings self.efield.clear() self.efield.addItems(value_list) self.efield.setCurrentIndex(value_list.index(initial_value)) return def get_myvalue(self): if self.mytype == bool: return self.cb.isChecked() else: if self.is_popup: the_txt = self.efield.currentText() else: if self.multiline: the_txt = self.efield.toPlainText() else: the_txt = self.efield.text() if (self.mytype == str) or (self.mytype == unicode): return (self.mytype)(the_txt) else: # if we have a numerical type, the user might have entered a list separated by spaces. Handle that specially the_val = re.findall(r"\S+", the_txt) # We might have a list of values separated by spaces if this is a numerical variable if len(the_val) == 1: # it's just a single value result = (self.mytype)(the_txt) else: # it's a list. We want to convert treat this as a monte sequence res = [] for v in the_val: res.append((self.mytype)(v)) result = MonteSequence(res) return result def set_myvalue(self, val): if self.mytype == bool: self.cb.setChecked(val) elif self.is_popup: self.efield.setCurrentIndex(self.value_list.index(val)) else: if type(val) == list: result = "" for x in val: result = result + str(x) + " " self.efield.setText(result) else: if self.multiline: self.efield.clear() self.efield.appendPlainText(str(val)) else: self.efield.setText(str(val)) value = property(get_myvalue, set_myvalue)
class beso_gui(QDialog): def __init__(self): super().__init__() self.title = 'BESO Topology Optimization (experimental)' self.left = 250 self.top = 30 self.width = 550 self.height = 730 beso_gui.inp_file = "" beso_gui.beso_dir = os.path.dirname(__file__) self.initUI() # def closeEvent(self, event): # self.close() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) # Select analysis file button button = QPushButton('Select analysis file', self) button.setToolTip('*.inp CalculiX analysis file.') button.move(10, 10) button.clicked.connect(self.on_click) # Text box - file path and name self.textbox_file_name = QLineEdit(self) self.textbox_file_name.move(120, 15) self.textbox_file_name.resize(420, 20) self.textbox_file_name.setText("None analysis file selected") self.textbox_file_name.setToolTip('Analysis file.') # Update button button1 = QPushButton('Update domains', self) button1.setToolTip( 'Update naming inputs and material data from FreeCAD.') button1.move(10, 50) button1.clicked.connect(self.on_click1) # Domains definition # Label above domains definition label21 = QLabel('Domain 0', self) label21.setStyleSheet("font-weight: bold") label21.move(120, 50) label21 = QLabel('Domain 1', self) label21.setStyleSheet("font-weight: bold") label21.move(260, 50) label21 = QLabel('Domain 2', self) label21.setStyleSheet("font-weight: bold") label21.move(400, 50) label24 = QLabel('Material object', self) label24.move(20, 80) label25 = QLabel('Thickness object', self) label25.move(20, 110) label26 = QLabel('As design domain', self) label26.move(20, 140) label27 = QLabel('Stress limit [MPa]', self) label27.move(20, 170) # Combo box - select domain by material object self.combo = QComboBox(self) self.combo.setToolTip('Material object to define the domain.') self.combo.move(120, 80) self.combo.resize(140, 30) self.combo.currentIndexChanged.connect(self.on_change) self.combo1 = QComboBox(self) self.combo1.setToolTip('Material object to define the domain.') self.combo1.move(260, 80) self.combo1.resize(140, 30) self.combo1.currentIndexChanged.connect(self.on_change1) self.combo2 = QComboBox(self) self.combo2.setToolTip('Material object to define the domain.') self.combo2.move(400, 80) self.combo2.resize(140, 30) self.combo2.currentIndexChanged.connect(self.on_change2) # Combo box - select thickness object self.combo0t = QComboBox(self) self.combo0t.setToolTip( 'Thickness object to specify if domain is for shells.') self.combo0t.move(120, 110) self.combo0t.resize(140, 30) self.combo1t = QComboBox(self) self.combo1t.setToolTip( 'Thickness object to specify if domain is for shells.') self.combo1t.move(260, 110) self.combo1t.resize(140, 30) self.combo2t = QComboBox(self) self.combo2t.setToolTip( 'Thickness object to specify if domain is for shells.') self.combo2t.move(400, 110) self.combo2t.resize(140, 30) self.textbox3 = QLineEdit(self) self.textbox3.move(120, 170) self.textbox3.resize(40, 20) # self.textbox3.setText("") self.textbox3.setToolTip( 'Thickness [mm] of shell elements in the domain.\n' 'This value overwrites thickness defined in FreeCAD') self.textbox4 = QLineEdit(self) self.textbox4.move(260, 170) self.textbox4.resize(40, 20) # self.textbox4.setText("") self.textbox4.setToolTip( 'Thickness [mm] of shell elements in the domain.\n' 'This value overwrites thickness defined in FreeCAD') self.textbox5 = QLineEdit(self) self.textbox5.move(400, 170) self.textbox5.resize(40, 20) # self.textbox5.setText("") self.textbox5.setToolTip( 'Thickness [mm] of shell elements in the domain.\n' 'This value overwrites thickness defined in FreeCAD') # Check box - design or nondesign self.checkbox = QCheckBox('', self) self.checkbox.setChecked(True) self.checkbox.setToolTip('Check to be the design domain.') self.checkbox.move(120, 140) self.checkbox1 = QCheckBox('', self) self.checkbox1.setChecked(True) self.checkbox1.setToolTip('Check to be the design domain.') self.checkbox1.move(260, 140) self.checkbox2 = QCheckBox('', self) self.checkbox2.setChecked(True) self.checkbox2.setToolTip('Check to be the design domain.') self.checkbox2.move(400, 140) # Text box - stress limit self.textbox = QLineEdit(self) self.textbox.move(120, 170) self.textbox.resize(40, 20) # self.textbox.setText("") self.textbox.setToolTip( 'Von Mises stress [MPa] limit, when reached, material removing will stop.' ) self.textbox1 = QLineEdit(self) self.textbox1.move(260, 170) self.textbox1.resize(40, 20) # self.textbox1.setText("") self.textbox1.setToolTip( 'Von Mises stress [MPa] limit, when reached, material removing will stop.' ) self.textbox2 = QLineEdit(self) self.textbox2.move(400, 170) self.textbox2.resize(40, 20) # self.textbox2.setText("") self.textbox2.setToolTip( 'Von Mises stress [MPa] limit, when reached, material removing will stop.' ) # Filters # Label above filter definition label31 = QLabel('Filter 0', self) label31.setStyleSheet("font-weight: bold") label31.move(120, 210) label32 = QLabel('Filter 1', self) label32.setStyleSheet("font-weight: bold") label32.move(260, 210) label33 = QLabel('Filter 2', self) label33.setStyleSheet("font-weight: bold") label33.move(400, 210) label34 = QLabel('Type', self) label34.move(20, 240) label35 = QLabel('Range [mm]', self) label35.move(20, 270) label36 = QLabel('Direction vector', self) label36.move(20, 300) label37 = QLabel('Apply to', self) label37.move(20, 330) # Combo box - select filter type self.combo6 = QComboBox(self) self.combo6.setToolTip( 'Filters:\n' '"simple" to suppress checkerboard effect,\n' '"casting" to prescribe casting direction (opposite to milling direction)\n' 'Recommendation: for casting use as first "casting" and as second "simple"' ) self.combo6.addItem("None") self.combo6.addItem("simple") self.combo6.addItem("casting") self.combo6.setCurrentIndex(1) self.combo6.move(120, 240) self.combo6.currentIndexChanged.connect(self.on_change6) self.combo7 = QComboBox(self) self.combo7.setToolTip( 'Filters:\n' '"simple" to suppress checkerboard effect,\n' '"casting" to prescribe casting direction (opposite to milling direction)\n' 'Recommendation: for casting use as first "casting" and as second "simple"' ) self.combo7.addItem("None") self.combo7.addItem("simple") self.combo7.addItem("casting") self.combo7.move(260, 240) self.combo7.currentIndexChanged.connect(self.on_change7) self.combo8 = QComboBox(self) self.combo8.setToolTip( 'Filters:\n' '"simple" to suppress checkerboard effect,\n' '"casting" to prescribe casting direction (opposite to milling direction)\n' 'Recommendation: for casting use as first "casting" and as second "simple"' ) self.combo8.addItem("None") self.combo8.addItem("simple") self.combo8.addItem("casting") self.combo8.move(400, 240) self.combo8.currentIndexChanged.connect(self.on_change8) # Text box - filter range self.textbox6 = QLineEdit(self) self.textbox6.move(120, 270) self.textbox6.resize(50, 20) # self.textbox6.setText("") self.textbox6.setToolTip( 'Filter range [mm], recommended two times mesh size.') self.textbox7 = QLineEdit(self) self.textbox7.move(260, 270) self.textbox7.resize(50, 20) # self.textbox7.setText("") self.textbox7.setToolTip( 'Filter range [mm], recommended two times mesh size.') self.textbox7.setEnabled(False) self.textbox8 = QLineEdit(self) self.textbox8.move(400, 270) self.textbox8.resize(50, 20) # self.textbox8.setText("") self.textbox8.setToolTip( 'Filter range [mm], recommended two times mesh size.') self.textbox8.setEnabled(False) # Text box - casting direction self.textbox9 = QLineEdit(self) self.textbox9.move(120, 300) self.textbox9.resize(80, 20) self.textbox9.setText("0, 0, 1") self.textbox9.setEnabled(False) self.textbox9.setToolTip( 'Casting direction vector, e.g. direction in z axis:\n' '0, 0, 1\n\n' 'solid void\n' 'XXXXXX.................\n' 'XXX........................\n' 'XX........................... --> z axis\n' 'XXXXX....................\n' 'XXXXXXXXXXX......') self.textbox10 = QLineEdit(self) self.textbox10.move(260, 300) self.textbox10.resize(80, 20) self.textbox10.resize(80, 20) self.textbox10.setText("0, 0, 1") self.textbox10.setEnabled(False) self.textbox10.setToolTip( 'Casting direction vector, e.g. direction in z axis:\n' '0, 0, 1\n\n' 'solid void\n' 'XXXXXX.................\n' 'XXX........................\n' 'XX........................... --> z axis\n' 'XXXXX....................\n' 'XXXXXXXXXXX......') self.textbox11 = QLineEdit(self) self.textbox11.move(400, 300) self.textbox11.resize(80, 20) self.textbox11.setText("0, 0, 1") self.textbox11.setEnabled(False) self.textbox11.setToolTip( 'Casting direction vector, e.g. direction in z axis:\n' '0, 0, 1\n\n' 'solid void\n' 'XXXXXX.................\n' 'XXX........................\n' 'XX........................... --> z axis\n' 'XXXXX....................\n' 'XXXXXXXXXXX......') # list widget - select domains self.widget = QListWidget(self) self.widget.setToolTip( 'Domains affected by the filter.\n' 'Select only from domains which you defined above.') self.widget.move(120, 330) self.widget.resize(140, 120) self.widget.setSelectionMode(QAbstractItemView.MultiSelection) self.widget1 = QListWidget(self) self.widget1.setToolTip( 'Domains affected by the filter.\n' 'Select only from domains which you defined above.') self.widget1.move(260, 330) self.widget1.resize(140, 120) self.widget1.setSelectionMode(QAbstractItemView.MultiSelection) self.widget1.setEnabled(False) self.widget2 = QListWidget(self) self.widget2.setToolTip( 'Domains affected by the filter.\n' 'Select only from domains which you defined above.') self.widget2.move(400, 330) self.widget2.resize(140, 120) self.widget2.setSelectionMode(QAbstractItemView.MultiSelection) self.widget2.setEnabled(False) # Other settings label40 = QLabel('Other settings', self) label40.setStyleSheet("font-weight: bold") label40.move(10, 470) # AR, RR slider label41 = QLabel('Change per iteration: low', self) label41.setFixedWidth(150) label41.move(10, 500) label42 = QLabel('high', self) label42.move(240, 500) self.slider = QSlider(Qt.Horizontal, self) self.slider.setRange(1, 3) self.slider.setSingleStep(1) self.slider.setValue(2) self.slider.move(150, 500) self.slider.resize(80, 30) self.slider.setToolTip( 'Sets mass change per iteration, which is controlled as\n' 'slow: mass_addition_ratio=0.01, mass_removal_ratio=0.02\n' 'middle: mass_addition_ratio=0.015, mass_removal_ratio=0.03\n' 'fast: mass_addition_ratio=0.03, mass_removal_ratio=0.06') # optimization base combobox label51 = QLabel('Optimization base', self) label51.move(10, 530) self.combo51 = QComboBox(self) self.combo51.setToolTip( 'Basic principle to determine if element should remain or be removed:\n' '"stiffness" to maximize stiffness (minimize compliance),\n' '"heat" to maximize heat flow.') self.combo51.addItem("stiffness") self.combo51.addItem("heat") self.combo51.move(120, 530) # mass goal ratio label52 = QLabel('Mass goal ratio', self) label52.move(10, 560) self.textbox52 = QLineEdit(self) self.textbox52.move(120, 560) self.textbox52.resize(50, 20) self.textbox52.setText("0.4") self.textbox52.setToolTip( 'Fraction of all design domains masses to be achieved;\n' 'between 0 and 1.') # generate conf. file button button21 = QPushButton('Generate conf. file', self) button21.setToolTip( 'Writes configuration file with optimization parameters.') button21.move(10, 600) button21.clicked.connect(self.on_click21) # edit conf. file button button22 = QPushButton('Edit conf. file', self) button22.setToolTip('Opens configuration file for hand modifications.') button22.move(10, 630) button22.clicked.connect(self.on_click22) # run optimization button button23 = QPushButton('Run optimization', self) button23.setToolTip('Writes configuration file and runs optimization.') button23.move(10, 660) button23.clicked.connect(self.on_click23) # generate conf file and run optimization button button24 = QPushButton('Generate conf.\nfile and run\noptimization', self) button24.setToolTip('Writes configuration file and runs optimization.') button24.move(120, 600) button24.resize(100, 90) button24.clicked.connect(self.on_click24) # help buttons label41 = QLabel('Help', self) label41.move(440, 560) button31 = QPushButton('Example', self) button31.setToolTip( 'https://github.com/fandaL/beso/wiki/Example-4:-GUI-in-FreeCAD') button31.move(440, 590) # button31.resize(80, 50) button31.clicked.connect(self.on_click31) button32 = QPushButton('Conf. comments', self) button32.setToolTip( 'https://github.com/fandaL/beso/blob/master/beso_conf.py') button32.move(440, 620) # button32.resize(80, 50) button32.clicked.connect(self.on_click32) button33 = QPushButton('Close', self) button33.move(440, 690) # button33.resize(80, 50) button33.clicked.connect(self.on_click33) # open log file button40 = QPushButton('Open log file', self) button40.setToolTip('Opens log file in your text editor.\n' '(Does not refresh automatically.)') button40.move(10, 690) button40.clicked.connect(self.on_click40) self.on_click1() # first update self.show() # @pyqtSlot() def on_click(self): ex2 = SelectFile() self.show() self.textbox_file_name.setText(self.inp_file) def on_click1(self): # get material objects self.materials = [] self.thicknesses = [] for obj in App.ActiveDocument.Objects: if obj.Name[:23] in ["MechanicalSolidMaterial", "SolidMaterial"]: self.materials.append(obj) elif obj.Name[:17] == "ElementGeometry2D": self.thicknesses.append(obj) # update materials combo boxes self.combo.clear() self.combo.addItem("None") self.combo1.clear() self.combo1.addItem("None") self.combo2.clear() self.combo2.addItem("None") self.combo0t.clear() self.combo0t.addItem("None") self.combo1t.clear() self.combo1t.addItem("None") self.combo2t.clear() self.combo2t.addItem("None") self.widget.clear() self.widget.addItem("All defined") self.widget.addItem("Domain 0") self.widget.addItem("Domain 1") self.widget.addItem("Domain 2") self.widget.setCurrentItem(self.widget.item(0)) self.widget1.clear() self.widget1.addItem("All defined") self.widget1.addItem("Domain 0") self.widget1.addItem("Domain 1") self.widget1.addItem("Domain 2") self.widget1.setCurrentItem(self.widget1.item(0)) self.widget2.clear() self.widget2.addItem("All defined") self.widget2.addItem("Domain 0") self.widget2.addItem("Domain 1") self.widget2.addItem("Domain 2") self.widget2.setCurrentItem(self.widget2.item(0)) for mat in self.materials: self.combo.addItem(mat.Label) self.combo1.addItem(mat.Label) self.combo2.addItem(mat.Label) if self.materials: self.combo.setCurrentIndex(1) for th in self.thicknesses: self.combo0t.addItem(th.Label) self.combo1t.addItem(th.Label) self.combo2t.addItem(th.Label) def on_click21(self): """Overwrite beso_conf.py file in the macro directory""" file_name = os.path.split(self.textbox_file_name.text())[1] path = os.path.split(self.textbox_file_name.text())[0] fea = ccxtools.FemToolsCcx() fea.setup_ccx() path_calculix = fea.ccx_binary optimization_base = self.combo51.currentText() elset_id = self.combo.currentIndex() - 1 thickness_id = self.combo0t.currentIndex() - 1 if elset_id != -1: if thickness_id != -1: elset = self.materials[elset_id].Name + self.thicknesses[ thickness_id].Name else: # 0 means None thickness selected elset = self.materials[elset_id].Name + "Solid" modulus = float( self.materials[elset_id].Material["YoungsModulus"].split() [0]) # MPa if self.materials[elset_id].Material["YoungsModulus"].split( )[1] != "MPa": raise Exception(" units not recognised in " + self.materials[elset_id].Name) poisson = float( self.materials[elset_id].Material["PoissonRatio"].split()[0]) try: density = float(self.materials[elset_id].Material["Density"]. split()[0]) * 1e-12 # kg/m3 -> t/mm3 if self.materials[elset_id].Material["Density"].split( )[1] not in ["kg/m^3", "kg/m3"]: raise Exception(" units not recognised in " + self.materials[elset_id].Name) except KeyError: density = 0. try: conductivity = float( self.materials[elset_id].Material["ThermalConductivity"]. split()[0]) # W/m/K if self.materials[elset_id].Material[ "ThermalConductivity"].split()[1] != "W/m/K": raise Exception(" units not recognised in " + self.materials[elset_id].Name) except KeyError: conductivity = 0. try: if self.materials[elset_id].Material[ "ThermalExpansionCoefficient"].split()[1] == "um/m/K": expansion = float(self.materials[elset_id]. Material["ThermalExpansionCoefficient"]. split()[0]) * 1e-6 # um/m/K -> mm/mm/K elif self.materials[elset_id].Material[ "ThermalExpansionCoefficient"].split()[1] == "m/m/K": expansion = float( self.materials[elset_id]. Material["ThermalExpansionCoefficient"].split() [0]) # m/m/K -> mm/mm/K else: raise Exception(" units not recognised in " + self.materials[elset_id].Name) except KeyError: expansion = 0. try: specific_heat = float( self.materials[elset_id].Material["SpecificHeat"].split() [0]) * 1e6 # J/kg/K -> mm^2/s^2/K if self.materials[elset_id].Material["SpecificHeat"].split( )[1] != "J/kg/K": raise Exception(" units not recognised in " + self.materials[elset_id].Name) except KeyError: specific_heat = 0. if thickness_id != -1: thickness = str( self.thicknesses[thickness_id].Thickness).split()[0] # mm if str(self.thicknesses[thickness_id].Thickness).split( )[1] != "mm": raise Exception(" units not recognised in " + self.thicknesses[thickness_id].Name) else: thickness = 0. optimized = self.checkbox.isChecked() if self.textbox.text(): von_mises = float(self.textbox.text()) else: von_mises = 0. elset_id1 = self.combo1.currentIndex() - 1 thickness_id1 = self.combo0t.currentIndex() - 1 if elset_id1 != -1: if thickness_id1 != -1: elset1 = self.materials[elset_id1].Name + self.thicknesses[ thickness_id1].Name else: # 0 means None thickness selected elset1 = self.materials[elset_id1].Name + "Solid" modulus1 = float( self.materials[elset_id1].Material["YoungsModulus"].split() [0]) # MPa if self.materials[elset_id1].Material["YoungsModulus"].split( )[1] != "MPa": raise Exception(" units not recognised in " + self.materials[elset_id1].Name) poisson1 = float( self.materials[elset_id1].Material["PoissonRatio"].split()[0]) try: density1 = float(self.materials[elset_id1].Material["Density"]. split()[0]) * 1e-12 # kg/m3 -> t/mm3 if self.materials[elset_id1].Material["Density"].split( )[1] not in ["kg/m^3", "kg/m3"]: raise Exception(" units not recognised in " + self.materials[elset_id1].Name) except KeyError: density1 = 0. try: conductivity1 = float( self.materials[elset_id1].Material["ThermalConductivity"]. split()[0]) # W/m/K if self.materials[elset_id1].Material[ "ThermalConductivity"].split()[1] != "W/m/K": raise Exception(" units not recognised in " + self.materials[elset_id1].Name) except KeyError: conductivity1 = 0. try: if self.materials[elset_id1].Material[ "ThermalExpansionCoefficient"].split()[1] == "um/m/K": expansion1 = float(self.materials[elset_id1]. Material["ThermalExpansionCoefficient"]. split()[0]) * 1e-6 # um/m/K -> mm/mm/K elif self.materials[elset_id1].Material[ "ThermalExpansionCoefficient"].split()[1] == "m/m/K": expansion1 = float( self.materials[elset_id1]. Material["ThermalExpansionCoefficient"].split() [0]) # m/m/K -> mm/mm/K else: raise Exception(" units not recognised in " + self.materials[elset_id1].Name) except KeyError: expansion1 = 0. try: specific_heat1 = float( self.materials[elset_id1].Material["SpecificHeat"].split() [0]) * 1e6 # J/kg/K -> mm^2/s^2/K if self.materials[elset_id1].Material["SpecificHeat"].split( )[1] != "J/kg/K": raise Exception(" units not recognised in " + self.materials[elset_id1].Name) except KeyError: specific_heat1 = 0. if thickness_id1 != -1: thickness1 = str( self.thicknesses[thickness_id1].Thickness).split()[0] # mm if str(self.thicknesses[thickness_id1].Thickness).split( )[1] != "mm": raise Exception(" units not recognised in " + self.thicknesses[thickness_id1].Name) else: thickness1 = 0. optimized1 = self.checkbox1.isChecked() if self.textbox1.text(): von_mises1 = float(self.textbox1.text()) else: von_mises1 = 0. elset_id2 = self.combo2.currentIndex() - 1 thickness_id2 = self.combo0t.currentIndex() - 1 if elset_id2 != -1: if thickness_id2 != -1: elset2 = self.materials[elset_id2].Name + self.thicknesses[ thickness_id2].Name else: # 0 means None thickness selected else2t = self.materials[elset_id2].Name + "Solid" modulus2 = float( self.materials[elset_id2].Material["YoungsModulus"].split() [0]) # MPa if self.materials[elset_id2].Material["YoungsModulus"].split( )[1] != "MPa": raise Exception(" units not recognised in " + self.materials[elset_id2].Name) poisson2 = float( self.materials[elset_id2].Material["PoissonRatio"].split()[0]) try: density2 = float(self.materials[elset_id2].Material["Density"]. split()[0]) * 1e-12 # kg/m3 -> t/mm3 if self.materials[elset_id2].Material["Density"].split( )[1] not in ["kg/m^3", "kg/m3"]: raise Exception(" units not recognised in " + self.materials[elset_id2].Name) except KeyError: density2 = 0. try: conductivity2 = float( self.materials[elset_id2].Material["ThermalConductivity"]. split()[0]) # W/m/K if self.materials[elset_id2].Material[ "ThermalConductivity"].split()[1] != "W/m/K": raise Exception(" units not recognised in " + self.materials[elset_id2].Name) except KeyError: conductivity2 = 0. try: if self.materials[elset_id2].Material[ "ThermalExpansionCoefficient"].split()[1] == "um/m/K": expansion2 = float(self.materials[elset_id2]. Material["ThermalExpansionCoefficient"]. split()[0]) * 1e-6 # um/m/K -> mm/mm/K elif self.materials[elset_id2].Material[ "ThermalExpansionCoefficient"].split()[1] == "m/m/K": expansion2 = float( self.materials[elset_id2]. Material["ThermalExpansionCoefficient"].split() [0]) # m/m/K -> mm/mm/K else: raise Exception(" units not recognised in " + self.materials[elset_id2].Name) except KeyError: expansion2 = 0. try: specific_heat2 = float( self.materials[elset_id2].Material["SpecificHeat"].split() [0]) * 1e6 # J/kg/K -> mm^2/s^2/K if self.materials[elset_id2].Material["SpecificHeat"].split( )[1] != "J/kg/K": raise Exception(" units not recognised in " + self.materials[elset_id2].Name) except KeyError: specific_heat2 = 0. if thickness_id2 != -1: thickness2 = str( self.thicknesses[thickness_id2].Thickness).split()[0] # mm if str(self.thicknesses[thickness_id2].Thickness).split( )[1] != "mm": raise Exception(" units not recognised in " + self.thicknesses[thickness_id2].Name) else: thickness2 = 0. optimized2 = self.checkbox2.isChecked() if self.textbox2.text(): von_mises2 = float(self.textbox2.text()) else: von_mises2 = 0. with open(os.path.join(self.beso_dir, "beso_conf.py"), "w") as f: f.write( "# This is the configuration file with input parameters. It will be executed as python commands\n" ) f.write("# Written by beso_fc_gui.py at {}\n".format( datetime.datetime.now())) f.write("\n") f.write("path_calculix = '{}'\n".format(path_calculix)) f.write("path = '{}'\n".format(path)) f.write("file_name = '{}'\n".format(file_name)) f.write("\n") if elset_id != -1: f.write("elset_name = '{}'\n".format(elset)) f.write( "domain_optimized[elset_name] = {}\n".format(optimized)) f.write("domain_density[elset_name] = [{}, {}]\n".format( density * 1e-6, density)) if thickness: f.write("domain_thickness[elset_name] = [{}, {}]\n".format( thickness, thickness)) if von_mises: f.write( "domain_FI[elset_name] = [[('stress_von_Mises', {:.6})],\n" .format(von_mises * 1e6)) f.write( " [('stress_von_Mises', {:.6})]]\n" .format(von_mises)) f.write( "domain_material[elset_name] = ['*ELASTIC\\n{:.6}, {}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY\\n" "{:.6}\\n*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n',\n" .format(modulus * 1e-6, poisson, density * 1e-6, conductivity * 1e-6, expansion * 1e-6, specific_heat * 1e-6)) f.write( " '*ELASTIC\\n{:.6}, {:.6}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY\\n" "{:.6}\\n*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n']\n" .format(modulus, poisson, density, conductivity, expansion, specific_heat)) f.write("\n") if elset_id1 != -1: f.write("elset_name = '{}'\n".format(elset1)) f.write( "domain_optimized[elset_name] = {}\n".format(optimized1)) f.write("domain_density[elset_name] = [{}, {}]\n".format( density1 * 1e-6, density1)) if thickness1: f.write("domain_thickness[elset_name] = [{}, {}]\n".format( thickness1, thickness1)) if von_mises1: f.write( "domain_FI[elset_name] = [[('stress_von_Mises', {:.6})],\n" .format(von_mises1 * 1e6)) f.write( " [('stress_von_Mises', {:.6})]]\n" .format(von_mises1)) f.write( "domain_material[elset_name] = ['*ELASTIC\\n{:.6}, {:.6}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY" "\\n{:.6}\\n*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n',\n" .format(modulus1 * 1e-6, poisson1, density1 * 1e-6, conductivity1 * 1e-6, expansion1 * 1e-6, specific_heat1 * 1e-6)) f.write( " '*ELASTIC\\n{:.6}, {:.6}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY\\n" "{:.6}\\n" "*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n']\n". format(modulus1, poisson1, density1, conductivity1, expansion1, specific_heat1)) f.write("\n") if elset_id2 != -1: f.write("elset_name = '{}'\n".format(elset2)) f.write( "domain_optimized[elset_name] = {}\n".format(optimized2)) f.write("domain_density[elset_name] = [{}, {}]\n".format( density2 * 1e-6, density2)) if thickness2: f.write("domain_thickness[elset_name] = [{}, {}]\n".format( thickness2, thickness2)) if von_mises2: f.write( "domain_FI[elset_name] = [[('stress_von_Mises', {:.6})],\n" .format(von_mises2 * 1e6)) f.write( " [('stress_von_Mises', {:.6})]]\n" .format(von_mises2)) f.write( "domain_material[elset_name] = ['*ELASTIC\\n{:.6}, {:.6}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY" "\\n{:.6}\\n*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n',\n" .format(modulus2 * 1e-6, poisson2, density2 * 1e-6, conductivity2 * 1e-6, expansion2 * 1e-6, specific_heat2 * 1e-6)) f.write( " '*ELASTIC\\n{:.6}, {:.6}\\n*DENSITY\\n{:.6}\\n*CONDUCTIVITY\\n" "{:.6}\\n*EXPANSION\\n{:.6}\\n*SPECIFIC HEAT\\n{:.6}\\n']\n" .format(modulus2, poisson2, density2, conductivity2, expansion2, specific_heat2)) f.write("\n") f.write("mass_goal_ratio = " + self.textbox52.text()) f.write("\n") f.write("filter_list = [") filter = self.combo6.currentText() range = self.textbox6.text() direction = self.textbox9.text() selection = [item.text() for item in self.widget.selectedItems()] filter_domains = [] if "All defined" not in selection: if "Domain 0" in selection: filter_domains.append(elset) if "Domain 1" in selection: filter_domains.append(elset1) if "Domain 2" in selection: filter_domains.append(elset2) if filter == "simple": f.write("['simple', {}".format(range)) for dn in filter_domains: f.write(", '{}'".format(dn)) f.write("],\n") elif filter == "casting": f.write("['casting', {}, ({})".format(range, direction)) for dn in filter_domains: f.write(", '{}'".format(dn)) f.write("],\n") filter1 = self.combo7.currentText() range1 = self.textbox7.text() direction1 = self.textbox10.text() selection = [item.text() for item in self.widget1.selectedItems()] filter_domains1 = [] if "All defined" not in selection: if "Domain 0" in selection: filter_domains1.append(elset) if "Domain 1" in selection: filter_domains1.append(elset1) if "Domain 2" in selection: filter_domains1.append(elset2) if filter1 == "simple": f.write(" ['simple', {}".format(range1)) for dn in filter_domains1: f.write(", '{}'".format(dn)) f.write("],\n") elif filter1 == "casting": f.write(" ['casting', {}, ({})".format( range1, direction1)) for dn in filter_domains1: f.write(", '{}'".format(dn)) f.write("],\n") filter2 = self.combo8.currentText() range2 = self.textbox8.text() direction2 = self.textbox11.text() selection = [item.text() for item in self.widget2.selectedItems()] filter_domains2 = [] if "All defined" not in selection: if "Domain 0" in selection: filter_domains2.append(elset) if "Domain 1" in selection: filter_domains2.append(elset1) if "Domain 2" in selection: filter_domains2.append(elset2) if filter2 == "simple": f.write(" ['simple', {}".format(range2)) for dn in filter_domains2: f.write(", '{}'".format(dn)) f.write("],\n") elif filter2 == "casting": f.write(" ['casting', {}, ({})".format( range2, direction2)) for dn in filter_domains2: f.write(", '{}'".format(dn)) f.write("],\n") f.write(" ]\n") f.write("\n") f.write("optimization_base = '{}'\n".format(optimization_base)) f.write("\n") slider_position = self.slider.value() if slider_position == 1: f.write("mass_addition_ratio = 0.01\n") f.write("mass_removal_ratio = 0.02\n") if slider_position == 2: f.write("mass_addition_ratio = 0.015\n") f.write("mass_removal_ratio = 0.03\n") if slider_position == 3: f.write("mass_addition_ratio = 0.03\n") f.write("mass_removal_ratio = 0.06\n") f.write("ratio_type = 'relative'\n") f.write("\n") def on_click22(self): """Open beso_conf.py in FreeCAD editor""" FreeCADGui.insert(os.path.join(self.beso_dir, "beso_conf.py")) def on_click23(self): """"Run optimization""" # run in own thread (not freezing FreeCAD): needs also to comment "plt.show()" on the end of beso_main.py # self.optimization_thread = RunOptimization("beso_main") # self.optimization_thread.start() # run in foreground (freeze FreeCAD) exec(open(os.path.join(beso_gui.beso_dir, "beso_main.py")).read()) def on_click24(self): self.on_click21() # generate beso_conf.py self.on_click23() # run optimization def on_click31(self): webbrowser.open_new_tab( "https://github.com/fandaL/beso/wiki/Example-4:-GUI-in-FreeCAD") def on_click32(self): webbrowser.open_new_tab( "https://github.com/fandaL/beso/blob/master/beso_conf.py") def on_click33(self): self.close() def on_click40(self): """Open log file""" if self.textbox_file_name.text() in [ "None analysis file selected", "" ]: print("None analysis file selected") else: log_file = os.path.normpath(self.textbox_file_name.text()[:-4] + ".log") webbrowser.open(log_file) def on_change(self): if self.combo.currentText() == "None": self.combo0t.setEnabled(False) self.checkbox.setEnabled(False) self.textbox.setEnabled(False) else: self.combo0t.setEnabled(True) self.checkbox.setEnabled(True) self.textbox.setEnabled(True) def on_change1(self): if self.combo1.currentText() == "None": self.combo1t.setEnabled(False) self.checkbox1.setEnabled(False) self.textbox1.setEnabled(False) else: self.combo1t.setEnabled(True) self.checkbox1.setEnabled(True) self.textbox1.setEnabled(True) def on_change2(self): if self.combo2.currentText() == "None": self.combo2t.setEnabled(False) self.checkbox2.setEnabled(False) self.textbox2.setEnabled(False) else: self.combo2t.setEnabled(True) self.checkbox2.setEnabled(True) self.textbox2.setEnabled(True) def on_change6(self): if self.combo6.currentText() == "None": self.textbox6.setEnabled(False) self.textbox9.setEnabled(False) self.widget.setEnabled(False) elif self.combo6.currentText() == "casting": self.textbox6.setEnabled(True) self.textbox9.setEnabled(True) self.widget.setEnabled(True) else: self.textbox6.setEnabled(True) self.textbox9.setEnabled(False) self.widget.setEnabled(True) def on_change7(self): if self.combo7.currentText() == "None": self.textbox7.setEnabled(False) self.textbox10.setEnabled(False) self.widget1.setEnabled(False) elif self.combo7.currentText() == "casting": self.textbox7.setEnabled(True) self.textbox10.setEnabled(True) self.widget1.setEnabled(True) else: self.textbox7.setEnabled(True) self.textbox10.setEnabled(False) self.widget1.setEnabled(True) def on_change8(self): if self.combo8.currentText() == "None": self.textbox8.setEnabled(False) self.textbox11.setEnabled(False) self.widget2.setEnabled(False) elif self.combo8.currentText() == "casting": self.textbox8.setEnabled(True) self.textbox11.setEnabled(True) self.widget2.setEnabled(True) else: self.textbox8.setEnabled(True) self.textbox11.setEnabled(False) self.widget2.setEnabled(True)