Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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"))
Ejemplo n.º 3
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")
Ejemplo n.º 4
0
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'])))
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
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,
        )
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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))
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
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))
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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))
Ejemplo n.º 16
0
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 {}
Ejemplo n.º 17
0
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)
Ejemplo n.º 18
0
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()
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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))
Ejemplo n.º 21
0
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
Ejemplo n.º 22
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()
Ejemplo n.º 23
0
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.")
Ejemplo n.º 25
0
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)
Ejemplo n.º 26
0
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
Ejemplo n.º 27
0
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
Ejemplo n.º 28
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))
Ejemplo n.º 29
0
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}")
Ejemplo n.º 30
0
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))