def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.server = FortuneServer() statusLabel = QLabel() statusLabel.setTextInteractionFlags(Qt.TextBrowserInteraction) statusLabel.setWordWrap(True) quitButton = QPushButton("Quit") quitButton.setAutoDefault(False) if not self.server.listen(): QMessageBox.critical( self, "Threaded Fortune Server", "Unable to start the server: %s." % self.server.errorString()) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address( ) != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() statusLabel.setText("The server is running on\n\nIP: %s\nport: %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.server.serverPort())) quitButton.clicked.connect(self.close) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(quitButton) buttonLayout.addStretch(1) mainLayout = QVBoxLayout() mainLayout.addWidget(statusLabel) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("Threaded Fortune Server")
class Controls(QWidget): def __init__(self, parent, init_label, mainfunction, quitfunction): super().__init__(parent) self.button = QPushButton(init_label) self.button.clicked.connect(mainfunction) self.button.setAutoDefault(True) quitbutton = QPushButton('終わる') quitbutton.setStyleSheet('background-color: #c00; color: white;') quitbutton.clicked.connect(quitfunction) layout = QHBoxLayout() layout.addWidget(self.button) layout.addWidget(quitbutton) self.setLayout(layout) def set_button(self, label): self.button.setText(label) def hide_button(self): self.button.hide()
class Ui_Config(object): def setupUi(self, Config): if not Config.objectName(): Config.setObjectName(u"Config") Config.resize(600, 650) Config.setSizeGripEnabled(True) self.vboxLayout = QVBoxLayout(Config) self.vboxLayout.setSpacing(6) self.vboxLayout.setContentsMargins(11, 11, 11, 11) self.vboxLayout.setObjectName(u"vboxLayout") self.vboxLayout.setContentsMargins(8, 8, 8, 8) self.hboxLayout = QHBoxLayout() self.hboxLayout.setSpacing(6) self.hboxLayout.setObjectName(u"hboxLayout") self.hboxLayout.setContentsMargins(0, 0, 0, 0) self.ButtonGroup1 = QGroupBox(Config) self.ButtonGroup1.setObjectName(u"ButtonGroup1") sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.ButtonGroup1.sizePolicy().hasHeightForWidth()) self.ButtonGroup1.setSizePolicy(sizePolicy) self.vboxLayout1 = QVBoxLayout(self.ButtonGroup1) self.vboxLayout1.setSpacing(6) self.vboxLayout1.setContentsMargins(11, 11, 11, 11) self.vboxLayout1.setObjectName(u"vboxLayout1") self.vboxLayout1.setContentsMargins(11, 11, 11, 11) self.size_176_220 = QRadioButton(self.ButtonGroup1) self.size_176_220.setObjectName(u"size_176_220") self.vboxLayout1.addWidget(self.size_176_220) self.size_240_320 = QRadioButton(self.ButtonGroup1) self.size_240_320.setObjectName(u"size_240_320") self.vboxLayout1.addWidget(self.size_240_320) self.size_320_240 = QRadioButton(self.ButtonGroup1) self.size_320_240.setObjectName(u"size_320_240") self.vboxLayout1.addWidget(self.size_320_240) self.size_640_480 = QRadioButton(self.ButtonGroup1) self.size_640_480.setObjectName(u"size_640_480") self.vboxLayout1.addWidget(self.size_640_480) self.size_800_600 = QRadioButton(self.ButtonGroup1) self.size_800_600.setObjectName(u"size_800_600") self.vboxLayout1.addWidget(self.size_800_600) self.size_1024_768 = QRadioButton(self.ButtonGroup1) self.size_1024_768.setObjectName(u"size_1024_768") self.vboxLayout1.addWidget(self.size_1024_768) self.hboxLayout1 = QHBoxLayout() self.hboxLayout1.setSpacing(6) self.hboxLayout1.setObjectName(u"hboxLayout1") self.hboxLayout1.setContentsMargins(0, 0, 0, 0) self.size_custom = QRadioButton(self.ButtonGroup1) self.size_custom.setObjectName(u"size_custom") sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth( self.size_custom.sizePolicy().hasHeightForWidth()) self.size_custom.setSizePolicy(sizePolicy1) self.hboxLayout1.addWidget(self.size_custom) self.size_width = QSpinBox(self.ButtonGroup1) self.size_width.setObjectName(u"size_width") self.size_width.setMinimum(1) self.size_width.setMaximum(1280) self.size_width.setSingleStep(16) self.size_width.setValue(400) self.hboxLayout1.addWidget(self.size_width) self.size_height = QSpinBox(self.ButtonGroup1) self.size_height.setObjectName(u"size_height") self.size_height.setMinimum(1) self.size_height.setMaximum(1024) self.size_height.setSingleStep(16) self.size_height.setValue(300) self.hboxLayout1.addWidget(self.size_height) self.vboxLayout1.addLayout(self.hboxLayout1) self.hboxLayout.addWidget(self.ButtonGroup1) self.ButtonGroup2 = QGroupBox(Config) self.ButtonGroup2.setObjectName(u"ButtonGroup2") self.vboxLayout2 = QVBoxLayout(self.ButtonGroup2) self.vboxLayout2.setSpacing(6) self.vboxLayout2.setContentsMargins(11, 11, 11, 11) self.vboxLayout2.setObjectName(u"vboxLayout2") self.vboxLayout2.setContentsMargins(11, 11, 11, 11) self.depth_1 = QRadioButton(self.ButtonGroup2) self.depth_1.setObjectName(u"depth_1") self.vboxLayout2.addWidget(self.depth_1) self.depth_4gray = QRadioButton(self.ButtonGroup2) self.depth_4gray.setObjectName(u"depth_4gray") self.vboxLayout2.addWidget(self.depth_4gray) self.depth_8 = QRadioButton(self.ButtonGroup2) self.depth_8.setObjectName(u"depth_8") self.vboxLayout2.addWidget(self.depth_8) self.depth_12 = QRadioButton(self.ButtonGroup2) self.depth_12.setObjectName(u"depth_12") self.vboxLayout2.addWidget(self.depth_12) self.depth_15 = QRadioButton(self.ButtonGroup2) self.depth_15.setObjectName(u"depth_15") self.vboxLayout2.addWidget(self.depth_15) self.depth_16 = QRadioButton(self.ButtonGroup2) self.depth_16.setObjectName(u"depth_16") self.vboxLayout2.addWidget(self.depth_16) self.depth_18 = QRadioButton(self.ButtonGroup2) self.depth_18.setObjectName(u"depth_18") self.vboxLayout2.addWidget(self.depth_18) self.depth_24 = QRadioButton(self.ButtonGroup2) self.depth_24.setObjectName(u"depth_24") self.vboxLayout2.addWidget(self.depth_24) self.depth_32 = QRadioButton(self.ButtonGroup2) self.depth_32.setObjectName(u"depth_32") self.vboxLayout2.addWidget(self.depth_32) self.depth_32_argb = QRadioButton(self.ButtonGroup2) self.depth_32_argb.setObjectName(u"depth_32_argb") self.vboxLayout2.addWidget(self.depth_32_argb) self.hboxLayout.addWidget(self.ButtonGroup2) self.vboxLayout.addLayout(self.hboxLayout) self.hboxLayout2 = QHBoxLayout() self.hboxLayout2.setSpacing(6) self.hboxLayout2.setObjectName(u"hboxLayout2") self.hboxLayout2.setContentsMargins(0, 0, 0, 0) self.TextLabel1_3 = QLabel(Config) self.TextLabel1_3.setObjectName(u"TextLabel1_3") self.hboxLayout2.addWidget(self.TextLabel1_3) self.skin = QComboBox(Config) self.skin.addItem("") self.skin.setObjectName(u"skin") sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy2.setHorizontalStretch(0) sizePolicy2.setVerticalStretch(0) sizePolicy2.setHeightForWidth( self.skin.sizePolicy().hasHeightForWidth()) self.skin.setSizePolicy(sizePolicy2) self.hboxLayout2.addWidget(self.skin) self.vboxLayout.addLayout(self.hboxLayout2) self.touchScreen = QCheckBox(Config) self.touchScreen.setObjectName(u"touchScreen") self.vboxLayout.addWidget(self.touchScreen) self.lcdScreen = QCheckBox(Config) self.lcdScreen.setObjectName(u"lcdScreen") self.vboxLayout.addWidget(self.lcdScreen) self.spacerItem = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxLayout.addItem(self.spacerItem) self.TextLabel1 = QLabel(Config) self.TextLabel1.setObjectName(u"TextLabel1") sizePolicy.setHeightForWidth( self.TextLabel1.sizePolicy().hasHeightForWidth()) self.TextLabel1.setSizePolicy(sizePolicy) self.TextLabel1.setWordWrap(True) self.vboxLayout.addWidget(self.TextLabel1) self.GroupBox1 = QGroupBox(Config) self.GroupBox1.setObjectName(u"GroupBox1") self.gridLayout = QGridLayout(self.GroupBox1) self.gridLayout.setSpacing(6) self.gridLayout.setContentsMargins(11, 11, 11, 11) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setHorizontalSpacing(6) self.gridLayout.setVerticalSpacing(6) self.gridLayout.setContentsMargins(11, 11, 11, 11) self.TextLabel3 = QLabel(self.GroupBox1) self.TextLabel3.setObjectName(u"TextLabel3") self.gridLayout.addWidget(self.TextLabel3, 6, 0, 1, 1) self.bslider = QSlider(self.GroupBox1) self.bslider.setObjectName(u"bslider") palette = QPalette() brush = QBrush(QColor(128, 128, 128, 255)) brush.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.WindowText, brush) brush1 = QBrush(QColor(0, 0, 255, 255)) brush1.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Button, brush1) brush2 = QBrush(QColor(127, 127, 255, 255)) brush2.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Light, brush2) brush3 = QBrush(QColor(38, 38, 255, 255)) brush3.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Midlight, brush3) brush4 = QBrush(QColor(0, 0, 127, 255)) brush4.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Dark, brush4) brush5 = QBrush(QColor(0, 0, 170, 255)) brush5.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Mid, brush5) brush6 = QBrush(QColor(0, 0, 0, 255)) brush6.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Text, brush6) brush7 = QBrush(QColor(255, 255, 255, 255)) brush7.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.BrightText, brush7) palette.setBrush(QPalette.Active, QPalette.ButtonText, brush) palette.setBrush(QPalette.Active, QPalette.Base, brush7) brush8 = QBrush(QColor(220, 220, 220, 255)) brush8.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Window, brush8) palette.setBrush(QPalette.Active, QPalette.Shadow, brush6) brush9 = QBrush(QColor(10, 95, 137, 255)) brush9.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.Highlight, brush9) palette.setBrush(QPalette.Active, QPalette.HighlightedText, brush7) palette.setBrush(QPalette.Active, QPalette.Link, brush6) palette.setBrush(QPalette.Active, QPalette.LinkVisited, brush6) brush10 = QBrush(QColor(232, 232, 232, 255)) brush10.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Active, QPalette.AlternateBase, brush10) palette.setBrush(QPalette.Inactive, QPalette.WindowText, brush) palette.setBrush(QPalette.Inactive, QPalette.Button, brush1) palette.setBrush(QPalette.Inactive, QPalette.Light, brush2) palette.setBrush(QPalette.Inactive, QPalette.Midlight, brush3) palette.setBrush(QPalette.Inactive, QPalette.Dark, brush4) palette.setBrush(QPalette.Inactive, QPalette.Mid, brush5) palette.setBrush(QPalette.Inactive, QPalette.Text, brush6) palette.setBrush(QPalette.Inactive, QPalette.BrightText, brush7) palette.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) palette.setBrush(QPalette.Inactive, QPalette.Base, brush7) palette.setBrush(QPalette.Inactive, QPalette.Window, brush8) palette.setBrush(QPalette.Inactive, QPalette.Shadow, brush6) palette.setBrush(QPalette.Inactive, QPalette.Highlight, brush9) palette.setBrush(QPalette.Inactive, QPalette.HighlightedText, brush7) palette.setBrush(QPalette.Inactive, QPalette.Link, brush6) palette.setBrush(QPalette.Inactive, QPalette.LinkVisited, brush6) palette.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush10) palette.setBrush(QPalette.Disabled, QPalette.WindowText, brush) palette.setBrush(QPalette.Disabled, QPalette.Button, brush1) palette.setBrush(QPalette.Disabled, QPalette.Light, brush2) palette.setBrush(QPalette.Disabled, QPalette.Midlight, brush3) palette.setBrush(QPalette.Disabled, QPalette.Dark, brush4) palette.setBrush(QPalette.Disabled, QPalette.Mid, brush5) palette.setBrush(QPalette.Disabled, QPalette.Text, brush6) palette.setBrush(QPalette.Disabled, QPalette.BrightText, brush7) palette.setBrush(QPalette.Disabled, QPalette.ButtonText, brush) palette.setBrush(QPalette.Disabled, QPalette.Base, brush7) palette.setBrush(QPalette.Disabled, QPalette.Window, brush8) palette.setBrush(QPalette.Disabled, QPalette.Shadow, brush6) palette.setBrush(QPalette.Disabled, QPalette.Highlight, brush9) palette.setBrush(QPalette.Disabled, QPalette.HighlightedText, brush7) palette.setBrush(QPalette.Disabled, QPalette.Link, brush6) palette.setBrush(QPalette.Disabled, QPalette.LinkVisited, brush6) palette.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush10) self.bslider.setPalette(palette) self.bslider.setMaximum(400) self.bslider.setValue(100) self.bslider.setOrientation(Qt.Horizontal) self.gridLayout.addWidget(self.bslider, 6, 1, 1, 1) self.blabel = QLabel(self.GroupBox1) self.blabel.setObjectName(u"blabel") self.gridLayout.addWidget(self.blabel, 6, 2, 1, 1) self.TextLabel2 = QLabel(self.GroupBox1) self.TextLabel2.setObjectName(u"TextLabel2") self.gridLayout.addWidget(self.TextLabel2, 4, 0, 1, 1) self.gslider = QSlider(self.GroupBox1) self.gslider.setObjectName(u"gslider") palette1 = QPalette() palette1.setBrush(QPalette.Active, QPalette.WindowText, brush) brush11 = QBrush(QColor(0, 255, 0, 255)) brush11.setStyle(Qt.SolidPattern) palette1.setBrush(QPalette.Active, QPalette.Button, brush11) brush12 = QBrush(QColor(127, 255, 127, 255)) brush12.setStyle(Qt.SolidPattern) palette1.setBrush(QPalette.Active, QPalette.Light, brush12) brush13 = QBrush(QColor(38, 255, 38, 255)) brush13.setStyle(Qt.SolidPattern) palette1.setBrush(QPalette.Active, QPalette.Midlight, brush13) brush14 = QBrush(QColor(0, 127, 0, 255)) brush14.setStyle(Qt.SolidPattern) palette1.setBrush(QPalette.Active, QPalette.Dark, brush14) brush15 = QBrush(QColor(0, 170, 0, 255)) brush15.setStyle(Qt.SolidPattern) palette1.setBrush(QPalette.Active, QPalette.Mid, brush15) palette1.setBrush(QPalette.Active, QPalette.Text, brush6) palette1.setBrush(QPalette.Active, QPalette.BrightText, brush7) palette1.setBrush(QPalette.Active, QPalette.ButtonText, brush) palette1.setBrush(QPalette.Active, QPalette.Base, brush7) palette1.setBrush(QPalette.Active, QPalette.Window, brush8) palette1.setBrush(QPalette.Active, QPalette.Shadow, brush6) palette1.setBrush(QPalette.Active, QPalette.Highlight, brush9) palette1.setBrush(QPalette.Active, QPalette.HighlightedText, brush7) palette1.setBrush(QPalette.Active, QPalette.Link, brush6) palette1.setBrush(QPalette.Active, QPalette.LinkVisited, brush6) palette1.setBrush(QPalette.Active, QPalette.AlternateBase, brush10) palette1.setBrush(QPalette.Inactive, QPalette.WindowText, brush) palette1.setBrush(QPalette.Inactive, QPalette.Button, brush11) palette1.setBrush(QPalette.Inactive, QPalette.Light, brush12) palette1.setBrush(QPalette.Inactive, QPalette.Midlight, brush13) palette1.setBrush(QPalette.Inactive, QPalette.Dark, brush14) palette1.setBrush(QPalette.Inactive, QPalette.Mid, brush15) palette1.setBrush(QPalette.Inactive, QPalette.Text, brush6) palette1.setBrush(QPalette.Inactive, QPalette.BrightText, brush7) palette1.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) palette1.setBrush(QPalette.Inactive, QPalette.Base, brush7) palette1.setBrush(QPalette.Inactive, QPalette.Window, brush8) palette1.setBrush(QPalette.Inactive, QPalette.Shadow, brush6) palette1.setBrush(QPalette.Inactive, QPalette.Highlight, brush9) palette1.setBrush(QPalette.Inactive, QPalette.HighlightedText, brush7) palette1.setBrush(QPalette.Inactive, QPalette.Link, brush6) palette1.setBrush(QPalette.Inactive, QPalette.LinkVisited, brush6) palette1.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush10) palette1.setBrush(QPalette.Disabled, QPalette.WindowText, brush) palette1.setBrush(QPalette.Disabled, QPalette.Button, brush11) palette1.setBrush(QPalette.Disabled, QPalette.Light, brush12) palette1.setBrush(QPalette.Disabled, QPalette.Midlight, brush13) palette1.setBrush(QPalette.Disabled, QPalette.Dark, brush14) palette1.setBrush(QPalette.Disabled, QPalette.Mid, brush15) palette1.setBrush(QPalette.Disabled, QPalette.Text, brush6) palette1.setBrush(QPalette.Disabled, QPalette.BrightText, brush7) palette1.setBrush(QPalette.Disabled, QPalette.ButtonText, brush) palette1.setBrush(QPalette.Disabled, QPalette.Base, brush7) palette1.setBrush(QPalette.Disabled, QPalette.Window, brush8) palette1.setBrush(QPalette.Disabled, QPalette.Shadow, brush6) palette1.setBrush(QPalette.Disabled, QPalette.Highlight, brush9) palette1.setBrush(QPalette.Disabled, QPalette.HighlightedText, brush7) palette1.setBrush(QPalette.Disabled, QPalette.Link, brush6) palette1.setBrush(QPalette.Disabled, QPalette.LinkVisited, brush6) palette1.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush10) self.gslider.setPalette(palette1) self.gslider.setMaximum(400) self.gslider.setValue(100) self.gslider.setOrientation(Qt.Horizontal) self.gridLayout.addWidget(self.gslider, 4, 1, 1, 1) self.glabel = QLabel(self.GroupBox1) self.glabel.setObjectName(u"glabel") self.gridLayout.addWidget(self.glabel, 4, 2, 1, 1) self.TextLabel7 = QLabel(self.GroupBox1) self.TextLabel7.setObjectName(u"TextLabel7") self.gridLayout.addWidget(self.TextLabel7, 0, 0, 1, 1) self.TextLabel8 = QLabel(self.GroupBox1) self.TextLabel8.setObjectName(u"TextLabel8") self.gridLayout.addWidget(self.TextLabel8, 0, 2, 1, 1) self.gammaslider = QSlider(self.GroupBox1) self.gammaslider.setObjectName(u"gammaslider") palette2 = QPalette() palette2.setBrush(QPalette.Active, QPalette.WindowText, brush) palette2.setBrush(QPalette.Active, QPalette.Button, brush7) palette2.setBrush(QPalette.Active, QPalette.Light, brush7) palette2.setBrush(QPalette.Active, QPalette.Midlight, brush7) brush16 = QBrush(QColor(127, 127, 127, 255)) brush16.setStyle(Qt.SolidPattern) palette2.setBrush(QPalette.Active, QPalette.Dark, brush16) brush17 = QBrush(QColor(170, 170, 170, 255)) brush17.setStyle(Qt.SolidPattern) palette2.setBrush(QPalette.Active, QPalette.Mid, brush17) palette2.setBrush(QPalette.Active, QPalette.Text, brush6) palette2.setBrush(QPalette.Active, QPalette.BrightText, brush7) palette2.setBrush(QPalette.Active, QPalette.ButtonText, brush) palette2.setBrush(QPalette.Active, QPalette.Base, brush7) palette2.setBrush(QPalette.Active, QPalette.Window, brush8) palette2.setBrush(QPalette.Active, QPalette.Shadow, brush6) palette2.setBrush(QPalette.Active, QPalette.Highlight, brush9) palette2.setBrush(QPalette.Active, QPalette.HighlightedText, brush7) palette2.setBrush(QPalette.Active, QPalette.Link, brush6) palette2.setBrush(QPalette.Active, QPalette.LinkVisited, brush6) palette2.setBrush(QPalette.Active, QPalette.AlternateBase, brush10) palette2.setBrush(QPalette.Inactive, QPalette.WindowText, brush) palette2.setBrush(QPalette.Inactive, QPalette.Button, brush7) palette2.setBrush(QPalette.Inactive, QPalette.Light, brush7) palette2.setBrush(QPalette.Inactive, QPalette.Midlight, brush7) palette2.setBrush(QPalette.Inactive, QPalette.Dark, brush16) palette2.setBrush(QPalette.Inactive, QPalette.Mid, brush17) palette2.setBrush(QPalette.Inactive, QPalette.Text, brush6) palette2.setBrush(QPalette.Inactive, QPalette.BrightText, brush7) palette2.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) palette2.setBrush(QPalette.Inactive, QPalette.Base, brush7) palette2.setBrush(QPalette.Inactive, QPalette.Window, brush8) palette2.setBrush(QPalette.Inactive, QPalette.Shadow, brush6) palette2.setBrush(QPalette.Inactive, QPalette.Highlight, brush9) palette2.setBrush(QPalette.Inactive, QPalette.HighlightedText, brush7) palette2.setBrush(QPalette.Inactive, QPalette.Link, brush6) palette2.setBrush(QPalette.Inactive, QPalette.LinkVisited, brush6) palette2.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush10) palette2.setBrush(QPalette.Disabled, QPalette.WindowText, brush) palette2.setBrush(QPalette.Disabled, QPalette.Button, brush7) palette2.setBrush(QPalette.Disabled, QPalette.Light, brush7) palette2.setBrush(QPalette.Disabled, QPalette.Midlight, brush7) palette2.setBrush(QPalette.Disabled, QPalette.Dark, brush16) palette2.setBrush(QPalette.Disabled, QPalette.Mid, brush17) palette2.setBrush(QPalette.Disabled, QPalette.Text, brush6) palette2.setBrush(QPalette.Disabled, QPalette.BrightText, brush7) palette2.setBrush(QPalette.Disabled, QPalette.ButtonText, brush) palette2.setBrush(QPalette.Disabled, QPalette.Base, brush7) palette2.setBrush(QPalette.Disabled, QPalette.Window, brush8) palette2.setBrush(QPalette.Disabled, QPalette.Shadow, brush6) palette2.setBrush(QPalette.Disabled, QPalette.Highlight, brush9) palette2.setBrush(QPalette.Disabled, QPalette.HighlightedText, brush7) palette2.setBrush(QPalette.Disabled, QPalette.Link, brush6) palette2.setBrush(QPalette.Disabled, QPalette.LinkVisited, brush6) palette2.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush10) self.gammaslider.setPalette(palette2) self.gammaslider.setMaximum(400) self.gammaslider.setValue(100) self.gammaslider.setOrientation(Qt.Horizontal) self.gridLayout.addWidget(self.gammaslider, 0, 1, 1, 1) self.TextLabel1_2 = QLabel(self.GroupBox1) self.TextLabel1_2.setObjectName(u"TextLabel1_2") self.gridLayout.addWidget(self.TextLabel1_2, 2, 0, 1, 1) self.rlabel = QLabel(self.GroupBox1) self.rlabel.setObjectName(u"rlabel") self.gridLayout.addWidget(self.rlabel, 2, 2, 1, 1) self.rslider = QSlider(self.GroupBox1) self.rslider.setObjectName(u"rslider") palette3 = QPalette() palette3.setBrush(QPalette.Active, QPalette.WindowText, brush) brush18 = QBrush(QColor(255, 0, 0, 255)) brush18.setStyle(Qt.SolidPattern) palette3.setBrush(QPalette.Active, QPalette.Button, brush18) brush19 = QBrush(QColor(255, 127, 127, 255)) brush19.setStyle(Qt.SolidPattern) palette3.setBrush(QPalette.Active, QPalette.Light, brush19) brush20 = QBrush(QColor(255, 38, 38, 255)) brush20.setStyle(Qt.SolidPattern) palette3.setBrush(QPalette.Active, QPalette.Midlight, brush20) brush21 = QBrush(QColor(127, 0, 0, 255)) brush21.setStyle(Qt.SolidPattern) palette3.setBrush(QPalette.Active, QPalette.Dark, brush21) brush22 = QBrush(QColor(170, 0, 0, 255)) brush22.setStyle(Qt.SolidPattern) palette3.setBrush(QPalette.Active, QPalette.Mid, brush22) palette3.setBrush(QPalette.Active, QPalette.Text, brush6) palette3.setBrush(QPalette.Active, QPalette.BrightText, brush7) palette3.setBrush(QPalette.Active, QPalette.ButtonText, brush) palette3.setBrush(QPalette.Active, QPalette.Base, brush7) palette3.setBrush(QPalette.Active, QPalette.Window, brush8) palette3.setBrush(QPalette.Active, QPalette.Shadow, brush6) palette3.setBrush(QPalette.Active, QPalette.Highlight, brush9) palette3.setBrush(QPalette.Active, QPalette.HighlightedText, brush7) palette3.setBrush(QPalette.Active, QPalette.Link, brush6) palette3.setBrush(QPalette.Active, QPalette.LinkVisited, brush6) palette3.setBrush(QPalette.Active, QPalette.AlternateBase, brush10) palette3.setBrush(QPalette.Inactive, QPalette.WindowText, brush) palette3.setBrush(QPalette.Inactive, QPalette.Button, brush18) palette3.setBrush(QPalette.Inactive, QPalette.Light, brush19) palette3.setBrush(QPalette.Inactive, QPalette.Midlight, brush20) palette3.setBrush(QPalette.Inactive, QPalette.Dark, brush21) palette3.setBrush(QPalette.Inactive, QPalette.Mid, brush22) palette3.setBrush(QPalette.Inactive, QPalette.Text, brush6) palette3.setBrush(QPalette.Inactive, QPalette.BrightText, brush7) palette3.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) palette3.setBrush(QPalette.Inactive, QPalette.Base, brush7) palette3.setBrush(QPalette.Inactive, QPalette.Window, brush8) palette3.setBrush(QPalette.Inactive, QPalette.Shadow, brush6) palette3.setBrush(QPalette.Inactive, QPalette.Highlight, brush9) palette3.setBrush(QPalette.Inactive, QPalette.HighlightedText, brush7) palette3.setBrush(QPalette.Inactive, QPalette.Link, brush6) palette3.setBrush(QPalette.Inactive, QPalette.LinkVisited, brush6) palette3.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush10) palette3.setBrush(QPalette.Disabled, QPalette.WindowText, brush) palette3.setBrush(QPalette.Disabled, QPalette.Button, brush18) palette3.setBrush(QPalette.Disabled, QPalette.Light, brush19) palette3.setBrush(QPalette.Disabled, QPalette.Midlight, brush20) palette3.setBrush(QPalette.Disabled, QPalette.Dark, brush21) palette3.setBrush(QPalette.Disabled, QPalette.Mid, brush22) palette3.setBrush(QPalette.Disabled, QPalette.Text, brush6) palette3.setBrush(QPalette.Disabled, QPalette.BrightText, brush7) palette3.setBrush(QPalette.Disabled, QPalette.ButtonText, brush) palette3.setBrush(QPalette.Disabled, QPalette.Base, brush7) palette3.setBrush(QPalette.Disabled, QPalette.Window, brush8) palette3.setBrush(QPalette.Disabled, QPalette.Shadow, brush6) palette3.setBrush(QPalette.Disabled, QPalette.Highlight, brush9) palette3.setBrush(QPalette.Disabled, QPalette.HighlightedText, brush7) palette3.setBrush(QPalette.Disabled, QPalette.Link, brush6) palette3.setBrush(QPalette.Disabled, QPalette.LinkVisited, brush6) palette3.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush10) self.rslider.setPalette(palette3) self.rslider.setMaximum(400) self.rslider.setValue(100) self.rslider.setOrientation(Qt.Horizontal) self.gridLayout.addWidget(self.rslider, 2, 1, 1, 1) self.PushButton3 = QPushButton(self.GroupBox1) self.PushButton3.setObjectName(u"PushButton3") self.gridLayout.addWidget(self.PushButton3, 8, 0, 1, 3) self.MyCustomWidget1 = GammaView(self.GroupBox1) self.MyCustomWidget1.setObjectName(u"MyCustomWidget1") self.gridLayout.addWidget(self.MyCustomWidget1, 0, 3, 9, 1) self.vboxLayout.addWidget(self.GroupBox1) self.hboxLayout3 = QHBoxLayout() self.hboxLayout3.setSpacing(6) self.hboxLayout3.setObjectName(u"hboxLayout3") self.hboxLayout3.setContentsMargins(0, 0, 0, 0) self.spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.hboxLayout3.addItem(self.spacerItem1) self.buttonOk = QPushButton(Config) self.buttonOk.setObjectName(u"buttonOk") self.buttonOk.setAutoDefault(True) self.hboxLayout3.addWidget(self.buttonOk) self.buttonCancel = QPushButton(Config) self.buttonCancel.setObjectName(u"buttonCancel") self.buttonCancel.setAutoDefault(True) self.hboxLayout3.addWidget(self.buttonCancel) self.vboxLayout.addLayout(self.hboxLayout3) self.retranslateUi(Config) self.size_width.valueChanged.connect(self.size_custom.click) self.size_height.valueChanged.connect(self.size_custom.click) self.buttonOk.setDefault(True) QMetaObject.connectSlotsByName(Config) # setupUi def retranslateUi(self, Config): Config.setWindowTitle( QCoreApplication.translate("Config", u"Configure", None)) self.ButtonGroup1.setTitle( QCoreApplication.translate("Config", u"Size", None)) self.size_176_220.setText( QCoreApplication.translate("Config", u"176x220 \"SmartPhone\"", None)) self.size_240_320.setText( QCoreApplication.translate("Config", u"240x320 \"PDA\"", None)) self.size_320_240.setText( QCoreApplication.translate("Config", u"320x240 \"TV\" / \"QVGA\"", None)) self.size_640_480.setText( QCoreApplication.translate("Config", u"640x480 \"VGA\"", None)) self.size_800_600.setText( QCoreApplication.translate("Config", u"800x600", None)) self.size_1024_768.setText( QCoreApplication.translate("Config", u"1024x768", None)) self.size_custom.setText( QCoreApplication.translate("Config", u"Custom", None)) self.ButtonGroup2.setTitle( QCoreApplication.translate("Config", u"Depth", None)) self.depth_1.setText( QCoreApplication.translate("Config", u"1 bit monochrome", None)) self.depth_4gray.setText( QCoreApplication.translate("Config", u"4 bit grayscale", None)) self.depth_8.setText( QCoreApplication.translate("Config", u"8 bit", None)) self.depth_12.setText( QCoreApplication.translate("Config", u"12 (16) bit", None)) self.depth_15.setText( QCoreApplication.translate("Config", u"15 bit", None)) self.depth_16.setText( QCoreApplication.translate("Config", u"16 bit", None)) self.depth_18.setText( QCoreApplication.translate("Config", u"18 bit", None)) self.depth_24.setText( QCoreApplication.translate("Config", u"24 bit", None)) self.depth_32.setText( QCoreApplication.translate("Config", u"32 bit", None)) self.depth_32_argb.setText( QCoreApplication.translate("Config", u"32 bit ARGB", None)) self.TextLabel1_3.setText( QCoreApplication.translate("Config", u"Skin", None)) self.skin.setItemText( 0, QCoreApplication.translate("Config", u"None", None)) self.touchScreen.setText( QCoreApplication.translate( "Config", u"Emulate touch screen (no mouse move)", None)) self.lcdScreen.setText( QCoreApplication.translate( "Config", u"Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", None)) self.TextLabel1.setText( QCoreApplication.translate( "Config", u"<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", None)) self.GroupBox1.setTitle( QCoreApplication.translate("Config", u"Gamma", None)) self.TextLabel3.setText( QCoreApplication.translate("Config", u"Blue", None)) self.blabel.setText(QCoreApplication.translate("Config", u"1.0", None)) self.TextLabel2.setText( QCoreApplication.translate("Config", u"Green", None)) self.glabel.setText(QCoreApplication.translate("Config", u"1.0", None)) self.TextLabel7.setText( QCoreApplication.translate("Config", u"All", None)) self.TextLabel8.setText( QCoreApplication.translate("Config", u"1.0", None)) self.TextLabel1_2.setText( QCoreApplication.translate("Config", u"Red", None)) self.rlabel.setText(QCoreApplication.translate("Config", u"1.0", None)) self.PushButton3.setText( QCoreApplication.translate("Config", u"Set all to 1.0", None)) self.buttonOk.setText( QCoreApplication.translate("Config", u"&OK", None)) self.buttonCancel.setText( QCoreApplication.translate("Config", u"&Cancel", None))
class SettingsWindow(QDialog): def __init__(self, parent: Optional[QWidget] = None, firstStart: bool = False) -> None: super().__init__(parent, ) if parent: self.setWindowTitle('Settings') else: self.setWindowTitle(getTitleString('Settings')) self.setAttribute(Qt.WA_DeleteOnClose) settings = QSettings() mainLayout = QVBoxLayout(self) mainLayout.setContentsMargins(5, 5, 5, 5) # First Start info if firstStart: firstStartInfo = QLabel( ''' <p><strong>Hello! It looks like this is your first time using w3modmanager, or the game installation path recently changed.</strong></p> <p> Please review the settings below. </p> ''', self) firstStartInfo.setWordWrap(True) firstStartInfo.setContentsMargins(10, 10, 10, 10) firstStartInfo.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) mainLayout.addWidget(firstStartInfo) # Game gbGame = QGroupBox('Game Path', self) mainLayout.addWidget(gbGame) gbGameLayout = QVBoxLayout(gbGame) gamePathLayout = QHBoxLayout() self.gamePath = QLineEdit(self) self.gamePath.setPlaceholderText('Path to witcher3.exe...') if settings.value('gamePath'): self.gamePath.setText(str(settings.value('gamePath'))) self.gamePath.textChanged.connect( lambda: self.validateGamePath(self.gamePath.text())) gamePathLayout.addWidget(self.gamePath) self.locateGame = QPushButton('Detect', self) self.locateGame.clicked.connect(self.locateGameEvent) self.locateGame.setToolTip( 'Automatically detect the game path if possible') gamePathLayout.addWidget(self.locateGame) selectGame = QPushButton('Browse', self) selectGame.clicked.connect(self.selectGameEvent) gamePathLayout.addWidget(selectGame) gbGameLayout.addLayout(gamePathLayout) gamePathInfoLayout = QHBoxLayout() self.gamePathInfo = QLabel('', self) self.gamePathInfo.setContentsMargins(4, 4, 4, 4) self.gamePathInfo.setMinimumHeight(40) self.gamePathInfo.setWordWrap(True) gamePathInfoLayout.addWidget(self.gamePathInfo) gbGameLayout.addLayout(gamePathInfoLayout) # Config gbConfig = QGroupBox('Game Config', self) mainLayout.addWidget(gbConfig) gbConfigLayout = QVBoxLayout(gbConfig) configPathLayout = QHBoxLayout() self.configPath = QLineEdit(self) self.configPath.setPlaceholderText('Path to config folder...') if settings.value('configPath'): self.configPath.setText(str(settings.value('configPath'))) self.configPath.textChanged.connect( lambda: self.validateConfigPath(self.configPath.text())) configPathLayout.addWidget(self.configPath) self.locateConfig = QPushButton('Detect', self) self.locateConfig.clicked.connect(self.locateConfigEvent) self.locateConfig.setToolTip( 'Automatically detect the config folder if possible') configPathLayout.addWidget(self.locateConfig) selectConfig = QPushButton('Browse', self) selectConfig.clicked.connect(self.selectConfigEvent) configPathLayout.addWidget(selectConfig) gbConfigLayout.addLayout(configPathLayout) configPathInfoLayout = QHBoxLayout() self.configPathInfo = QLabel('', self) self.configPathInfo.setContentsMargins(4, 4, 4, 4) self.configPathInfo.setMinimumHeight(40) self.configPathInfo.setWordWrap(True) configPathInfoLayout.addWidget(self.configPathInfo) gbConfigLayout.addLayout(configPathInfoLayout) # Script Merger gbScriptMerger = QGroupBox('Script Merger', self) mainLayout.addWidget(gbScriptMerger) gbScriptMergerLayout = QVBoxLayout(gbScriptMerger) scriptMergerPathLayout = QHBoxLayout() self.scriptMergerPath = QLineEdit(self) self.scriptMergerPath.setPlaceholderText( 'Path to WitcherScriptMerger.exe...') if settings.value('scriptMergerPath'): self.scriptMergerPath.setText( str(settings.value('scriptMergerPath'))) self.scriptMergerPath.textChanged.connect( lambda: self.validateScriptMergerPath(self.scriptMergerPath.text() )) scriptMergerPathLayout.addWidget(self.scriptMergerPath) self.locateScriptMerger = QPushButton('Detect', self) self.locateScriptMerger.clicked.connect(self.locateScriptMergerEvent) self.locateScriptMerger.setToolTip( 'Automatically detect the script merger path if possible') scriptMergerPathLayout.addWidget(self.locateScriptMerger) selectScriptMerger = QPushButton('Browse', self) selectScriptMerger.clicked.connect(self.selectScriptMergerEvent) scriptMergerPathLayout.addWidget(selectScriptMerger) gbScriptMergerLayout.addLayout(scriptMergerPathLayout) scriptMergerPathInfoLayout = QHBoxLayout() self.scriptMergerPathInfo = QLabel('', self) self.scriptMergerPathInfo.setOpenExternalLinks(True) self.scriptMergerPathInfo.setContentsMargins(4, 4, 4, 4) self.scriptMergerPathInfo.setMinimumHeight(40) self.scriptMergerPathInfo.setWordWrap(True) scriptMergerPathInfoLayout.addWidget(self.scriptMergerPathInfo) gbScriptMergerLayout.addLayout(scriptMergerPathInfoLayout) # Nexus Mods API gbNexusModsAPI = QGroupBox('Nexus Mods API', self) mainLayout.addWidget(gbNexusModsAPI) gbNexusModsAPILayout = QVBoxLayout(gbNexusModsAPI) self.nexusAPIKey = QLineEdit(self) self.nexusAPIKey.setPlaceholderText('Personal API Key...') if settings.value('nexusAPIKey'): self.nexusAPIKey.setText(str(settings.value('nexusAPIKey'))) self.nexusAPIKey.textChanged.connect( lambda: self.validateApiKey(self.nexusAPIKey.text())) gbNexusModsAPILayout.addWidget(self.nexusAPIKey) self.nexusAPIKeyInfo = QLabel('🌐', self) self.nexusAPIKeyInfo.setOpenExternalLinks(True) self.nexusAPIKeyInfo.setWordWrap(True) self.nexusAPIKeyInfo.setContentsMargins(4, 4, 4, 4) self.nexusAPIKeyInfo.setMinimumHeight(48) gbNexusModsAPILayout.addWidget(self.nexusAPIKeyInfo) self.nexusGetInfo = QCheckBox('Get Mod details after adding a new mod', self) self.nexusGetInfo.setChecked( settings.value('nexusGetInfo', 'True') == 'True') self.nexusGetInfo.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusGetInfo) self.nexusCheckUpdates = QCheckBox('Check for Mod updates on startup', self) self.nexusCheckUpdates.setChecked( settings.value('nexusCheckUpdates', 'False') == 'True') self.nexusCheckUpdates.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusCheckUpdates) self.nexusCheckClipboard = QCheckBox( 'Monitor the Clipboard for Nexus Mods URLs', self) self.nexusCheckClipboard.setChecked( settings.value('nexusCheckClipboard', 'False') == 'True') self.nexusCheckClipboard.setDisabled(True) gbNexusModsAPILayout.addWidget(self.nexusCheckClipboard) # Output gbOutput = QGroupBox('Output Preferences', self) mainLayout.addWidget(gbOutput) gbOutputLayout = QVBoxLayout(gbOutput) self.unhideOutput = QCheckBox('Auto-show output panel', self) self.unhideOutput.setChecked( settings.value('unhideOutput', 'True') == 'True') gbOutputLayout.addWidget(self.unhideOutput) self.debugOutput = QCheckBox('Show debug output', self) self.debugOutput.setChecked( settings.value('debugOutput', 'False') == 'True') gbOutputLayout.addWidget(self.debugOutput) # Actions actionsLayout = QHBoxLayout() actionsLayout.setAlignment(Qt.AlignRight) self.save = QPushButton('Save', self) self.save.clicked.connect(self.saveEvent) self.save.setAutoDefault(True) self.save.setDefault(True) actionsLayout.addWidget(self.save) cancel = QPushButton('Cancel', self) cancel.clicked.connect(self.cancelEvent) actionsLayout.addWidget(cancel) mainLayout.addLayout(actionsLayout) # Setup if not settings.value('gamePath'): self.locateGameEvent() self.setMinimumSize(QSize(440, 440)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.validGamePath = False self.validConfigPath = False self.validNexusAPIKey = False self.validScriptMergerPath = False self.validateGamePath(self.gamePath.text()) self.validateConfigPath(self.configPath.text()) self.validateApiKey(self.nexusAPIKey.text()) self.validateScriptMergerPath(self.scriptMergerPath.text()) self.updateSaveButton() self.finished.connect( lambda: self.validateApiKey.cancel()) # type: ignore def saveEvent(self) -> None: settings = QSettings() settings.setValue('settingsWindowGeometry', self.saveGeometry()) settings.setValue('gamePath', self.gamePath.text()) settings.setValue('configPath', self.configPath.text()) settings.setValue('scriptMergerPath', self.scriptMergerPath.text()) settings.setValue('nexusAPIKey', self.nexusAPIKey.text()) settings.setValue('nexusGetInfo', str(self.nexusGetInfo.isChecked())) settings.setValue('nexusCheckUpdates', str(self.nexusCheckUpdates.isChecked())) settings.setValue('nexusCheckClipboard', str(self.nexusCheckClipboard.isChecked())) settings.setValue('debugOutput', str(self.debugOutput.isChecked())) settings.setValue('unhideOutput', str(self.unhideOutput.isChecked())) self.close() def cancelEvent(self) -> None: self.close() def selectGameEvent(self) -> None: dialog: QFileDialog = QFileDialog(self, 'Select witcher3.exe', '', 'The Witcher 3 (witcher3.exe)') dialog.setOptions(QFileDialog.ReadOnly) dialog.setFileMode(QFileDialog.ExistingFile) if (dialog.exec_()): if dialog.selectedFiles(): self.gamePath.setText(dialog.selectedFiles()[0]) def selectConfigEvent(self) -> None: dialog: QFileDialog = QFileDialog(self, 'Select config folder', '', 'The Witcher 3') dialog.setOptions(QFileDialog.ReadOnly) dialog.setFileMode(QFileDialog.Directory) if (dialog.exec_()): if dialog.selectedFiles(): self.configPath.setText(dialog.selectedFiles()[0]) def selectScriptMergerEvent(self) -> None: dialog: QFileDialog = QFileDialog( self, 'Select WitcherScriptMerger.exe', '', 'Script Merger (WitcherScriptMerger.exe)') dialog.setOptions(QFileDialog.ReadOnly) dialog.setFileMode(QFileDialog.ExistingFile) if (dialog.exec_()): if dialog.selectedFiles(): self.scriptMergerPath.setText(dialog.selectedFiles()[0]) def locateGameEvent(self) -> None: game = fetcher.findGamePath() if game: self.gamePath.setText(str(game)) else: self.gamePathInfo.setText(''' <font color="#888"> Could not detect The Witcher 3!<br> Please make sure the game is installed, or set the path manually. </font>''') def locateConfigEvent(self) -> None: config = fetcher.findConfigPath() if config: self.configPath.setText(str(config)) else: self.configPathInfo.setText(''' <font color="#888"> Could not detect a valid config path! Please make sure the The Witcher 3 was started at least once, or set the path manually. </font>''') def locateScriptMergerEvent(self) -> None: scriptmerger = findScriptMergerPath() if scriptmerger: self.scriptMergerPath.setText(str(scriptmerger)) else: self.scriptMergerPathInfo.setText(''' <font color="#888"> Could not detect Script Merger! Please make sure Script Merger is running,<br> or set the path manually. Download Script Merger <a href="https://www.nexusmods.com/witcher3/mods/484">here</a>. </font>''') def validateGamePath(self, text: str) -> bool: # validate game installation path if not verifyGamePath(Path(text)): self.gamePath.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.gamePathInfo.setText( '<font color="#888">Please enter a valid game path.</font>') self.validGamePath = False self.locateGame.setDisabled(False) self.updateSaveButton() return False else: self.gamePath.setStyleSheet('') self.gamePathInfo.setText( '<font color="#888">Everything looks good!</font>') self.validGamePath = True self.locateGame.setDisabled(True) self.updateSaveButton() return True def validateConfigPath(self, text: str) -> bool: # validate game config path if not verifyConfigPath(Path(text)): self.configPath.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.configPathInfo.setText('''<font color="#888"> Please enter a valid config path. You need to start the The Witcher 3 at least once to generate the necessary user.settings and input.settings files.</font> ''') self.validConfigPath = False self.locateConfig.setDisabled(False) self.updateSaveButton() return False else: self.configPath.setStyleSheet('') self.configPathInfo.setText( '<font color="#888">Everything looks good!</font>') self.validConfigPath = True self.locateConfig.setDisabled(True) self.updateSaveButton() return True def validateScriptMergerPath(self, text: str) -> bool: # validate script merger path if not text: self.scriptMergerPath.setStyleSheet('') self.scriptMergerPathInfo.setText(''' <font color="#888">Script Merger is used to resolve conflicts between mods \ by merging scripts and other text files. \ Download Script Merger <a href="https://www.nexusmods.com/witcher3/mods/484">here</a>.</font> ''') self.validScriptMergerPath = True self.updateSaveButton() return True if not verifyScriptMergerPath(Path(text)): self.scriptMergerPath.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.scriptMergerPathInfo.setText( '''<font color="#888">Please enter a valid script merger path.</font> ''') self.validScriptMergerPath = False self.locateScriptMerger.setDisabled(False) self.updateSaveButton() return False else: self.scriptMergerPath.setStyleSheet('') self.scriptMergerPathInfo.setText( '<font color="#888">Everything looks good!</font>') self.validScriptMergerPath = True self.locateScriptMerger.setDisabled(True) self.updateSaveButton() return True @debounce(200, cancel_running=True) async def validateApiKey(self, text: str) -> bool: # validate neus mods api key self.nexusGetInfo.setDisabled(True) self.nexusCheckUpdates.setDisabled(True) self.nexusCheckClipboard.setDisabled(True) self.nexusAPIKey.setStyleSheet('') if not text: self.nexusAPIKeyInfo.setText(''' <font color="#888">The API Key is used to check for mod updates, \ to get mod details and to download mods. \ Get your Personal API Key <a href="https://www.nexusmods.com/users/myaccount?tab=api">here</a>.</font> ''') self.validNexusAPIKey = True self.updateSaveButton() return True self.nexusAPIKeyInfo.setText('🌐') try: apiUser = await getUserInformation(text) except UnauthorizedError: self.nexusAPIKey.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.nexusAPIKeyInfo.setText(''' <font color="#888">Not a valid API Key. \ Get your Personal API Key <a href="https://www.nexusmods.com/users/myaccount?tab=api">here</a>.</font> ''') self.validNexusAPIKey = False self.updateSaveButton() return False except (RequestError, ResponseError, Exception) as e: self.nexusAPIKey.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.nexusAPIKeyInfo.setText(f''' <font color="#888">Could not validate API Key: {str(e) if str(e) else 'Request error'}.</font> ''') self.validNexusAPIKey = False self.updateSaveButton() return False self.nexusAPIKeyInfo.setText( f'<font color="#888">Valid API Key for {apiUser["name"]}!</font>') self.validNexusAPIKey = True self.nexusGetInfo.setDisabled(False) self.nexusCheckUpdates.setDisabled(False) self.nexusCheckClipboard.setDisabled(False) self.updateSaveButton() return True def updateSaveButton(self) -> None: # TODO: release: disable saving invalid settings # self.save.setDisabled(not all(( # self.validConfigPath, # self.validGamePath, # self.validNexusAPIKey, # self.validScriptMergerPath, # ))) # noqa self.save.setDisabled(False)
class DownloadWindow(QDialog): def __init__(self, parent: Optional[QWidget] = None, url: str = '') -> None: super().__init__(parent, ) if parent: self.setWindowTitle('Download Mod') else: self.setWindowTitle(getTitleString('Download Mod')) self.setAttribute(Qt.WA_DeleteOnClose) mainLayout = QVBoxLayout(self) mainLayout.setContentsMargins(5, 5, 5, 5) self.signals = DownloadWindowEvents(self) # URL input gbUrl = QGroupBox('Mod URL') gbUrlLayout = QVBoxLayout() gbUrl.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.url = QLineEdit() self.url.setPlaceholderText( 'https://www.nexusmods.com/witcher3/mods/...') self.url.setText(url) self.url.textChanged.connect(lambda: self.validateUrl(self.url.text())) gbUrlLayout.addWidget(self.url) self.urlInfo = QLabel('🌐') self.urlInfo.setContentsMargins(4, 4, 4, 4) self.urlInfo.setMinimumHeight(36) self.urlInfo.setWordWrap(True) gbUrlLayout.addWidget(self.urlInfo) gbUrl.setLayout(gbUrlLayout) mainLayout.addWidget(gbUrl) # File selection gbFiles = QGroupBox('Mod Files') gbFilesLayout = QVBoxLayout() gbFiles.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.files = QTableWidget(0, 4) self.files.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.files.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.files.setContextMenuPolicy(Qt.CustomContextMenu) self.files.setSelectionMode(QAbstractItemView.ExtendedSelection) self.files.setSelectionBehavior(QAbstractItemView.SelectRows) self.files.setWordWrap(False) self.files.setSortingEnabled(True) self.files.setFocusPolicy(Qt.StrongFocus) self.files.verticalHeader().hide() self.files.setSortingEnabled(True) self.files.sortByColumn(2, Qt.DescendingOrder) self.files.verticalHeader().setVisible(False) self.files.verticalHeader().setDefaultSectionSize(25) self.files.horizontalHeader().setHighlightSections(False) self.files.horizontalHeader().setStretchLastSection(True) self.files.setHorizontalHeaderLabels( ['File Name', 'Version', 'Upload Date', 'Description']) self.files.setEditTriggers(QAbstractItemView.NoEditTriggers) self.files.verticalScrollBar().valueChanged.connect( lambda: self.files.clearFocus()) self.files.itemSelectionChanged.connect(lambda: self.validateFiles()) self.files.setDisabled(True) self.files.setStyleSheet(''' QTableView { gridline-color: rgba(255,255,255,1); } QTableView::item { padding: 5px; margin: 1px 0; } QTableView::item:!selected:hover { background-color: rgb(217, 235, 249); padding: 0; } ''') gbFilesLayout.addWidget(self.files) _mouseMoveEvent = self.files.mouseMoveEvent self.files.hoverIndexRow = -1 def mouseMoveEvent(event: QMouseEvent) -> None: self.files.hoverIndexRow = self.files.indexAt(event.pos()).row() _mouseMoveEvent(event) self.files.mouseMoveEvent = mouseMoveEvent # type: ignore self.files.setItemDelegate(ModListItemDelegate(self.files)) self.files.setMouseTracking(True) gbFiles.setLayout(gbFilesLayout) mainLayout.addWidget(gbFiles) # Actions actionsLayout = QHBoxLayout() actionsLayout.setAlignment(Qt.AlignRight) self.download = QPushButton('Download', self) self.download.clicked.connect(lambda: self.downloadEvent()) self.download.setAutoDefault(True) self.download.setDefault(True) self.download.setDisabled(True) actionsLayout.addWidget(self.download) cancel = QPushButton('Cancel', self) cancel.clicked.connect(self.cancelEvent) actionsLayout.addWidget(cancel) mainLayout.addLayout(actionsLayout) # Setup self.setMinimumSize(QSize(420, 420)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.resize(QSize(720, 420)) self.finished.connect( lambda: self.validateUrl.cancel()) # type: ignore self.finished.connect( lambda: self.downloadEvent.cancel()) # type: ignore self.modId = 0 self.validateUrl(self.url.text()) def cancelEvent(self) -> None: self.close() @debounce(200, cancel_running=True) async def validateUrl(self, url: str) -> bool: self.download.setDisabled(True) self.files.setDisabled(True) self.files.clearSelection() self.files.clearFocus() self.files.clearContents() self.files.setRowCount(0) self.files.setSortingEnabled(False) self.url.setStyleSheet('') self.modId = 0 if not url: self.urlInfo.setText(''' <font color="#888">Please enter a valid mod url.</font> ''') return False modId = getModId(url) if not modId: self.files.setDisabled(True) self.url.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.urlInfo.setText(''' <font color="#888">Please enter a valid mod url.</font> ''') return False self.urlInfo.setText('🌐') try: filesResponse = await getModFiles(modId) except (RequestError, ResponseError, Exception) as e: self.url.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.urlInfo.setText(f''' <font color="#888">Could not get mod files: {e}.</font> ''') return False try: files = filesResponse['files'] if not len(files): self.urlInfo.setText(f''' <font color="#888">Mod "{modId}" has no files!</font> ''') return False self.files.setRowCount(len(files)) for i in range(len(files)): file = files[i] fileid = int(file['file_id']) name = str(file['name']) version = str(file['version']) _uploadtime = dateparser.parse(file['uploaded_time']) uploadtime = _uploadtime.astimezone(tz=None).strftime( '%Y-%m-%d %H:%M:%S') if _uploadtime else '?' description = html.unescape(str(file['description'])) nameItem = QTableWidgetItem(name) nameItem.setToolTip(name) nameItem.setData(Qt.UserRole, fileid) self.files.setItem(i, 0, nameItem) versionItem = QTableWidgetItem(version) versionItem.setToolTip(version) self.files.setItem(i, 1, versionItem) uploadtimeItem = QTableWidgetItem(uploadtime) uploadtimeItem.setToolTip(uploadtime) self.files.setItem(i, 2, uploadtimeItem) descriptionItem = QTableWidgetItem(description) descriptionItem.setToolTip(description) self.files.setItem(i, 3, descriptionItem) except KeyError as e: logger.exception( f'Could not find key "{str(e)}" in mod files response') self.urlInfo.setText(f''' <font color="#888">Could not find key "{str(e)}" in mod files response.</font> ''') return False self.urlInfo.setText(f''' <font color="#888">Found {len(files)} available files.</font> ''') self.files.resizeColumnsToContents() self.files.setDisabled(False) self.files.setSortingEnabled(True) self.modId = modId return True def validateFiles(self) -> bool: selection = self.files.selectionModel().selectedRows() if len(selection) > 0: self.download.setText(f'Download {len(selection)} mods') self.download.setDisabled(False) return True return False @debounce(25, cancel_running=True) async def downloadEvent(self) -> None: self.download.setDisabled(True) self.url.setDisabled(True) selection = self.files.selectionModel().selectedRows() files = [ self.files.item(index.row(), 0).data(Qt.UserRole) for index in selection ] self.files.setDisabled(True) try: urls = await asyncio.gather( *[getModFileUrls(self.modId, file) for file in files], loop=asyncio.get_running_loop()) except (RequestError, ResponseError, Exception) as e: self.url.setStyleSheet(''' *{ border: 1px solid #B22222; padding: 1px 0px; } ''') self.urlInfo.setText(f''' <font color="#888">Could not download mod files: {e}.</font> ''') return try: self.signals.download.emit([url[0]['URI'] for url in urls]) except KeyError as e: logger.exception( f'Could not find key "{str(e)}" in file download response') self.urlInfo.setText(f''' <font color="#888">Could not find key "{str(e)}" in file download response.</font> ''') return self.close()