class ProgressExample(QWidget): """The main ui components""" def __init__(self, parent=None): super(ProgressExample, self).__init__(parent) self.setupUi() def setupUi(self): self.setWindowTitle('QProgressBar Example') self.btn = QPushButton('Click Me!') self.btn.clicked.connect(self.btnFunc) self.pBar = QProgressBar() self.pBar.setValue(0) self.resize(300, 100) self.vbox = QVBoxLayout() self.vbox.addWidget(self.pBar) self.vbox.addWidget(self.btn) self.setLayout(self.vbox) self.show() def btnFunc(self): self.thread = Thread() self.thread._signal.connect(self.signal_accept) self.thread.start() self.btn.setEnabled(False) def signal_accept(self, msg): self.pBar.setValue(int(msg)) if self.pBar.value() == 99: self.pBar.setValue(0) self.btn.setEnabled(True)
class Window(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.clicksCount = 0 self.setupUi() def setupUi(self): self.setWindowTitle("Freezing GUI") self.resize(300, 150) self.centralWidget = QWidget() self.setCentralWidget(self.centralWidget) # Create and connect widgets self.clicksLabel = QLabel("Counting: 0 clicks", self) self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.stepLabel = QLabel("Long-Running Step: 0") self.stepLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.countBtn = QPushButton("Click me!", self) self.countBtn.clicked.connect(self.countClicks) self.longRunningBtn = QPushButton("Long-Running Task!", self) self.longRunningBtn.clicked.connect(self.runLongTask) # Set the layout layout = QVBoxLayout() layout.addWidget(self.clicksLabel) layout.addWidget(self.countBtn) layout.addStretch() layout.addWidget(self.stepLabel) layout.addWidget(self.longRunningBtn) self.centralWidget.setLayout(layout) def countClicks(self): self.clicksCount += 1 self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks") def reportProgress(self, n): self.stepLabel.setText(f"Long-Running Step: {n}") def runLongTask(self): # 创建 QThread self.thread = QThread() # 创建 worker 对象 self.worker = Worker() # 将 work 移到 thread self.worker.moveToThread(self.thread) # 连接信号和槽 self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.worker.progress.connect(self.reportProgress) # 启动线程 self.thread.start() # 结束 self.longRunningBtn.setEnabled(False) self.thread.finished.connect( lambda: self.longRunningBtn.setEnabled(True)) self.thread.finished.connect( lambda: self.stepLabel.setText("Long-Running Step: 0"))
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle("My App") self.button = QPushButton("Press Me!") self.button.clicked.connect(self.the_button_was_clicked) self.setCentralWidget(self.button) def the_button_was_clicked(self): self.button.setText("You already clicked me.") self.button.setEnabled(False) self.setWindowTitle("My Oneshot App")
class myWindow(QMainWindow): def __init__(self) -> None: super().__init__() self.resize(500, 300) # 非组件对象 self.values = {} self.ut = UpdateValues() # 界面组件对象 self.centralwidget = QWidget(self) self.table = QTableWidget(self.centralwidget) self.startButton = QPushButton(self.centralwidget, text='开始') self.stopButton = QPushButton(self.centralwidget, text='停止') self.stopButton.setDisabled(True) self.table.setColumnCount(3) self.table.setHorizontalHeaderItem(0, QTableWidgetItem('GID')) self.table.setHorizontalHeaderItem(2, QTableWidgetItem('name')) self.table.setHorizontalHeaderItem(1, QTableWidgetItem('speed')) self.table.horizontalHeader().setStretchLastSection(True) self.table.setRowCount(1) self.layout = QGridLayout(self.centralwidget) self.layout.addWidget(self.startButton) self.layout.addWidget(self.stopButton) self.layout.addWidget(self.table) self.setCentralWidget(self.centralwidget) self.ut.resultReady.connect(self.on_changeValue) self.startButton.clicked.connect(self.changeValue) self.stopButton.clicked.connect(self.stopUpdate) def changeValue(self): self.startButton.setDisabled(True) self.stopButton.setEnabled(True) self.ut.isRun = 1 self.ut.start() def stopUpdate(self): self.ut.isRun = 0 self.startButton.setEnabled(True) self.stopButton.setDisabled(True) @Slot() def on_changeValue(self, values: dict): print(values) self.table.setItem(0, 0, QTableWidgetItem(str(values['gid']))) self.table.setItem(0, 1, QTableWidgetItem(str(values['file']))) self.table.setItem(0, 2, QTableWidgetItem(str(values['speed'])))
def setup_ui(self): super(FontUI, self).setup_ui() sys_radio = QRadioButton("系统字体") sys_radio.setChecked(True) font_combo = QComboBox() for item in self.system_fonts: font_combo.addItem(item[1]) font_combo.setCurrentIndex(0) font_combo.currentIndexChanged.connect(self.refresh_font) custom_radio = QRadioButton("自选字体") custom_radio.setCheckable(True) custom_radio.setChecked(False) custom_radio.toggled.connect(self.on_custom_radio_toggled) custom_edit = QLineEdit() custom_edit.setPlaceholderText("自定义字体(*.ttf, *.otf)") custom_edit.setReadOnly(True) custom_edit.setEnabled(False) custom_btn = QPushButton(text="浏览") custom_btn.setEnabled(False) custom_btn.clicked.connect(self.on_custom_clicked) font_group = QButtonGroup(self) font_group.addButton(sys_radio, 0) font_group.addButton(custom_radio, 1) font_group.setExclusive(True) input_label = QLabel("输出字符") input_edit = MLineEdit() import_btn = QPushButton(text="从文本文件导入") import_btn.clicked.connect(self.on_import_btn_clicked) self.main_layout.setColumnStretch(1, 1) self.main_layout.addWidget(sys_radio, 1, 0, 1, 1) self.main_layout.addWidget(font_combo, 1, 1, 1, 2) self.main_layout.addWidget(custom_radio, 2, 0, 1, 1) self.main_layout.addWidget(custom_edit, 2, 1, 1, 1) self.main_layout.addWidget(custom_btn, 2, 2, 1, 1) self.main_layout.addWidget(input_label, 3, 0, 1, 1) self.main_layout.addWidget(import_btn, 3, 2, 1, 1) self.main_layout.addWidget(input_edit, 4, 0, 1, 3) self.input_edit = input_edit self.font_combo = font_combo self.custom_btn = custom_btn self.custom_edit = custom_edit self.refresh_font()
class RunTab(QWidget): def __init__(self, main_window): super().__init__() self.main_window = main_window self.layout = QVBoxLayout(self) self.validation_panel = ValidationPanel(self.main_window) self.layout.addLayout(self.validation_panel.layout) self.log_panel = LogPanel(self) self.layout.addWidget(self.log_panel.widget) self.run_button = QPushButton("Run", self) self.run_button.clicked.connect(self.run) self.layout.addWidget(self.run_button) self.main_window.running_changed.connect( lambda b: self.run_button.setEnabled(not b)) self.thread = RunThread( lambda: self.main_window.running_changed.emit(True), lambda: self.main_window.running_changed.emit(False), ) def run(self): self.validation_panel.clear() self.log_panel.clear() self.thread.start( self.main_window.config, self.log_panel, self.validation_panel, )
class MontageDialog(QDialog): def __init__(self, parent, montages, selected=None): super().__init__(parent) self.setWindowTitle("Set montage") vbox = QVBoxLayout(self) self.montages = QListWidget() self.montages.insertItems(0, montages) self.montages.setSelectionMode(QListWidget.SingleSelection) if selected is not None: for i in range(self.montages.count()): if self.montages.item(i).data(0) == selected: self.montages.item(i).setSelected(True) vbox.addWidget(self.montages) hbox = QHBoxLayout() self.view_button = QPushButton("View") self.view_button.clicked.connect(self.view_montage) hbox.addWidget(self.view_button) hbox.addStretch() self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) hbox.addWidget(self.buttonbox) vbox.addLayout(hbox) self.buttonbox.accepted.connect(self.accept) self.buttonbox.rejected.connect(self.reject) self.montages.itemSelectionChanged.connect(self.toggle_buttons) self.toggle_buttons() # initialize OK and View buttons state @Slot() def toggle_buttons(self): """Toggle OK and View buttons. """ if self.montages.selectedItems(): self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(True) self.view_button.setEnabled(True) else: self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(False) self.view_button.setEnabled(False) def view_montage(self): name = self.montages.selectedItems()[0].data(0) montage = make_standard_montage(name) fig = montage.plot(show_names=True, show=False) win = fig.canvas.manager.window win.setWindowModality(Qt.WindowModal) win.setWindowTitle("Montage") win.statusBar().hide() # not necessary since matplotlib 3.3 fig.show()
class GroupBoxWorkout(QGroupBox, BasicWidget): def __init__(self, title, parent): super().__init__(title, parent) self.setLayout(QHBoxLayout(self)) self.button_start = QPushButton("Start Workout", self) self.button_start.clicked.connect(self.switch_button_ability) self.layout().addWidget(self.button_start) self.button_finish = QPushButton("Finish Workout", self) self.button_finish.setDisabled(True) self.button_finish.clicked.connect(self.switch_button_ability) self.layout().addWidget(self.button_finish) def switch_button_ability(self): if self.button_start.isEnabled( ) and not self.button_finish.isEnabled(): self.button_start.setDisabled(True) self.button_finish.setEnabled(True) elif not self.button_start.isEnabled( ) and self.button_finish.isEnabled(): self.button_start.setEnabled(True) self.button_finish.setDisabled(True)
class WinForm(QWidget): def __init__(self, parent=None): super(WinForm, self).__init__(parent) self.setWindowTitle("QTimer demo") self.listFile = QListWidget() self.label = QLabel('显示当前时间') self.startBtn = QPushButton('开始') self.endBtn = QPushButton('结束') layout = QGridLayout(self) # 初始化一个定时器 self.timer = QTimer(self) # showTime()方法 self.timer.timeout.connect(self.showTime) layout.addWidget(self.label, 0, 0, 1, 2) layout.addWidget(self.startBtn, 1, 0) layout.addWidget(self.endBtn, 1, 1) self.startBtn.clicked.connect(self.startTimer) self.endBtn.clicked.connect(self.endTimer) self.setLayout(layout) def showTime(self): # 获取系统现在的时间 time = QDateTime.currentDateTime() # 设置系统时间显示格式 timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd") # 在标签上显示时间 self.label.setText(timeDisplay) def startTimer(self): # 设置计时间隔并启动 self.timer.start(1000) self.startBtn.setEnabled(False) self.endBtn.setEnabled(True) def endTimer(self): self.timer.stop() self.startBtn.setEnabled(True) self.endBtn.setEnabled(False)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() centralWidget = QWidget() self.setCentralWidget(centralWidget) layout = QFormLayout(centralWidget) textLayout = QHBoxLayout() self.text = QLineEdit('Hello, PySide6') self.text.setClearButtonEnabled(True) textLayout.addWidget(self.text) self.sayButton = QPushButton('Say') textLayout.addWidget(self.sayButton) self.text.returnPressed.connect(self.sayButton.animateClick) self.sayButton.clicked.connect(self.say) layout.addRow('Text:', textLayout) self.voiceCombo = QComboBox() layout.addRow('Voice:', self.voiceCombo) self.volumeSlider = QSlider(Qt.Horizontal) self.volumeSlider.setMinimum(0) self.volumeSlider.setMaximum(100) self.volumeSlider.setValue(100) layout.addRow('Volume:', self.volumeSlider) self.engine = None engineNames = QTextToSpeech.availableEngines() if len(engineNames) > 0: engineName = engineNames[0] self.engine = QTextToSpeech(engineName) self.engine.stateChanged.connect(self.stateChanged) self.setWindowTitle( 'QTextToSpeech Example ({})'.format(engineName)) self.voices = [] for voice in self.engine.availableVoices(): self.voices.append(voice) self.voiceCombo.addItem(voice.name()) else: self.setWindowTitle('QTextToSpeech Example (no engines available)') self.sayButton.setEnabled(False) def say(self): self.sayButton.setEnabled(False) self.engine.setVoice(self.voices[self.voiceCombo.currentIndex()]) self.engine.setVolume(float(self.volumeSlider.value()) / 100) self.engine.say(self.text.text()) def stateChanged(self, state): if (state == QTextToSpeech.State.Ready): self.sayButton.setEnabled(True)
class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.setWindowModality(Qt.ApplicationModal) MainWindow.resize(1492, 1852) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) MainWindow.setMinimumSize(QSize(700, 700)) MainWindow.setMaximumSize(QSize(16777215, 16777215)) MainWindow.setBaseSize(QSize(600, 600)) font = QFont() font.setPointSize(12) font.setKerning(True) MainWindow.setFont(font) MainWindow.setAutoFillBackground(False) MainWindow.setStyleSheet(u"") MainWindow.setDocumentMode(False) MainWindow.setTabShape(QTabWidget.Rounded) MainWindow.setDockOptions(QMainWindow.AllowTabbedDocks|QMainWindow.AnimatedDocks) MainWindow.setUnifiedTitleAndToolBarOnMac(False) self.action_Quit = QAction(MainWindow) self.action_Quit.setObjectName(u"action_Quit") self.main_widget = QWidget(MainWindow) self.main_widget.setObjectName(u"main_widget") self.main_widget.setEnabled(True) self.main_widget.setMinimumSize(QSize(650, 650)) self.main_widget.setContextMenuPolicy(Qt.DefaultContextMenu) self.main_widget.setAutoFillBackground(False) self.main_widget.setStyleSheet(u"") self.main_layout = QGridLayout(self.main_widget) self.main_layout.setObjectName(u"main_layout") self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.log_button = QPushButton(self.main_widget) self.log_button.setObjectName(u"log_button") sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.log_button.sizePolicy().hasHeightForWidth()) self.log_button.setSizePolicy(sizePolicy1) self.log_button.setMinimumSize(QSize(24, 24)) font1 = QFont() font1.setPointSize(9) font1.setBold(True) font1.setKerning(True) self.log_button.setFont(font1) self.log_button.setCursor(QCursor(Qt.PointingHandCursor)) self.log_button.setCheckable(False) self.log_button.setFlat(True) self.horizontalLayout_2.addWidget(self.log_button) self.main_layout.addLayout(self.horizontalLayout_2, 5, 2, 1, 1) self.shuttle_widget = QWidget(self.main_widget) self.shuttle_widget.setObjectName(u"shuttle_widget") self.shuttle_widget.setMinimumSize(QSize(600, 600)) self.shuttle_widget.setMaximumSize(QSize(600, 600)) self.shuttle_widget.setAutoFillBackground(False) self.shuttle_widget.setStyleSheet(u"QWidget#shuttle_widget {background: url(images/ShuttleXpress_Black.png);\n" " background-repeat:no-repeat;}\n" " ") self.button_1 = QCheckBox(self.shuttle_widget) self.button_1.setObjectName(u"button_1") self.button_1.setGeometry(QRect(80, 266, 24, 24)) sizePolicy1.setHeightForWidth(self.button_1.sizePolicy().hasHeightForWidth()) self.button_1.setSizePolicy(sizePolicy1) self.button_1.setMinimumSize(QSize(24, 24)) self.button_1.setFont(font) self.button_1.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.usb_status = QPushButton(self.shuttle_widget) self.usb_status.setObjectName(u"usb_status") self.usb_status.setEnabled(False) self.usb_status.setGeometry(QRect(288, 10, 24, 24)) sizePolicy1.setHeightForWidth(self.usb_status.sizePolicy().hasHeightForWidth()) self.usb_status.setSizePolicy(sizePolicy1) self.usb_status.setMinimumSize(QSize(24, 24)) self.usb_status.setFont(font1) self.usb_status.setCursor(QCursor(Qt.ArrowCursor)) self.usb_status.setAutoFillBackground(False) self.usb_status.setText(u"") icon = QIcon() icon.addFile(u"images/usb_black_24.png", QSize(), QIcon.Disabled, QIcon.Off) icon.addFile(u"images/usb_white_24.png", QSize(), QIcon.Disabled, QIcon.On) self.usb_status.setIcon(icon) self.usb_status.setIconSize(QSize(24, 24)) self.usb_status.setCheckable(True) self.usb_status.setChecked(False) self.usb_status.setFlat(True) self.button_5 = QCheckBox(self.shuttle_widget) self.button_5.setObjectName(u"button_5") self.button_5.setGeometry(QRect(498, 266, 24, 24)) sizePolicy1.setHeightForWidth(self.button_5.sizePolicy().hasHeightForWidth()) self.button_5.setSizePolicy(sizePolicy1) self.button_5.setMinimumSize(QSize(24, 24)) self.button_5.setFont(font) self.button_5.setLayoutDirection(Qt.RightToLeft) self.button_5.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_pos4 = QRadioButton(self.shuttle_widget) self.wheel_pos4.setObjectName(u"wheel_pos4") self.wheel_pos4.setGeometry(QRect(382, 164, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos4.sizePolicy().hasHeightForWidth()) self.wheel_pos4.setSizePolicy(sizePolicy1) self.wheel_pos4.setMinimumSize(QSize(24, 24)) self.wheel_pos4.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_cent0 = QRadioButton(self.shuttle_widget) self.wheel_cent0.setObjectName(u"wheel_cent0") self.wheel_cent0.setGeometry(QRect(289, 130, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_cent0.sizePolicy().hasHeightForWidth()) self.wheel_cent0.setSizePolicy(sizePolicy1) self.wheel_cent0.setMinimumSize(QSize(24, 24)) self.wheel_cent0.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_cent0.setChecked(True) self.wheel_pos1 = QRadioButton(self.shuttle_widget) self.wheel_pos1.setObjectName(u"wheel_pos1") self.wheel_pos1.setGeometry(QRect(314, 133, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos1.sizePolicy().hasHeightForWidth()) self.wheel_pos1.setSizePolicy(sizePolicy1) self.wheel_pos1.setMinimumSize(QSize(24, 24)) self.wheel_pos1.setStyleSheet(u"color: white;") self.wheel_pos2 = QRadioButton(self.shuttle_widget) self.wheel_pos2.setObjectName(u"wheel_pos2") self.wheel_pos2.setGeometry(QRect(338, 139, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos2.sizePolicy().hasHeightForWidth()) self.wheel_pos2.setSizePolicy(sizePolicy1) self.wheel_pos2.setMinimumSize(QSize(24, 24)) self.wheel_pos2.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.dial = QDial(self.shuttle_widget) self.dial.setObjectName(u"dial") self.dial.setGeometry(QRect(197, 178, 216, 216)) sizePolicy2 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy2.setHorizontalStretch(0) sizePolicy2.setVerticalStretch(0) sizePolicy2.setHeightForWidth(self.dial.sizePolicy().hasHeightForWidth()) self.dial.setSizePolicy(sizePolicy2) self.dial.setMinimumSize(QSize(24, 24)) self.dial.setAutoFillBackground(False) self.dial.setStyleSheet(u"background-color: black;") self.dial.setMinimum(0) self.dial.setMaximum(10) self.dial.setPageStep(1) self.dial.setValue(5) self.dial.setSliderPosition(5) self.dial.setInvertedAppearance(False) self.dial.setInvertedControls(False) self.dial.setWrapping(True) self.dial.setNotchTarget(3.700000000000000) self.dial.setNotchesVisible(False) self.wheel_neg6 = QRadioButton(self.shuttle_widget) self.wheel_neg6.setObjectName(u"wheel_neg6") self.wheel_neg6.setGeometry(QRect(162, 204, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg6.sizePolicy().hasHeightForWidth()) self.wheel_neg6.setSizePolicy(sizePolicy1) self.wheel_neg6.setMinimumSize(QSize(24, 24)) self.wheel_neg6.setStyleSheet(u"color: white;") self.wheel_pos5 = QRadioButton(self.shuttle_widget) self.wheel_pos5.setObjectName(u"wheel_pos5") self.wheel_pos5.setGeometry(QRect(400, 182, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos5.sizePolicy().hasHeightForWidth()) self.wheel_pos5.setSizePolicy(sizePolicy1) self.wheel_pos5.setMinimumSize(QSize(24, 24)) self.wheel_pos5.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.button_2 = QCheckBox(self.shuttle_widget) self.button_2.setObjectName(u"button_2") self.button_2.setGeometry(QRect(156, 122, 24, 24)) sizePolicy1.setHeightForWidth(self.button_2.sizePolicy().hasHeightForWidth()) self.button_2.setSizePolicy(sizePolicy1) self.button_2.setMinimumSize(QSize(24, 24)) self.button_2.setFont(font) self.button_2.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_neg5 = QRadioButton(self.shuttle_widget) self.wheel_neg5.setObjectName(u"wheel_neg5") self.wheel_neg5.setGeometry(QRect(178, 182, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg5.sizePolicy().hasHeightForWidth()) self.wheel_neg5.setSizePolicy(sizePolicy1) self.wheel_neg5.setMinimumSize(QSize(24, 24)) self.wheel_neg5.setStyleSheet(u"color: white;") self.wheel_pos6 = QRadioButton(self.shuttle_widget) self.wheel_pos6.setObjectName(u"wheel_pos6") self.wheel_pos6.setGeometry(QRect(416, 204, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos6.sizePolicy().hasHeightForWidth()) self.wheel_pos6.setSizePolicy(sizePolicy1) self.wheel_pos6.setMinimumSize(QSize(24, 24)) self.wheel_pos6.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_neg1 = QRadioButton(self.shuttle_widget) self.wheel_neg1.setObjectName(u"wheel_neg1") self.wheel_neg1.setGeometry(QRect(264, 133, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg1.sizePolicy().hasHeightForWidth()) self.wheel_neg1.setSizePolicy(sizePolicy1) self.wheel_neg1.setMinimumSize(QSize(24, 24)) self.wheel_neg1.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.button_4 = QCheckBox(self.shuttle_widget) self.button_4.setObjectName(u"button_4") self.button_4.setGeometry(QRect(430, 122, 24, 24)) sizePolicy1.setHeightForWidth(self.button_4.sizePolicy().hasHeightForWidth()) self.button_4.setSizePolicy(sizePolicy1) self.button_4.setMinimumSize(QSize(24, 24)) self.button_4.setFont(font) self.button_4.setLayoutDirection(Qt.RightToLeft) self.button_4.setAutoFillBackground(False) self.button_4.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_pos7 = QRadioButton(self.shuttle_widget) self.wheel_pos7.setObjectName(u"wheel_pos7") self.wheel_pos7.setGeometry(QRect(427, 229, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos7.sizePolicy().hasHeightForWidth()) self.wheel_pos7.setSizePolicy(sizePolicy1) self.wheel_pos7.setMinimumSize(QSize(24, 24)) self.wheel_pos7.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.button_3 = QCheckBox(self.shuttle_widget) self.button_3.setObjectName(u"button_3") self.button_3.setGeometry(QRect(290, 72, 24, 24)) sizePolicy1.setHeightForWidth(self.button_3.sizePolicy().hasHeightForWidth()) self.button_3.setSizePolicy(sizePolicy1) self.button_3.setMinimumSize(QSize(24, 24)) self.button_3.setFont(font) self.button_3.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.button_3.setTristate(False) self.wheel_neg2 = QRadioButton(self.shuttle_widget) self.wheel_neg2.setObjectName(u"wheel_neg2") self.wheel_neg2.setGeometry(QRect(240, 139, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg2.sizePolicy().hasHeightForWidth()) self.wheel_neg2.setSizePolicy(sizePolicy1) self.wheel_neg2.setMinimumSize(QSize(24, 24)) self.wheel_neg2.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_pos3 = QRadioButton(self.shuttle_widget) self.wheel_pos3.setObjectName(u"wheel_pos3") self.wheel_pos3.setGeometry(QRect(361, 149, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_pos3.sizePolicy().hasHeightForWidth()) self.wheel_pos3.setSizePolicy(sizePolicy1) self.wheel_pos3.setMinimumSize(QSize(24, 24)) self.wheel_pos3.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_neg3 = QRadioButton(self.shuttle_widget) self.wheel_neg3.setObjectName(u"wheel_neg3") self.wheel_neg3.setGeometry(QRect(217, 149, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg3.sizePolicy().hasHeightForWidth()) self.wheel_neg3.setSizePolicy(sizePolicy1) self.wheel_neg3.setMinimumSize(QSize(24, 24)) self.wheel_neg3.setStyleSheet(u"color: white;") self.wheel_neg4 = QRadioButton(self.shuttle_widget) self.wheel_neg4.setObjectName(u"wheel_neg4") self.wheel_neg4.setGeometry(QRect(196, 164, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg4.sizePolicy().hasHeightForWidth()) self.wheel_neg4.setSizePolicy(sizePolicy1) self.wheel_neg4.setMinimumSize(QSize(24, 24)) self.wheel_neg4.setStyleSheet(u"background: #000000ff;\n" " color: white;\n" " ") self.wheel_neg7 = QRadioButton(self.shuttle_widget) self.wheel_neg7.setObjectName(u"wheel_neg7") self.wheel_neg7.setGeometry(QRect(151, 229, 24, 24)) sizePolicy1.setHeightForWidth(self.wheel_neg7.sizePolicy().hasHeightForWidth()) self.wheel_neg7.setSizePolicy(sizePolicy1) self.wheel_neg7.setMinimumSize(QSize(24, 24)) self.wheel_neg7.setStyleSheet(u"color: white;") self.dial.raise_() self.button_1.raise_() self.usb_status.raise_() self.button_5.raise_() self.wheel_pos4.raise_() self.wheel_cent0.raise_() self.wheel_pos1.raise_() self.wheel_pos2.raise_() self.wheel_neg6.raise_() self.wheel_pos5.raise_() self.button_2.raise_() self.wheel_neg5.raise_() self.wheel_pos6.raise_() self.wheel_neg1.raise_() self.button_4.raise_() self.wheel_pos7.raise_() self.button_3.raise_() self.wheel_neg2.raise_() self.wheel_pos3.raise_() self.wheel_neg3.raise_() self.wheel_neg4.raise_() self.wheel_neg7.raise_() self.main_layout.addWidget(self.shuttle_widget, 3, 2, 1, 1) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") self.about_button = QPushButton(self.main_widget) self.about_button.setObjectName(u"about_button") sizePolicy1.setHeightForWidth(self.about_button.sizePolicy().hasHeightForWidth()) self.about_button.setSizePolicy(sizePolicy1) self.about_button.setMinimumSize(QSize(24, 24)) self.about_button.setFont(font1) self.about_button.setCursor(QCursor(Qt.WhatsThisCursor)) self.about_button.setCheckable(False) self.about_button.setFlat(True) self.horizontalLayout.addWidget(self.about_button) self.main_layout.addLayout(self.horizontalLayout, 1, 2, 1, 1) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.plug_button = QPushButton(self.main_widget) self.plug_button.setObjectName(u"plug_button") sizePolicy1.setHeightForWidth(self.plug_button.sizePolicy().hasHeightForWidth()) self.plug_button.setSizePolicy(sizePolicy1) self.plug_button.setMinimumSize(QSize(24, 24)) self.plug_button.setFont(font1) self.plug_button.setCursor(QCursor(Qt.PointingHandCursor)) self.plug_button.setCheckable(False) self.plug_button.setFlat(True) self.horizontalLayout_3.addWidget(self.plug_button) self.main_layout.addLayout(self.horizontalLayout_3, 3, 1, 1, 1) self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName(u"verticalLayout") self.conf_button = QPushButton(self.main_widget) self.conf_button.setObjectName(u"conf_button") sizePolicy1.setHeightForWidth(self.conf_button.sizePolicy().hasHeightForWidth()) self.conf_button.setSizePolicy(sizePolicy1) self.conf_button.setMinimumSize(QSize(24, 24)) self.conf_button.setFont(font1) self.conf_button.setCursor(QCursor(Qt.PointingHandCursor)) self.conf_button.setCheckable(False) self.conf_button.setFlat(True) self.verticalLayout.addWidget(self.conf_button) self.main_layout.addLayout(self.verticalLayout, 3, 4, 1, 1) MainWindow.setCentralWidget(self.main_widget) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") self.statusbar.setMinimumSize(QSize(600, 0)) MainWindow.setStatusBar(self.statusbar) self.about_widget = QDockWidget(MainWindow) self.about_widget.setObjectName(u"about_widget") self.about_widget.setEnabled(True) sizePolicy3 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy3.setHorizontalStretch(0) sizePolicy3.setVerticalStretch(0) sizePolicy3.setHeightForWidth(self.about_widget.sizePolicy().hasHeightForWidth()) self.about_widget.setSizePolicy(sizePolicy3) self.about_widget.setMinimumSize(QSize(600, 600)) self.about_widget.setVisible(True) self.about_widget.setFloating(False) self.about_widget.setFeatures(QDockWidget.DockWidgetClosable|QDockWidget.DockWidgetMovable) self.about_widget.setAllowedAreas(Qt.TopDockWidgetArea) self.about_layout = QWidget() self.about_layout.setObjectName(u"about_layout") sizePolicy3.setHeightForWidth(self.about_layout.sizePolicy().hasHeightForWidth()) self.about_layout.setSizePolicy(sizePolicy3) self.about_layout.setAutoFillBackground(False) self.gridLayout_3 = QGridLayout(self.about_layout) self.gridLayout_3.setObjectName(u"gridLayout_3") self.about_text = QTextEdit(self.about_layout) self.about_text.setObjectName(u"about_text") self.about_text.setFocusPolicy(Qt.WheelFocus) self.about_text.setAcceptDrops(False) self.about_text.setStyleSheet(u"color: white;") self.about_text.setFrameShape(QFrame.StyledPanel) self.about_text.setFrameShadow(QFrame.Sunken) self.about_text.setUndoRedoEnabled(False) self.about_text.setReadOnly(True) self.about_text.setAcceptRichText(True) self.gridLayout_3.addWidget(self.about_text, 0, 0, 1, 1) self.about_widget.setWidget(self.about_layout) MainWindow.addDockWidget(Qt.TopDockWidgetArea, self.about_widget) self.log_widget = QDockWidget(MainWindow) self.log_widget.setObjectName(u"log_widget") self.log_widget.setEnabled(True) self.log_widget.setMinimumSize(QSize(550, 158)) self.log_widget.setFont(font) self.log_widget.setVisible(True) self.log_widget.setFloating(False) self.log_widget.setFeatures(QDockWidget.DockWidgetClosable|QDockWidget.DockWidgetFloatable|QDockWidget.DockWidgetMovable) self.log_widget.setAllowedAreas(Qt.BottomDockWidgetArea) self.log_layout = QWidget() self.log_layout.setObjectName(u"log_layout") sizePolicy4 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy4.setHorizontalStretch(0) sizePolicy4.setVerticalStretch(0) sizePolicy4.setHeightForWidth(self.log_layout.sizePolicy().hasHeightForWidth()) self.log_layout.setSizePolicy(sizePolicy4) self.gridLayout_2 = QGridLayout(self.log_layout) self.gridLayout_2.setObjectName(u"gridLayout_2") self.log_content_layout = QVBoxLayout() self.log_content_layout.setObjectName(u"log_content_layout") self.log_content_layout.setSizeConstraint(QLayout.SetDefaultConstraint) self.log_text = QPlainTextEdit(self.log_layout) self.log_text.setObjectName(u"log_text") sizePolicy4.setHeightForWidth(self.log_text.sizePolicy().hasHeightForWidth()) self.log_text.setSizePolicy(sizePolicy4) self.log_text.setMinimumSize(QSize(0, 0)) self.log_text.setAcceptDrops(False) self.log_text.setFrameShape(QFrame.StyledPanel) self.log_text.setFrameShadow(QFrame.Sunken) self.log_text.setUndoRedoEnabled(False) self.log_text.setReadOnly(True) self.log_content_layout.addWidget(self.log_text) self.buttons_layout = QHBoxLayout() self.buttons_layout.setObjectName(u"buttons_layout") self.buttons_layout.setSizeConstraint(QLayout.SetDefaultConstraint) self.log_clear_button = QToolButton(self.log_layout) self.log_clear_button.setObjectName(u"log_clear_button") icon1 = QIcon() icon1.addFile(u"images/delete-sweep_24.png", QSize(), QIcon.Normal, QIcon.Off) self.log_clear_button.setIcon(icon1) self.log_clear_button.setIconSize(QSize(24, 24)) self.buttons_layout.addWidget(self.log_clear_button) self.log_content_layout.addLayout(self.buttons_layout) self.gridLayout_2.addLayout(self.log_content_layout, 0, 0, 1, 1) self.log_widget.setWidget(self.log_layout) MainWindow.addDockWidget(Qt.BottomDockWidgetArea, self.log_widget) self.config_widget = QDockWidget(MainWindow) self.config_widget.setObjectName(u"config_widget") self.config_widget.setEnabled(True) self.config_widget.setMinimumSize(QSize(250, 600)) self.config_widget.setFloating(False) self.config_widget.setFeatures(QDockWidget.DockWidgetClosable|QDockWidget.DockWidgetFloatable|QDockWidget.DockWidgetMovable) self.config_widget.setAllowedAreas(Qt.RightDockWidgetArea) self.config_layout = QWidget() self.config_layout.setObjectName(u"config_layout") self.gridLayout = QGridLayout(self.config_layout) self.gridLayout.setObjectName(u"gridLayout") self.config_content_layout = QFormLayout() self.config_content_layout.setObjectName(u"config_content_layout") self.gridLayout.addLayout(self.config_content_layout, 0, 0, 1, 1) self.config_widget.setWidget(self.config_layout) MainWindow.addDockWidget(Qt.RightDockWidgetArea, self.config_widget) self.plugins_widget = QDockWidget(MainWindow) self.plugins_widget.setObjectName(u"plugins_widget") self.plugins_widget.setMinimumSize(QSize(250, 600)) self.plugins_widget.setAllowedAreas(Qt.LeftDockWidgetArea) self.dockWidgetContents = QWidget() self.dockWidgetContents.setObjectName(u"dockWidgetContents") self.plugins_widget.setWidget(self.dockWidgetContents) MainWindow.addDockWidget(Qt.LeftDockWidgetArea, self.plugins_widget) self.about_widget.raise_() self.log_widget.raise_() self.retranslateUi(MainWindow) self.usb_status.setDefault(False) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Contour ShuttleXpress", None)) self.action_Quit.setText(QCoreApplication.translate("MainWindow", u"&Quit", None)) #if QT_CONFIG(tooltip) self.log_button.setToolTip("") #endif // QT_CONFIG(tooltip) #if QT_CONFIG(statustip) self.log_button.setStatusTip(QCoreApplication.translate("MainWindow", u"Log", None)) #endif // QT_CONFIG(statustip) self.log_button.setText(QCoreApplication.translate("MainWindow", u"//", None)) #if QT_CONFIG(statustip) self.button_1.setStatusTip(QCoreApplication.translate("MainWindow", u"Button 1", None)) #endif // QT_CONFIG(statustip) self.button_1.setText("") #if QT_CONFIG(tooltip) self.usb_status.setToolTip("") #endif // QT_CONFIG(tooltip) #if QT_CONFIG(statustip) self.usb_status.setStatusTip(QCoreApplication.translate("MainWindow", u"USB connection status", None)) #endif // QT_CONFIG(statustip) #if QT_CONFIG(whatsthis) self.usb_status.setWhatsThis(QCoreApplication.translate("MainWindow", u"USB Status", None)) #endif // QT_CONFIG(whatsthis) #if QT_CONFIG(statustip) self.button_5.setStatusTip(QCoreApplication.translate("MainWindow", u"Button 5", None)) #endif // QT_CONFIG(statustip) self.button_5.setText("") #if QT_CONFIG(statustip) self.wheel_pos4.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 4", None)) #endif // QT_CONFIG(statustip) self.wheel_pos4.setText("") #if QT_CONFIG(statustip) self.wheel_cent0.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: center", None)) #endif // QT_CONFIG(statustip) self.wheel_cent0.setText("") #if QT_CONFIG(statustip) self.wheel_pos1.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 1", None)) #endif // QT_CONFIG(statustip) self.wheel_pos1.setText("") #if QT_CONFIG(statustip) self.wheel_pos2.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 2", None)) #endif // QT_CONFIG(statustip) self.wheel_pos2.setText("") #if QT_CONFIG(statustip) self.dial.setStatusTip(QCoreApplication.translate("MainWindow", u"Dial", None)) #endif // QT_CONFIG(statustip) #if QT_CONFIG(statustip) self.wheel_neg6.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 6", None)) #endif // QT_CONFIG(statustip) self.wheel_neg6.setText("") #if QT_CONFIG(statustip) self.wheel_pos5.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 5", None)) #endif // QT_CONFIG(statustip) self.wheel_pos5.setText("") #if QT_CONFIG(statustip) self.button_2.setStatusTip(QCoreApplication.translate("MainWindow", u"Button 2", None)) #endif // QT_CONFIG(statustip) self.button_2.setText("") #if QT_CONFIG(statustip) self.wheel_neg5.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 5", None)) #endif // QT_CONFIG(statustip) self.wheel_neg5.setText("") #if QT_CONFIG(statustip) self.wheel_pos6.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 6", None)) #endif // QT_CONFIG(statustip) self.wheel_pos6.setText("") #if QT_CONFIG(statustip) self.wheel_neg1.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 1", None)) #endif // QT_CONFIG(statustip) self.wheel_neg1.setText("") #if QT_CONFIG(statustip) self.button_4.setStatusTip(QCoreApplication.translate("MainWindow", u"Button 4", None)) #endif // QT_CONFIG(statustip) self.button_4.setText("") #if QT_CONFIG(statustip) self.wheel_pos7.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 7", None)) #endif // QT_CONFIG(statustip) self.wheel_pos7.setText("") #if QT_CONFIG(statustip) self.button_3.setStatusTip(QCoreApplication.translate("MainWindow", u"Button 3", None)) #endif // QT_CONFIG(statustip) self.button_3.setText("") #if QT_CONFIG(statustip) self.wheel_neg2.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 2", None)) #endif // QT_CONFIG(statustip) self.wheel_neg2.setText("") #if QT_CONFIG(statustip) self.wheel_pos3.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: right 3", None)) #endif // QT_CONFIG(statustip) self.wheel_pos3.setText("") #if QT_CONFIG(statustip) self.wheel_neg3.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 3", None)) #endif // QT_CONFIG(statustip) self.wheel_neg3.setText("") #if QT_CONFIG(statustip) self.wheel_neg4.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 4", None)) #endif // QT_CONFIG(statustip) self.wheel_neg4.setText(QCoreApplication.translate("MainWindow", u"-", None)) #if QT_CONFIG(statustip) self.wheel_neg7.setStatusTip(QCoreApplication.translate("MainWindow", u"Wheel position: left 7", None)) #endif // QT_CONFIG(statustip) self.wheel_neg7.setText("") #if QT_CONFIG(tooltip) self.about_button.setToolTip("") #endif // QT_CONFIG(tooltip) #if QT_CONFIG(statustip) self.about_button.setStatusTip(QCoreApplication.translate("MainWindow", u"About", None)) #endif // QT_CONFIG(statustip) self.about_button.setText(QCoreApplication.translate("MainWindow", u"?", None)) #if QT_CONFIG(tooltip) self.plug_button.setToolTip("") #endif // QT_CONFIG(tooltip) #if QT_CONFIG(statustip) self.plug_button.setStatusTip(QCoreApplication.translate("MainWindow", u"Configuration", None)) #endif // QT_CONFIG(statustip) self.plug_button.setText(QCoreApplication.translate("MainWindow", u"#", None)) #if QT_CONFIG(tooltip) self.conf_button.setToolTip("") #endif // QT_CONFIG(tooltip) #if QT_CONFIG(statustip) self.conf_button.setStatusTip(QCoreApplication.translate("MainWindow", u"Configuration", None)) #endif // QT_CONFIG(statustip) self.conf_button.setText(QCoreApplication.translate("MainWindow", u"=", None)) self.about_widget.setWindowTitle(QCoreApplication.translate("MainWindow", u"About", None)) self.about_text.setDocumentTitle("") self.log_widget.setWindowTitle(QCoreApplication.translate("MainWindow", u"Log", None)) self.log_clear_button.setText(QCoreApplication.translate("MainWindow", u"Clear", None)) self.config_widget.setWindowTitle(QCoreApplication.translate("MainWindow", u"Configuration", None)) self.plugins_widget.setWindowTitle(QCoreApplication.translate("MainWindow", u"Plugins", None))
class MainWidget(QWidget): def __init__(self, parent: QWidget, model: Model) -> None: super().__init__(parent) logger.add(self.log) settings = QSettings() self.mainlayout = QVBoxLayout() self.mainlayout.setContentsMargins(5, 5, 5, 5) self.setLayout(self.mainlayout) # summary summarylayout = FlowLayout() summarylayout.setContentsMargins(0, 0, 0, 0) self.summary = QWidget() self.summary.setLayout(summarylayout) self.mainlayout.addWidget(self.summary) self.summary.setVisible( settings.value('showSummary', 'True') == 'True') detailslayout = QHBoxLayout() detailslayout.setContentsMargins(1, 0, 0, 0) detailslayout.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) detailslayout.setSpacing(15) details = QWidget() details.setLayout(detailslayout) summarylayout.addWidget(details) self.modstotal = QLabel() detailslayout.addWidget(self.modstotal) self.modsenabled = QLabel() detailslayout.addWidget(self.modsenabled) self.overridden = QLabel() detailslayout.addWidget(self.overridden) self.conflicts = QLabel() detailslayout.addWidget(self.conflicts) buttonslayout = QHBoxLayout() buttonslayout.setContentsMargins(0, 0, 0, 0) buttonslayout.setAlignment(Qt.AlignRight | Qt.AlignVCenter) buttons = QWidget() buttons.setLayout(buttonslayout) summarylayout.addWidget(buttons) self.startscriptmerger = QPushButton('Start Script Merger') self.startscriptmerger.setContentsMargins(0, 0, 0, 0) self.startscriptmerger.setMinimumWidth(140) self.startscriptmerger.setIcon( QIcon(str(getRuntimePath('resources/icons/script.ico')))) self.startscriptmerger.clicked.connect(lambda: [ openExecutable(Path(str(settings.value('scriptMergerPath'))), True) ]) self.startscriptmerger.setEnabled( verifyScriptMergerPath( Path(str(settings.value('scriptMergerPath')))) is not None) buttonslayout.addWidget(self.startscriptmerger) self.startgame = QPushButton('Start Game') self.startgame.setContentsMargins(0, 0, 0, 0) self.startgame.setMinimumWidth(100) self.startgame.setIcon( QIcon(str(getRuntimePath('resources/icons/w3b.ico')))) buttonslayout.addWidget(self.startgame) # splitter self.splitter = QSplitter(Qt.Vertical) self.stack = QStackedWidget() self.splitter.addWidget(self.stack) # mod list widget self.modlistwidget = QWidget() self.modlistlayout = QVBoxLayout() self.modlistlayout.setContentsMargins(0, 0, 0, 0) self.modlistwidget.setLayout(self.modlistlayout) self.stack.addWidget(self.modlistwidget) # search bar self.searchbar = QLineEdit() self.searchbar.setPlaceholderText('Search...') self.modlistlayout.addWidget(self.searchbar) # mod list self.modlist = ModList(self, model) self.modlistlayout.addWidget(self.modlist) self.searchbar.textChanged.connect(lambda e: self.modlist.setFilter(e)) # welcome message welcomelayout = QVBoxLayout() welcomelayout.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) welcomewidget = QWidget() welcomewidget.setLayout(welcomelayout) welcomewidget.dragEnterEvent = self.modlist.dragEnterEvent # type: ignore welcomewidget.dragMoveEvent = self.modlist.dragMoveEvent # type: ignore welcomewidget.dragLeaveEvent = self.modlist.dragLeaveEvent # type: ignore welcomewidget.dropEvent = self.modlist.dropEvent # type: ignore welcomewidget.setAcceptDrops(True) icon = QIcon(str(getRuntimePath('resources/icons/open-folder.ico'))) iconpixmap = icon.pixmap(32, 32) icon = QLabel() icon.setPixmap(iconpixmap) icon.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) icon.setContentsMargins(4, 4, 4, 4) welcomelayout.addWidget(icon) welcome = QLabel('''<p><font> No mod installed yet. Drag a mod into this area to get started! </font></p>''') welcome.setAttribute(Qt.WA_TransparentForMouseEvents) welcome.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) welcomelayout.addWidget(welcome) self.stack.addWidget(welcomewidget) # output log self.output = QTextEdit(self) self.output.setTextInteractionFlags(Qt.NoTextInteraction) self.output.setReadOnly(True) self.output.setContextMenuPolicy(Qt.NoContextMenu) self.output.setPlaceholderText('Program output...') self.splitter.addWidget(self.output) # TODO: enhancement: show indicator if scripts have to be merged self.splitter.setStretchFactor(0, 1) self.splitter.setStretchFactor(1, 0) self.mainlayout.addWidget(self.splitter) # TODO: incomplete: make start game button functional if len(model): self.stack.setCurrentIndex(0) self.splitter.setSizes([self.splitter.size().height(), 50]) else: self.stack.setCurrentIndex(1) self.splitter.setSizes([self.splitter.size().height(), 0]) model.updateCallbacks.append(self.modelUpdateEvent) asyncio.create_task(model.loadInstalled()) def keyPressEvent(self, event: QKeyEvent) -> None: if event.key() == Qt.Key_Escape: self.modlist.setFocus() self.searchbar.setText('') elif event.matches(QKeySequence.Find): self.searchbar.setFocus() elif event.matches(QKeySequence.Paste): self.pasteEvent() # TODO: enhancement: add start game / start script merger shortcuts else: super().keyPressEvent(event) def pasteEvent(self) -> None: clipboard = QApplication.clipboard().text().splitlines() if len(clipboard) == 1 and isValidNexusModsUrl(clipboard[0]): self.parentWidget().showDownloadModDialog() else: urls = [ url for url in QApplication.clipboard().text().splitlines() if len(str(url.strip())) ] if all( isValidModDownloadUrl(url) or isValidFileUrl(url) for url in urls): asyncio.create_task(self.modlist.checkInstallFromURLs(urls)) def modelUpdateEvent(self, model: Model) -> None: total = len(model) enabled = len([mod for mod in model if model[mod].enabled]) overridden = sum( len(file) for file in model.conflicts.bundled.values()) conflicts = sum(len(file) for file in model.conflicts.scripts.values()) self.modstotal.setText( f'<font color="#73b500" size="4">{total}</font> \ <font color="#888" text-align="center">Installed Mod{"" if total == 1 else "s"}</font>' ) self.modsenabled.setText( f'<font color="#73b500" size="4">{enabled}</font> \ <font color="#888">Enabled Mod{"" if enabled == 1 else "s"}</font>' ) self.overridden.setText( f'<font color="{"#b08968" if overridden > 0 else "#84C318"}" size="4">{overridden}</font> \ <font color="#888">Overridden File{"" if overridden == 1 else "s"}</font> ' ) self.conflicts.setText( f'<font color="{"#E55934" if conflicts > 0 else "#aad576"}" size="4">{conflicts}</font> \ <font color="#888">Unresolved Conflict{"" if conflicts == 1 else "s"}</font> ' ) if len(model) > 0: if self.stack.currentIndex() != 0: self.stack.setCurrentIndex(0) self.repaint() else: if self.stack.currentIndex() != 1: self.stack.setCurrentIndex(1) self.repaint() def unhideOutput(self) -> None: if self.splitter.sizes()[1] < 10: self.splitter.setSizes([self.splitter.size().height(), 50]) def unhideModList(self) -> None: if self.splitter.sizes()[0] < 10: self.splitter.setSizes([50, self.splitter.size().height()]) def log(self, message: Any) -> None: # format log messages to user readable output settings = QSettings() record = message.record message = record['message'] extra = record['extra'] level = record['level'].name.lower() name = str(extra['name'] ) if 'name' in extra and extra['name'] is not None else '' path = str(extra['path'] ) if 'path' in extra and extra['path'] is not None else '' dots = bool( extra['dots'] ) if 'dots' in extra and extra['dots'] is not None else False newline = bool( extra['newline'] ) if 'newline' in extra and extra['newline'] is not None else False output = bool( extra['output'] ) if 'output' in extra and extra['output'] is not None else bool( message) modlist = bool( extra['modlist'] ) if 'modlist' in extra and extra['modlist'] is not None else False if level in ['debug' ] and settings.value('debugOutput', 'False') != 'True': if newline: self.output.append(f'') return n = '<br>' if newline else '' d = '...' if dots else '' if len(name) and len(path): path = f' ({path})' if output: message = html.escape(message, quote=True) if level in ['success', 'error', 'warning']: message = f'<strong>{message}</strong>' if level in ['success']: message = f'<font color="#04c45e">{message}</font>' if level in ['error', 'critical']: message = f'<font color="#ee3b3b">{message}</font>' if level in ['warning']: message = f'<font color="#ff6500">{message}</font>' if level in ['debug', 'trace']: message = f'<font color="#aaa">{message}</font>' path = f'<font color="#aaa">{path}</font>' if path else '' d = f'<font color="#aaa">{d}</font>' if d else '' time = record['time'].astimezone( tz=None).strftime('%Y-%m-%d %H:%M:%S') message = f'<font color="#aaa">{time}</font> {message}' self.output.append( f'{n}{message.strip()}{" " if name or path else ""}{name}{path}{d}' ) else: self.output.append(f'') self.output.verticalScrollBar().setValue( self.output.verticalScrollBar().maximum()) self.output.repaint() if modlist: self.unhideModList() if settings.value('unhideOutput', 'True') == 'True' and output: self.unhideOutput()
class AppendDialog(QDialog): def __init__(self, parent, compatibles, title="Append data"): super().__init__(parent) self.setWindowTitle(title) vbox = QVBoxLayout(self) grid = QGridLayout() grid.addWidget(QLabel("Source"), 0, 0, Qt.AlignCenter) grid.addWidget(QLabel("Destination"), 0, 2, Qt.AlignCenter) self.source = QListWidget(self) self.source.setAcceptDrops(True) self.source.setDragEnabled(True) self.source.setSelectionMode(QAbstractItemView.ExtendedSelection) self.source.setDefaultDropAction(Qt.DropAction.MoveAction) self.source.insertItems(0, [d["name"] for d in compatibles]) grid.addWidget(self.source, 1, 0) self.move_button = QPushButton("→") self.move_button.setEnabled(False) grid.addWidget(self.move_button, 1, 1, Qt.AlignHCenter) self.destination = QListWidget(self) self.destination.setAcceptDrops(True) self.destination.setDragEnabled(True) self.destination.setSelectionMode(QAbstractItemView.ExtendedSelection) self.destination.setDefaultDropAction(Qt.DropAction.MoveAction) grid.addWidget(self.destination, 1, 2) vbox.addLayout(grid) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonbox.accepted.connect(self.accept) self.buttonbox.rejected.connect(self.reject) vbox.addWidget(self.buttonbox) vbox.setSizeConstraint(QVBoxLayout.SetFixedSize) self.destination.model().rowsInserted.connect(self.toggle_ok_button) self.destination.model().rowsRemoved.connect(self.toggle_ok_button) self.source.itemSelectionChanged.connect(self.toggle_move_source) self.destination.itemSelectionChanged.connect( self.toggle_move_destination) self.move_button.clicked.connect(self.move) self.toggle_ok_button() self.toggle_move_source() self.toggle_move_destination() @property def names(self): names = [] for it in range(self.destination.count()): names.append(self.destination.item(it).text()) return names @Slot() def toggle_ok_button(self): """Toggle OK button.""" if self.destination.count() > 0: self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(True) else: self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(False) @Slot() def toggle_move_source(self): if self.source.selectedItems(): self.move_button.setEnabled(True) self.move_button.setText("→") self.destination.clearSelection() elif not self.destination.selectedItems(): self.move_button.setEnabled(False) @Slot() def toggle_move_destination(self): if self.destination.selectedItems(): self.move_button.setEnabled(True) self.move_button.setText("←") self.source.clearSelection() elif not self.source.selectedItems(): self.move_button.setEnabled(False) @Slot() def move(self): if self.source.selectedItems(): for item in self.source.selectedItems(): self.destination.addItem(item.text()) self.source.takeItem(self.source.row(item)) elif self.destination.selectedItems(): for item in self.destination.selectedItems(): self.source.addItem(item.text()) self.destination.takeItem(self.destination.row(item))
class UIOpenPatientWindow(object): patient_info_initialized = QtCore.Signal(object) def setup_ui(self, open_patient_window_instance): if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) open_patient_window_instance.setObjectName("OpenPatientWindowInstance") open_patient_window_instance.setWindowIcon(window_icon) open_patient_window_instance.resize(840, 530) # Create a vertical box for containing the other elements and layouts self.open_patient_window_instance_vertical_box = QVBoxLayout() self.open_patient_window_instance_vertical_box.setObjectName( "OpenPatientWindowInstanceVerticalBox") # Create a label to prompt the user to enter the path to the directory that contains the DICOM files self.open_patient_directory_prompt = QLabel() self.open_patient_directory_prompt.setObjectName( "OpenPatientDirectoryPrompt") self.open_patient_directory_prompt.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_prompt) # Create a horizontal box to hold the input box for the directory and the choose button self.open_patient_directory_input_horizontal_box = QHBoxLayout() self.open_patient_directory_input_horizontal_box.setObjectName( "OpenPatientDirectoryInputHorizontalBox") # Create a textbox to contain the path to the directory that contains the DICOM files self.open_patient_directory_input_box = UIOpenPatientWindowDragAndDropEvent( self) self.open_patient_directory_input_box.setObjectName( "OpenPatientDirectoryInputBox") self.open_patient_directory_input_box.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_input_box.returnPressed.connect( self.scan_directory_for_patient) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_input_box) # Create a choose button to open the file dialog self.open_patient_directory_choose_button = QPushButton() self.open_patient_directory_choose_button.setObjectName( "OpenPatientDirectoryChooseButton") self.open_patient_directory_choose_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_choose_button.resize( self.open_patient_directory_choose_button.sizeHint().width(), self.open_patient_directory_input_box.height()) self.open_patient_directory_choose_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_choose_button) self.open_patient_directory_choose_button.clicked.connect( self.choose_button_clicked) # Create a widget to hold the input fields self.open_patient_directory_input_widget = QWidget() self.open_patient_directory_input_horizontal_box.setStretch(0, 4) self.open_patient_directory_input_widget.setLayout( self.open_patient_directory_input_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_input_widget) # Create a horizontal box to hold the stop button and direction to the user on where to select the patient self.open_patient_appear_prompt_and_stop_horizontal_box = QHBoxLayout() self.open_patient_appear_prompt_and_stop_horizontal_box.setObjectName( "OpenPatientAppearPromptAndStopHorizontalBox") # Create a label to show direction on where the files will appear self.open_patient_directory_appear_prompt = QLabel() self.open_patient_directory_appear_prompt.setObjectName( "OpenPatientDirectoryAppearPrompt") self.open_patient_directory_appear_prompt.setAlignment(Qt.AlignLeft) self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_directory_appear_prompt) self.open_patient_appear_prompt_and_stop_horizontal_box.addStretch(1) # Create a button to stop searching self.open_patient_window_stop_button = QPushButton() self.open_patient_window_stop_button.setObjectName( "OpenPatientWindowStopButton") self.open_patient_window_stop_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_stop_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_stop_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_stop_button.clicked.connect( self.stop_button_clicked) self.open_patient_window_stop_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_stop_button.setVisible( False) # Button doesn't show until a search commences self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_window_stop_button) # Create a widget to hold the layout self.open_patient_appear_prompt_and_stop_widget = QWidget() self.open_patient_appear_prompt_and_stop_widget.setLayout( self.open_patient_appear_prompt_and_stop_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_appear_prompt_and_stop_widget) # Create a tree view list to list out all patients in the directory selected above self.open_patient_window_patients_tree = QTreeWidget() self.open_patient_window_patients_tree.setObjectName( "OpenPatientWindowPatientsTree") self.open_patient_window_patients_tree.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_patients_tree.resize( self.open_patient_window_patients_tree.sizeHint().width(), self.open_patient_window_patients_tree.sizeHint().height()) self.open_patient_window_patients_tree.setHeaderHidden(False) self.open_patient_window_patients_tree.setHeaderLabels([""]) self.open_patient_window_patients_tree.itemChanged.connect( self.tree_item_changed) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patients_tree) self.last_patient = None # Create a label to show what would happen if they select the patient self.open_patient_directory_result_label = QtWidgets.QLabel() self.open_patient_directory_result_label.setObjectName( "OpenPatientDirectoryResultLabel") self.open_patient_directory_result_label.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_result_label) # Create a horizontal box to hold the Cancel and Open button self.open_patient_window_patient_open_actions_horizontal_box = QHBoxLayout( ) self.open_patient_window_patient_open_actions_horizontal_box.setObjectName( "OpenPatientWindowPatientOpenActionsHorizontalBox") self.open_patient_window_patient_open_actions_horizontal_box.addStretch( 1) # Add a button to go back/exit from the application self.open_patient_window_exit_button = QPushButton() self.open_patient_window_exit_button.setObjectName( "OpenPatientWindowExitButton") self.open_patient_window_exit_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_exit_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_exit_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_exit_button.clicked.connect( self.exit_button_clicked) self.open_patient_window_exit_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_patient_open_actions_horizontal_box.addWidget( self.open_patient_window_exit_button) # Add a button to confirm opening of the patient self.open_patient_window_confirm_button = QPushButton() self.open_patient_window_confirm_button.setObjectName( "OpenPatientWindowConfirmButton") self.open_patient_window_confirm_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_confirm_button.resize( self.open_patient_window_confirm_button.sizeHint().width(), self.open_patient_window_confirm_button.sizeHint().height()) self.open_patient_window_confirm_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_confirm_button.setDisabled(True) self.open_patient_window_confirm_button.clicked.connect( self.confirm_button_clicked) self.open_patient_window_confirm_button.setProperty( "QPushButtonClass", "success-button") self.open_patient_window_patient_open_actions_horizontal_box.addWidget( self.open_patient_window_confirm_button) # Create a widget to house all of the actions button for open patient window self.open_patient_window_patient_open_actions_widget = QWidget() self.open_patient_window_patient_open_actions_widget.setLayout( self.open_patient_window_patient_open_actions_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patient_open_actions_widget) # Set the vertical box fourth element, the tree view, to stretch out as far as possible self.open_patient_window_instance_vertical_box.setStretch( 3, 4) # Stretch the treeview out as far as possible self.open_patient_window_instance_central_widget = QWidget() self.open_patient_window_instance_central_widget.setObjectName( "OpenPatientWindowInstanceCentralWidget") self.open_patient_window_instance_central_widget.setLayout( self.open_patient_window_instance_vertical_box) # Create threadpool for multithreading self.threadpool = QThreadPool() print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) # Create interrupt event for stopping the directory search self.interrupt_flag = threading.Event() # Bind all texts into the buttons and labels self.retranslate_ui(open_patient_window_instance) # Set the central widget, ready for display open_patient_window_instance.setCentralWidget( self.open_patient_window_instance_central_widget) # Set the current stylesheet to the instance and connect it back to the caller through slot _stylesheet = open(resource_path(self.stylesheet_path)).read() open_patient_window_instance.setStyleSheet(_stylesheet) QtCore.QMetaObject.connectSlotsByName(open_patient_window_instance) def retranslate_ui(self, open_patient_window_instance): _translate = QtCore.QCoreApplication.translate open_patient_window_instance.setWindowTitle( _translate("OpenPatientWindowInstance", "OnkoDICOM - Select Patient")) self.open_patient_directory_prompt.setText( _translate( "OpenPatientWindowInstance", "Choose the path of the folder containing DICOM files to load Patient's details:" )) self.open_patient_directory_input_box.setPlaceholderText( _translate( "OpenPatientWindowInstance", "Enter DICOM Files Path (For example, C:\path\\to\your\DICOM\Files)" )) self.open_patient_directory_choose_button.setText( _translate("OpenPatientWindowInstance", "Choose")) self.open_patient_directory_appear_prompt.setText( _translate( "OpenPatientWindowInstance", "Patient File directory shown below once file path chosen. Please select the file(s) you want to open:" )) self.open_patient_directory_result_label.setText( "The selected directory(s) above will be opened in the OnkoDICOM program." ) self.open_patient_window_stop_button.setText( _translate("OpenPatientWindowInstance", "Stop Search")) self.open_patient_window_exit_button.setText( _translate("OpenPatientWindowInstance", "Exit")) self.open_patient_window_confirm_button.setText( _translate("OpenPatientWindowInstance", "Confirm")) def exit_button_clicked(self): QCoreApplication.exit(0) def scan_directory_for_patient(self): # Reset tree view header and last patient self.open_patient_window_patients_tree.setHeaderLabels([""]) self.last_patient = None self.filepath = self.open_patient_directory_input_box.text() # Proceed if a folder was selected if self.filepath != "": # Update the QTreeWidget to reflect data being loaded # First, clear the widget of any existing data self.open_patient_window_patients_tree.clear() # Next, update the tree widget self.open_patient_window_patients_tree.addTopLevelItem( QTreeWidgetItem(["Loading selected directory..."])) # The choose button is disabled until the thread finishes executing self.open_patient_directory_choose_button.setEnabled(False) # Reveals the Stop Search button for the duration of the search self.open_patient_window_stop_button.setVisible(True) # The interrupt flag is then un-set if a previous search has been stopped. self.interrupt_flag.clear() # Then, create a new thread that will load the selected folder worker = Worker(DICOMDirectorySearch.get_dicom_structure, self.filepath, self.interrupt_flag, progress_callback=True) worker.signals.result.connect(self.on_search_complete) worker.signals.progress.connect(self.search_progress) # Execute the thread self.threadpool.start(worker) def choose_button_clicked(self): """ Executes when the choose button is clicked. Gets filepath from the user and loads all files and subdirectories. """ # Get folder path from pop up dialog box self.filepath = QtWidgets.QFileDialog.getExistingDirectory( None, 'Select patient folder...', '') self.open_patient_directory_input_box.setText(self.filepath) self.scan_directory_for_patient() def stop_button_clicked(self): self.interrupt_flag.set() def search_progress(self, progress_update): """ Current progress of the file search. """ self.open_patient_window_patients_tree.clear() self.open_patient_window_patients_tree.addTopLevelItem( QTreeWidgetItem([ "Loading selected directory... (%s files searched)" % progress_update ])) def on_search_complete(self, dicom_structure): """ Executes once the directory search is complete. :param dicom_structure: DICOMStructure object constructed by the directory search. """ self.open_patient_directory_choose_button.setEnabled(True) self.open_patient_window_stop_button.setVisible(False) self.open_patient_window_patients_tree.clear() if dicom_structure is None: # dicom_structure will be None if function was interrupted. return for patient_item in dicom_structure.get_tree_items_list(): self.open_patient_window_patients_tree.addTopLevelItem( patient_item) if len(dicom_structure.patients) == 0: QMessageBox.about(self, "No files found", "Selected directory contains no DICOM files.") def tree_item_changed(self, item, _): """ Executes when a tree item is checked or unchecked. If a different patient is checked, uncheck the previous patient. Inform user about missing DICOM files. """ selected_patient = item # If the item is not top-level, bubble up to see which top-level item this item belongs to if self.open_patient_window_patients_tree.invisibleRootItem( ).indexOfChild(item) == -1: while self.open_patient_window_patients_tree.invisibleRootItem( ).indexOfChild(selected_patient) == -1: selected_patient = selected_patient.parent() # Uncheck previous patient if a different patient is selected if item.checkState( 0 ) == Qt.CheckState.Checked and self.last_patient != selected_patient: if self.last_patient is not None: self.last_patient.setCheckState(0, Qt.CheckState.Unchecked) self.last_patient.setSelected(False) self.last_patient = selected_patient # Get the types of all selected leaves self.selected_series_types = set() for checked_item in self.get_checked_leaves(): series_type = checked_item.dicom_object.get_series_type() if type(series_type) == str: self.selected_series_types.add(series_type) else: self.selected_series_types.update(series_type) # Check the existence of IMAGE, RTSTRUCT and RTDOSE files if len(list({'CT', 'MR', 'PT'} & self.selected_series_types)) == 0: header = "Cannot proceed without an image file." self.open_patient_window_confirm_button.setDisabled(True) elif 'RTSTRUCT' not in self.selected_series_types: header = "DVH and Radiomics calculations are not available without a RTSTRUCT file." elif 'RTDOSE' not in self.selected_series_types: header = "DVH calculations are not available without a RTDOSE file." else: header = "" self.open_patient_window_patients_tree.setHeaderLabel(header) if len(list({'CT', 'MR', 'PT'} & self.selected_series_types)) != 0: self.open_patient_window_confirm_button.setDisabled(False) def confirm_button_clicked(self): """ Begins loading of the selected files. """ selected_files = [] for item in self.get_checked_leaves(): selected_files += item.dicom_object.get_files() self.progress_window = ProgressWindow( self, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) self.progress_window.signal_loaded.connect(self.on_loaded) self.progress_window.signal_error.connect(self.on_loading_error) self.progress_window.start_loading(selected_files) self.progress_window.exec_() def on_loaded(self, results): """ Executes when the progress bar finishes loaded the selected files. """ if results[0] is True: # Will be NoneType if loading was interrupted. self.patient_info_initialized.emit( results[1]) # Emits the progress window. def on_loading_error(self, error_code): """ Error handling for progress window. """ if error_code == 0: QMessageBox.about( self.progress_window, "Unable to open selection", "Selected files cannot be opened as they are not a DICOM-RT set." ) self.progress_window.close() elif error_code == 1: QMessageBox.about( self.progress_window, "Unable to open selection", "Selected files cannot be opened as they contain unsupported DICOM classes." ) self.progress_window.close() def get_checked_leaves(self): """ :return: A list of all QTreeWidgetItems in the QTreeWidget that are both leaves and checked. """ checked_items = [] def recurse(parent_item: QTreeWidgetItem): for i in range(parent_item.childCount()): child = parent_item.child(i) grand_children = child.childCount() if grand_children > 0: recurse(child) else: if child.checkState(0) == Qt.Checked: checked_items.append(child) recurse(self.open_patient_window_patients_tree.invisibleRootItem()) return checked_items
class Ui_ReferenceDataDialog(object): def setupUi(self, ReferenceDataDialog): if not ReferenceDataDialog.objectName(): ReferenceDataDialog.setObjectName(u"ReferenceDataDialog") ReferenceDataDialog.resize(869, 300) self.verticalLayout = QVBoxLayout(ReferenceDataDialog) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(2, 2, 2, 2) self.EditFrame = QFrame(ReferenceDataDialog) self.EditFrame.setObjectName(u"EditFrame") sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.EditFrame.sizePolicy().hasHeightForWidth()) self.EditFrame.setSizePolicy(sizePolicy) self.EditFrame.setFrameShape(QFrame.Panel) self.EditFrame.setFrameShadow(QFrame.Plain) self.EditFrame.setLineWidth(0) self.edit_layout = QHBoxLayout(self.EditFrame) self.edit_layout.setObjectName(u"edit_layout") self.edit_layout.setContentsMargins(0, 0, 0, 0) self.GroupLbl = QLabel(self.EditFrame) self.GroupLbl.setObjectName(u"GroupLbl") self.edit_layout.addWidget(self.GroupLbl) self.GroupCombo = QComboBox(self.EditFrame) self.GroupCombo.setObjectName(u"GroupCombo") self.edit_layout.addWidget(self.GroupCombo) self.Toggle = QCheckBox(self.EditFrame) self.Toggle.setObjectName(u"Toggle") self.Toggle.setChecked(False) self.edit_layout.addWidget(self.Toggle) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.edit_layout.addItem(self.horizontalSpacer) self.AddBtn = QPushButton(self.EditFrame) self.AddBtn.setObjectName(u"AddBtn") self.edit_layout.addWidget(self.AddBtn) self.AddChildBtn = QPushButton(self.EditFrame) self.AddChildBtn.setObjectName(u"AddChildBtn") self.edit_layout.addWidget(self.AddChildBtn) self.RemoveBtn = QPushButton(self.EditFrame) self.RemoveBtn.setObjectName(u"RemoveBtn") self.edit_layout.addWidget(self.RemoveBtn) self.CommitBtn = QPushButton(self.EditFrame) self.CommitBtn.setObjectName(u"CommitBtn") self.CommitBtn.setEnabled(False) self.edit_layout.addWidget(self.CommitBtn) self.RevertBtn = QPushButton(self.EditFrame) self.RevertBtn.setObjectName(u"RevertBtn") self.RevertBtn.setEnabled(False) self.edit_layout.addWidget(self.RevertBtn) self.verticalLayout.addWidget(self.EditFrame) self.SearchFrame = QFrame(ReferenceDataDialog) self.SearchFrame.setObjectName(u"SearchFrame") self.SearchFrame.setFrameShape(QFrame.Panel) self.SearchFrame.setFrameShadow(QFrame.Plain) self.SearchFrame.setLineWidth(0) self.search_layout = QHBoxLayout(self.SearchFrame) self.search_layout.setObjectName(u"search_layout") self.search_layout.setContentsMargins(0, 0, 0, 0) self.SearchLbl = QLabel(self.SearchFrame) self.SearchLbl.setObjectName(u"SearchLbl") self.search_layout.addWidget(self.SearchLbl) self.SearchString = QLineEdit(self.SearchFrame) self.SearchString.setObjectName(u"SearchString") self.search_layout.addWidget(self.SearchString) self.verticalLayout.addWidget(self.SearchFrame) self.DataView = QTableView(ReferenceDataDialog) self.DataView.setObjectName(u"DataView") self.DataView.setEditTriggers(QAbstractItemView.AnyKeyPressed | QAbstractItemView.EditKeyPressed | QAbstractItemView.SelectedClicked) self.DataView.setAlternatingRowColors(True) self.DataView.setSelectionBehavior(QAbstractItemView.SelectRows) self.DataView.verticalHeader().setVisible(True) self.DataView.verticalHeader().setMinimumSectionSize(20) self.DataView.verticalHeader().setDefaultSectionSize(20) self.verticalLayout.addWidget(self.DataView) self.TreeView = QTreeView(ReferenceDataDialog) self.TreeView.setObjectName(u"TreeView") self.TreeView.setEditTriggers(QAbstractItemView.AnyKeyPressed | QAbstractItemView.EditKeyPressed | QAbstractItemView.SelectedClicked) self.TreeView.setTabKeyNavigation(True) self.TreeView.setAlternatingRowColors(True) self.TreeView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.TreeView.setExpandsOnDoubleClick(False) self.TreeView.header().setStretchLastSection(False) self.verticalLayout.addWidget(self.TreeView) self.retranslateUi(ReferenceDataDialog) QMetaObject.connectSlotsByName(ReferenceDataDialog) # setupUi def retranslateUi(self, ReferenceDataDialog): ReferenceDataDialog.setWindowTitle( QCoreApplication.translate("ReferenceDataDialog", u"Reference Data", None)) self.GroupLbl.setText( QCoreApplication.translate("ReferenceDataDialog", u"Account Type:", None)) self.Toggle.setText( QCoreApplication.translate("ReferenceDataDialog", u"Show inactive", None)) #if QT_CONFIG(tooltip) self.AddBtn.setToolTip( QCoreApplication.translate("ReferenceDataDialog", u"Add new", None)) #endif // QT_CONFIG(tooltip) self.AddBtn.setText("") #if QT_CONFIG(tooltip) self.AddChildBtn.setToolTip( QCoreApplication.translate("ReferenceDataDialog", u"Add child", None)) #endif // QT_CONFIG(tooltip) self.AddChildBtn.setText("") #if QT_CONFIG(tooltip) self.RemoveBtn.setToolTip( QCoreApplication.translate("ReferenceDataDialog", u"Delete", None)) #endif // QT_CONFIG(tooltip) self.RemoveBtn.setText("") #if QT_CONFIG(tooltip) self.CommitBtn.setToolTip( QCoreApplication.translate("ReferenceDataDialog", u"Save changes", None)) #endif // QT_CONFIG(tooltip) self.CommitBtn.setText("") #if QT_CONFIG(tooltip) self.RevertBtn.setToolTip( QCoreApplication.translate("ReferenceDataDialog", u"Revert changes", None)) #endif // QT_CONFIG(tooltip) self.RevertBtn.setText("") self.SearchLbl.setText( QCoreApplication.translate("ReferenceDataDialog", u"Search:", None))
class Importador(QWidget): """GUI class for the BGG -> Ludopedia importer""" enable_editables = Signal(bool) alternative_chosen = Signal(object) def __init__(self, parent=None): super().__init__(parent) self.thread = QThread() self.worker = None grid_layout = QGridLayout(self) login_group_box = self.create_login_group() data_group_box = self.create_data_group() self.enable_editables.connect(login_group_box.setEnabled) self.enable_editables.connect(data_group_box.setEnabled) self.import_button = QPushButton('Importar', self) self.import_button.setEnabled(False) self.enable_editables.connect(self.import_button.setEnabled) self.import_button.clicked.connect(self.enable_editables) self.import_button.clicked.connect(self.load_data) self.bgg_user_line_edit.textChanged.connect(self.enable_import) self.ludo_mail_line_edit.textChanged.connect(self.enable_import) self.ludo_pass_line_edit.textChanged.connect(self.enable_import) grid_layout.addWidget(login_group_box, 1, 1, 1, 2) grid_layout.addWidget(data_group_box, 2, 1, 1, 2) grid_layout.addWidget(self.import_button, 8, 2) self.log_widget = QTextEdit(self) self.log_widget.setReadOnly(True) grid_layout.addWidget(self.log_widget, 9, 1, 30, 2) def create_qlineedit(self, text): """Creates a label with the given text and an accompanying line edit""" line_edit = QLineEdit(self) line_edit_label = QLabel(text, line_edit) line_edit_label.setBuddy(line_edit) return (line_edit, line_edit_label) def create_login_group(self): """Create labels and line edits for providing BGG and ludopedia login information""" (self.bgg_user_line_edit, bgg_user_label) = self.create_qlineedit('Usuario BoardGameGeek:') (self.ludo_mail_line_edit, ludo_mail_label) = self.create_qlineedit('E-mail Ludopedia:') (self.ludo_pass_line_edit, ludo_pass_label) = self.create_qlineedit('Senha Ludopedia:') self.ludo_pass_line_edit.setEchoMode(QLineEdit.PasswordEchoOnEdit) group_box = QGroupBox('Login') grid_layout = QGridLayout(group_box) grid_layout.addWidget(bgg_user_label, 1, 1) grid_layout.addWidget(self.bgg_user_line_edit, 1, 2) grid_layout.addWidget(ludo_mail_label, 2, 1) grid_layout.addWidget(self.ludo_mail_line_edit, 2, 2) grid_layout.addWidget(ludo_pass_label, 3, 1) grid_layout.addWidget(self.ludo_pass_line_edit, 3, 2) group_box.setLayout(grid_layout) return group_box def create_data_group(self): """Creates group for holding specific choice data selection""" button_group = QButtonGroup(self) button_group.setExclusive(True) colecao_radio_button = QRadioButton('Coleção') self.partidas_radio_button = QRadioButton('Partidas') colecao_radio_button.setChecked(True) button_group.addButton(colecao_radio_button) button_group.addButton(self.partidas_radio_button) (self.min_date_picker, min_date_label) = create_date_picker('À Partir de:', self) (self.max_date_picker, max_date_label) = create_date_picker('Até:', self) self.min_date_picker.dateChanged.connect( self.max_date_picker.setMinimumDate) colecao_radio_button.toggled.connect(self.min_date_picker.setDisabled) colecao_radio_button.toggled.connect(self.max_date_picker.setDisabled) self.map_users_button = QPushButton( 'Ver mapa de usuarios BGG -> Ludopedia', self) self.map_users_button.setEnabled(False) self.map_users_button.clicked.connect(self.user_map) colecao_radio_button.toggled.connect(self.map_users_button.setDisabled) group_box = QGroupBox('Dados') grid_layout = QGridLayout(group_box) grid_layout.addWidget(colecao_radio_button, 1, 1) grid_layout.addWidget(self.partidas_radio_button, 1, 2) grid_layout.addWidget(min_date_label, 2, 1) grid_layout.addWidget(self.min_date_picker, 2, 2) grid_layout.addWidget(max_date_label, 3, 1) grid_layout.addWidget(self.max_date_picker, 3, 2) grid_layout.addWidget(self.map_users_button, 4, 1, 1, 2) group_box.setLayout(grid_layout) return group_box def enable_import(self): """Slot to toggle state of the import button""" self.import_button.setDisabled(not self.bgg_user_line_edit.text() or not self.ludo_mail_line_edit.text() or not self.ludo_pass_line_edit.text()) def log_text(self, message_type, text): """Logs the given text to the QPlainTextWidget""" current_time = QTime.currentTime().toString() if message_type == MessageType.ERROR: self.log_widget.insertHtml( f'[{current_time}] {ERROR_HTML}{text}<br>') elif message_type == MessageType.GENERIC: self.log_widget.insertHtml(f'[{current_time}] {text}<br>') elif message_type == MessageType.DEBUG and ENABLE_DEBUG: self.log_widget.insertHtml( f'[{current_time}] {DEBUG_HTML}{text}<br>') self.log_widget.moveCursor(QTextCursor.End) if ENABLE_DEBUG: print(text) def disconnect_thread(self): """Disconnect the started signal from the thread""" self.thread.started.disconnect() def configure_thread(self, worker): """Does basic thread startup and cleanup configuration""" worker.finished.connect(self.thread.quit) worker.moveToThread(self.thread) self.thread.started.connect(worker.run) worker.message.connect(self.log_text) worker.finished.connect(self.disconnect_thread) worker.exit_on_error.connect(self.thread.quit) worker.exit_on_error.connect(lambda: self.enable_editables.emit(True)) def load_data(self): """Load data from bgg""" try: (session, ludo_user_id) = self.login_ludopedia() bgg_user = self.bgg_user_line_edit.text() if self.partidas_radio_button.isChecked(): current_date = format_qdate(QDate.currentDate()) min_date = parse_date( format_qdate(self.min_date_picker.date()), current_date) max_date = parse_date( format_qdate(self.max_date_picker.date()), min_date) self.worker = BGGPlayFetcher(bgg_user, min_date, max_date) self.configure_thread(self.worker) self.worker.finished.connect(lambda plays: self.post_plays( session, plays, bgg_user, ludo_user_id)) else: self.worker = BGGColectionFetcher(bgg_user) self.configure_thread(self.worker) self.worker.finished.connect( lambda bgg_collection: self.import_collection( session, bgg_collection)) self.thread.start() except InputError: self.enable_editables.emit(True) def show_play_table(self, plays): """Shows a table with all the plays to be imported, allowing user to select some to skip""" tree_model = PlayTableModel(plays) table_widget = QTableView() table_widget.setModel(tree_model) table_widget.verticalHeader().setVisible(False) table_view_header = table_widget.horizontalHeader() table_view_header.setStretchLastSection(True) for column in range(tree_model.columnCount()): column_size = tree_model.data(tree_model.index(0, column), PlayTableModel.SIZE_ROLE) table_view_header.resizeSection(column, column_size) table_widget_dialog = QDialog(self) table_widget_dialog.setModal(True) grid_layout = QGridLayout(table_widget_dialog) grid_layout.addWidget(table_widget, 1, 1) table_widget_dialog.resize(800, 600) table_widget_dialog.exec_() skipped_plays = tree_model.get_skipped_plays() return [play for play in plays if play.id not in skipped_plays] def post_plays(self, session, plays, bgg_user, ludo_user_id): """Receives plays from the Play Fetched thread and start the Ludopedia Logger""" user_map = self.get_bgg_to_ludo_users() if bgg_user not in user_map: user_map[bgg_user] = ludo_user_id selected_plays = self.show_play_table(plays) self.worker = LudopediaPlayLogger(session, selected_plays, bgg_user, user_map) self.worker.request_search.connect( self.request_search_and_show_alternatives, Qt.BlockingQueuedConnection) self.worker.request_alternative.connect(self.request_alternative, Qt.BlockingQueuedConnection) self.alternative_chosen.connect(self.worker.receive_alternative, Qt.DirectConnection) self.configure_thread(self.worker) self.worker.finished.connect(lambda: self.enable_editables.emit(True)) self.thread.start() def user_map(self): """Slot to show user map from bgg to ludopedia""" user_map_dialog = QDialog(self) user_map_dialog.setModal(True) bgg_to_ludo = self.get_bgg_to_ludo_users() user_list = [f'{key} -> {value}' for key, value in bgg_to_ludo.items()] list_widget = QListWidget(user_map_dialog) list_widget.addItems(user_list) list_widget.setResizeMode(QListView.Adjust) list_widget.sortItems() grid_layout = QGridLayout(user_map_dialog) grid_layout.addWidget(list_widget, 1, 1) user_map_dialog.resize(400, 400) user_map_dialog.show() def login_ludopedia(self): """Logins into Ludopedia manually and returns the session and user_id""" self.log_text(MessageType.GENERIC, 'Obtendo dados do Ludopedia') payload = { 'email': self.ludo_mail_line_edit.text(), 'pass': self.ludo_pass_line_edit.text() } session = requests.Session() session_request = session.post(LUDOPEDIA_LOGIN_URL, data=payload) if 'senha incorretos' in session_request.text: self.log_text( MessageType.ERROR, 'Não foi possível logar na Ludopedia com as informações fornecidas' ) raise InputError user_re = re.search(r'id_usuario=(\d+)', session_request.text) user_id = user_re.group(1) if user_re else None return (session, user_id) def import_collection(self, session, collection): """Imports a given collection into Ludopedia""" self.worker = LudopediaCollectionLogger(session, collection) self.configure_thread(self.worker) self.worker.finished.connect(lambda: self.enable_editables.emit(True)) self.thread.start() def show_alternatives_dialog(self, bgg_play, data): """Show alternative games to use as the game to log a play""" alternatives_dialog = QInputDialog(self) alternatives_list = [ f'{item["nm_jogo"]} ({item["ano_publicacao"]})' for item in data ] alternatives_dialog.setComboBoxItems(alternatives_list) alternatives_dialog.setOption(QInputDialog.UseListViewForComboBoxItems) game_str = f'{bgg_play.game_name} ({bgg_play.year_published})' alternatives_dialog.setLabelText( f'Escolha uma alternativa para o jogo "{game_str}"') if alternatives_dialog.exec_(): selected_index = alternatives_list.index( alternatives_dialog.textValue()) return data[selected_index] return None def request_search_and_show_alternatives(self, session, bgg_play): """Request a new string to use for game search and then show results to be picked""" new_search_dialog = QInputDialog(self) game_str = f'{bgg_play.game_name} ({bgg_play.year_published})' new_search_dialog.setLabelText( f'Jogo "{game_str}" não encontrado\nBuscar por:') new_search_dialog.setInputMode(QInputDialog.TextInput) if new_search_dialog.exec_(): data = search_ludopedia_games(session, new_search_dialog.textValue()) data = self.show_alternatives_dialog(bgg_play, data) self.alternative_chosen.emit(data) def request_alternative(self, bgg_play, data): """Request an alternative from user and emit choice""" alternative = self.show_alternatives_dialog(bgg_play, data) self.alternative_chosen.emit(alternative) def get_bgg_to_ludo_users(self): """Reads usuarios.txt file to map a bgg user to its corresponding ludopedia one""" try: parser = ConfigParser() with open("usuarios.txt") as lines: lines = chain(("[top]", ), lines) parser.read_file(lines) bgg_to_ludo_user = dict(parser['top']) bgg_to_ludo_user_id = dict() for bgg_user, ludo_user in bgg_to_ludo_user.items(): if is_invalid_bgg_user(bgg_user): self.log_text( MessageType.ERROR, f'Usuário do BGG "{bgg_user}" inválido' f' no mapa de usuários') continue if ludo_user.isdigit(): bgg_to_ludo_user_id[bgg_user] = ludo_user self.log_text( MessageType.DEBUG, f'Usuário do BGG "{bgg_user}" já mapeado' f' ao id ludopedia: {ludo_user}') else: ludo_user_id = get_ludo_user_id(ludo_user) if ludo_user_id: self.log_text(MessageType.DEBUG, f'{ludo_user_id} para {ludo_user}') bgg_to_ludo_user_id[bgg_user] = ludo_user_id else: self.log_text( MessageType.ERROR, f'Falha ao buscar id de usuario da' f' ludopedia para "{ludo_user}"') return bgg_to_ludo_user_id except FileNotFoundError: self.log_error( MessageType.ERROR, 'Não foi possível encontrar o arquivo "usuarios.txt') return {}
class AdapterSettingsDialog(QDialog): def __init__(self, parent, data): assert type(data) == BinaryView self.bv = data QDialog.__init__(self, parent) debug_state = binjaplug.get_state(self.bv) self.setWindowTitle("Debug Adapter Settings") self.setMinimumSize(UIContext.getScaledWindowSize(400, 130)) self.setAttribute(Qt.WA_DeleteOnClose) layout = QVBoxLayout() layout.setSpacing(0) titleLabel = QLabel("Adapter Settings") titleLayout = QHBoxLayout() titleLayout.setContentsMargins(0, 0, 0, 0) titleLayout.addWidget(titleLabel) self.adapterEntry = QPushButton(self) self.adapterMenu = QMenu(self) for adapter in DebugAdapter.ADAPTER_TYPE: if not DebugAdapter.ADAPTER_TYPE.can_use(adapter): continue def select_adapter(adapter): return lambda: self.selectAdapter(adapter) self.adapterMenu.addAction(adapter.name, select_adapter(adapter)) if adapter == debug_state.adapter_type: self.adapterEntry.setText(adapter.name) self.adapterEntry.setMenu(self.adapterMenu) self.argumentsEntry = QLineEdit(self) self.addressEntry = QLineEdit(self) self.portEntry = QLineEdit(self) self.requestTerminalEmulator = QCheckBox(self) self.formLayout = QFormLayout() self.formLayout.addRow("Adapter Type", self.adapterEntry) self.formLayout.addRow("Command Line Arguments", self.argumentsEntry) self.formLayout.addRow("Address", self.addressEntry) self.formLayout.addRow("Port", self.portEntry) self.formLayout.addRow("Request Terminal Emulator", self.requestTerminalEmulator) buttonLayout = QHBoxLayout() buttonLayout.setContentsMargins(0, 0, 0, 0) self.cancelButton = QPushButton("Cancel") self.cancelButton.clicked.connect(lambda: self.reject()) self.acceptButton = QPushButton("Accept") self.acceptButton.clicked.connect(lambda: self.accept()) self.acceptButton.setDefault(True) buttonLayout.addStretch(1) buttonLayout.addWidget(self.cancelButton) buttonLayout.addWidget(self.acceptButton) layout.addLayout(titleLayout) layout.addSpacing(10) layout.addLayout(self.formLayout) layout.addStretch(1) layout.addSpacing(10) layout.addLayout(buttonLayout) self.setLayout(layout) self.addressEntry.setText(debug_state.remote_host) self.portEntry.setText(str(debug_state.remote_port)) self.addressEntry.textEdited.connect(lambda: self.apply()) self.portEntry.textEdited.connect(lambda: self.apply()) self.argumentsEntry.setText(' '.join( shlex.quote(arg) for arg in debug_state.command_line_args)) self.argumentsEntry.textEdited.connect(lambda: self.updateArguments()) self.requestTerminalEmulator.setChecked( debug_state.request_terminal_emulator) self.requestTerminalEmulator.stateChanged.connect(lambda: self.apply()) self.accepted.connect(lambda: self.apply()) def selectAdapter(self, adapter): self.bv.store_metadata('debugger.adapter_type', adapter.value) debug_state = binjaplug.get_state(self.bv) debug_state.adapter_type = adapter self.adapterEntry.setText(adapter.name) if DebugAdapter.ADAPTER_TYPE.use_exec(adapter): self.argumentsEntry.setEnabled(True) self.addressEntry.setEnabled(False) self.portEntry.setEnabled(False) elif DebugAdapter.ADAPTER_TYPE.use_connect(adapter): self.argumentsEntry.setEnabled(False) self.addressEntry.setEnabled(True) self.portEntry.setEnabled(True) def apply(self): debug_state = binjaplug.get_state(self.bv) arguments = shlex.split(self.argumentsEntry.text()) debug_state.command_line_args = arguments self.bv.store_metadata('debugger.command_line_args', arguments) address = self.addressEntry.text() port = int(self.portEntry.text()) debug_state.remote_host = address debug_state.remote_port = port self.bv.store_metadata('debugger.remote_host', address) self.bv.store_metadata('debugger.remote_port', port) request_terminal_emulator = self.requestTerminalEmulator.isChecked() debug_state.request_terminal_emulator = request_terminal_emulator self.bv.store_metadata('debugger.request_terminal_emulator', request_terminal_emulator) def updateArguments(self): try: arguments = shlex.split(self.argumentsEntry.text()) self.acceptButton.setEnabled(True) except: self.acceptButton.setEnabled(False)
class VideoFinderAddLink(AddLinkWindow): running_thread = None threadPool = {} def __init__(self, parent, receiver_slot, settings, video_dict={}): super().__init__(parent, receiver_slot, settings, video_dict) self.setWindowTitle( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Video Finder')) self.size_label.hide() # empty lists for no_audio and no_video and video_audio files self.no_audio_list = [] self.no_video_list = [] self.video_audio_list = [] self.media_title = '' # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # extension_label self.extension_label = QLabel(self.link_frame) self.change_name_horizontalLayout.addWidget(self.extension_label) # Fetch Button self.url_submit_pushButtontton = QPushButton(self.link_frame) self.link_horizontalLayout.addWidget(self.url_submit_pushButtontton) # Status Box self.status_box_textEdit = QTextEdit(self.link_frame) self.status_box_textEdit.setMaximumHeight(150) self.link_verticalLayout.addWidget(self.status_box_textEdit) # Select format horizontal layout select_format_horizontalLayout = QHBoxLayout() # Selection Label self.select_format_label = QLabel(self.link_frame) select_format_horizontalLayout.addWidget(self.select_format_label) # Selection combobox self.media_comboBox = QComboBox(self.link_frame) self.media_comboBox.setMinimumWidth(200) select_format_horizontalLayout.addWidget(self.media_comboBox) # Duration label self.duration_label = QLabel(self.link_frame) select_format_horizontalLayout.addWidget(self.duration_label) self.format_selection_frame = QFrame(self) self.format_selection_frame.setLayout(select_format_horizontalLayout) self.link_verticalLayout.addWidget(self.format_selection_frame) # advanced_format_selection_checkBox self.advanced_format_selection_checkBox = QCheckBox(self) self.link_verticalLayout.addWidget( self.advanced_format_selection_checkBox) # advanced_format_selection_frame self.advanced_format_selection_frame = QFrame(self) self.link_verticalLayout.addWidget( self.advanced_format_selection_frame) advanced_format_selection_horizontalLayout = QHBoxLayout( self.advanced_format_selection_frame) # video_format_selection self.video_format_selection_label = QLabel( self.advanced_format_selection_frame) self.video_format_selection_comboBox = QComboBox( self.advanced_format_selection_frame) # audio_format_selection self.audio_format_selection_label = QLabel( self.advanced_format_selection_frame) self.audio_format_selection_comboBox = QComboBox( self.advanced_format_selection_frame) for widget in [ self.video_format_selection_label, self.video_format_selection_comboBox, self.audio_format_selection_label, self.audio_format_selection_comboBox ]: advanced_format_selection_horizontalLayout.addWidget(widget) # Set Texts self.url_submit_pushButtontton.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Fetch Media List')) self.select_format_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Select a format')) self.video_format_selection_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Video format:')) self.audio_format_selection_label.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Audio format:')) self.advanced_format_selection_checkBox.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Advanced options')) # Add Slot Connections self.url_submit_pushButtontton.setEnabled(False) self.change_name_lineEdit.setEnabled(False) self.ok_pushButton.setEnabled(False) self.download_later_pushButton.setEnabled(False) self.format_selection_frame.setEnabled(True) self.advanced_format_selection_frame.setEnabled(False) self.advanced_format_selection_checkBox.toggled.connect( self.advancedFormatFrame) self.url_submit_pushButtontton.clicked.connect(self.submitClicked) self.media_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'video_audio')) self.video_format_selection_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'video')) self.audio_format_selection_comboBox.activated.connect( partial(self.mediaSelectionChanged, 'audio')) self.link_lineEdit.textChanged.disconnect( super().linkLineChanged) # Should be disconnected. self.link_lineEdit.textChanged.connect(self.linkLineChangedHere) self.setMinimumSize(650, 480) self.status_box_textEdit.hide() self.format_selection_frame.hide() self.advanced_format_selection_frame.hide() self.advanced_format_selection_checkBox.hide() if 'link' in video_dict.keys() and video_dict['link']: self.link_lineEdit.setText(video_dict['link']) self.url_submit_pushButtontton.setEnabled(True) else: # check clipboard clipboard = QApplication.clipboard() text = clipboard.text() if (("tp:/" in text[2:6]) or ("tps:/" in text[2:7])): self.link_lineEdit.setText(str(text)) self.url_submit_pushButtontton.setEnabled(True) def advancedFormatFrame(self, button): if self.advanced_format_selection_checkBox.isChecked(): self.advanced_format_selection_frame.setEnabled(True) self.format_selection_frame.setEnabled(False) self.mediaSelectionChanged( 'video', int(self.video_format_selection_comboBox.currentIndex())) else: self.advanced_format_selection_frame.setEnabled(False) self.format_selection_frame.setEnabled(True) self.mediaSelectionChanged('video_audio', int(self.media_comboBox.currentIndex())) def getReadableSize(self, size): try: return '{:1.2f} MB'.format(int(size) / 1048576) except: return str(size) def getReadableDuration(self, seconds): try: seconds = int(seconds) hours = seconds // 3600 seconds = seconds % 3600 minutes = seconds // 60 seconds = seconds % 60 return '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds) except: return str(seconds) # Define native slots def urlChanged(self, value): if ' ' in value or value == '': self.url_submit_pushButtontton.setEnabled(False) self.url_submit_pushButtontton.setToolTip( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Please enter a valid video link')) else: self.url_submit_pushButtontton.setEnabled(True) self.url_submit_pushButtontton.setToolTip('') def submitClicked(self, button=None): # Clear media list self.media_comboBox.clear() self.format_selection_frame.hide() self.advanced_format_selection_checkBox.hide() self.advanced_format_selection_frame.hide() self.video_format_selection_comboBox.clear() self.audio_format_selection_comboBox.clear() self.change_name_lineEdit.clear() self.threadPool.clear() self.change_name_checkBox.setChecked(False) self.video_audio_list.clear() self.no_video_list.clear() self.no_audio_list.clear() self.url_submit_pushButtontton.setEnabled(False) self.status_box_textEdit.setText( QCoreApplication.translate("ytaddlink_src_ui_tr", 'Fetching Media Info...')) self.status_box_textEdit.show() self.ok_pushButton.setEnabled(False) self.download_later_pushButton.setEnabled(False) dictionary_to_send = deepcopy(self.plugin_add_link_dictionary) # More options more_options = self.collectMoreOptions() for k in more_options.keys(): dictionary_to_send[k] = more_options[k] dictionary_to_send['link'] = self.link_lineEdit.text() fetcher_thread = MediaListFetcherThread(self.fetchedResult, dictionary_to_send, self) self.parent.threadPool.append(fetcher_thread) self.parent.threadPool[len(self.parent.threadPool) - 1].start() def fileNameChanged(self, value): if value.strip() == '': self.ok_pushButton.setEnabled(False) def mediaSelectionChanged(self, combobox, index): try: if combobox == 'video_audio': if self.media_comboBox.currentText() == 'Best quality': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[-1]['ext']) else: self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText( '.' + self.video_audio_list[index]['ext']) self.change_name_checkBox.setChecked(True) elif combobox == 'video': if self.video_format_selection_comboBox.currentText( ) != 'No video': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[index - 1]['ext']) self.change_name_checkBox.setChecked(True) else: if self.audio_format_selection_comboBox.currentText( ) != 'No audio': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_video_list[ int(self.audio_format_selection_comboBox. currentIndex()) - 1]['ext']) self.change_name_checkBox.setChecked(True) else: self.change_name_lineEdit.setChecked(False) elif combobox == 'audio': if self.audio_format_selection_comboBox.currentText( ) != 'No audio' and self.video_format_selection_comboBox.currentText( ) == 'No video': self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_video_list[index - 1]['ext']) self.change_name_checkBox.setChecked(True) elif (self.audio_format_selection_comboBox.currentText() == 'No audio' and self.video_format_selection_comboBox.currentText() != 'No video') or ( self.audio_format_selection_comboBox.currentText() != 'No audio' and self.video_format_selection_comboBox.currentText() != 'No video'): self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[ int(self.video_format_selection_comboBox.currentIndex( )) - 1]['ext']) self.change_name_checkBox.setChecked(True) elif self.audio_format_selection_comboBox.currentText( ) == 'No audio' and self.video_format_selection_comboBox.currentText( ) == 'No video': self.change_name_checkBox.setChecked(False) except Exception as ex: logger.sendToLog(ex, "ERROR") def fetchedResult(self, media_dict): self.url_submit_pushButtontton.setEnabled(True) if 'error' in media_dict.keys(): self.status_box_textEdit.setText('<font color="#f11">' + str(media_dict['error']) + '</font>') self.status_box_textEdit.show() else: # Show the media list # add no audio and no video options to the comboboxes self.video_format_selection_comboBox.addItem('No video') self.audio_format_selection_comboBox.addItem('No audio') self.media_title = media_dict['title'] if 'formats' not in media_dict.keys( ) and 'entries' in media_dict.keys(): formats = media_dict['entries'] formats = formats[0] media_dict['formats'] = formats['formats'] elif 'formats' not in media_dict.keys( ) and 'format' in media_dict.keys(): media_dict['formats'] = [media_dict.copy()] try: i = 0 for f in media_dict['formats']: no_audio = False no_video = False text = '' if 'acodec' in f.keys(): # only video, no audio if f['acodec'] == 'none': no_audio = True # resolution if 'height' in f.keys(): text = text + ' ' + '{}p'.format(f['height']) if 'vcodec' in f.keys(): # if f['vcodec'] == 'none' and f['acodec'] != 'none': # continue # No video, show audio bit rate if f['vcodec'] == 'none': text = text + '{}kbps'.format(f['abr']) no_video = True if 'ext' in f.keys(): text = text + ' ' + '.{}'.format(f['ext']) if 'filesize' in f.keys() and f['filesize']: # Youtube api does not supply file size for some formats, so check it. text = text + ' ' + '{}'.format( self.getReadableSize(f['filesize'])) else: # Start spider to find file size input_dict = deepcopy(self.plugin_add_link_dictionary) input_dict['link'] = f['url'] more_options = self.collectMoreOptions() for key in more_options.keys(): input_dict[key] = more_options[key] size_fetcher = FileSizeFetcherThread(input_dict, i) self.threadPool[str(i)] = { 'thread': size_fetcher, 'item_id': i } self.parent.threadPool.append(size_fetcher) self.parent.threadPool[len(self.parent.threadPool) - 1].start() self.parent.threadPool[len(self.parent.threadPool) - 1].FOUND.connect( self.findFileSize) # Add current format to the related comboboxes if no_audio: self.no_audio_list.append(f) self.video_format_selection_comboBox.addItem(text) elif no_video: self.no_video_list.append(f) self.audio_format_selection_comboBox.addItem(text) else: self.video_audio_list.append(f) self.media_comboBox.addItem(text) i = i + 1 self.status_box_textEdit.hide() if 'duration' in media_dict.keys(): self.duration_label.setText( 'Duration ' + self.getReadableDuration(media_dict['duration'])) self.format_selection_frame.show() self.advanced_format_selection_checkBox.show() self.advanced_format_selection_frame.show() self.ok_pushButton.setEnabled(True) self.download_later_pushButton.setEnabled(True) # if we have no options for separate audio and video, then hide advanced_format_selection... if len(self.no_audio_list) == 0 and len( self.no_video_list) == 0: self.advanced_format_selection_checkBox.hide() self.advanced_format_selection_frame.hide() # set index of comboboxes on best available quality. # we have both audio and video if len(self.no_audio_list) != 0 and len( self.no_video_list) != 0: self.media_comboBox.addItem('Best quality') self.media_comboBox.setCurrentIndex( len(self.video_audio_list)) self.change_name_lineEdit.setText(self.media_title) self.extension_label.setText('.' + self.no_audio_list[-1]['ext']) self.change_name_checkBox.setChecked(True) # video and audio are not separate elif len(self.video_audio_list) != 0: self.media_comboBox.setCurrentIndex( len(self.video_audio_list) - 1) if len(self.no_audio_list) != 0: self.video_format_selection_comboBox.setCurrentIndex( len(self.no_audio_list)) if len(self.no_video_list) != 0: self.audio_format_selection_comboBox.setCurrentIndex( len(self.no_video_list)) # if we have only audio or we have only video then hide media_comboBox if len(self.video_audio_list) == 0: self.media_comboBox.hide() self.select_format_label.hide() # only video if len(self.no_video_list) != 0 and len( self.no_audio_list) == 0: self.mediaSelectionChanged( 'video', int(self.video_format_selection_comboBox. currentIndex())) self.advanced_format_selection_checkBox.setChecked( True) self.advanced_format_selection_checkBox.hide() # only audio elif len(self.no_video_list) == 0 and len( self.no_audio_list) != 0: self.mediaSelectionChanged( 'audio', int(self.audio_format_selection_comboBox. currentIndex())) self.advanced_format_selection_checkBox.setChecked( True) self.advanced_format_selection_checkBox.hide() # audio and video else: self.mediaSelectionChanged( 'video_audio', int(self.media_comboBox.currentIndex())) except Exception as ex: logger.sendToLog(ex, "ERROR") def findFileSize(self, result): try: item_id = self.threadPool[str(result['thread_key'])]['item_id'] if result['file_size'] and result['file_size'] != '0': text = self.media_comboBox.itemText(item_id) self.media_comboBox.setItemText( item_id, '{} - {}'.format(text, result['file_size'])) except Exception as ex: logger.sendToLog(ex, "ERROR") def linkLineChangedHere(self, lineEdit): if str(lineEdit) == '': self.url_submit_pushButtontton.setEnabled(False) else: self.url_submit_pushButtontton.setEnabled(True) # This method collects additional information like proxy ip, user, password etc. def collectMoreOptions(self): options = { 'ip': None, 'port': None, 'proxy_user': None, 'proxy_passwd': None, 'download_user': None, 'download_passwd': None } if self.proxy_checkBox.isChecked(): options['ip'] = self.ip_lineEdit.text() options['port'] = self.port_spinBox.value() options['proxy_user'] = self.proxy_user_lineEdit.text() options['proxy_passwd'] = self.proxy_pass_lineEdit.text() if self.download_checkBox.isChecked(): options['download_user'] = self.download_user_lineEdit.text() options['download_passwd'] = self.download_pass_lineEdit.text() # These info (keys) are required for spider to find file size, because spider() does not check if key exists. additional_info = [ 'header', 'load_cookies', 'user_agent', 'referer', 'out' ] for i in additional_info: if i not in self.plugin_add_link_dictionary.keys(): options[i] = None return options # user submitted information by pressing ok_pushButton, so get information # from VideoFinderAddLink window and return them to the mainwindow with callback! def okButtonPressed(self, download_later, button=None): link_list = [] # separate audio format and video format is selected. if self.advanced_format_selection_checkBox.isChecked(): if self.video_format_selection_comboBox.currentText( ) == 'No video' and self.audio_format_selection_comboBox.currentText( ) != 'No audio': # only audio link must be added to the link_list audio_link = self.no_video_list[ self.audio_format_selection_comboBox.currentIndex() - 1]['url'] link_list.append(audio_link) elif self.video_format_selection_comboBox.currentText( ) != 'No video' and self.audio_format_selection_comboBox.currentText( ) == 'No audio': # only video link must be added to the link_list video_link = self.no_audio_list[ self.video_format_selection_comboBox.currentIndex() - 1]['url'] link_list.append(video_link) elif self.video_format_selection_comboBox.currentText( ) != 'No video' and self.audio_format_selection_comboBox.currentText( ) != 'No audio': # video and audio links must be added to the link_list audio_link = self.no_video_list[ self.audio_format_selection_comboBox.currentIndex() - 1]['url'] video_link = self.no_audio_list[ self.video_format_selection_comboBox.currentIndex() - 1]['url'] link_list = [video_link, audio_link] elif self.video_format_selection_comboBox.currentText( ) == 'No video' and self.audio_format_selection_comboBox.currentText( ) == 'No audio': # no video and audio is selected! REALLY?!. user is DRUNK! close the window! :)) self.close() else: if self.media_comboBox.currentText() == 'Best quality': # the last item in no_video_list and no_audio_list are the best. video_link = self.no_audio_list[-1]['url'] audio_link = self.no_video_list[-1]['url'] link_list = [video_link, audio_link] else: audio_and_video_link = self.video_audio_list[ self.media_comboBox.currentIndex()]['url'] link_list.append(audio_and_video_link) # write user's new inputs in persepolis_setting for next time :) self.persepolis_setting.setValue('add_link_initialization/ip', self.ip_lineEdit.text()) self.persepolis_setting.setValue('add_link_initialization/port', self.port_spinBox.value()) self.persepolis_setting.setValue('add_link_initialization/proxy_user', self.proxy_user_lineEdit.text()) self.persepolis_setting.setValue( 'add_link_initialization/download_user', self.download_user_lineEdit.text()) # get proxy information if not (self.proxy_checkBox.isChecked()): ip = None port = None proxy_user = None proxy_passwd = None else: ip = self.ip_lineEdit.text() if not (ip): ip = None port = self.port_spinBox.value() if not (port): port = None proxy_user = self.proxy_user_lineEdit.text() if not (proxy_user): proxy_user = None proxy_passwd = self.proxy_pass_lineEdit.text() if not (proxy_passwd): proxy_passwd = None # get download username and password information if not (self.download_checkBox.isChecked()): download_user = None download_passwd = None else: download_user = self.download_user_lineEdit.text() if not (download_user): download_user = None download_passwd = self.download_pass_lineEdit.text() if not (download_passwd): download_passwd = None # check that if user limits download speed. if not (self.limit_checkBox.isChecked()): limit = 0 else: if self.limit_comboBox.currentText() == "KiB/s": limit = str(self.limit_spinBox.value()) + str("K") else: limit = str(self.limit_spinBox.value()) + str("M") # get start time for download if user set that. if not (self.start_checkBox.isChecked()): start_time = None else: start_time = self.start_time_qDataTimeEdit.text() # get end time for download if user set that. if not (self.end_checkBox.isChecked()): end_time = None else: end_time = self.end_time_qDateTimeEdit.text() # set name for file(s) if self.change_name_checkBox.isChecked(): name = str(self.change_name_lineEdit.text()) if name == '': name = 'video_finder_file' else: name = 'video_finder_file' # video finder always finds extension # but if it can't find file extension # use mp4 for extension. if str(self.extension_label.text()) == '': extension = '.mp4' else: extension = str(self.extension_label.text()) # did user select separate audio and video? if len(link_list) == 2: video_name = name + extension audio_name = name + '.' + \ str(self.no_video_list[self.audio_format_selection_comboBox.currentIndex() - 1]['ext']) name_list = [video_name, audio_name] else: name_list = [name + extension] # get number of connections connections = self.connections_spinBox.value() # get download_path download_path = self.download_folder_lineEdit.text() # referer if self.referer_lineEdit.text() != '': referer = self.referer_lineEdit.text() else: referer = None # header if self.header_lineEdit.text() != '': header = self.header_lineEdit.text() else: header = None # user_agent if self.user_agent_lineEdit.text() != '': user_agent = self.user_agent_lineEdit.text() else: user_agent = None # load_cookies if self.load_cookies_lineEdit.text() != '': load_cookies = self.load_cookies_lineEdit.text() else: load_cookies = None add_link_dictionary_list = [] if len(link_list) == 1: # save information in a dictionary(add_link_dictionary). add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[0], 'start_time': start_time, 'end_time': end_time, 'link': link_list[0], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } add_link_dictionary_list.append(add_link_dictionary) else: video_add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[0], 'start_time': start_time, 'end_time': end_time, 'link': link_list[0], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } audio_add_link_dictionary = { 'referer': referer, 'header': header, 'user_agent': user_agent, 'load_cookies': load_cookies, 'out': name_list[1], 'start_time': None, 'end_time': end_time, 'link': link_list[1], 'ip': ip, 'port': port, 'proxy_user': proxy_user, 'proxy_passwd': proxy_passwd, 'download_user': download_user, 'download_passwd': download_passwd, 'connections': connections, 'limit_value': limit, 'download_path': download_path } add_link_dictionary_list = [ video_add_link_dictionary, audio_add_link_dictionary ] # get category of download category = str(self.add_queue_comboBox.currentText()) del self.plugin_add_link_dictionary # return information to mainwindow self.callback(add_link_dictionary_list, download_later, category) # close window self.close()
class ImageDialog(QDialog): def __init__(self, src, dst): super(ImageDialog, self).__init__() self.set_up_ui(src, dst) self.open() def set_up_ui(self, src, dst): self.setWindowTitle('File Already exists') self.setFixedHeight(300) self.setFixedWidth(440) self.dst_dirname, self.dst_file = os.path.split(dst) self.dst_filename, self.dst_file_extension = os.path.splitext(self.dst_file) label_src_image = QLabel(self) label_src_image.setMinimumSize(180, 120) label_src_image.setAlignment(Qt.AlignCenter) label_dst_image = QLabel(self) label_dst_image.setMinimumSize(180, 120) label_dst_image.setAlignment(Qt.AlignCenter) self.display_image(label_src_image, src) self.display_image(label_dst_image, dst) str_format = "<p align='center'>Date : {} <br> size : {}</p>" src_date = datetime.fromtimestamp(os.path.getmtime(src)).ctime() src_size = self.convert_size(os.path.getsize(src)) src_info = str_format.format(src_date, src_size) dst_date = datetime.fromtimestamp(os.path.getmtime(src)).ctime() dst_size = self.convert_size(os.path.getsize(dst)) dst_info = str_format.format(dst_date, dst_size) frame = QFrame() frame.setFrameShape(QFrame.HLine) frame.setFrameShadow(QFrame.Sunken) # button box button_box = QDialogButtonBox() button_box.setOrientation(Qt.Horizontal) button_box.setStandardButtons(QDialogButtonBox.Cancel) self.button_rename = QPushButton('Rename') self.button_rename.clicked.connect(lambda: QDialog.done(self, 3)) button_box.addButton(self.button_rename, QDialogButtonBox.ApplyRole) self.button_overwrite = button_box.addButton('Overwrite', QDialogButtonBox.AcceptRole) button_box.rejected.connect(self.reject) button_box.accepted.connect(self.accept) # line edit self.edit_file_name = QLineEdit() self.edit_file_name.textChanged.connect(self.text_changed) self.edit_file_name.setText(os.path.basename(dst)) button_new_name = QPushButton('Suggest new name') layout_new_name = QHBoxLayout() layout_new_name.addWidget(self.edit_file_name) layout_new_name.addWidget(button_new_name) button_new_name.clicked.connect(lambda: self.sugest_new_name(dst)) self.grid = QGridLayout() # self.grid.setVerticalSpacing(10) self.grid.addWidget(QLabel('This action will overwrite the destination.'), 0, 0, 1, 2) self.grid.addWidget(QLabel('<b>Source</b>'), 1, 0, Qt.AlignHCenter) self.grid.addWidget(QLabel('<b>Destination</b>'), 1, 1, Qt.AlignHCenter) self.grid.addWidget(label_dst_image, 2, 0, Qt.AlignHCenter) self.grid.addWidget(label_src_image, 2, 1, Qt.AlignHCenter) self.grid.addWidget(QLabel(src_info), 3, 0, Qt.AlignHCenter) self.grid.addWidget(QLabel(dst_info), 3, 1, Qt.AlignHCenter) self.grid.addLayout(layout_new_name, 4, 0, 1, 2) self.grid.addWidget(frame, 6, 0, 1, 2) self.grid.addWidget(button_box, 7, 0, 1, 2) self.setLayout(self.grid) def display_image(self, label, file): image_reader = QImageReader(file) if image_reader.imageCount() > 1: movie = QMovie(file,) movie.setCacheMode(QMovie.CacheAll) movie.jumpToFrame(0) size = QSize(min(label.width(), label.height()), min(label.width(), label.height())) movie.setScaledSize(size) label.setMovie(movie) movie.start() else: label.setPixmap((QPixmap(file).scaled(label.size(), Qt.KeepAspectRatio))) def convert_size(self, size): if size == 0: return '0 B' size_name = ('B', 'KB', 'MB') i = int(floor(log(size, 1024))) p = pow(1024, i) s = round(size / p, 2) return '%s %s' % (s, size_name[i]) def sugest_new_name(self, dst): count = 0 while os.path.isfile(os.path.join(self.dst_dirname, os.path.basename(self.edit_file_name.text()))): count += 1 new_name = self.dst_filename + " ({})".format(count) + self.dst_file_extension self.edit_file_name.setText(new_name) def text_changed(self): if self.dst_file == self.edit_file_name.text(): self.button_rename.setEnabled(False) self.button_overwrite.setEnabled(True) else: self.button_rename.setEnabled(True) self.button_overwrite.setEnabled(False)
class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(1020, 588) self.actionSave = QAction(MainWindow) self.actionSave.setObjectName(u"actionSave") self.actionExit = QAction(MainWindow) self.actionExit.setObjectName(u"actionExit") self.actionExit_2 = QAction(MainWindow) self.actionExit_2.setObjectName(u"actionExit_2") self.openini = QAction(MainWindow) self.openini.setObjectName(u"openini") self.openjson = QAction(MainWindow) self.openjson.setObjectName(u"openjson") self.main_widget = QWidget(MainWindow) self.main_widget.setObjectName(u"main_widget") self.ini_widget = QWidget(self.main_widget) self.ini_widget.setObjectName(u"ini_widget") self.ini_widget.setGeometry(QRect(670, 10, 341, 551)) self.initable = QTableWidget(self.ini_widget) if (self.initable.columnCount() < 2): self.initable.setColumnCount(2) self.initable.setObjectName(u"initable") self.initable.setEnabled(True) self.initable.setGeometry(QRect(10, 60, 321, 451)) font = QFont() self.initable.setFont(font) self.initable.setEditTriggers(QAbstractItemView.DoubleClicked) self.initable.setDragEnabled(False) self.initable.setSelectionMode(QAbstractItemView.ExtendedSelection) self.initable.setSelectionBehavior(QAbstractItemView.SelectRows) self.initable.setWordWrap(False) self.initable.setRowCount(0) self.initable.setColumnCount(2) self.initable.horizontalHeader().setDefaultSectionSize(110) self.initable.horizontalHeader().setProperty("showSortIndicator", False) self.initable.horizontalHeader().setStretchLastSection(True) self.initable.verticalHeader().setDefaultSectionSize(21) self.inilabel = QLabel(self.ini_widget) self.inilabel.setObjectName(u"inilabel") self.inilabel.setGeometry(QRect(10, 10, 181, 16)) self.inipath = QTextBrowser(self.ini_widget) self.inipath.setObjectName(u"inipath") self.inipath.setEnabled(True) self.inipath.setGeometry(QRect(10, 30, 321, 22)) self.inipath.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.iniapply = QPushButton(self.ini_widget) self.iniapply.setObjectName(u"iniapply") self.iniapply.setEnabled(True) self.iniapply.setGeometry(QRect(250, 520, 80, 21)) self.inidel = QPushButton(self.ini_widget) self.inidel.setObjectName(u"inidel") self.inidel.setEnabled(False) self.inidel.setGeometry(QRect(10, 520, 80, 21)) self.iniadd = QPushButton(self.ini_widget) self.iniadd.setObjectName(u"iniadd") self.iniadd.setEnabled(False) self.iniadd.setGeometry(QRect(100, 520, 80, 21)) self.json_widget = QWidget(self.main_widget) self.json_widget.setObjectName(u"json_widget") self.json_widget.setGeometry(QRect(0, 10, 661, 551)) self.checkBox = QCheckBox(self.json_widget) self.checkBox.setObjectName(u"checkBox") self.checkBox.setEnabled(True) self.checkBox.setGeometry(QRect(20, 100, 131, 20)) self.checkBox.setChecked(True) self.delentry = QPushButton(self.json_widget) self.delentry.setObjectName(u"delentry") self.delentry.setEnabled(False) self.delentry.setGeometry(QRect(10, 520, 80, 21)) self.remote = QLineEdit(self.json_widget) self.remote.setObjectName(u"remote") self.remote.setEnabled(True) self.remote.setGeometry(QRect(20, 130, 601, 22)) self.textBrowser = QTextBrowser(self.json_widget) self.textBrowser.setObjectName(u"textBrowser") self.textBrowser.setEnabled(True) self.textBrowser.setGeometry(QRect(20, 30, 601, 22)) self.textBrowser.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.addButton = QPushButton(self.json_widget) self.addButton.setObjectName(u"addButton") self.addButton.setEnabled(True) self.addButton.setGeometry(QRect(280, 160, 61, 22)) self.table = QTableWidget(self.json_widget) if (self.table.columnCount() < 2): self.table.setColumnCount(2) self.table.setObjectName(u"table") self.table.setEnabled(True) self.table.setGeometry(QRect(10, 200, 641, 311)) self.table.setFont(font) self.table.setEditTriggers(QAbstractItemView.DoubleClicked) self.table.setDragEnabled(False) self.table.setSelectionMode(QAbstractItemView.ExtendedSelection) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setWordWrap(False) self.table.setRowCount(0) self.table.setColumnCount(2) self.table.horizontalHeader().setDefaultSectionSize(80) self.table.horizontalHeader().setProperty("showSortIndicator", False) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setDefaultSectionSize(21) self.path = QLineEdit(self.json_widget) self.path.setObjectName(u"path") self.path.setEnabled(True) self.path.setGeometry(QRect(20, 70, 531, 22)) self.apply = QPushButton(self.json_widget) self.apply.setObjectName(u"apply") self.apply.setEnabled(True) self.apply.setGeometry(QRect(570, 520, 80, 21)) self.label = QLabel(self.json_widget) self.label.setObjectName(u"label") self.label.setGeometry(QRect(20, 10, 181, 16)) self.browse = QPushButton(self.json_widget) self.browse.setObjectName(u"browse") self.browse.setGeometry(QRect(560, 70, 61, 22)) MainWindow.setCentralWidget(self.main_widget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 1020, 19)) self.File = QMenu(self.menubar) self.File.setObjectName(u"File") self.menuOpen = QMenu(self.File) self.menuOpen.setObjectName(u"menuOpen") MainWindow.setMenuBar(self.menubar) self.menubar.addAction(self.File.menuAction()) self.File.addAction(self.menuOpen.menuAction()) self.File.addAction(self.actionSave) self.File.addSeparator() self.File.addAction(self.actionExit_2) self.menuOpen.addAction(self.openini) self.menuOpen.addAction(self.openjson) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle( QCoreApplication.translate("MainWindow", u"frii-config", None)) self.actionSave.setText( QCoreApplication.translate("MainWindow", u"Save", None)) self.actionExit.setText( QCoreApplication.translate("MainWindow", u"Exit", None)) self.actionExit_2.setText( QCoreApplication.translate("MainWindow", u"Exit", None)) self.openini.setText( QCoreApplication.translate("MainWindow", u"Main config (frii_update.ini)", None)) self.openjson.setText( QCoreApplication.translate("MainWindow", u"Repository information (info.json)", None)) self.inilabel.setText( QCoreApplication.translate("MainWindow", u"Configuration (frii_update.ini)", None)) self.iniapply.setText( QCoreApplication.translate("MainWindow", u"Save", None)) self.inidel.setText( QCoreApplication.translate("MainWindow", u"Delete", None)) self.iniadd.setText( QCoreApplication.translate("MainWindow", u"Insert", None)) self.checkBox.setText( QCoreApplication.translate("MainWindow", u"Clone repository", None)) self.delentry.setText( QCoreApplication.translate("MainWindow", u"Delete", None)) self.remote.setText( QCoreApplication.translate("MainWindow", u"Enter repository URL here", None)) self.addButton.setText( QCoreApplication.translate("MainWindow", u"Next", None)) self.path.setText( QCoreApplication.translate("MainWindow", u"Enter repository path here", None)) self.apply.setText( QCoreApplication.translate("MainWindow", u"Save", None)) self.label.setText( QCoreApplication.translate("MainWindow", u"Saved Information (info.json)", None)) self.browse.setText( QCoreApplication.translate("MainWindow", u"Browse", None)) self.File.setTitle( QCoreApplication.translate("MainWindow", u"File", None)) self.menuOpen.setTitle( QCoreApplication.translate("MainWindow", u"Open", None))
class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.items = 0 # Example data self._data = { "Water": 24.5, "Electricity": 55.1, "Rent": 850.0, "Supermarket": 230.4, "Internet": 29.99, "Spätkauf": 21.85, "BVG Ticket": 60.0, "Coffee": 22.45, "Meetup": 0.0 } # Left self.table = QTableWidget() self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(["Description", "Quantity"]) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # Chart self.chart_view = QChartView() self.chart_view.setRenderHint(QPainter.Antialiasing) # Right self.description = QLineEdit() self.quantity = QLineEdit() self.add = QPushButton("Add") self.clear = QPushButton("Clear") self.quit = QPushButton("Quit") self.plot = QPushButton("Plot") # Disabling 'Add' button self.add.setEnabled(False) self.right = QVBoxLayout() self.right.setContentsMargins(10, 10, 10, 10) self.right.addWidget(QLabel("Description")) self.right.addWidget(self.description) self.right.addWidget(QLabel("Quantity")) self.right.addWidget(self.quantity) self.right.addWidget(self.add) self.right.addWidget(self.plot) self.right.addWidget(self.chart_view) self.right.addWidget(self.clear) self.right.addWidget(self.quit) # QWidget Layout self.layout = QHBoxLayout() self.layout.addWidget(self.table) self.layout.addLayout(self.right) # Set the layout to the QWidget self.setLayout(self.layout) # Signals and Slots self.add.clicked.connect(self.add_element) self.quit.clicked.connect(self.quit_application) self.plot.clicked.connect(self.plot_data) self.clear.clicked.connect(self.clear_table) self.description.textChanged[str].connect(self.check_disable) self.quantity.textChanged[str].connect(self.check_disable) # Fill example data self.fill_table() @Slot() def add_element(self): des = self.description.text() qty = self.quantity.text() self.table.insertRow(self.items) self.table.setItem(self.items, 0, QTableWidgetItem(des)) self.table.setItem(self.items, 1, QTableWidgetItem(qty)) self.description.setText("") self.quantity.setText("") self.items += 1 @Slot() def check_disable(self, s): if not self.description.text() or not self.quantity.text(): self.add.setEnabled(False) else: self.add.setEnabled(True) @Slot() def plot_data(self): # Get table information series = QPieSeries() for i in range(self.table.rowCount()): text = self.table.item(i, 0).text() number = float(self.table.item(i, 1).text()) series.append(text, number) chart = QChart() chart.addSeries(series) chart.legend().setAlignment(Qt.AlignLeft) self.chart_view.setChart(chart) @Slot() def quit_application(self): QApplication.quit() def fill_table(self, data=None): data = self._data if not data else data for desc, price in data.items(): self.table.insertRow(self.items) self.table.setItem(self.items, 0, QTableWidgetItem(desc)) self.table.setItem(self.items, 1, QTableWidgetItem(str(price))) self.items += 1 @Slot() def clear_table(self): self.table.setRowCount(0) self.items = 0
class UIDeleteROIWindow(): def setup_ui(self, delete_roi_window_instance, regions_of_interest, dataset_rtss, deleting_rois_structure_tuple): # Initialise the 2 lists for containing the ROI(s) that we are going to keep and delete respectively self.regions_of_interest_to_keep = [] self.regions_of_interest_to_delete = [] # This is for holding the original list of ROI(s) self.regions_of_interest_list = regions_of_interest # This is for holding the DICOM dataset of that specific patient self.dataset_rtss = dataset_rtss # Assigning new tuple for holding the deleting ROI(s) self.deleting_rois_structure_tuple = deleting_rois_structure_tuple # Initialise a DeleteROIWindow if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) delete_roi_window_instance.setObjectName("DeleteRoiWindowInstance") delete_roi_window_instance.setWindowIcon(window_icon) delete_roi_window_instance.resize(800, 606) # Create a vertical box to hold all widgets self.delete_roi_window_instance_vertical_box = QVBoxLayout() self.delete_roi_window_instance_vertical_box.setObjectName( "DeleteRoiWindowInstanceVerticalBox") # Create a label for holding the window's title self.delete_roi_window_title = QLabel() self.delete_roi_window_title.setObjectName("DeleteRoiWindowTitle") self.delete_roi_window_title.setProperty("QLabelClass", "window-title") self.delete_roi_window_title.setAlignment(Qt.AlignLeft) self.delete_roi_window_instance_vertical_box.addWidget( self.delete_roi_window_title) # Create a label for holding the instruction of how to delete the ROIs self.delete_roi_window_instruction = QLabel() self.delete_roi_window_instruction.setObjectName( "DeleteRoiWindowInstruction") self.delete_roi_window_instruction.setAlignment(Qt.AlignCenter) self.delete_roi_window_instance_vertical_box.addWidget( self.delete_roi_window_instruction) # Create a horizontal box for holding the 2 lists and the move left, move right buttons self.delete_roi_window_keep_and_delete_box = QHBoxLayout() self.delete_roi_window_keep_and_delete_box.setObjectName( "DeleteRoiWindowKeepAndDeleteBox") # ================================= KEEP BOX ================================= # Create a vertical box for holding the label and the tree view for holding the ROIs that we are keeping self.delete_roi_window_keep_vertical_box = QVBoxLayout() self.delete_roi_window_keep_vertical_box.setObjectName( "DeleteRoiWindowKeepVerticalBox") # Create a label for the tree view with the list of ROIs to keep self.delete_roi_window_keep_tree_view_label = QLabel() self.delete_roi_window_keep_tree_view_label.setObjectName( "DeleteRoiWindowKeepTreeViewLabel") self.delete_roi_window_keep_tree_view_label.setProperty( "QLabelClass", ["tree-view-label", "tree-view-label-keep-delete"]) self.delete_roi_window_keep_tree_view_label.setAlignment( Qt.AlignCenter) self.delete_roi_window_keep_tree_view_label.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_keep_tree_view_label.resize( self.delete_roi_window_keep_tree_view_label.sizeHint().width(), self.delete_roi_window_keep_tree_view_label.sizeHint().height()) self.delete_roi_window_keep_vertical_box.addWidget( self.delete_roi_window_keep_tree_view_label) # Create a tree view for containing the list of ROIs to keep self.delete_roi_window_keep_tree_view = QTreeWidget() self.delete_roi_window_keep_tree_view.setObjectName( "DeleteRoiWindowKeepTreeView") self.delete_roi_window_keep_tree_view.setHeaderHidden(True) self.delete_roi_window_keep_tree_view.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_keep_tree_view.resize( self.delete_roi_window_keep_tree_view.sizeHint().width(), self.delete_roi_window_keep_tree_view.sizeHint().height()) self.delete_roi_window_keep_vertical_box.addWidget( self.delete_roi_window_keep_tree_view) self.delete_roi_window_keep_vertical_box.setStretch(1, 4) # Create a widget to hold the keep vertical box self.delete_roi_window_keep_widget = QWidget() self.delete_roi_window_keep_widget.setObjectName( "DeleteRoiWindowKeepWidget") self.delete_roi_window_keep_widget.setLayout( self.delete_roi_window_keep_vertical_box) self.delete_roi_window_keep_and_delete_box.addStretch(1) self.delete_roi_window_keep_and_delete_box.addWidget( self.delete_roi_window_keep_widget) # ================================= KEEP BOX ================================= # ================================= MOVE LEFT/RIGHT BOX ================================= # Create a vertical box for holding the 2 buttons for moving left and right self.delete_roi_window_move_left_right_vertical_box = QVBoxLayout() self.delete_roi_window_move_left_right_vertical_box.setObjectName( "DeleteRoiWindowMoveLeftRightVerticalBox") # Create Move Right Button / Delete Button self.move_right_button = QPushButton() self.move_right_button.setObjectName("MoveRightButton") self.move_right_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.move_right_button.resize( self.move_right_button.sizeHint().width(), self.move_right_button.sizeHint().height()) self.move_right_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.move_right_button.clicked.connect( self.move_right_button_onClicked) self.move_right_button.setProperty("QPushButtonClass", "fail-button") self.delete_roi_window_move_left_right_vertical_box.addStretch(1) self.delete_roi_window_move_left_right_vertical_box.addWidget( self.move_right_button) # Create Move Left Button / Keep Button self.move_left_button = QPushButton() self.move_left_button.setObjectName("MoveLeftButton") self.move_left_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.move_left_button.resize(self.move_left_button.sizeHint().width(), self.move_left_button.sizeHint().height()) self.move_left_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.move_left_button.clicked.connect(self.move_left_button_onClicked) self.move_left_button.setProperty("QPushButtonClass", "success-button") self.delete_roi_window_move_left_right_vertical_box.addWidget( self.move_left_button) self.delete_roi_window_move_left_right_vertical_box.addStretch(1) # Create a widget for holding the 2 buttons self.delete_roi_window_move_left_right_widget = QWidget() self.delete_roi_window_move_left_right_widget.setObjectName( "DeleteRoiWindowMoveLeftRightWidget") self.delete_roi_window_move_left_right_widget.setLayout( self.delete_roi_window_move_left_right_vertical_box) self.delete_roi_window_keep_and_delete_box.addWidget( self.delete_roi_window_move_left_right_widget) # ================================= MOVE LEFT/RIGHT BOX ================================= # ================================= DELETE BOX ================================= # Create a vertical box for holding the label and the tree view for holding the ROIs that we are deleting self.delete_roi_window_delete_vertical_box = QVBoxLayout() self.delete_roi_window_delete_vertical_box.setObjectName( "DeleteRoiWindowDeleteVerticalBox") # Create a label for the tree view with the list of ROIs to delete self.delete_roi_window_delete_tree_view_label = QLabel() self.delete_roi_window_delete_tree_view_label.setObjectName( "DeleteRoiWindowDeleteTreeViewLabel") self.delete_roi_window_delete_tree_view_label.setProperty( "QLabelClass", ["tree-view-label", "tree-view-label-keep-delete"]) self.delete_roi_window_delete_tree_view_label.setAlignment( Qt.AlignCenter) self.delete_roi_window_delete_tree_view_label.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_delete_tree_view_label.resize( self.delete_roi_window_delete_tree_view_label.sizeHint().width(), self.delete_roi_window_delete_tree_view_label.sizeHint().height()) self.delete_roi_window_delete_vertical_box.addWidget( self.delete_roi_window_delete_tree_view_label) # Create a tree view for containing the list of ROIs to delete self.delete_roi_window_delete_tree_view = QTreeWidget() self.delete_roi_window_delete_tree_view.setObjectName( "DeleteRoiWindowDeleteTreeView") self.delete_roi_window_delete_tree_view.setHeaderHidden(True) self.delete_roi_window_delete_tree_view.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_delete_tree_view.resize( self.delete_roi_window_delete_tree_view.sizeHint().width(), self.delete_roi_window_delete_tree_view.sizeHint().height()) self.delete_roi_window_delete_vertical_box.addWidget( self.delete_roi_window_delete_tree_view) self.delete_roi_window_delete_vertical_box.setStretch(1, 4) # Create a widget to hold the delete vertical box self.delete_roi_window_delete_widget = QWidget() self.delete_roi_window_delete_widget.setObjectName( "DeleteRoiWindowDeleteWidget") self.delete_roi_window_delete_widget.setLayout( self.delete_roi_window_delete_vertical_box) self.delete_roi_window_keep_and_delete_box.addWidget( self.delete_roi_window_delete_widget) self.delete_roi_window_keep_and_delete_box.addStretch(1) self.delete_roi_window_keep_and_delete_box.setStretch(1, 4) self.delete_roi_window_keep_and_delete_box.setStretch(3, 4) # ================================= DELETE BOX ================================= # Create a widget to hold the keep and delete box self.delete_roi_window_keep_and_delete_widget = QWidget() self.delete_roi_window_keep_and_delete_widget.setObjectName( "DeleteRoiWindowKeepAndDeleteWidget") self.delete_roi_window_keep_and_delete_widget.setLayout( self.delete_roi_window_keep_and_delete_box) self.delete_roi_window_instance_vertical_box.addWidget( self.delete_roi_window_keep_and_delete_widget) # Create a horizontal box to hold 2 action buttons for this window self.delete_roi_window_action_buttons_box = QHBoxLayout() self.delete_roi_window_action_buttons_box.setObjectName( "DeleteRoiWindowActionButtonsBox") # Create the cancel button self.delete_roi_window_cancel_button = QPushButton() self.delete_roi_window_cancel_button.setObjectName( "DeleteRoiWindowCancelButton") self.delete_roi_window_cancel_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_cancel_button.resize( self.delete_roi_window_cancel_button.sizeHint().width(), self.delete_roi_window_cancel_button.sizeHint().height()) self.delete_roi_window_cancel_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.delete_roi_window_cancel_button.clicked.connect( self.on_cancel_button_clicked) self.delete_roi_window_cancel_button.setProperty( "QPushButtonClass", "fail-button") self.delete_roi_window_action_buttons_box.addStretch(1) self.delete_roi_window_action_buttons_box.addWidget( self.delete_roi_window_cancel_button) # Create the confirm button self.delete_roi_window_confirm_button = QPushButton() self.delete_roi_window_confirm_button.setObjectName( "DeleteRoiWindowConfirmButton") self.delete_roi_window_confirm_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_confirm_button.resize( self.delete_roi_window_confirm_button.sizeHint().width(), self.delete_roi_window_confirm_button.sizeHint().height()) self.delete_roi_window_confirm_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.delete_roi_window_confirm_button.clicked.connect( self.confirm_button_onClicked) self.delete_roi_window_confirm_button.setEnabled(False) self.delete_roi_window_confirm_button.setProperty( "QPushButtonClass", "success-button") self.delete_roi_window_action_buttons_box.addWidget( self.delete_roi_window_confirm_button) # Create a widget to hold the action buttons self.delete_roi_window_action_buttons_widget = QWidget() self.delete_roi_window_action_buttons_widget.setObjectName( "DeleteRoiWindowActionButtonsWidget") self.delete_roi_window_action_buttons_widget.setLayout( self.delete_roi_window_action_buttons_box) self.delete_roi_window_instance_vertical_box.addWidget( self.delete_roi_window_action_buttons_widget) # Set text for all attributes self.retranslate_ui(delete_roi_window_instance) # Create a central widget to hold the vertical layout box self.delete_roi_window_instance_central_widget = QWidget() self.delete_roi_window_instance_central_widget.setObjectName( "DeleteRoiWindowInstanceCentralWidget") self.delete_roi_window_instance_central_widget.setLayout( self.delete_roi_window_instance_vertical_box) self.delete_roi_window_instance_vertical_box.setStretch(2, 4) # Set the central widget for the main window and style the window delete_roi_window_instance.setCentralWidget( self.delete_roi_window_instance_central_widget) delete_roi_window_instance.setStyleSheet(stylesheet) # Load the ROIs in self.display_rois_in_listViewKeep() # Set the selection mode to multi so that we can select multiple ROIs to delete self.delete_roi_window_keep_tree_view.setSelectionMode( QAbstractItemView.MultiSelection) self.delete_roi_window_delete_tree_view.setSelectionMode( QAbstractItemView.MultiSelection) QtCore.QMetaObject.connectSlotsByName(delete_roi_window_instance) def retranslate_ui(self, delete_roi_window_instance): _translate = QtCore.QCoreApplication.translate delete_roi_window_instance.setWindowTitle( _translate("DeleteRoiWindowInstance", "OnkoDICOM - Delete ROI(s)")) self.delete_roi_window_title.setText( _translate("DeleteRoiWindowTitle", "Delete ROI(s)")) self.delete_roi_window_instruction.setText( _translate( "DeleteRoiWindowInstruction", "Move the Regions of Interest to be deleted to the right-hand side or vice versa" )) self.delete_roi_window_keep_tree_view_label.setText( _translate("DeleteRoiWindowKeepTreeViewLabel", "To Keep")) self.delete_roi_window_delete_tree_view_label.setText( _translate("DeleteRoiWindowDeleteTreeViewLabel", "To Delete")) self.move_right_button.setText( _translate("MoveRightButton", "Move Right ->>>")) self.move_left_button.setText( _translate("MoveLeftButton", "<<<- Move Left")) self.delete_roi_window_cancel_button.setText( _translate("DeleteRoiWindowCancelButton", "Cancel")) self.delete_roi_window_confirm_button.setText( _translate("DeleteRoiWindowConfirmButton", "Confirm")) def on_cancel_button_clicked(self): self.close() def display_rois_in_listViewKeep(self): self.regions_of_interest_to_keep.clear() for roi_id, roi_dict in self.regions_of_interest_list.items(): self.regions_of_interest_to_keep.append(roi_dict['name']) self.delete_roi_window_keep_tree_view.clear() self.delete_roi_window_keep_tree_view.setIndentation(0) self.item = QTreeWidgetItem(["item"]) for index in self.regions_of_interest_to_keep: item = QTreeWidgetItem([index]) self.delete_roi_window_keep_tree_view.addTopLevelItem(item) def move_right_button_onClicked(self): root_item = self.delete_roi_window_keep_tree_view.invisibleRootItem() for index in range(root_item.childCount()): item = root_item.child(index) if item in self.delete_roi_window_keep_tree_view.selectedItems(): # This will get ROI name self.regions_of_interest_to_delete.append(item.text(0)) # Move to the right column list self.delete_roi_window_delete_tree_view.clear() self.delete_roi_window_delete_tree_view.setIndentation(0) for roi in self.regions_of_interest_to_delete: item = QTreeWidgetItem([roi]) self.delete_roi_window_delete_tree_view.addTopLevelItem(item) self.delete_roi_window_confirm_button.setEnabled(True) # Delete moved items from the left column list self.regions_of_interest_to_keep = [ x for x in self.regions_of_interest_to_keep if x not in self.regions_of_interest_to_delete ] self.delete_roi_window_keep_tree_view.clear() for index in self.regions_of_interest_to_keep: item = QTreeWidgetItem([index]) self.delete_roi_window_keep_tree_view.addTopLevelItem(item) def move_left_button_onClicked(self): root_item = self.delete_roi_window_delete_tree_view.invisibleRootItem() for index in range(root_item.childCount()): item = root_item.child(index) if item in self.delete_roi_window_delete_tree_view.selectedItems(): # This will get ROI name self.regions_of_interest_to_keep.append(item.text(0)) # Move to the left column list self.delete_roi_window_keep_tree_view.clear() self.delete_roi_window_keep_tree_view.setIndentation(0) for roi in self.regions_of_interest_to_keep: item = QTreeWidgetItem([roi]) self.delete_roi_window_keep_tree_view.addTopLevelItem(item) # Delete moved items from the right column list self.regions_of_interest_to_delete = [ x for x in self.regions_of_interest_to_delete if x not in self.regions_of_interest_to_keep ] self.delete_roi_window_delete_tree_view.clear() for index in self.regions_of_interest_to_delete: item = QTreeWidgetItem([index]) self.delete_roi_window_delete_tree_view.addTopLevelItem(item) if len(self.regions_of_interest_to_delete) == 0: self.delete_roi_window_confirm_button.setEnabled(False) def confirm_button_onClicked(self): confirmation_dialog = QMessageBox.information( self, 'Delete ROI(s)?', 'Region(s) of Interest in the To Delete table will be deleted. ' 'Would you like to continue?', QMessageBox.Yes | QMessageBox.No) if confirmation_dialog == QMessageBox.Yes: progress_window = DeleteROIProgressWindow( self, QtCore.Qt.WindowTitleHint) progress_window.signal_roi_deleted.connect(self.on_rois_deleted) progress_window.start_deleting(self.dataset_rtss, self.regions_of_interest_to_delete) progress_window.show() def on_rois_deleted(self, new_rtss): self.deleting_rois_structure_tuple.emit((new_rtss, { "delete": self.regions_of_interest_to_delete })) QMessageBox.about(self, "Saved", "Regions of interest successfully deleted!") self.close()
class UIImageFusionWindow(object): image_fusion_info_initialized = QtCore.Signal(object) def setup_ui(self, open_image_fusion_select_instance): """Sets up a UI""" if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) open_image_fusion_select_instance.setObjectName( "OpenPatientWindowInstance") open_image_fusion_select_instance.setWindowIcon(window_icon) open_image_fusion_select_instance.resize(840, 530) # Create a vertical box for containing the other elements and layouts self.open_patient_window_instance_vertical_box = QVBoxLayout() self.open_patient_window_instance_vertical_box.setObjectName( "OpenPatientWindowInstanceVerticalBox") # Create a label to prompt the user to enter the path to the # directory that contains the DICOM files self.open_patient_directory_prompt = QLabel() self.open_patient_directory_prompt.setObjectName( "OpenPatientDirectoryPrompt") self.open_patient_directory_prompt.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_prompt) # Create a horizontal box to hold the input box for the directory # and the choose button self.open_patient_directory_input_horizontal_box = QHBoxLayout() self.open_patient_directory_input_horizontal_box.setObjectName( "OpenPatientDirectoryInputHorizontalBox") # Create a textbox to contain the path to the directory that contains # the DICOM files self.open_patient_directory_input_box = \ UIImageFusionWindowDragAndDropEvent(self) self.open_patient_directory_input_box.setObjectName( "OpenPatientDirectoryInputBox") self.open_patient_directory_input_box.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_input_box.returnPressed.connect( self.scan_directory_for_patient) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_input_box) # Create a choose button to open the file dialog self.open_patient_directory_choose_button = QPushButton() self.open_patient_directory_choose_button.setObjectName( "OpenPatientDirectoryChooseButton") self.open_patient_directory_choose_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_choose_button.resize( self.open_patient_directory_choose_button.sizeHint().width(), self.open_patient_directory_input_box.height()) self.open_patient_directory_choose_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_choose_button) self.open_patient_directory_choose_button.clicked.connect( self.choose_button_clicked) # Create a widget to hold the input fields self.open_patient_directory_input_widget = QWidget() self.open_patient_directory_input_horizontal_box.setStretch(0, 4) self.open_patient_directory_input_widget.setLayout( self.open_patient_directory_input_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_input_widget) # Create a horizontal box to hold the stop button and direction to # the user on where to select the patient self.open_patient_appear_prompt_and_stop_horizontal_box = QHBoxLayout() self.open_patient_appear_prompt_and_stop_horizontal_box.setObjectName( "OpenPatientAppearPromptAndStopHorizontalBox") # Create a label to show direction on where the files will appear self.open_patient_directory_appear_prompt = QLabel() self.open_patient_directory_appear_prompt.setObjectName( "OpenPatientDirectoryAppearPrompt") self.open_patient_directory_appear_prompt.setAlignment(Qt.AlignLeft) self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_directory_appear_prompt) self.open_patient_appear_prompt_and_stop_horizontal_box.addStretch(1) # Create a button to stop searching self.open_patient_window_stop_button = QPushButton() self.open_patient_window_stop_button.setObjectName( "OpenPatientWindowStopButton") self.open_patient_window_stop_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_stop_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_stop_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_stop_button.clicked.connect( self.stop_button_clicked) self.open_patient_window_stop_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_stop_button.setVisible(False) self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_window_stop_button) # Create a widget to hold the layout self.open_patient_appear_prompt_and_stop_widget = QWidget() self.open_patient_appear_prompt_and_stop_widget.setLayout( self.open_patient_appear_prompt_and_stop_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_appear_prompt_and_stop_widget) # Create a tree view list to list out all patients in the directory # selected above self.open_patient_window_patients_tree = QTreeWidget() self.open_patient_window_patients_tree.setObjectName( "OpenPatientWindowPatientsTree") self.open_patient_window_patients_tree.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_patients_tree.resize( self.open_patient_window_patients_tree.sizeHint().width(), self.open_patient_window_patients_tree.sizeHint().height()) self.open_patient_window_patients_tree.setHeaderHidden(False) self.open_patient_window_patients_tree.setHeaderLabels([""]) self.open_patient_window_patients_tree.itemChanged.connect( self.tree_item_clicked) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patients_tree) self.last_patient = None # Create a label to show what would happen if they select the patient self.open_patient_directory_result_label = QtWidgets.QLabel() self.open_patient_directory_result_label.setObjectName( "OpenPatientDirectoryResultLabel") self.open_patient_directory_result_label.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_result_label) # Create a horizontal box to hold the Cancel and Open button self.open_patient_window_patient_open_actions_horizontal_box = \ QHBoxLayout() self.open_patient_window_patient_open_actions_horizontal_box. \ setObjectName("OpenPatientWindowPatientOpenActionsHorizontalBox") self.open_patient_window_patient_open_actions_horizontal_box. \ addStretch(1) # Add a button to go back/close from the application self.open_patient_window_close_button = QPushButton() self.open_patient_window_close_button.setObjectName( "OpenPatientWindowcloseButton") self.open_patient_window_close_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_close_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_close_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_close_button.clicked.connect( self.close_button_clicked) self.open_patient_window_close_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_patient_open_actions_horizontal_box. \ addWidget(self.open_patient_window_close_button) # Add a button to confirm opening of the patient self.open_patient_window_confirm_button = QPushButton() self.open_patient_window_confirm_button.setObjectName( "OpenPatientWindowConfirmButton") self.open_patient_window_confirm_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_confirm_button.resize( self.open_patient_window_confirm_button.sizeHint().width(), self.open_patient_window_confirm_button.sizeHint().height()) self.open_patient_window_confirm_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_confirm_button.setDisabled(True) self.open_patient_window_confirm_button.clicked.connect( self.confirm_button_clicked) self.open_patient_window_confirm_button.setProperty( "QPushButtonClass", "success-button") self.open_patient_window_patient_open_actions_horizontal_box. \ addWidget( self.open_patient_window_confirm_button) # Create a widget to house all of the actions button for open patient # window self.open_patient_window_patient_open_actions_widget = QWidget() self.open_patient_window_patient_open_actions_widget.setLayout( self.open_patient_window_patient_open_actions_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patient_open_actions_widget) # Set the vertical box fourth element, the tree view, to stretch # out as far as possible self.open_patient_window_instance_vertical_box.setStretch(3, 4) self.open_patient_window_instance_central_widget = QWidget() self.open_patient_window_instance_central_widget.setObjectName( "OpenPatientWindowInstanceCentralWidget") self.open_patient_window_instance_central_widget.setLayout( self.open_patient_window_instance_vertical_box) # Create threadpool for multithreading self.threadpool = QThreadPool() # print("Multithreading with maximum %d threads" % self.threadpool. # maxThreadCount()) # Create interrupt event for stopping the directory search self.interrupt_flag = threading.Event() # Bind all texts into the buttons and labels self.retranslate_ui(open_image_fusion_select_instance) # Set the central widget, ready for display open_image_fusion_select_instance.setCentralWidget( self.open_patient_window_instance_central_widget) # Set the current stylesheet to the instance and connect it back # to the caller through slot _stylesheet = open(resource_path(self.stylesheet_path)).read() open_image_fusion_select_instance.setStyleSheet(_stylesheet) QtCore.QMetaObject.connectSlotsByName( open_image_fusion_select_instance) def retranslate_ui(self, open_image_fusion_select_instance): """Translates UI""" _translate = QtCore.QCoreApplication.translate open_image_fusion_select_instance.setWindowTitle( _translate("OpenPatientWindowInstance", "OnkoDICOM - Select Patient")) self.open_patient_directory_prompt.setText(_translate( "OpenPatientWindowInstance", "Choose an image to merge with:")) self.open_patient_directory_input_box.setPlaceholderText( _translate("OpenPatientWindowInstance", "Enter DICOM Files Path (For example, " "C:\path\\to\your\DICOM\Files)")) self.open_patient_directory_choose_button.setText(_translate( "OpenPatientWindowInstance", "Choose")) self.open_patient_directory_appear_prompt.setText(_translate( "OpenPatientWindowInstance", "Please select below the image set you wish to overlay:")) self.open_patient_directory_result_label. \ setText("The selected imageset(s) above will be " "co-registered with the current imageset.") self.open_patient_window_stop_button.setText(_translate( "OpenPatientWindowInstance", "Stop Search")) self.open_patient_window_close_button.setText(_translate( "OpenPatientWindowInstance", "Close")) self.open_patient_window_confirm_button.setText(_translate( "OpenPatientWindowInstance", "Confirm")) def update_patient(self): self.clear_checked_leaves() self.patient_dict_container = PatientDictContainer() self.patient = self.patient_dict_container.get("basic_info") self.patient_id = self.patient['id'] dataset = self.patient_dict_container.dataset[0] self.patient_current_image_series_uid = \ dataset.get("SeriesInstanceUID") def clear_checked_leaves(self): """ Resets all leaves to their unchecked state """ def recurse(parent_item: QTreeWidgetItem): for i in range(parent_item.childCount()): child = parent_item.child(i) grand_children = child.childCount() if grand_children > 0: recurse(child) else: if child.checkState(0) == Qt.Checked: child.setCheckState(0, Qt.CheckState.Unchecked) child.setSelected(False) recurse(self.open_patient_window_patients_tree.invisibleRootItem()) self.open_patient_window_patients_tree.collapseAll() def close_button_clicked(self): """Closes the window.""" self.close() def scan_directory_for_patient(self): # Reset tree view header and last patient self.open_patient_window_confirm_button.setDisabled(True) self.open_patient_window_patients_tree.setHeaderLabels([""]) self.last_patient = None self.filepath = self.open_patient_directory_input_box.text() # Proceed if a folder was selected if self.filepath != "": # Update the QTreeWidget to reflect data being loaded # First, clear the widget of any existing data self.open_patient_window_patients_tree.clear() # Next, update the tree widget self.open_patient_window_patients_tree.addTopLevelItem( QTreeWidgetItem(["Loading selected directory..."])) # The choose button is disabled until the thread finishes executing self.open_patient_directory_choose_button.setEnabled(False) # Reveals the Stop Search button for the duration of the search self.open_patient_window_stop_button.setVisible(True) # The interrupt flag is then un-set if a previous search has been # stopped. self.interrupt_flag.clear() # Then, create a new thread that will load the selected folder worker = Worker(DICOMDirectorySearch.get_dicom_structure, self.filepath, self.interrupt_flag, progress_callback=True) worker.signals.result.connect(self.on_search_complete) worker.signals.progress.connect(self.search_progress) # Execute the thread self.threadpool.start(worker) def choose_button_clicked(self): """ Executes when the choose button is clicked. Gets filepath from the user and loads all files and subdirectories. """ # Get folder path from pop up dialog box self.filepath = QtWidgets.QFileDialog.getExistingDirectory( None, 'Select patient folder...', '') self.open_patient_directory_input_box.setText(self.filepath) self.scan_directory_for_patient() def stop_button_clicked(self): self.interrupt_flag.set() def search_progress(self, progress_update): """ Current progress of the file search. """ self.open_patient_window_patients_tree.clear() self.open_patient_window_patients_tree.addTopLevelItem( QTreeWidgetItem(["Loading selected directory... " "(%s files searched)" % progress_update])) def on_search_complete(self, dicom_structure): """ Executes once the directory search is complete. :param dicom_structure: DICOMStructure object constructed by the directory search. """ self.open_patient_directory_choose_button.setEnabled(True) self.open_patient_window_stop_button.setVisible(False) self.open_patient_window_patients_tree.clear() # dicom_structure will be None if function was interrupted. if dicom_structure is None: return for patient_item in dicom_structure.get_tree_items_list(): self.open_patient_window_patients_tree.addTopLevelItem( patient_item) patient_item.setExpanded(True) # Display all studies # Display all image sets for i in range(patient_item.childCount()): study = patient_item.child(i) study.setExpanded(True) if len(dicom_structure.patients) == 0: QMessageBox.about(self, "No files found", "Selected directory contains no DICOM files.") def tree_item_clicked(self, item, _): """ Executes when a tree item is checked or unchecked. If a different patient is checked, uncheck the previous patient. Inform user about missing DICOM files. """ # If patient is only selected, but not checked, set it to "focus" to # coincide with stylesheet. And if the selected item is an image set, # display its child branches. if item.checkState(0) == Qt.CheckState.Unchecked: self.open_patient_window_patients_tree.setCurrentItem(item) else: # Otherwise don't "focus", then set patient as selected self.open_patient_window_patients_tree.setCurrentItem(None) item.setSelected(True) # Expand or collapse the tree branch if item is an image series # Only collapse if the selected image series is expanded but unchecked # Otherwise, expand its tree branch to show RT files is_expanded = False \ if (item.isExpanded() is True and item.checkState(0) == Qt.CheckState.Unchecked) else True self.display_a_tree_branch(item, is_expanded) selected_patient = item # If the item is not top-level, bubble up to see which top-level item # this item belongs to if self.open_patient_window_patients_tree.invisibleRootItem(). \ indexOfChild(item) == -1: while self.open_patient_window_patients_tree.invisibleRootItem(). \ indexOfChild(selected_patient) == -1: selected_patient = selected_patient.parent() # Uncheck previous patient if a different patient is selected if item.checkState(0) == Qt.CheckState.Checked and self.last_patient \ != selected_patient: if self.last_patient is not None: last_patient_checked_items = self.get_checked_nodes( self.last_patient) for checked_item in last_patient_checked_items: checked_item.setCheckState(0, Qt.Unchecked) self.last_patient = selected_patient # Check selected items and display warning messages self.check_selected_items(selected_patient) def display_a_tree_branch(self, node, is_expanded): # TO DO: # Could Team 23 please update the defintion of this docstring as # well as same function presented in OpenPatientWindow. """ Displays a tree branch Parameters: node : root node the tree is_expanded (boolean): flag for checking if a particular node/leaf is expanded. """ node.setExpanded(is_expanded) if node.childCount() > 0: for i in range(node.childCount()): self.display_a_tree_branch(node.child(i), is_expanded) else: return def check_selected_items(self, selected_patient): """ Check and display warning messages based on the existence and quantity of image series, RTSTRUCT, RTPLAN, RTDOSE and SR files Parameters: selected_patient (DICOMStructure): DICOM Object of patient """ # Get the types of all selected leaves & Get the names of all selected # studies checked_nodes = self.get_checked_nodes( self.open_patient_window_patients_tree.invisibleRootItem()) selected_series_types = [checked_node.dicom_object.get_series_type() for checked_node in checked_nodes] selected_series_id = [checked_node.dicom_object.series_uid for checked_node in checked_nodes] # Total number of selected image series total_selected_image_series = selected_series_types.count('CT') + \ selected_series_types.count('MR') + \ selected_series_types.count('PT') # Check the existence of IMAGE, RTSTRUCT, RTPLAN and RTDOSE files proceed = True if total_selected_image_series < 1: header = "Cannot proceed without an image." proceed = False elif total_selected_image_series > 1: header = "Cannot proceed with more than 1 selected image." proceed = False elif selected_patient.dicom_object.patient_id.strip() != \ self.patient_id: header = "Cannot proceed with different patient." proceed = False elif self.patient_current_image_series_uid in selected_series_id: header = "Cannot fuse with the same series." proceed = False elif not self.check_selected_items_referencing(checked_nodes): # Check that selected items properly reference each other header = "Selected series do not reference each other." proceed = False elif 'RTSTRUCT' not in selected_series_types and \ self.check_existing_rtss(checked_nodes): header = "The associated RTSTRUCT must be selected." proceed = False elif 'RTDOSE' in selected_series_types: header = "Cannot fuse with a RTDOSE file." proceed = False else: header = "" self.open_patient_window_confirm_button.setDisabled(not proceed) # Set the tree header self.open_patient_window_patients_tree.setHeaderLabel(header) def check_selected_items_referencing(self, items): """ Check if selected tree items properly reference each other. :param items: List of selected DICOMWidgetItems. :return: True if the selected items belong to the same tree branch. """ # Dictionary of series of different file types series = { "IMAGE": None, "RTSTRUCT": None, "RTPLAN": None, "RTDOSE": None, "SR": None } for item in items: series_type = item.dicom_object.get_series_type() if series_type in series: series[series_type] = item else: series["IMAGE"] = item # Check if the RTSTRUCT, RTPLAN, and RTDOSE are a child item of the # image series if series["IMAGE"]: if series["RTSTRUCT"] and series["RTSTRUCT"].parent() != \ series["IMAGE"]: return False if series["RTPLAN"] and \ series["RTPLAN"].parent().parent() != series["IMAGE"]: return False if series["SR"] and series["SR"].parent() != series["IMAGE"]: return False return True def check_existing_rtss(self, items): """ Check for existing rtss :return: bool, whether there is a rtss associated with the selected image series """ image_series = ['CT', 'MR', 'PT'] for item in items: if item.dicom_object.get_series_type() in image_series: for i in range(item.childCount()): if item.child(i).dicom_object: return True return False def get_checked_nodes(self, root): """ :param root: QTreeWidgetItem as a root. :return: A list of all QTreeWidgetItems in the QTreeWidget that are checked under the root. """ checked_items = [] def recurse(parent_item: QTreeWidgetItem): for i in range(parent_item.childCount()): child = parent_item.child(i) if int(child.flags()) & int(Qt.ItemIsUserCheckable) and \ child.checkState(0) == Qt.Checked: checked_items.append(child) grand_children = child.childCount() if grand_children > 0: recurse(child) recurse(root) return checked_items def confirm_button_clicked(self): """ Begins loading of the selected files. """ selected_files = [] for item in self.get_checked_nodes( self.open_patient_window_patients_tree.invisibleRootItem()): selected_files += item.dicom_object.get_files() self.progress_window = ImageFusionProgressWindow(self) self.progress_window.signal_loaded.connect(self.on_loaded) self.progress_window.signal_error.connect(self.on_loading_error) self.progress_window.start_loading(selected_files) def on_loaded(self, results): """ Executes when the progress bar finishes loaded the selected files. """ if results[0] is True: # Will be NoneType if loading was interrupted. self.image_fusion_info_initialized.emit(results[1]) def on_loading_error(self, exception): """ Error handling for progress window. """ if type(exception[1]) == ImageLoading.NotRTSetError: QMessageBox.about(self.progress_window, "Unable to open selection", "Selected files cannot be opened as they are not" " a DICOM-RT set.") self.progress_window.close() elif type(exception[1]) == ImageLoading.NotAllowedClassError: QMessageBox.about(self.progress_window, "Unable to open selection", "Selected files cannot be opened as they contain" " unsupported DICOM classes.") self.progress_window.close()
class RacetimeBrowserDialog(QDialog, Ui_RacetimeBrowserDialog): races: List[RaceEntry] permalink: Optional[Permalink] = None def __init__(self): super().__init__() self.setupUi(self) common_qt_lib.set_default_window_icon(self) self.refresh_button = QPushButton("Refresh") self.button_box.addButton(self.refresh_button, QDialogButtonBox.ResetRole) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Ok).setText("Import") self.button_box.accepted.connect(self.attempt_join) self.button_box.rejected.connect(self.reject) self.refresh_button.clicked.connect(self.refresh) self._status_checks = ( (self.status_open_check, "open"), (self.status_invitational_check, "invitational"), (self.status_pending_check, "pending"), (self.status_inprogress_check, "in_progress"), (self.status_finished_check, "finished"), (self.status_cancelled_check, "cancelled"), ) for check, _ in self._status_checks: check.stateChanged.connect(self.update_list) self.filter_name_edit.textEdited.connect(self.update_list) self._game_checks = set() for game in _SUPPORTED_GAME_URLS: game_checkbox = QCheckBox(game.long_name) game_checkbox.setChecked(True) self.game_check_layout.addWidget(game_checkbox) game_checkbox.stateChanged.connect(self.update_list) self._game_checks.add((game_checkbox, game)) self.table_widget.itemSelectionChanged.connect( self.on_selection_changed) self.table_widget.itemDoubleClicked.connect(self.on_double_click) @asyncSlot() @handle_network_errors async def refresh(self) -> bool: self.refresh_button.setEnabled(False) self.races = [] try: for game in _SUPPORTED_GAME_URLS: race_url = _SUPPORTED_GAME_URLS[game] try: raw_races = await _query_server(race_url) except aiohttp.ClientError as e: await async_dialog.warning( self, "Connection error", f"Unable to retrieve races from `{race_url}`: {e}") return False self.races.extend([ RaceEntry.from_json(item, game) for item in raw_races["current_races"] ]) self.update_list() return True finally: self.refresh_button.setEnabled(True) def on_selection_changed(self): self.button_box.button(QDialogButtonBox.Ok).setEnabled( len(self.table_widget.selectedItems()) > 0) @property def selected_race(self): return self.table_widget.selectedItems()[0].data(Qt.UserRole) @asyncSlot(QTableWidgetItem) async def on_double_click(self, item: QTableWidgetItem): await self.attempt_join() @asyncSlot() @handle_network_errors async def attempt_join(self): if not self.races: return race = self.selected_race permalink = None for word in race.info.split(" "): try: permalink = Permalink.from_str(word) except ValueError: continue except UnsupportedPermalink: continue if permalink is None: await async_dialog.warning( self, "Missing permalink", "Unable to get a valid Permalink from this race's info.") else: self.permalink = permalink return self.accept() def update_list(self): self.table_widget.clear() self.table_widget.setHorizontalHeaderLabels([ "Name", "Game", "Status", "Entrants", "Goal", "Info", "Opened At" ]) name_filter = self.filter_name_edit.text().strip() displayed_status = set() for (check, status) in self._status_checks: if check.isChecked(): displayed_status.add(status) displayed_games = set() for (check, game) in self._game_checks: if check.isChecked(): displayed_games.add(game) visible_races = [ race for race in self.races if (race.status in displayed_status and name_filter in race.name and race.game in displayed_games) ] self.table_widget.setRowCount(len(visible_races)) for i, session in enumerate(visible_races): name = QTableWidgetItem(session.name) status = QTableWidgetItem(session.verbose_status) entrants = QTableWidgetItem(str(session.entrants)) goal = QTableWidgetItem(session.goal) info = QTableWidgetItem(session.info) opened_at = QTableWidgetItem( session.opened_at.astimezone().strftime("%c")) game_name = QTableWidgetItem(session.game.short_name) name.setData(Qt.UserRole, session) self.table_widget.setItem(i, 0, name) self.table_widget.setItem(i, 1, game_name) self.table_widget.setItem(i, 2, status) self.table_widget.setItem(i, 3, entrants) self.table_widget.setItem(i, 4, goal) self.table_widget.setItem(i, 5, info) self.table_widget.setItem(i, 6, opened_at) self.status_label.setText( f"{len(self.races)} races total, {len(visible_races)} displayed.")
class AnnotationsDialog(QDialog): def __init__(self, parent, onset, duration, description): super().__init__(parent) self.setWindowTitle("Edit Annotations") self.table = QTableWidget(len(onset), 3) for row, annotation in enumerate(zip(onset, duration, description)): self.table.setItem(row, 0, IntTableWidgetItem(annotation[0])) self.table.setItem(row, 1, IntTableWidgetItem(annotation[1])) self.table.setItem(row, 2, QTableWidgetItem(annotation[2])) self.table.setHorizontalHeaderLabels(["Onset", "Duration", "Type"]) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setShowGrid(False) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setSortingEnabled(True) self.table.sortByColumn(0, Qt.AscendingOrder) vbox = QVBoxLayout(self) vbox.addWidget(self.table) hbox = QHBoxLayout() self.add_button = QPushButton("+") self.remove_button = QPushButton("-") buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) hbox.addWidget(self.add_button) hbox.addWidget(self.remove_button) hbox.addStretch() hbox.addWidget(buttonbox) vbox.addLayout(hbox) buttonbox.accepted.connect(self.accept) buttonbox.rejected.connect(self.reject) self.table.itemSelectionChanged.connect(self.toggle_buttons) self.remove_button.clicked.connect(self.remove_event) self.add_button.clicked.connect(self.add_event) self.toggle_buttons() self.resize(500, 500) @Slot() def toggle_buttons(self): """Toggle + and - buttons.""" n_items = len(self.table.selectedItems()) if n_items == 3: # one row (3 items) selected self.add_button.setEnabled(True) self.remove_button.setEnabled(True) elif n_items > 3: # more than one row selected self.add_button.setEnabled(False) self.remove_button.setEnabled(True) else: # no rows selected self.add_button.setEnabled(False) self.remove_button.setEnabled(False) def add_event(self): current_row = self.table.selectedIndexes()[0].row() pos = int(self.table.item(current_row, 0).data(Qt.DisplayRole)) self.table.setSortingEnabled(False) self.table.insertRow(current_row) self.table.setItem(current_row, 0, IntTableWidgetItem(pos)) self.table.setItem(current_row, 1, IntTableWidgetItem(0)) self.table.setItem(current_row, 2, QTableWidgetItem("New Annotation")) self.table.setSortingEnabled(True) def remove_event(self): rows = {index.row() for index in self.table.selectedIndexes()} self.table.clearSelection() for row in sorted(rows, reverse=True): self.table.removeRow(row)
class AbstractOperationDetails(QWidget): dbUpdated = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.model = None self.table_name = '' self.mapper = None self.modified = False self.name = "N/A" self.operation_type = None self.layout = QGridLayout(self) self.layout.setContentsMargins(2, 2, 2, 2) self.bold_font = QFont() self.bold_font.setBold(True) self.main_label = QLabel(self) self.main_label.setFont(self.bold_font) self.layout.addWidget(self.main_label, 0, 0, 1, 1, Qt.AlignLeft) self.commit_button = QPushButton(load_icon("accept.png"), '', self) self.commit_button.setToolTip(self.tr("Commit changes")) self.commit_button.setEnabled(False) self.revert_button = QPushButton(load_icon("cancel.png"), '', self) self.revert_button.setToolTip(self.tr("Cancel changes")) self.revert_button.setEnabled(False) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) def _init_db(self, table_name): self.table_name = table_name self.model = QSqlTableModel(parent=self, db=db_connection()) self.model.setTable(table_name) self.model.setEditStrategy(QSqlTableModel.OnManualSubmit) self.mapper = QDataWidgetMapper(self.model) self.mapper.setModel(self.model) self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit) self.model.dataChanged.connect(self.onDataChange) self.commit_button.clicked.connect(self.saveChanges) self.revert_button.clicked.connect(self.revertChanges) def isCustom(self): return True def setId(self, id): self.model.setFilter(f"id={id}") self.mapper.setCurrentModelIndex(self.model.index(0, 0)) @Slot() def onDataChange(self, _index_start, _index_stop, _role): self.modified = True self.commit_button.setEnabled(True) self.revert_button.setEnabled(True) @Slot() def saveChanges(self): if not self.model.submitAll(): logging.fatal( self.tr("Operation submit failed: ") + self.model.lastError().text()) return False self.modified = False self.commit_button.setEnabled(False) self.revert_button.setEnabled(False) self.dbUpdated.emit() @Slot() def revertChanges(self): self.model.revertAll() self.modified = False self.commit_button.setEnabled(False) self.revert_button.setEnabled(False) def createNew(self, account_id=0): if self.modified: self.revertChanges() logging.warning( self.tr( "Unsaved changes were reverted to create new operation")) self.model.setFilter(f"{self.table_name}.id = 0") new_record = self.prepareNew(account_id) assert self.model.insertRows(0, 1) self.model.setRecord(0, new_record) self.mapper.toLast() def prepareNew(self, account_id): new_record = self.model.record() new_record.setNull("id") new_record.setValue("op_type", self.operation_type) return new_record def copyNew(self): row = self.mapper.currentIndex() new_record = self.copyToNew(row) self.model.setFilter(f"{self.table_name}.id = 0") assert self.model.insertRows(0, 1) self.model.setRecord(0, new_record) self.mapper.toLast() def copyToNew(self, row): new_record = self.model.record(row) return new_record
class Widget(QWidget): def __init__(self): QWidget.__init__(self) self.items = 0 # Left self.table = QTableWidget() self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(["Description", "Quantity"]) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # Chart self.chart_view = QChartView() self.chart_view.setRenderHint(QPainter.Antialiasing) # Right self.description = QLineEdit() self.quantity = QLineEdit() self.add = QPushButton("Add") self.clear = QPushButton("Clear") self.quit = QPushButton("Quit") self.plot = QPushButton("Plot") # Disabling 'Add' button self.add.setEnabled(False) self.right = QVBoxLayout() self.right.setContentsMargins(10, 10, 10, 10) self.right_top = QGridLayout() self.right_top.addWidget(QLabel("Description"), 0, 0, 1, 1) self.right_top.addWidget(self.description, 0, 1, 1, 3) self.right_top.addWidget(QLabel("Quantity"), 1, 0, 1, 1) self.right_top.addWidget(self.quantity, 1, 1, 1, 1) self.right_top.addWidget(self.add, 1, 2, 1, 2) self.right.addLayout(self.right_top) self.right.addWidget(self.chart_view) self.right_bottom = QGridLayout() self.right_bottom.addWidget(self.plot, 0, 0, 1, 2) self.right_bottom.addWidget(self.clear, 1, 0) self.right_bottom.addWidget(self.quit, 1, 1) self.right.addLayout(self.right_bottom) # QWidget Layout self.layout = QHBoxLayout() self.layout.addWidget(self.table) self.layout.addLayout(self.right) # Set the layout to the QWidget self.setLayout(self.layout) # Signals and Slots self.add.clicked.connect(self.add_element) self.quit.clicked.connect(self.quit_application) self.plot.clicked.connect(self.plot_data) self.clear.clicked.connect(self.clear_table) self.description.textChanged[str].connect(self.check_disable) self.quantity.textChanged[str].connect(self.check_disable) @Slot() def add_element(self): des = self.description.text() qty = self.quantity.text() self.table.insertRow(self.items) self.table.setItem(self.items, 0, QTableWidgetItem(des)) self.table.setItem(self.items, 1, QTableWidgetItem(qty)) self.description.setText("") self.quantity.setText("") self.items += 1 @Slot() def check_disable(self, s): if not self.description.text() or not self.quantity.text(): self.add.setEnabled(False) else: self.add.setEnabled(True) @Slot() def plot_data(self): # Get table information series = QBarSeries() for i in range(self.table.rowCount()): text = self.table.item(i, 0).text() number = float(self.table.item(i, 1).text()) bar_set = QBarSet(text) bar_set.append(number) series.append(bar_set) chart = QChart() chart.addSeries(series) chart.legend().setAlignment(Qt.AlignLeft) self.chart_view.setChart(chart) @Slot() def quit_application(self): QApplication.quit() @Slot() def clear_table(self): self.table.setRowCount(0) self.items = 0
class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(1024, 768) self.actionOpen_ObjectBlueprints_xml = QAction(MainWindow) self.actionOpen_ObjectBlueprints_xml.setObjectName( u"actionOpen_ObjectBlueprints_xml") self.actionExit = QAction(MainWindow) self.actionExit.setObjectName(u"actionExit") self.actionWiki_template = QAction(MainWindow) self.actionWiki_template.setObjectName(u"actionWiki_template") self.actionWiki_template.setCheckable(True) self.actionWiki_template.setChecked(True) self.actionAttributes = QAction(MainWindow) self.actionAttributes.setObjectName(u"actionAttributes") self.actionAttributes.setCheckable(True) self.actionAll_attributes = QAction(MainWindow) self.actionAll_attributes.setObjectName(u"actionAll_attributes") self.actionAll_attributes.setCheckable(True) self.actionScan_wiki = QAction(MainWindow) self.actionScan_wiki.setObjectName(u"actionScan_wiki") self.actionUpload_templates = QAction(MainWindow) self.actionUpload_templates.setObjectName(u"actionUpload_templates") self.actionUpload_tiles = QAction(MainWindow) self.actionUpload_tiles.setObjectName(u"actionUpload_tiles") self.actionXML_source = QAction(MainWindow) self.actionXML_source.setObjectName(u"actionXML_source") self.actionXML_source.setCheckable(True) self.actionShow_help = QAction(MainWindow) self.actionShow_help.setObjectName(u"actionShow_help") self.actionUpload_extra_image_s_for_selected_objects = QAction( MainWindow) self.actionUpload_extra_image_s_for_selected_objects.setObjectName( u"actionUpload_extra_image_s_for_selected_objects") self.actionDiff_template_against_wiki = QAction(MainWindow) self.actionDiff_template_against_wiki.setObjectName( u"actionDiff_template_against_wiki") self.actionDark_mode = QAction(MainWindow) self.actionDark_mode.setObjectName(u"actionDark_mode") self.actionSuppress_image_comparison_popups = QAction(MainWindow) self.actionSuppress_image_comparison_popups.setObjectName( u"actionSuppress_image_comparison_popups") self.actionSuppress_image_comparison_popups.setCheckable(True) self.actionSuppress_image_comparison_popups.setChecked(False) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName(u"gridLayout") self.verticalLayout = QVBoxLayout() self.verticalLayout.setObjectName(u"verticalLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") self.plainTextEdit = QPlainTextEdit(self.centralwidget) self.plainTextEdit.setObjectName(u"plainTextEdit") font = QFont() font.setFamilies([u"Consolas"]) font.setPointSize(10) self.plainTextEdit.setFont(font) self.plainTextEdit.setUndoRedoEnabled(False) self.plainTextEdit.setReadOnly(True) self.horizontalLayout.addWidget(self.plainTextEdit) self.verticalLayout_4 = QVBoxLayout() self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.tile_label = QLabel(self.centralwidget) self.tile_label.setObjectName(u"tile_label") self.tile_label.setMinimumSize(QSize(160, 240)) font1 = QFont() font1.setFamilies([u"Segoe UI"]) self.tile_label.setFont(font1) self.tile_label.setStyleSheet(u"background-color: rgb(15, 59, 58);") self.verticalLayout_4.addWidget(self.tile_label) self.save_tile_button = QPushButton(self.centralwidget) self.save_tile_button.setObjectName(u"save_tile_button") font2 = QFont() font2.setFamilies([u"Segoe UI"]) font2.setPointSize(10) self.save_tile_button.setFont(font2) self.verticalLayout_4.addWidget(self.save_tile_button) self.swap_tile_button = QPushButton(self.centralwidget) self.swap_tile_button.setObjectName(u"swap_tile_button") self.swap_tile_button.setEnabled(True) self.swap_tile_button.setFont(font2) self.verticalLayout_4.addWidget(self.swap_tile_button) self.horizontalLayout.addLayout(self.verticalLayout_4) self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout_3 = QVBoxLayout() self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.search_label = QLabel(self.centralwidget) self.search_label.setObjectName(u"search_label") self.search_label.setMinimumSize(QSize(0, 0)) self.search_label.setFont(font2) self.horizontalLayout_2.addWidget(self.search_label) self.search_line_edit = QLineEdit(self.centralwidget) self.search_line_edit.setObjectName(u"search_line_edit") self.search_line_edit.setFont(font2) self.horizontalLayout_2.addWidget(self.search_line_edit) self.expand_all_button = QPushButton(self.centralwidget) self.expand_all_button.setObjectName(u"expand_all_button") self.expand_all_button.setMinimumSize(QSize(90, 0)) self.expand_all_button.setFont(font2) self.horizontalLayout_2.addWidget(self.expand_all_button) self.collapse_all_button = QPushButton(self.centralwidget) self.collapse_all_button.setObjectName(u"collapse_all_button") self.collapse_all_button.setMinimumSize(QSize(90, 0)) self.collapse_all_button.setFont(font2) self.horizontalLayout_2.addWidget(self.collapse_all_button) self.restore_all_button = QPushButton(self.centralwidget) self.restore_all_button.setObjectName(u"restore_all_button") self.restore_all_button.setMinimumSize(QSize(130, 0)) self.restore_all_button.setFont(font2) self.horizontalLayout_2.addWidget(self.restore_all_button) self.verticalLayout_3.addLayout(self.horizontalLayout_2) self.tree_target_widget = QWidget(self.centralwidget) self.tree_target_widget.setObjectName(u"tree_target_widget") self.tree_target_widget.setFont(font1) self.verticalLayout_3.addWidget(self.tree_target_widget, 0, Qt.AlignBottom) self.verticalLayout.addLayout(self.verticalLayout_3) self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 1024, 21)) self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName(u"menuFile") self.menuView = QMenu(self.menubar) self.menuView.setObjectName(u"menuView") self.menuWiki = QMenu(self.menubar) self.menuWiki.setObjectName(u"menuWiki") self.menuHelp = QMenu(self.menubar) self.menuHelp.setObjectName(u"menuHelp") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") MainWindow.setStatusBar(self.statusbar) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuWiki.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.menuFile.addAction(self.actionOpen_ObjectBlueprints_xml) self.menuFile.addAction(self.actionExit) self.menuView.addAction(self.actionWiki_template) self.menuView.addAction(self.actionAttributes) self.menuView.addAction(self.actionAll_attributes) self.menuView.addAction(self.actionXML_source) self.menuView.addSeparator() self.menuView.addAction(self.actionDark_mode) self.menuWiki.addAction(self.actionScan_wiki) self.menuWiki.addAction(self.actionDiff_template_against_wiki) self.menuWiki.addAction(self.actionUpload_templates) self.menuWiki.addAction(self.actionUpload_tiles) self.menuWiki.addAction( self.actionUpload_extra_image_s_for_selected_objects) self.menuWiki.addAction(self.actionSuppress_image_comparison_popups) self.menuHelp.addAction(self.actionShow_help) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle( QCoreApplication.translate("MainWindow", u"Qud Blueprint Explorer", None)) self.actionOpen_ObjectBlueprints_xml.setText( QCoreApplication.translate("MainWindow", u"Open ObjectBlueprints.xml...", None)) self.actionExit.setText( QCoreApplication.translate("MainWindow", u"Exit", None)) self.actionWiki_template.setText( QCoreApplication.translate("MainWindow", u"Wiki template", None)) self.actionAttributes.setText( QCoreApplication.translate("MainWindow", u"Attributes", None)) self.actionAll_attributes.setText( QCoreApplication.translate("MainWindow", u"All attributes", None)) self.actionScan_wiki.setText( QCoreApplication.translate("MainWindow", u"Scan wiki for selected objects", None)) self.actionUpload_templates.setText( QCoreApplication.translate( "MainWindow", u"Upload templates for selected objects", None)) self.actionUpload_tiles.setText( QCoreApplication.translate("MainWindow", u"Upload tiles for selected objects", None)) self.actionXML_source.setText( QCoreApplication.translate("MainWindow", u"XML source", None)) self.actionShow_help.setText( QCoreApplication.translate("MainWindow", u"Show help", None)) self.actionUpload_extra_image_s_for_selected_objects.setText( QCoreApplication.translate( "MainWindow", u"Upload extra image(s) for selected objects", None)) self.actionDiff_template_against_wiki.setText( QCoreApplication.translate("MainWindow", u"Diff template against wiki", None)) self.actionDark_mode.setText( QCoreApplication.translate("MainWindow", u"Toggle dark mode", None)) self.actionSuppress_image_comparison_popups.setText( QCoreApplication.translate("MainWindow", u"Suppress image comparison pop-ups", None)) self.tile_label.setText("") self.save_tile_button.setText( QCoreApplication.translate("MainWindow", u"Save tile...", None)) self.swap_tile_button.setText( QCoreApplication.translate("MainWindow", u"Toggle .png/.gif", None)) self.search_label.setText( QCoreApplication.translate("MainWindow", u"Search:", None)) self.expand_all_button.setText( QCoreApplication.translate("MainWindow", u"Expand all", None)) self.collapse_all_button.setText( QCoreApplication.translate("MainWindow", u"Collapse all", None)) self.restore_all_button.setText( QCoreApplication.translate("MainWindow", u"Default expansion", None)) self.menuFile.setTitle( QCoreApplication.translate("MainWindow", u"File", None)) self.menuView.setTitle( QCoreApplication.translate("MainWindow", u"View type", None)) self.menuWiki.setTitle( QCoreApplication.translate("MainWindow", u"Wiki", None)) self.menuHelp.setTitle( QCoreApplication.translate("MainWindow", u"Help", None))
class GameSessionBrowserDialog(QDialog, Ui_GameSessionBrowserDialog): sessions: List[GameSessionListEntry] visible_sessions: List[GameSessionListEntry] def __init__(self, network_client: QtNetworkClient): super().__init__() self.setupUi(self) common_qt_lib.set_default_window_icon(self) self.network_client = network_client self.refresh_button = QPushButton("Refresh") self.button_box.addButton(self.refresh_button, QDialogButtonBox.ResetRole) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Ok).setText("Join") self.button_box.accepted.connect(self.attempt_join) self.button_box.rejected.connect(self.reject) self.refresh_button.clicked.connect(self._refresh_slot) checks = ( self.has_password_yes_check, self.has_password_no_check, self.state_setup_check, self.state_inprogress_check, self.state_finished_check, self.filter_age_check, ) for check in checks: check.stateChanged.connect(self.update_list) self.filter_name_edit.textEdited.connect(self.update_list) self.filter_age_spin.valueChanged.connect(self.update_list) self.table_widget.itemSelectionChanged.connect( self.on_selection_changed) self.table_widget.itemDoubleClicked.connect(self.on_double_click) self.network_client.ConnectionStateUpdated.connect( self.on_server_connection_state_updated) self.on_server_connection_state_updated( self.network_client.connection_state) @handle_network_errors async def refresh(self, *, ignore_limit: bool = False): self.refresh_button.setEnabled(False) try: self.sessions = await self.network_client.get_game_session_list( ignore_limit) self.update_list() finally: self.refresh_button.setEnabled(True) return True @asyncSlot() async def _refresh_slot(self): await self.refresh(ignore_limit=True) def on_selection_changed(self): self.button_box.button(QDialogButtonBox.Ok).setEnabled( len(self.table_widget.selectedItems()) > 0) @property def selected_session(self) -> GameSessionListEntry: return self.table_widget.selectedItems()[0].data(Qt.UserRole) @asyncSlot(QTableWidgetItem) async def on_double_click(self, item: QTableWidgetItem): await self.attempt_join() @asyncSlot() @handle_network_errors async def attempt_join(self): if not self.visible_sessions: return session = self.selected_session if session.has_password: dialog = QInputDialog(self) dialog.setWindowTitle("Enter password") dialog.setLabelText("This session requires a password:"******"Incorrect Password", "The password entered was incorrect.") def update_list(self): self.table_widget.clear() self.table_widget.setHorizontalHeaderLabels([ "Name", "State", "Players", "Password?", "Creator", "Creation Date" ]) name_filter = self.filter_name_edit.text().strip() displayed_has_password = set() if self.has_password_yes_check.isChecked(): displayed_has_password.add(True) if self.has_password_no_check.isChecked(): displayed_has_password.add(False) displayed_states = set() for (check, state) in ((self.state_setup_check, GameSessionState.SETUP), (self.state_inprogress_check, GameSessionState.IN_PROGRESS), (self.state_finished_check, GameSessionState.FINISHED)): if check.isChecked(): displayed_states.add(state) dont_filter_age = not self.filter_age_check.isChecked() now = datetime.datetime.now(tz=datetime.timezone.utc) max_session_age = datetime.timedelta(days=self.filter_age_spin.value()) visible_sessions = [ session for session in reversed(self.sessions) if (session.has_password in displayed_has_password and session. state in displayed_states and name_filter in session.name and ( dont_filter_age or (now - session.creation_date) < max_session_age)) ] self.visible_sessions = visible_sessions self.table_widget.setRowCount(len(visible_sessions)) for i, session in enumerate(visible_sessions): name = QTableWidgetItem(session.name) state = QTableWidgetItem(session.state.user_friendly_name) players_item = QTableWidgetItem(str(session.num_players)) has_password = QTableWidgetItem( "Yes" if session.has_password else "No") creator = QTableWidgetItem(session.creator) creation_date = QTableWidgetItem( session.creation_date.astimezone().strftime("%Y-%m-%d %H:%M")) name.setData(Qt.UserRole, session) self.table_widget.setItem(i, 0, name) self.table_widget.setItem(i, 1, state) self.table_widget.setItem(i, 2, players_item) self.table_widget.setItem(i, 3, has_password) self.table_widget.setItem(i, 4, creator) self.table_widget.setItem(i, 5, creation_date) for i in range(6): self.table_widget.resizeColumnToContents(i) self.status_label.setText( f"{len(self.sessions)} sessions total, {len(visible_sessions)} displayed." ) def on_server_connection_state_updated(self, state: ConnectionState): self.server_connection_label.setText(f"Server: {state.value}")
class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(770, 640) MainWindow.setMinimumSize(QSize(770, 640)) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout_10 = QGridLayout(self.centralwidget) self.gridLayout_10.setObjectName(u"gridLayout_10") self.groupBoxConnection = QGroupBox(self.centralwidget) self.groupBoxConnection.setObjectName(u"groupBoxConnection") sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.groupBoxConnection.sizePolicy().hasHeightForWidth()) self.groupBoxConnection.setSizePolicy(sizePolicy) self.gridLayout_2 = QGridLayout(self.groupBoxConnection) self.gridLayout_2.setObjectName(u"gridLayout_2") self.pushButtonConnect = QPushButton(self.groupBoxConnection) self.pushButtonConnect.setObjectName(u"pushButtonConnect") sizePolicy1 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy1.setHorizontalStretch(1) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.pushButtonConnect.sizePolicy().hasHeightForWidth()) self.pushButtonConnect.setSizePolicy(sizePolicy1) self.gridLayout_2.addWidget(self.pushButtonConnect, 0, 1, 1, 1) self.labelUpdateDelay = QLabel(self.groupBoxConnection) self.labelUpdateDelay.setObjectName(u"labelUpdateDelay") self.gridLayout_2.addWidget(self.labelUpdateDelay, 1, 0, 1, 1) self.labelStatus = QLabel(self.groupBoxConnection) self.labelStatus.setObjectName(u"labelStatus") sizePolicy2 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy2.setHorizontalStretch(1) sizePolicy2.setVerticalStretch(0) sizePolicy2.setHeightForWidth(self.labelStatus.sizePolicy().hasHeightForWidth()) self.labelStatus.setSizePolicy(sizePolicy2) self.gridLayout_2.addWidget(self.labelStatus, 1, 2, 1, 1) self.comboBoxGameSelection = QComboBox(self.groupBoxConnection) self.comboBoxGameSelection.addItem("") self.comboBoxGameSelection.addItem("") self.comboBoxGameSelection.addItem("") self.comboBoxGameSelection.addItem("") self.comboBoxGameSelection.setObjectName(u"comboBoxGameSelection") sizePolicy3 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy3.setHorizontalStretch(1) sizePolicy3.setVerticalStretch(0) sizePolicy3.setHeightForWidth(self.comboBoxGameSelection.sizePolicy().hasHeightForWidth()) self.comboBoxGameSelection.setSizePolicy(sizePolicy3) self.gridLayout_2.addWidget(self.comboBoxGameSelection, 0, 0, 1, 1) self.doubleSpinBoxDelay = QDoubleSpinBox(self.groupBoxConnection) self.doubleSpinBoxDelay.setObjectName(u"doubleSpinBoxDelay") self.doubleSpinBoxDelay.setEnabled(False) self.doubleSpinBoxDelay.setMinimum(0.500000000000000) self.doubleSpinBoxDelay.setMaximum(2.000000000000000) self.gridLayout_2.addWidget(self.doubleSpinBoxDelay, 1, 1, 1, 1) self.gridLayout_10.addWidget(self.groupBoxConnection, 0, 0, 1, 1) self.tabWidget = QTabWidget(self.centralwidget) self.tabWidget.setObjectName(u"tabWidget") sizePolicy4 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy4.setHorizontalStretch(0) sizePolicy4.setVerticalStretch(5) sizePolicy4.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy4) self.tabGen6 = QWidget() self.tabGen6.setObjectName(u"tabGen6") self.gridLayout = QGridLayout(self.tabGen6) self.gridLayout.setObjectName(u"gridLayout") self.tabWidgetGen6 = QTabWidget(self.tabGen6) self.tabWidgetGen6.setObjectName(u"tabWidgetGen6") self.tabMain6 = QWidget() self.tabMain6.setObjectName(u"tabMain6") self.gridLayout_13 = QGridLayout(self.tabMain6) self.gridLayout_13.setObjectName(u"gridLayout_13") self.comboBoxMainIndex6 = QComboBox(self.tabMain6) self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.addItem("") self.comboBoxMainIndex6.setObjectName(u"comboBoxMainIndex6") self.comboBoxMainIndex6.setEnabled(False) sizePolicy3.setHeightForWidth(self.comboBoxMainIndex6.sizePolicy().hasHeightForWidth()) self.comboBoxMainIndex6.setSizePolicy(sizePolicy3) self.gridLayout_13.addWidget(self.comboBoxMainIndex6, 0, 0, 1, 1) self.groupBoxMainRNG6 = QGroupBox(self.tabMain6) self.groupBoxMainRNG6.setObjectName(u"groupBoxMainRNG6") sizePolicy2.setHeightForWidth(self.groupBoxMainRNG6.sizePolicy().hasHeightForWidth()) self.groupBoxMainRNG6.setSizePolicy(sizePolicy2) self.gridLayout_11 = QGridLayout(self.groupBoxMainRNG6) self.gridLayout_11.setObjectName(u"gridLayout_11") self.lineEditFrame6 = QLineEdit(self.groupBoxMainRNG6) self.lineEditFrame6.setObjectName(u"lineEditFrame6") sizePolicy5 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy5.setHorizontalStretch(0) sizePolicy5.setVerticalStretch(0) sizePolicy5.setHeightForWidth(self.lineEditFrame6.sizePolicy().hasHeightForWidth()) self.lineEditFrame6.setSizePolicy(sizePolicy5) self.lineEditFrame6.setReadOnly(True) self.gridLayout_11.addWidget(self.lineEditFrame6, 3, 2, 1, 2) self.labelTiny2 = QLabel(self.groupBoxMainRNG6) self.labelTiny2.setObjectName(u"labelTiny2") self.gridLayout_11.addWidget(self.labelTiny2, 5, 2, 1, 1) self.labelTiny0 = QLabel(self.groupBoxMainRNG6) self.labelTiny0.setObjectName(u"labelTiny0") self.gridLayout_11.addWidget(self.labelTiny0, 6, 2, 1, 1) self.lineEditInitialSeed6 = QLineEdit(self.groupBoxMainRNG6) self.lineEditInitialSeed6.setObjectName(u"lineEditInitialSeed6") sizePolicy5.setHeightForWidth(self.lineEditInitialSeed6.sizePolicy().hasHeightForWidth()) self.lineEditInitialSeed6.setSizePolicy(sizePolicy5) self.lineEditInitialSeed6.setMaxLength(8) self.lineEditInitialSeed6.setReadOnly(True) self.gridLayout_11.addWidget(self.lineEditInitialSeed6, 1, 2, 1, 2) self.labelTiny3 = QLabel(self.groupBoxMainRNG6) self.labelTiny3.setObjectName(u"labelTiny3") self.gridLayout_11.addWidget(self.labelTiny3, 5, 0, 1, 1) self.labelTiny1 = QLabel(self.groupBoxMainRNG6) self.labelTiny1.setObjectName(u"labelTiny1") self.gridLayout_11.addWidget(self.labelTiny1, 6, 0, 1, 1) self.labelMainCurrentSeed6 = QLabel(self.groupBoxMainRNG6) self.labelMainCurrentSeed6.setObjectName(u"labelMainCurrentSeed6") self.gridLayout_11.addWidget(self.labelMainCurrentSeed6, 2, 0, 1, 2) self.lineEditCurrentSeed6 = QLineEdit(self.groupBoxMainRNG6) self.lineEditCurrentSeed6.setObjectName(u"lineEditCurrentSeed6") sizePolicy5.setHeightForWidth(self.lineEditCurrentSeed6.sizePolicy().hasHeightForWidth()) self.lineEditCurrentSeed6.setSizePolicy(sizePolicy5) self.lineEditCurrentSeed6.setMaxLength(16) self.lineEditCurrentSeed6.setReadOnly(True) self.gridLayout_11.addWidget(self.lineEditCurrentSeed6, 2, 2, 1, 2) self.lineEditTiny2 = QLineEdit(self.groupBoxMainRNG6) self.lineEditTiny2.setObjectName(u"lineEditTiny2") self.gridLayout_11.addWidget(self.lineEditTiny2, 5, 3, 1, 1) self.lineEditTiny1 = QLineEdit(self.groupBoxMainRNG6) self.lineEditTiny1.setObjectName(u"lineEditTiny1") self.gridLayout_11.addWidget(self.lineEditTiny1, 6, 1, 1, 1) self.lineEditTiny3 = QLineEdit(self.groupBoxMainRNG6) self.lineEditTiny3.setObjectName(u"lineEditTiny3") self.gridLayout_11.addWidget(self.lineEditTiny3, 5, 1, 1, 1) self.labelMainInitialSeed6 = QLabel(self.groupBoxMainRNG6) self.labelMainInitialSeed6.setObjectName(u"labelMainInitialSeed6") self.gridLayout_11.addWidget(self.labelMainInitialSeed6, 1, 0, 1, 2) self.labelMainFrame6 = QLabel(self.groupBoxMainRNG6) self.labelMainFrame6.setObjectName(u"labelMainFrame6") self.gridLayout_11.addWidget(self.labelMainFrame6, 3, 0, 1, 1) self.lineEditTiny0 = QLineEdit(self.groupBoxMainRNG6) self.lineEditTiny0.setObjectName(u"lineEditTiny0") self.gridLayout_11.addWidget(self.lineEditTiny0, 6, 3, 1, 1) self.pushButtonMainUpdate6 = QPushButton(self.groupBoxMainRNG6) self.pushButtonMainUpdate6.setObjectName(u"pushButtonMainUpdate6") self.pushButtonMainUpdate6.setEnabled(False) self.gridLayout_11.addWidget(self.pushButtonMainUpdate6, 0, 0, 1, 4) self.labelSaveVariable = QLabel(self.groupBoxMainRNG6) self.labelSaveVariable.setObjectName(u"labelSaveVariable") self.gridLayout_11.addWidget(self.labelSaveVariable, 4, 0, 1, 1) self.lineEditSaveVariable = QLineEdit(self.groupBoxMainRNG6) self.lineEditSaveVariable.setObjectName(u"lineEditSaveVariable") self.lineEditSaveVariable.setReadOnly(True) self.gridLayout_11.addWidget(self.lineEditSaveVariable, 4, 2, 1, 2) self.gridLayout_13.addWidget(self.groupBoxMainRNG6, 0, 1, 2, 1) self.mainPokemon6 = PokemonDisplay(self.tabMain6) self.mainPokemon6.setObjectName(u"mainPokemon6") sizePolicy2.setHeightForWidth(self.mainPokemon6.sizePolicy().hasHeightForWidth()) self.mainPokemon6.setSizePolicy(sizePolicy2) self.gridLayout_13.addWidget(self.mainPokemon6, 1, 0, 1, 1) self.tabWidgetGen6.addTab(self.tabMain6, "") self.tabEgg6 = QWidget() self.tabEgg6.setObjectName(u"tabEgg6") self.gridLayout_15 = QGridLayout(self.tabEgg6) self.gridLayout_15.setObjectName(u"gridLayout_15") self.eggParent1_6 = PokemonDisplay(self.tabEgg6) self.eggParent1_6.setObjectName(u"eggParent1_6") sizePolicy2.setHeightForWidth(self.eggParent1_6.sizePolicy().hasHeightForWidth()) self.eggParent1_6.setSizePolicy(sizePolicy2) self.gridLayout_15.addWidget(self.eggParent1_6, 0, 0, 1, 1) self.eggParent2_6 = PokemonDisplay(self.tabEgg6) self.eggParent2_6.setObjectName(u"eggParent2_6") sizePolicy2.setHeightForWidth(self.eggParent2_6.sizePolicy().hasHeightForWidth()) self.eggParent2_6.setSizePolicy(sizePolicy2) self.gridLayout_15.addWidget(self.eggParent2_6, 0, 1, 1, 1) self.groupBoxEggRNG6 = QGroupBox(self.tabEgg6) self.groupBoxEggRNG6.setObjectName(u"groupBoxEggRNG6") sizePolicy2.setHeightForWidth(self.groupBoxEggRNG6.sizePolicy().hasHeightForWidth()) self.groupBoxEggRNG6.setSizePolicy(sizePolicy2) self.gridLayout_14 = QGridLayout(self.groupBoxEggRNG6) self.gridLayout_14.setObjectName(u"gridLayout_14") self.labelEggReady6 = QLabel(self.groupBoxEggRNG6) self.labelEggReady6.setObjectName(u"labelEggReady6") sizePolicy5.setHeightForWidth(self.labelEggReady6.sizePolicy().hasHeightForWidth()) self.labelEggReady6.setSizePolicy(sizePolicy5) self.gridLayout_14.addWidget(self.labelEggReady6, 1, 0, 1, 1) self.labelEggReadyStatus6 = QLabel(self.groupBoxEggRNG6) self.labelEggReadyStatus6.setObjectName(u"labelEggReadyStatus6") self.gridLayout_14.addWidget(self.labelEggReadyStatus6, 1, 1, 1, 1) self.lineEditEggSeed0_6 = QLineEdit(self.groupBoxEggRNG6) self.lineEditEggSeed0_6.setObjectName(u"lineEditEggSeed0_6") sizePolicy5.setHeightForWidth(self.lineEditEggSeed0_6.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed0_6.setSizePolicy(sizePolicy5) self.lineEditEggSeed0_6.setMaxLength(8) self.lineEditEggSeed0_6.setReadOnly(True) self.gridLayout_14.addWidget(self.lineEditEggSeed0_6, 3, 1, 1, 1) self.pushButtonEggUpdate6 = QPushButton(self.groupBoxEggRNG6) self.pushButtonEggUpdate6.setObjectName(u"pushButtonEggUpdate6") self.pushButtonEggUpdate6.setEnabled(False) self.gridLayout_14.addWidget(self.pushButtonEggUpdate6, 0, 0, 1, 2) self.labelEggSeed0_6 = QLabel(self.groupBoxEggRNG6) self.labelEggSeed0_6.setObjectName(u"labelEggSeed0_6") self.gridLayout_14.addWidget(self.labelEggSeed0_6, 3, 0, 1, 1) self.labelEggSeed1_6 = QLabel(self.groupBoxEggRNG6) self.labelEggSeed1_6.setObjectName(u"labelEggSeed1_6") self.gridLayout_14.addWidget(self.labelEggSeed1_6, 2, 0, 1, 1) self.lineEditEggSeed1_6 = QLineEdit(self.groupBoxEggRNG6) self.lineEditEggSeed1_6.setObjectName(u"lineEditEggSeed1_6") sizePolicy5.setHeightForWidth(self.lineEditEggSeed1_6.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed1_6.setSizePolicy(sizePolicy5) self.lineEditEggSeed1_6.setMaxLength(8) self.lineEditEggSeed1_6.setReadOnly(True) self.gridLayout_14.addWidget(self.lineEditEggSeed1_6, 2, 1, 1, 1) self.gridLayout_15.addWidget(self.groupBoxEggRNG6, 0, 2, 1, 1) self.tabWidgetGen6.addTab(self.tabEgg6, "") self.gridLayout.addWidget(self.tabWidgetGen6, 0, 0, 1, 1) self.tabWidget.addTab(self.tabGen6, "") self.tabGen7 = QWidget() self.tabGen7.setObjectName(u"tabGen7") self.tabGen7.setEnabled(False) self.gridLayout_12 = QGridLayout(self.tabGen7) self.gridLayout_12.setObjectName(u"gridLayout_12") self.tabWidgetGen7 = QTabWidget(self.tabGen7) self.tabWidgetGen7.setObjectName(u"tabWidgetGen7") self.tabMain7 = QWidget() self.tabMain7.setObjectName(u"tabMain7") self.gridLayout_7 = QGridLayout(self.tabMain7) self.gridLayout_7.setObjectName(u"gridLayout_7") self.comboBoxMainIndex7 = QComboBox(self.tabMain7) self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.addItem("") self.comboBoxMainIndex7.setObjectName(u"comboBoxMainIndex7") self.comboBoxMainIndex7.setEnabled(False) sizePolicy3.setHeightForWidth(self.comboBoxMainIndex7.sizePolicy().hasHeightForWidth()) self.comboBoxMainIndex7.setSizePolicy(sizePolicy3) self.gridLayout_7.addWidget(self.comboBoxMainIndex7, 0, 0, 1, 1) self.groupBoxMainRNG7 = QGroupBox(self.tabMain7) self.groupBoxMainRNG7.setObjectName(u"groupBoxMainRNG7") sizePolicy2.setHeightForWidth(self.groupBoxMainRNG7.sizePolicy().hasHeightForWidth()) self.groupBoxMainRNG7.setSizePolicy(sizePolicy2) self.gridLayout_3 = QGridLayout(self.groupBoxMainRNG7) self.gridLayout_3.setObjectName(u"gridLayout_3") self.labelMainInitialSeed7 = QLabel(self.groupBoxMainRNG7) self.labelMainInitialSeed7.setObjectName(u"labelMainInitialSeed7") self.gridLayout_3.addWidget(self.labelMainInitialSeed7, 1, 0, 1, 1) self.lineEditInitialSeed7 = QLineEdit(self.groupBoxMainRNG7) self.lineEditInitialSeed7.setObjectName(u"lineEditInitialSeed7") sizePolicy5.setHeightForWidth(self.lineEditInitialSeed7.sizePolicy().hasHeightForWidth()) self.lineEditInitialSeed7.setSizePolicy(sizePolicy5) self.lineEditInitialSeed7.setMaxLength(8) self.lineEditInitialSeed7.setReadOnly(True) self.gridLayout_3.addWidget(self.lineEditInitialSeed7, 1, 1, 1, 1) self.labelMainCurrentSeed7 = QLabel(self.groupBoxMainRNG7) self.labelMainCurrentSeed7.setObjectName(u"labelMainCurrentSeed7") self.gridLayout_3.addWidget(self.labelMainCurrentSeed7, 2, 0, 1, 1) self.lineEditCurrentSeed7 = QLineEdit(self.groupBoxMainRNG7) self.lineEditCurrentSeed7.setObjectName(u"lineEditCurrentSeed7") sizePolicy5.setHeightForWidth(self.lineEditCurrentSeed7.sizePolicy().hasHeightForWidth()) self.lineEditCurrentSeed7.setSizePolicy(sizePolicy5) self.lineEditCurrentSeed7.setMaxLength(16) self.lineEditCurrentSeed7.setReadOnly(True) self.gridLayout_3.addWidget(self.lineEditCurrentSeed7, 2, 1, 1, 1) self.labelMainFrame7 = QLabel(self.groupBoxMainRNG7) self.labelMainFrame7.setObjectName(u"labelMainFrame7") self.gridLayout_3.addWidget(self.labelMainFrame7, 3, 0, 1, 1) self.lineEditFrame7 = QLineEdit(self.groupBoxMainRNG7) self.lineEditFrame7.setObjectName(u"lineEditFrame7") sizePolicy5.setHeightForWidth(self.lineEditFrame7.sizePolicy().hasHeightForWidth()) self.lineEditFrame7.setSizePolicy(sizePolicy5) self.lineEditFrame7.setReadOnly(True) self.gridLayout_3.addWidget(self.lineEditFrame7, 3, 1, 1, 1) self.pushButtonMainUpdate7 = QPushButton(self.groupBoxMainRNG7) self.pushButtonMainUpdate7.setObjectName(u"pushButtonMainUpdate7") self.pushButtonMainUpdate7.setEnabled(False) self.gridLayout_3.addWidget(self.pushButtonMainUpdate7, 0, 0, 1, 2) self.gridLayout_7.addWidget(self.groupBoxMainRNG7, 0, 1, 2, 1) self.mainPokemon7 = PokemonDisplay(self.tabMain7) self.mainPokemon7.setObjectName(u"mainPokemon7") sizePolicy2.setHeightForWidth(self.mainPokemon7.sizePolicy().hasHeightForWidth()) self.mainPokemon7.setSizePolicy(sizePolicy2) self.gridLayout_7.addWidget(self.mainPokemon7, 1, 0, 1, 1) self.tabWidgetGen7.addTab(self.tabMain7, "") self.tabEgg7 = QWidget() self.tabEgg7.setObjectName(u"tabEgg7") self.gridLayout_6 = QGridLayout(self.tabEgg7) self.gridLayout_6.setObjectName(u"gridLayout_6") self.groupBoxEggRNG7 = QGroupBox(self.tabEgg7) self.groupBoxEggRNG7.setObjectName(u"groupBoxEggRNG7") sizePolicy2.setHeightForWidth(self.groupBoxEggRNG7.sizePolicy().hasHeightForWidth()) self.groupBoxEggRNG7.setSizePolicy(sizePolicy2) self.gridLayout_4 = QGridLayout(self.groupBoxEggRNG7) self.gridLayout_4.setObjectName(u"gridLayout_4") self.pushButtonEggUpdate7 = QPushButton(self.groupBoxEggRNG7) self.pushButtonEggUpdate7.setObjectName(u"pushButtonEggUpdate7") self.pushButtonEggUpdate7.setEnabled(False) self.gridLayout_4.addWidget(self.pushButtonEggUpdate7, 0, 0, 1, 2) self.labelEggReady7 = QLabel(self.groupBoxEggRNG7) self.labelEggReady7.setObjectName(u"labelEggReady7") sizePolicy5.setHeightForWidth(self.labelEggReady7.sizePolicy().hasHeightForWidth()) self.labelEggReady7.setSizePolicy(sizePolicy5) self.gridLayout_4.addWidget(self.labelEggReady7, 1, 0, 1, 1) self.labelEggReadyStatus7 = QLabel(self.groupBoxEggRNG7) self.labelEggReadyStatus7.setObjectName(u"labelEggReadyStatus7") self.gridLayout_4.addWidget(self.labelEggReadyStatus7, 1, 1, 1, 1) self.labelEggSeed3_7 = QLabel(self.groupBoxEggRNG7) self.labelEggSeed3_7.setObjectName(u"labelEggSeed3_7") self.gridLayout_4.addWidget(self.labelEggSeed3_7, 2, 0, 1, 1) self.lineEditEggSeed3_7 = QLineEdit(self.groupBoxEggRNG7) self.lineEditEggSeed3_7.setObjectName(u"lineEditEggSeed3_7") sizePolicy5.setHeightForWidth(self.lineEditEggSeed3_7.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed3_7.setSizePolicy(sizePolicy5) self.lineEditEggSeed3_7.setMaxLength(8) self.lineEditEggSeed3_7.setReadOnly(True) self.gridLayout_4.addWidget(self.lineEditEggSeed3_7, 2, 1, 1, 1) self.labelEggSeed2_7 = QLabel(self.groupBoxEggRNG7) self.labelEggSeed2_7.setObjectName(u"labelEggSeed2_7") self.gridLayout_4.addWidget(self.labelEggSeed2_7, 3, 0, 1, 1) self.lineEditEggSeed2_7 = QLineEdit(self.groupBoxEggRNG7) self.lineEditEggSeed2_7.setObjectName(u"lineEditEggSeed2_7") sizePolicy5.setHeightForWidth(self.lineEditEggSeed2_7.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed2_7.setSizePolicy(sizePolicy5) self.lineEditEggSeed2_7.setMaxLength(8) self.lineEditEggSeed2_7.setReadOnly(True) self.gridLayout_4.addWidget(self.lineEditEggSeed2_7, 3, 1, 1, 1) self.labelEggSeed1_7 = QLabel(self.groupBoxEggRNG7) self.labelEggSeed1_7.setObjectName(u"labelEggSeed1_7") self.gridLayout_4.addWidget(self.labelEggSeed1_7, 4, 0, 1, 1) self.lineEditEggSeed1_7 = QLineEdit(self.groupBoxEggRNG7) self.lineEditEggSeed1_7.setObjectName(u"lineEditEggSeed1_7") sizePolicy5.setHeightForWidth(self.lineEditEggSeed1_7.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed1_7.setSizePolicy(sizePolicy5) self.lineEditEggSeed1_7.setMaxLength(8) self.lineEditEggSeed1_7.setReadOnly(True) self.gridLayout_4.addWidget(self.lineEditEggSeed1_7, 4, 1, 1, 1) self.labelEggSeed0_7 = QLabel(self.groupBoxEggRNG7) self.labelEggSeed0_7.setObjectName(u"labelEggSeed0_7") self.gridLayout_4.addWidget(self.labelEggSeed0_7, 5, 0, 1, 1) self.lineEditEggSeed0_7 = QLineEdit(self.groupBoxEggRNG7) self.lineEditEggSeed0_7.setObjectName(u"lineEditEggSeed0_7") sizePolicy5.setHeightForWidth(self.lineEditEggSeed0_7.sizePolicy().hasHeightForWidth()) self.lineEditEggSeed0_7.setSizePolicy(sizePolicy5) self.lineEditEggSeed0_7.setMaxLength(8) self.lineEditEggSeed0_7.setReadOnly(True) self.gridLayout_4.addWidget(self.lineEditEggSeed0_7, 5, 1, 1, 1) self.gridLayout_6.addWidget(self.groupBoxEggRNG7, 0, 2, 2, 1) self.eggParent1_7 = PokemonDisplay(self.tabEgg7) self.eggParent1_7.setObjectName(u"eggParent1_7") sizePolicy2.setHeightForWidth(self.eggParent1_7.sizePolicy().hasHeightForWidth()) self.eggParent1_7.setSizePolicy(sizePolicy2) self.gridLayout_6.addWidget(self.eggParent1_7, 0, 0, 2, 1) self.eggParent2_7 = PokemonDisplay(self.tabEgg7) self.eggParent2_7.setObjectName(u"eggParent2_7") sizePolicy2.setHeightForWidth(self.eggParent2_7.sizePolicy().hasHeightForWidth()) self.eggParent2_7.setSizePolicy(sizePolicy2) self.gridLayout_6.addWidget(self.eggParent2_7, 0, 1, 2, 1) self.tabWidgetGen7.addTab(self.tabEgg7, "") self.tabSOS = QWidget() self.tabSOS.setObjectName(u"tabSOS") self.gridLayout_8 = QGridLayout(self.tabSOS) self.gridLayout_8.setObjectName(u"gridLayout_8") self.comboBoxSOSIndex = QComboBox(self.tabSOS) self.comboBoxSOSIndex.addItem("") self.comboBoxSOSIndex.addItem("") self.comboBoxSOSIndex.addItem("") self.comboBoxSOSIndex.addItem("") self.comboBoxSOSIndex.setObjectName(u"comboBoxSOSIndex") self.comboBoxSOSIndex.setEnabled(False) self.gridLayout_8.addWidget(self.comboBoxSOSIndex, 0, 0, 1, 1) self.groupBoxSOS = QGroupBox(self.tabSOS) self.groupBoxSOS.setObjectName(u"groupBoxSOS") sizePolicy2.setHeightForWidth(self.groupBoxSOS.sizePolicy().hasHeightForWidth()) self.groupBoxSOS.setSizePolicy(sizePolicy2) self.gridLayout_5 = QGridLayout(self.groupBoxSOS) self.gridLayout_5.setObjectName(u"gridLayout_5") self.pushButtonSOSUpdate = QPushButton(self.groupBoxSOS) self.pushButtonSOSUpdate.setObjectName(u"pushButtonSOSUpdate") self.pushButtonSOSUpdate.setEnabled(False) self.gridLayout_5.addWidget(self.pushButtonSOSUpdate, 0, 0, 1, 1) self.pushButtonSOSReset = QPushButton(self.groupBoxSOS) self.pushButtonSOSReset.setObjectName(u"pushButtonSOSReset") self.pushButtonSOSReset.setEnabled(False) self.gridLayout_5.addWidget(self.pushButtonSOSReset, 0, 1, 1, 1) self.labelSOSInitialSeed = QLabel(self.groupBoxSOS) self.labelSOSInitialSeed.setObjectName(u"labelSOSInitialSeed") self.gridLayout_5.addWidget(self.labelSOSInitialSeed, 1, 0, 1, 1) self.lineEditSOSInitialSeed = QLineEdit(self.groupBoxSOS) self.lineEditSOSInitialSeed.setObjectName(u"lineEditSOSInitialSeed") self.lineEditSOSInitialSeed.setMaxLength(8) self.lineEditSOSInitialSeed.setReadOnly(True) self.gridLayout_5.addWidget(self.lineEditSOSInitialSeed, 1, 1, 1, 1) self.labelSOSCurrentSeed = QLabel(self.groupBoxSOS) self.labelSOSCurrentSeed.setObjectName(u"labelSOSCurrentSeed") self.gridLayout_5.addWidget(self.labelSOSCurrentSeed, 2, 0, 1, 1) self.lineEditSOSCurrentSeed = QLineEdit(self.groupBoxSOS) self.lineEditSOSCurrentSeed.setObjectName(u"lineEditSOSCurrentSeed") self.lineEditSOSCurrentSeed.setMaxLength(8) self.lineEditSOSCurrentSeed.setReadOnly(True) self.gridLayout_5.addWidget(self.lineEditSOSCurrentSeed, 2, 1, 1, 1) self.labelSOSFrame = QLabel(self.groupBoxSOS) self.labelSOSFrame.setObjectName(u"labelSOSFrame") self.gridLayout_5.addWidget(self.labelSOSFrame, 3, 0, 1, 1) self.lineEditSOSFrame = QLineEdit(self.groupBoxSOS) self.lineEditSOSFrame.setObjectName(u"lineEditSOSFrame") self.lineEditSOSFrame.setMaxLength(8) self.lineEditSOSFrame.setReadOnly(True) self.gridLayout_5.addWidget(self.lineEditSOSFrame, 3, 1, 1, 1) self.labelSOSChainCount = QLabel(self.groupBoxSOS) self.labelSOSChainCount.setObjectName(u"labelSOSChainCount") self.gridLayout_5.addWidget(self.labelSOSChainCount, 4, 0, 1, 1) self.lineEditSOSChainCount = QLineEdit(self.groupBoxSOS) self.lineEditSOSChainCount.setObjectName(u"lineEditSOSChainCount") self.lineEditSOSChainCount.setMaxLength(8) self.lineEditSOSChainCount.setReadOnly(True) self.gridLayout_5.addWidget(self.lineEditSOSChainCount, 4, 1, 1, 1) self.gridLayout_8.addWidget(self.groupBoxSOS, 0, 1, 2, 1) self.sosPokemon = PokemonDisplay(self.tabSOS) self.sosPokemon.setObjectName(u"sosPokemon") sizePolicy2.setHeightForWidth(self.sosPokemon.sizePolicy().hasHeightForWidth()) self.sosPokemon.setSizePolicy(sizePolicy2) self.gridLayout_8.addWidget(self.sosPokemon, 1, 0, 1, 1) self.tabWidgetGen7.addTab(self.tabSOS, "") self.gridLayout_12.addWidget(self.tabWidgetGen7, 0, 0, 1, 1) self.tabWidget.addTab(self.tabGen7, "") self.gridLayout_10.addWidget(self.tabWidget, 1, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"CitraRNG 3.2.0", None)) self.groupBoxConnection.setTitle(QCoreApplication.translate("MainWindow", u"Connection", None)) self.pushButtonConnect.setText(QCoreApplication.translate("MainWindow", u"Connect", None)) self.labelUpdateDelay.setText(QCoreApplication.translate("MainWindow", u"Auto update delay(seconds):", None)) self.labelStatus.setText(QCoreApplication.translate("MainWindow", u"Status: Not Connected", None)) self.comboBoxGameSelection.setItemText(0, QCoreApplication.translate("MainWindow", u"XY", None)) self.comboBoxGameSelection.setItemText(1, QCoreApplication.translate("MainWindow", u"ORAS", None)) self.comboBoxGameSelection.setItemText(2, QCoreApplication.translate("MainWindow", u"SM", None)) self.comboBoxGameSelection.setItemText(3, QCoreApplication.translate("MainWindow", u"USUM", None)) self.comboBoxMainIndex6.setItemText(0, QCoreApplication.translate("MainWindow", u"Party 1", None)) self.comboBoxMainIndex6.setItemText(1, QCoreApplication.translate("MainWindow", u"Party 2", None)) self.comboBoxMainIndex6.setItemText(2, QCoreApplication.translate("MainWindow", u"Party 3", None)) self.comboBoxMainIndex6.setItemText(3, QCoreApplication.translate("MainWindow", u"Party 4", None)) self.comboBoxMainIndex6.setItemText(4, QCoreApplication.translate("MainWindow", u"Party 5", None)) self.comboBoxMainIndex6.setItemText(5, QCoreApplication.translate("MainWindow", u"Party 6", None)) self.comboBoxMainIndex6.setItemText(6, QCoreApplication.translate("MainWindow", u"Wild", None)) self.groupBoxMainRNG6.setTitle(QCoreApplication.translate("MainWindow", u"Main RNG", None)) self.labelTiny2.setText(QCoreApplication.translate("MainWindow", u"[2]", None)) self.labelTiny0.setText(QCoreApplication.translate("MainWindow", u"[0]", None)) self.labelTiny3.setText(QCoreApplication.translate("MainWindow", u"[3]", None)) self.labelTiny1.setText(QCoreApplication.translate("MainWindow", u"[1]", None)) self.labelMainCurrentSeed6.setText(QCoreApplication.translate("MainWindow", u"Current Seed:", None)) self.labelMainInitialSeed6.setText(QCoreApplication.translate("MainWindow", u"Initial Seed:", None)) self.labelMainFrame6.setText(QCoreApplication.translate("MainWindow", u"Frame:", None)) self.pushButtonMainUpdate6.setText(QCoreApplication.translate("MainWindow", u"Update", None)) self.labelSaveVariable.setText(QCoreApplication.translate("MainWindow", u"Save Variable:", None)) self.tabWidgetGen6.setTabText(self.tabWidgetGen6.indexOf(self.tabMain6), QCoreApplication.translate("MainWindow", u"Main", None)) self.groupBoxEggRNG6.setTitle(QCoreApplication.translate("MainWindow", u"Egg RNG", None)) self.labelEggReady6.setText(QCoreApplication.translate("MainWindow", u"Egg Ready:", None)) self.labelEggReadyStatus6.setText(QCoreApplication.translate("MainWindow", u"No egg yet", None)) self.pushButtonEggUpdate6.setText(QCoreApplication.translate("MainWindow", u"Update", None)) self.labelEggSeed0_6.setText(QCoreApplication.translate("MainWindow", u"[0]", None)) self.labelEggSeed1_6.setText(QCoreApplication.translate("MainWindow", u"[1]", None)) self.tabWidgetGen6.setTabText(self.tabWidgetGen6.indexOf(self.tabEgg6), QCoreApplication.translate("MainWindow", u"Egg", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabGen6), QCoreApplication.translate("MainWindow", u"Gen 6", None)) self.comboBoxMainIndex7.setItemText(0, QCoreApplication.translate("MainWindow", u"Party 1", None)) self.comboBoxMainIndex7.setItemText(1, QCoreApplication.translate("MainWindow", u"Party 2", None)) self.comboBoxMainIndex7.setItemText(2, QCoreApplication.translate("MainWindow", u"Party 3", None)) self.comboBoxMainIndex7.setItemText(3, QCoreApplication.translate("MainWindow", u"Party 4", None)) self.comboBoxMainIndex7.setItemText(4, QCoreApplication.translate("MainWindow", u"Party 5", None)) self.comboBoxMainIndex7.setItemText(5, QCoreApplication.translate("MainWindow", u"Party 6", None)) self.comboBoxMainIndex7.setItemText(6, QCoreApplication.translate("MainWindow", u"Wild", None)) self.groupBoxMainRNG7.setTitle(QCoreApplication.translate("MainWindow", u"Main RNG", None)) self.labelMainInitialSeed7.setText(QCoreApplication.translate("MainWindow", u"Initial Seed:", None)) self.labelMainCurrentSeed7.setText(QCoreApplication.translate("MainWindow", u"Current Seed:", None)) self.labelMainFrame7.setText(QCoreApplication.translate("MainWindow", u"Frame:", None)) self.pushButtonMainUpdate7.setText(QCoreApplication.translate("MainWindow", u"Update", None)) self.tabWidgetGen7.setTabText(self.tabWidgetGen7.indexOf(self.tabMain7), QCoreApplication.translate("MainWindow", u"Main", None)) self.groupBoxEggRNG7.setTitle(QCoreApplication.translate("MainWindow", u"Egg RNG", None)) self.pushButtonEggUpdate7.setText(QCoreApplication.translate("MainWindow", u"Update", None)) self.labelEggReady7.setText(QCoreApplication.translate("MainWindow", u"Egg Ready:", None)) self.labelEggReadyStatus7.setText(QCoreApplication.translate("MainWindow", u"No egg yet", None)) self.labelEggSeed3_7.setText(QCoreApplication.translate("MainWindow", u"[3]", None)) self.labelEggSeed2_7.setText(QCoreApplication.translate("MainWindow", u"[2]", None)) self.labelEggSeed1_7.setText(QCoreApplication.translate("MainWindow", u"[1]", None)) self.labelEggSeed0_7.setText(QCoreApplication.translate("MainWindow", u"[0]", None)) self.tabWidgetGen7.setTabText(self.tabWidgetGen7.indexOf(self.tabEgg7), QCoreApplication.translate("MainWindow", u"Egg", None)) self.comboBoxSOSIndex.setItemText(0, QCoreApplication.translate("MainWindow", u"SOS 1", None)) self.comboBoxSOSIndex.setItemText(1, QCoreApplication.translate("MainWindow", u"SOS 2", None)) self.comboBoxSOSIndex.setItemText(2, QCoreApplication.translate("MainWindow", u"SOS 3", None)) self.comboBoxSOSIndex.setItemText(3, QCoreApplication.translate("MainWindow", u"SOS 4", None)) self.groupBoxSOS.setTitle(QCoreApplication.translate("MainWindow", u"SOS RNG", None)) self.pushButtonSOSUpdate.setText(QCoreApplication.translate("MainWindow", u"Update", None)) #if QT_CONFIG(tooltip) self.pushButtonSOSReset.setToolTip(QCoreApplication.translate("MainWindow", u"This should be used after a battle", None)) #endif // QT_CONFIG(tooltip) self.pushButtonSOSReset.setText(QCoreApplication.translate("MainWindow", u"Reset", None)) self.labelSOSInitialSeed.setText(QCoreApplication.translate("MainWindow", u"Initial Seed:", None)) self.labelSOSCurrentSeed.setText(QCoreApplication.translate("MainWindow", u"Current Seed:", None)) self.labelSOSFrame.setText(QCoreApplication.translate("MainWindow", u"Frame:", None)) self.labelSOSChainCount.setText(QCoreApplication.translate("MainWindow", u"Chain Count:", None)) self.tabWidgetGen7.setTabText(self.tabWidgetGen7.indexOf(self.tabSOS), QCoreApplication.translate("MainWindow", u"SOS", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabGen7), QCoreApplication.translate("MainWindow", u"Gen 7", None))