def createFormGroupIntro(self): """Create forms for websocket connection to intro.""" self.formGroupIntro = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Style")) layout = QHBoxLayout() styleqb = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/intro", "intro") styleqb.connect2WS(self.controller, 'intro') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/intro.html")) layout.addWidget(styleqb, 2) layout.addWidget(button, 1) box.setLayout(layout) mainLayout.addWidget(box) self.hotkeyBox = QGroupBox(_("Hotkeys")) layout = QVBoxLayout() self.controller.websocketThread.unregister_hotkeys(force=True) self.cb_single_hotkey = QCheckBox( _("Use a single hotkey for both players")) self.cb_single_hotkey.stateChanged.connect(self.singleHotkeyChanged) layout.addWidget(self.cb_single_hotkey) self.hotkeys = dict() layout.addLayout(self.addHotkey("hotkey_player1", _("Player 1"))) layout.addLayout(self.addHotkey("hotkey_player2", _("Player 2"))) layout.addLayout(self.addHotkey("hotkey_debug", _("Debug"))) self.cb_single_hotkey.setChecked( self.hotkeys['hotkey_player1'].getKey() == self.hotkeys['hotkey_player2'].getKey()) self.connectHotkeys() label = QLabel(_("Player 1 is always the player your observer" " camera is centered on at start of a game.")) layout.addWidget(label) self.hotkeyBox.setLayout(layout) mainLayout.addWidget(self.hotkeyBox) self.introBox = QGroupBox(_("Animation")) layout = QFormLayout() self.cb_animation = QComboBox() animation = scctool.settings.config.parser.get("Intros", "animation") currentIdx = 0 idx = 0 options = dict() options['Fly-In'] = _("Fly-In") options['Slide'] = _("Slide") options['Fanfare'] = _("Fanfare") for key, item in options.items(): self.cb_animation.addItem(item, key) if(key == animation): currentIdx = idx idx += 1 self.cb_animation.setCurrentIndex(currentIdx) self.cb_animation.currentIndexChanged.connect(self.changed) label = QLabel(_("Animation:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_animation) self.sb_displaytime = QDoubleSpinBox() self.sb_displaytime.setRange(0, 10) self.sb_displaytime.setDecimals(1) self.sb_displaytime.setValue( scctool.settings.config.parser.getfloat("Intros", "display_time")) self.sb_displaytime.setSuffix(" " + _("Seconds")) self.sb_displaytime.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Display Duration:") + " "), self.sb_displaytime) self.sl_sound = QSlider(Qt.Horizontal) self.sl_sound.setMinimum(0) self.sl_sound.setMaximum(20) self.sl_sound.setValue( scctool.settings.config.parser.getint("Intros", "sound_volume")) self.sl_sound.setTickPosition(QSlider.TicksBothSides) self.sl_sound.setTickInterval(1) self.sl_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_sound) self.introBox.setLayout(layout) mainLayout.addWidget(self.introBox) self.ttsBox = QGroupBox(_("Text-to-Speech")) layout = QFormLayout() self.cb_tts_active = QCheckBox() self.cb_tts_active.setChecked( scctool.settings.config.parser.getboolean("Intros", "tts_active")) self.cb_tts_active.stateChanged.connect(self.changed) label = QLabel(_("Activate Text-to-Speech:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_tts_active) self.icons = {} self.icons['MALE'] = QIcon(scctool.settings.getResFile('male.png')) self.icons['FEMALE'] = QIcon(scctool.settings.getResFile('female.png')) self.cb_tts_voice = QComboBox() currentIdx = 0 idx = 0 tts_voices = self.controller.tts.getVoices() tts_voice = scctool.settings.config.parser.get("Intros", "tts_voice") for voice in tts_voices: self.cb_tts_voice.addItem( self.icons[voice['ssmlGender']], ' ' + voice['name'], voice['name']) if(voice['name'] == tts_voice): currentIdx = idx idx += 1 self.cb_tts_voice.setCurrentIndex(currentIdx) self.cb_tts_voice.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Voice:") + " "), self.cb_tts_voice) self.ttsBox.setStyleSheet("QComboBox { combobox-popup: 0; }") self.ttsBox.setLayout(layout) mainLayout.addWidget(self.ttsBox) self.sb_tts_pitch = QDoubleSpinBox() self.sb_tts_pitch.setRange(-20, 20) self.sb_tts_pitch.setDecimals(2) self.sb_tts_pitch.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_pitch")) self.sb_tts_pitch.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Pitch:") + " "), self.sb_tts_pitch) self.sb_tts_rate = QDoubleSpinBox() self.sb_tts_rate.setRange(0.25, 4.00) self.sb_tts_rate.setSingleStep(0.1) self.sb_tts_rate.setDecimals(2) self.sb_tts_rate.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_rate")) self.sb_tts_rate.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Rate:") + " "), self.sb_tts_rate) self.cb_tts_scope = QComboBox() scope = scctool.settings.config.parser.get("Intros", "tts_scope") currentIdx = 0 idx = 0 options = self.controller.tts.getOptions() for key, item in options.items(): self.cb_tts_scope.addItem(item['desc'], key) if(key == scope): currentIdx = idx idx += 1 self.cb_tts_scope.setCurrentIndex(currentIdx) self.cb_tts_scope.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Line:") + " "), self.cb_tts_scope) self.sl_tts_sound = QSlider(Qt.Horizontal) self.sl_tts_sound.setMinimum(0) self.sl_tts_sound.setMaximum(20) self.sl_tts_sound.setValue( scctool.settings.config.parser.getint("Intros", "tts_volume")) self.sl_tts_sound.setTickPosition(QSlider.TicksBothSides) self.sl_tts_sound.setTickInterval(1) self.sl_tts_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_tts_sound) text = _( "Text-to-Speech provided by Google-Cloud is paid for " "by StarCraft Casting Tool Patrons. To keep this service up " "consider becoming a <a href='{patreon}'>Patron</a> yourself. " "You can test all voices at {tts}.") patreon = 'https://www.patreon.com/StarCraftCastingTool' url = 'https://cloud.google.com/text-to-speech/' tts = "<a href='{}'>cloud.google.com/text-to-speech</a>" tts = tts.format(url) label = QLabel(text.format(patreon=patreon, tts=tts)) label.setAlignment(Qt.AlignJustify) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setMargin(5) layout.addRow(label) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupIntro.setLayout(mainLayout)
class SubwindowStyles(QWidget): """Show styles settings sub window.""" current_tab = -1 def createWindow(self, mainWindow, tab=''): """Create styles settings sub window.""" try: parent = None super().__init__(parent) self.setWindowIcon( QIcon(scctool.settings.getResFile('pantone.png'))) self.setWindowModality(Qt.ApplicationModal) self.mainWindow = mainWindow self.passEvent = False self.controller = mainWindow.controller self.__dataChanged = False self.createButtonGroup() self.createColorBox() self.createStyleBox() self.createFontBox() self.tabs = QTabWidget() self.tabs.addTab(self.styleBox, _("Styles")) self.tabs.addTab(self.colorBox, _("Colors")) self.tabs.addTab(self.fontBox, _("Font")) table = dict() table['styles'] = 0 table['colors'] = 1 table['font'] = 2 self.tabs.setCurrentIndex( table.get(tab, SubwindowStyles.current_tab)) self.tabs.currentChanged.connect(self.tabChanged) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabs) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) mainLayout.addLayout(self.buttonGroup) self.setLayout(mainLayout) self.resize(QSize(mainWindow.size().width() * .80, self.sizeHint().height())) relativeChange = + QPoint(mainWindow.size().width() / 2, mainWindow.size().height() / 3)\ - QPoint(self.size().width() / 2, self.size().height() / 3) self.move(mainWindow.pos() + relativeChange) self.setWindowTitle(_("Style Settings")) except Exception: module_logger.exception("message") @classmethod def tabChanged(cls, idx): """Save the current tab.""" SubwindowStyles.current_tab = idx def changed(self): """Handle data change.""" self.__dataChanged = True def createButtonGroup(self): """Create buttons.""" try: layout = QHBoxLayout() layout.addWidget(QLabel("")) buttonCancel = QPushButton(_('Cancel')) buttonCancel.clicked.connect(self.closeWindow) layout.addWidget(buttonCancel) buttonSave = QPushButton(_('&Save && Close')) buttonSave.setToolTip(_("Shortcut: {}").format("Ctrl+S")) self.shortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.shortcut.setAutoRepeat(False) self.shortcut.activated.connect(self.saveCloseWindow) buttonSave.clicked.connect(self.saveCloseWindow) layout.addWidget(buttonSave) self.buttonGroup = layout except Exception: module_logger.exception("message") def createStyleBox(self): """Create style box.""" self.styleBox = QWidget() layout = QFormLayout() try: container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_box", "mapicons_box") self.qb_boxStyle.connect2WS(self.controller, 'mapicons_box') label = QLabel(_("Box Map Icons:")) label.setMinimumWidth(110) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_box_1.html")) container.addWidget(self.qb_boxStyle) container.addWidget(button) layout.addRow(label, container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_landscapeStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_landscape", "mapicons_landscape") self.qb_landscapeStyle.connect2WS( self.controller, 'mapicons_landscape') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_landscape_1.html")) container.addWidget(self.qb_landscapeStyle) container.addWidget(button) layout.addRow(QLabel( _("Landscape Map Icons:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_scoreStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/score", "score") self.qb_scoreStyle.connect2WS(self.controller, 'score') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/score.html")) container.addWidget(self.qb_scoreStyle) container.addWidget(button) layout.addRow(QLabel(_("Score:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_introStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/intro", "intro") self.qb_introStyle.connect2WS(self.controller, 'intro') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/intro.html")) container.addWidget(self.qb_introStyle) container.addWidget(button) layout.addRow(QLabel(_("Intros:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_mapstatsStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapstats", "mapstats") self.qb_mapstatsStyle.connect2WS(self.controller, 'mapstats') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapstats.html")) container.addWidget(self.qb_mapstatsStyle) container.addWidget(button) layout.addRow(QLabel(_("Map Stats:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_aligulacStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/aligulac", "aligulac") self.qb_aligulacStyle.connect2WS(self.controller, 'aligulac') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/aligulac.html")) container.addWidget(self.qb_aligulacStyle) container.addWidget(button) layout.addRow(QLabel(_("Aligulac:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_countdownStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/countdown", "countdown") self.qb_countdownStyle.connect2WS(self.controller, 'countdown') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/countdown.html")) container.addWidget(self.qb_countdownStyle) container.addWidget(button) layout.addRow(QLabel(_("Countdown:")), container) except Exception: module_logger.exception("message") try: container = QHBoxLayout() self.qb_countdownStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/vetoes", "vetoes") self.qb_countdownStyle.connect2WS(self.controller, 'vetoes') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/vetoes.html")) container.addWidget(self.qb_countdownStyle) container.addWidget(button) layout.addRow(QLabel(_("Vetoes") + ':'), container) except Exception: module_logger.exception("message") layout.addRow(QLabel('')) stylesDisc = _( 'StarCraft Casting Tools allows you to make your own skins/styles' ' via CSS by placing an alternative CSS-files into ' 'casting_html/src/css/{browser-source}. If you do so, please' ' share these skins with this project. In case you need help' ' or just want to share your ideas for new skins' ' join our Discord Server.') label = QLabel(stylesDisc) label.setAlignment(Qt.AlignJustify) label.setWordWrap(True) layout.addRow(label) self.styleBox.setLayout(layout) def openHTML(self, file): """Open file in browser.""" self.controller.openURL(scctool.settings.getAbsPath(file)) def createColorBox(self): """Create box for color selection.""" self.colorBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Map and Score Icons")) layout = QVBoxLayout() self.default_color = ColorLayout( self, _("Default Border:"), scctool.settings.config.parser.get( "MapIcons", "default_border_color"), "#f29b00") layout.addLayout(self.default_color) self.winner_color = ColorLayout( self, _("Winner Highlight:"), scctool.settings.config.parser.get( "MapIcons", "winner_highlight_color"), "#f29b00") layout.addLayout(self.winner_color) self.win_color = ColorLayout( self, _("Win:"), scctool.settings.config.parser.get("MapIcons", "win_color"), "#008000") layout.addLayout(self.win_color) self.lose_color = ColorLayout( self, _("Lose:"), scctool.settings.config.parser.get("MapIcons", "lose_color"), "#f22200") layout.addLayout(self.lose_color) self.undecided_color = ColorLayout( self, _("Undecided:"), scctool.settings.config.parser.get("MapIcons", "undecided_color"), "#aaaaaa") layout.addLayout(self.undecided_color) self.notplayed_color = ColorLayout( self, _("Not played:"), scctool.settings.config.parser.get("MapIcons", "notplayed_color"), "#aaaaaa") layout.addLayout(self.notplayed_color) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Map Stats")) layout = QVBoxLayout() self.mapstats_color1 = ColorLayout( self, _("Color 1:"), scctool.settings.config.parser.get("Mapstats", "color1"), "#6495ed") layout.addLayout(self.mapstats_color1) self.mapstats_color2 = ColorLayout( self, _("Color 2:"), scctool.settings.config.parser.get("Mapstats", "color2"), "#000000") layout.addLayout(self.mapstats_color2) box.setLayout(layout) mainLayout.addWidget(box) self.colorBox.setLayout(mainLayout) def createFontBox(self): """Create box for font selection.""" self.fontBox = QWidget() layout = QGridLayout() label = QLabel( _("Warning: Using a custom font instead of the regular font" " defined in the Icon Styles can lead to unitentional" " appereance.") + _("The proper way is to create a custom skin.")) label.setWordWrap(True) label.setAlignment(Qt.AlignJustify) layout.addWidget(label, 1, 0, 1, 2) label = QLabel(_("Activate Custom Font") + ":") label.setMinimumWidth(110) self.cb_usefont = QCheckBox(" ") self.cb_usefont.setChecked( scctool.settings.config.parser.getboolean( "Style", "use_custom_font")) self.cb_usefont.stateChanged.connect(self.changed) layout.addWidget(label, 0, 0, alignment=Qt.AlignVCenter) layout.addWidget(self.cb_usefont, 0, 1, alignment=Qt.AlignVCenter) label = QLabel(_("Custom Font") + ":") label.setMinimumWidth(110) layout.addWidget(label, 2, 0) self.cb_font = QComboBox() my_font = scctool.settings.config.parser.get( "Style", "custom_font") fonts = QFontDatabase().families() for idx, font in enumerate(fonts): self.cb_font.addItem(str(font)) if str(font).lower().strip() == my_font.lower(): self.cb_font.setCurrentIndex(idx) self.cb_font.setStyleSheet("QComboBox { combobox-popup: 0; }") self.cb_font.currentIndexChanged.connect(self.changed) self.cb_font.currentIndexChanged.connect(self.updateFontPreview) layout.addWidget(self.cb_font, 2, 1) layout.setColumnStretch(1, 1) self.previewer = TextPreviewer() layout.addWidget(self.previewer, 3, 0, 1, 2) layout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding), 4, 0) self.fontBox.setLayout(layout) self.updateFontPreview() def updateFontPreview(self): """Update the font preview.""" font = self.cb_font.currentText().strip() self.previewer.setFont(font) def saveData(self): """Save data.""" if(self.__dataChanged): scctool.settings.config.parser.set( "MapIcons", "default_border_color", self.default_color.getColor()) scctool.settings.config.parser.set( "MapIcons", "undecided_color", self.undecided_color.getColor()) scctool.settings.config.parser.set( "MapIcons", "winner_highlight_color", self.winner_color.getColor()) scctool.settings.config.parser.set( "MapIcons", "win_color", self.win_color.getColor()) scctool.settings.config.parser.set( "MapIcons", "lose_color", self.lose_color.getColor()) scctool.settings.config.parser.set( "MapIcons", "notplayed_color", self.notplayed_color.getColor()) scctool.settings.config.parser.set( "Mapstats", "color1", self.mapstats_color1.getColor()) scctool.settings.config.parser.set( "Mapstats", "color2", self.mapstats_color2.getColor()) scctool.settings.config.parser.set( "Style", "use_custom_font", str(self.cb_usefont.isChecked())) scctool.settings.config.parser.set( "Style", "custom_font", self.cb_font.currentText().strip()) colors = {'color1': self.mapstats_color1.getColor(), 'color2': self.mapstats_color2.getColor()} self.controller.websocketThread.changeColors('mapstats', colors) self.controller.websocketThread.changeFont() self.controller.matchMetaDataChanged() self.__dataChanged = False def saveCloseWindow(self): """Save and close window.""" self.saveData() self.passEvent = True self.close() def closeWindow(self): """Close window.""" self.passEvent = True self.close() def closeEvent(self, event): """Handle close event.""" try: if(not self.__dataChanged): event.accept() return if(not self.passEvent): if(self.isMinimized()): self.showNormal() buttonReply = QMessageBox.question( self, _('Save data?'), _("Save data?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.saveData() event.accept() except Exception: module_logger.exception("message")
class SubwindowBrowserSources(QWidget): """Show connections settings sub window.""" current_tab = -1 def createWindow(self, mainWindow, tab=''): """Create window.""" try: parent = None super().__init__(parent) # self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowIcon( QIcon(scctool.settings.getResFile('browser.png'))) self.setWindowModality(Qt.ApplicationModal) self.mainWindow = mainWindow self.passEvent = False self.controller = mainWindow.controller self.__dataChanged = False self.createButtonGroup() self.createTabs(tab) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabs) mainLayout.addLayout(self.buttonGroup) self.setLayout(mainLayout) self.resize(QSize(mainWindow.size().width() * 0.8, self.sizeHint().height())) relativeChange = QPoint(mainWindow.size().width() / 2, mainWindow.size().height() / 3) -\ QPoint(self.size().width() / 2, self.size().height() / 3) self.move(mainWindow.pos() + relativeChange) self.setWindowTitle(_("Browser Sources")) except Exception as e: module_logger.exception("message") def createTabs(self, tab): """Create tabs.""" self.tabs = QTabWidget() self.createFormGroupIntro() self.createFormGroupMapstats() self.createFormGroupMapBox() self.createFormGroupMapLandscape() # Add tabs self.tabs.addTab(self.formGroupIntro, _("Intros")) self.tabs.addTab(self.formGroupMapstats, _("Mapstats")) self.tabs.addTab(self.formGroupMapBox, _("Box Map Icons")) self.tabs.addTab(self.formGroupMapLandscape, _("Landscape Map Icons")) table = dict() table['intro'] = 0 table['mapstats'] = 1 table['mapicons_box'] = 2 table['mapicons_landscape'] = 3 self.tabs.setCurrentIndex( table.get(tab, SubwindowBrowserSources.current_tab)) self.tabs.currentChanged.connect(self.tabChanged) def tabChanged(self, idx): SubwindowBrowserSources.current_tab = idx def addHotkey(self, ident, label): element = HotkeyLayout( self, ident, label, scctool.settings.config.parser.get("Intros", ident)) self.hotkeys[ident] = element return element def connectHotkeys(self): for ident, key in self.hotkeys.items(): if ident == 'hotkey_debug': for ident2, key2 in self.hotkeys.items(): if ident == ident2: continue key.modified.connect(key2.check_dublicate) key.modified.connect(self.hotkeyChanged) def hotkeyChanged(self, key, ident): self.changed() if(ident == 'hotkey_player1' and self.cb_single_hotkey.isChecked()): self.hotkeys['hotkey_player2'].setData( self.hotkeys['hotkey_player1'].getKey()) if not key: return if((ident == 'hotkey_player1' and key == self.hotkeys['hotkey_player2'].getKey()['name']) or (ident == 'hotkey_player2' and key == self.hotkeys['hotkey_player1'].getKey()['name'])): self.cb_single_hotkey.setChecked(True) if(ident in ['hotkey_player1', 'hotkey_player2'] and key == self.hotkeys['hotkey_debug'].getKey()['name']): self.hotkeys['hotkey_debug'].clear() def singleHotkeyChanged(self): checked = self.cb_single_hotkey.isChecked() self.hotkeys['hotkey_player2'].setDisabled(checked) if checked: self.hotkeys['hotkey_player2'].setData( self.hotkeys['hotkey_player1'].getKey()) elif(self.hotkeys['hotkey_player1'].getKey() == self.hotkeys['hotkey_player2'].getKey()): self.hotkeys['hotkey_player2'].clear() def createFormGroupMapstats(self): self.formGroupMapstats = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapstats", "mapstats") self.qb_boxStyle.connect2WS(self.controller, 'mapstats') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapstats.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.cb_mappool = QComboBox() self.cb_mappool.addItem(_("Current Ladder Map Pool")) self.cb_mappool.addItem(_("Custom Map Pool (defined below)")) self.cb_mappool.addItem(_("Currently entered Maps only")) self.cb_mappool.setCurrentIndex( self.controller.mapstatsManager.getMapPoolType()) self.cb_mappool.currentIndexChanged.connect(self.changed) layout.addRow(QLabel(_("Map Pool:")), self.cb_mappool) self.cb_autoset_map = QCheckBox(_("Select the next map automatically")) self.cb_autoset_map.setChecked( scctool.settings.config.parser.getboolean( "Mapstats", "autoset_next_map")) self.cb_autoset_map.stateChanged.connect(self.changed) label = QLabel(_("Next Map:")) label.setMinimumWidth(120) layout.addRow(label, self.cb_autoset_map) self.cb_mark_played = QCheckBox(_("Mark already played maps")) self.cb_mark_played.setChecked( scctool.settings.config.parser.getboolean( "Mapstats", "mark_played")) self.cb_mark_played.stateChanged.connect(self.changed) label = QLabel(_("Mark:")) label.setMinimumWidth(120) layout.addRow(label, self.cb_mark_played) box.setLayout(layout) mainLayout.addWidget(box) box = QGroupBox(_("Custom Map Pool")) layout = QGridLayout() self.maplist = QListWidget() self.maplist.setSortingEnabled(True) ls = list(self.controller.mapstatsManager.getCustomMapPool()) self.maplist.addItems(ls) self.maplist.setCurrentItem(self.maplist.item(0)) layout.addWidget(self.maplist, 0, 0, 3, 1) qb_add = QPushButton() pixmap = QIcon( scctool.settings.getResFile('add.png')) qb_add.setIcon(pixmap) qb_add.clicked.connect(self.addMap) layout.addWidget(qb_add, 0, 1) qb_remove = QPushButton() pixmap = QIcon( scctool.settings.getResFile('delete.png')) qb_remove.clicked.connect(self.removeMap) qb_remove.setIcon(pixmap) layout.addWidget(qb_remove, 1, 1) self.sc_removeMap = QShortcut(QKeySequence("Del"), self) self.sc_removeMap.setAutoRepeat(False) self.sc_removeMap.activated.connect(self.removeMap) box.setLayout(layout) mainLayout.addWidget(box) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapstats.setLayout(mainLayout) def addMap(self): maplist = list(scctool.settings.maps) for i in range(self.maplist.count()): map = str(self.maplist.item(i).text()) if map in maplist: maplist.remove(map) if len(maplist) > 0: map, ok = QInputDialog.getItem( self, _('Add Map'), _('Please select a map') + ':', maplist, editable=False) if ok: self.__dataChanged = True item = QListWidgetItem(map) self.maplist.addItem(item) self.maplist.setCurrentItem(item) else: QMessageBox.information( self, _("No maps available"), _('All available maps have already been added.')) def removeMap(self): item = self.maplist.currentItem() if item: self.maplist.takeItem(self.maplist.currentRow()) self.__dataChanged = True def createFormGroupMapBox(self): self.formGroupMapBox = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_box", "mapicons_box") self.qb_boxStyle.connect2WS(self.controller, 'mapicons_box') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_box_1.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.sb_padding_box = QDoubleSpinBox() self.sb_padding_box.setRange(0, 50) self.sb_padding_box.setDecimals(1) self.sb_padding_box.setValue( scctool.settings.config.parser.getfloat("MapIcons", "padding_box")) self.sb_padding_box.setSuffix(" " + _("Pixel")) self.sb_padding_box.valueChanged.connect( lambda x: self.changePadding('box', x)) layout.addRow(QLabel( _("Icon Padding:") + " "), self.sb_padding_box) box.setLayout(layout) mainLayout.addWidget(box) options = self.controller.matchControl.scopes self.scope_box = dict() for idx in range(0, 3): self.scope_box[idx] = ScopeGroupBox( _("Icon Set {} Scope".format(idx + 1)), options, scctool.settings.config.parser.get( "MapIcons", "scope_box_{}".format(idx + 1)), self) self.scope_box[idx].dataModified.connect(self.changed) mainLayout.addWidget(self.scope_box[idx]) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapBox.setLayout(mainLayout) def createFormGroupMapLandscape(self): self.formGroupMapLandscape = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("General")) layout = QFormLayout() container = QHBoxLayout() self.qb_boxStyle = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/mapicons_landscape", "mapicons_landscape") self.qb_boxStyle.connect2WS(self.controller, 'mapicons_landscape') label = QLabel(_("Style:")) label.setMinimumWidth(120) button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/mapicons_landscape_1.html")) container.addWidget(self.qb_boxStyle, 2) container.addWidget(button, 1) layout.addRow(label, container) self.sb_padding_landscape = QDoubleSpinBox() self.sb_padding_landscape.setRange(0, 50) self.sb_padding_landscape.setDecimals(1) self.sb_padding_landscape.setValue( scctool.settings.config.parser.getfloat( "MapIcons", "padding_landscape")) self.sb_padding_landscape.setSuffix(" " + _("Pixel")) self.sb_padding_landscape.valueChanged.connect( lambda x: self.changePadding('landscape', x)) layout.addRow(QLabel( _("Icon Padding:") + " "), self.sb_padding_landscape) box.setLayout(layout) mainLayout.addWidget(box) options = self.controller.matchControl.scopes self.scope_landscape = dict() for idx in range(0, 3): self.scope_landscape[idx] = ScopeGroupBox( _("Icon Set {} Scope".format(idx + 1)), options, scctool.settings.config.parser.get( "MapIcons", "scope_landscape_{}".format(idx + 1)), self) self.scope_landscape[idx].dataModified.connect(self.changed) mainLayout.addWidget(self.scope_landscape[idx]) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupMapLandscape.setLayout(mainLayout) def createFormGroupIntro(self): """Create forms for websocket connection to intro.""" self.formGroupIntro = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Style")) layout = QHBoxLayout() styleqb = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/intro", "intro") styleqb.connect2WS(self.controller, 'intro') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/intro.html")) layout.addWidget(styleqb, 2) layout.addWidget(button, 1) box.setLayout(layout) mainLayout.addWidget(box) self.hotkeyBox = QGroupBox(_("Hotkeys")) layout = QVBoxLayout() self.controller.websocketThread.unregister_hotkeys(force=True) self.cb_single_hotkey = QCheckBox( _("Use a single hotkey for both players")) self.cb_single_hotkey.stateChanged.connect(self.singleHotkeyChanged) layout.addWidget(self.cb_single_hotkey) self.hotkeys = dict() layout.addLayout(self.addHotkey("hotkey_player1", _("Player 1"))) layout.addLayout(self.addHotkey("hotkey_player2", _("Player 2"))) layout.addLayout(self.addHotkey("hotkey_debug", _("Debug"))) self.cb_single_hotkey.setChecked( self.hotkeys['hotkey_player1'].getKey() == self.hotkeys['hotkey_player2'].getKey()) self.connectHotkeys() label = QLabel(_("Player 1 is always the player your observer" " camera is centered on at start of a game.")) layout.addWidget(label) self.hotkeyBox.setLayout(layout) mainLayout.addWidget(self.hotkeyBox) self.introBox = QGroupBox(_("Animation")) layout = QFormLayout() self.cb_animation = QComboBox() animation = scctool.settings.config.parser.get("Intros", "animation") currentIdx = 0 idx = 0 options = dict() options['Fly-In'] = _("Fly-In") options['Slide'] = _("Slide") options['Fanfare'] = _("Fanfare") for key, item in options.items(): self.cb_animation.addItem(item, key) if(key == animation): currentIdx = idx idx += 1 self.cb_animation.setCurrentIndex(currentIdx) self.cb_animation.currentIndexChanged.connect(self.changed) label = QLabel(_("Animation:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_animation) self.sb_displaytime = QDoubleSpinBox() self.sb_displaytime.setRange(0, 10) self.sb_displaytime.setDecimals(1) self.sb_displaytime.setValue( scctool.settings.config.parser.getfloat("Intros", "display_time")) self.sb_displaytime.setSuffix(" " + _("Seconds")) self.sb_displaytime.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Display Duration:") + " "), self.sb_displaytime) self.sl_sound = QSlider(Qt.Horizontal) self.sl_sound.setMinimum(0) self.sl_sound.setMaximum(20) self.sl_sound.setValue( scctool.settings.config.parser.getint("Intros", "sound_volume")) self.sl_sound.setTickPosition(QSlider.TicksBothSides) self.sl_sound.setTickInterval(1) self.sl_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_sound) self.introBox.setLayout(layout) mainLayout.addWidget(self.introBox) self.ttsBox = QGroupBox(_("Text-to-Speech")) layout = QFormLayout() self.cb_tts_active = QCheckBox() self.cb_tts_active.setChecked( scctool.settings.config.parser.getboolean("Intros", "tts_active")) self.cb_tts_active.stateChanged.connect(self.changed) label = QLabel(_("Activate Text-to-Speech:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_tts_active) self.icons = {} self.icons['MALE'] = QIcon(scctool.settings.getResFile('male.png')) self.icons['FEMALE'] = QIcon(scctool.settings.getResFile('female.png')) self.cb_tts_voice = QComboBox() currentIdx = 0 idx = 0 tts_voices = self.controller.tts.getVoices() tts_voice = scctool.settings.config.parser.get("Intros", "tts_voice") for voice in tts_voices: self.cb_tts_voice.addItem( self.icons[voice['ssmlGender']], ' ' + voice['name'], voice['name']) if(voice['name'] == tts_voice): currentIdx = idx idx += 1 self.cb_tts_voice.setCurrentIndex(currentIdx) self.cb_tts_voice.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Voice:") + " "), self.cb_tts_voice) self.ttsBox.setStyleSheet("QComboBox { combobox-popup: 0; }") self.ttsBox.setLayout(layout) mainLayout.addWidget(self.ttsBox) self.sb_tts_pitch = QDoubleSpinBox() self.sb_tts_pitch.setRange(-20, 20) self.sb_tts_pitch.setDecimals(2) self.sb_tts_pitch.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_pitch")) self.sb_tts_pitch.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Pitch:") + " "), self.sb_tts_pitch) self.sb_tts_rate = QDoubleSpinBox() self.sb_tts_rate.setRange(0.25, 4.00) self.sb_tts_rate.setSingleStep(0.1) self.sb_tts_rate.setDecimals(2) self.sb_tts_rate.setValue( scctool.settings.config.parser.getfloat("Intros", "tts_rate")) self.sb_tts_rate.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Rate:") + " "), self.sb_tts_rate) self.cb_tts_scope = QComboBox() scope = scctool.settings.config.parser.get("Intros", "tts_scope") currentIdx = 0 idx = 0 options = self.controller.tts.getOptions() for key, item in options.items(): self.cb_tts_scope.addItem(item['desc'], key) if(key == scope): currentIdx = idx idx += 1 self.cb_tts_scope.setCurrentIndex(currentIdx) self.cb_tts_scope.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Line:") + " "), self.cb_tts_scope) self.sl_tts_sound = QSlider(Qt.Horizontal) self.sl_tts_sound.setMinimum(0) self.sl_tts_sound.setMaximum(20) self.sl_tts_sound.setValue( scctool.settings.config.parser.getint("Intros", "tts_volume")) self.sl_tts_sound.setTickPosition(QSlider.TicksBothSides) self.sl_tts_sound.setTickInterval(1) self.sl_tts_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_tts_sound) text = _( "Text-to-Speech provided by Google-Cloud is paid for " "by StarCraft Casting Tool Patrons. To keep this service up " "consider becoming a <a href='{patreon}'>Patron</a> yourself. " "You can test all voices at {tts}.") patreon = 'https://www.patreon.com/StarCraftCastingTool' url = 'https://cloud.google.com/text-to-speech/' tts = "<a href='{}'>cloud.google.com/text-to-speech</a>" tts = tts.format(url) label = QLabel(text.format(patreon=patreon, tts=tts)) label.setAlignment(Qt.AlignJustify) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setMargin(5) layout.addRow(label) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupIntro.setLayout(mainLayout) def createButtonGroup(self): """Create buttons.""" try: layout = QHBoxLayout() layout.addWidget(QLabel("")) buttonCancel = QPushButton(_('Cancel')) buttonCancel.clicked.connect(self.closeWindow) layout.addWidget(buttonCancel) buttonSave = QPushButton(_('&Save && Close')) buttonSave.setToolTip(_("Shortcut: {}").format("Ctrl+S")) self.shortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.shortcut.setAutoRepeat(False) self.shortcut.activated.connect(self.saveCloseWindow) buttonSave.clicked.connect(self.saveCloseWindow) layout.addWidget(buttonSave) self.buttonGroup = layout except Exception as e: module_logger.exception("message") def changed(self, *values): """Handle changed data.""" self.__dataChanged = True def saveData(self): """Save the data to config.""" if(self.__dataChanged): self.saveWebsocketdata() maps = list() for i in range(self.maplist.count()): maps.append(str(self.maplist.item(i).text()).strip()) self.controller.mapstatsManager.setCustomMapPool(maps) self.controller.mapstatsManager.setMapPoolType( self.cb_mappool.currentIndex()) scctool.settings.config.parser.set( "Mapstats", "autoset_next_map", str(self.cb_autoset_map.isChecked())) scctool.settings.config.parser.set( "Mapstats", "mark_played", str(self.cb_mark_played.isChecked())) self.controller.mapstatsManager.sendMapPool() self.mainWindow.updateAllMapButtons() for idx in range(0, 3): scctool.settings.config.parser.set( "MapIcons", "scope_box_{}".format(idx + 1), self.scope_box[idx].getScope()) scctool.settings.config.parser.set( "MapIcons", "scope_landscape_{}".format(idx + 1), self.scope_landscape[idx].getScope()) self.controller.matchMetaDataChanged() self.__dataChanged = False # self.controller.refreshButtonStatus() def saveWebsocketdata(self): """Save Websocket data.""" for ident, key in self.hotkeys.items(): string = scctool.settings.config.dumpHotkey(key.getKey()) scctool.settings.config.parser.set("Intros", ident, string) scctool.settings.config.parser.set( "Intros", "display_time", str(self.sb_displaytime.value())) scctool.settings.config.parser.set( "Intros", "sound_volume", str(self.sl_sound.value())) scctool.settings.config.parser.set( "Intros", "animation", self.cb_animation.currentData().strip()) scctool.settings.config.parser.set( "Intros", "tts_voice", self.cb_tts_voice.currentData().strip()) scctool.settings.config.parser.set( "Intros", "tts_scope", self.cb_tts_scope.currentData().strip()) scctool.settings.config.parser.set( "Intros", "tts_active", str(self.cb_tts_active.isChecked())) scctool.settings.config.parser.set( "Intros", "tts_volume", str(self.sl_tts_sound.value())) scctool.settings.config.parser.set( "Intros", "tts_pitch", str(self.sb_tts_pitch.value())) scctool.settings.config.parser.set( "Intros", "tts_rate", str(self.sb_tts_rate.value())) def openHTML(self, file): """Open file in browser.""" self.controller.openURL(scctool.settings.getAbsPath(file)) def changePadding(self, scope, padding): scctool.settings.config.parser.set( "MapIcons", "padding_{}".format(scope), str(padding)) self.controller.websocketThread.changePadding( "mapicons_{}".format(scope), padding) def saveCloseWindow(self): """Save and close window.""" self.saveData() self.closeWindow() def closeWindow(self): """Close window without save.""" self.passEvent = True self.close() def closeEvent(self, event): """Handle close event.""" try: if(not self.__dataChanged): self.controller.updateHotkeys() event.accept() return if(not self.passEvent): if(self.isMinimized()): self.showNormal() buttonReply = QMessageBox.question( self, _('Save data?'), _("Do you want to save the data?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.saveData() self.controller.updateHotkeys() event.accept() except Exception as e: module_logger.exception("message")
def createFormGroupIntro(self): """Create forms for websocket connection to intro.""" self.formGroupIntro = QWidget() mainLayout = QVBoxLayout() box = QGroupBox(_("Style")) layout = QHBoxLayout() styleqb = StyleComboBox( scctool.settings.casting_html_dir + "/src/css/intro", "intro") styleqb.connect2WS(self.controller, 'intro') button = QPushButton(_("Show in Browser")) button.clicked.connect(lambda: self.openHTML( scctool.settings.casting_html_dir + "/intro.html")) layout.addWidget(styleqb, 2) layout.addWidget(button, 1) box.setLayout(layout) mainLayout.addWidget(box) self.hotkeyBox = QGroupBox(_("Hotkeys")) layout = QVBoxLayout() try: keyboard.unhook_all() except AttributeError: pass self.cb_single_hotkey = QCheckBox( _("Use a single hotkey for both players")) self.cb_single_hotkey.stateChanged.connect(self.singleHotkeyChanged) layout.addWidget(self.cb_single_hotkey) self.hotkeys = dict() layout.addLayout(self.addHotkey("hotkey_player1", _("Player 1"))) layout.addLayout(self.addHotkey("hotkey_player2", _("Player 2"))) layout.addLayout(self.addHotkey("hotkey_debug", _("Debug"))) self.cb_single_hotkey.setChecked( self.hotkeys['hotkey_player1'].getKey() == self.hotkeys['hotkey_player2'].getKey()) self.connectHotkeys() label = QLabel(_("Player 1 is always the player your observer" " camera is centered on at start of a game.")) layout.addWidget(label) self.hotkeyBox.setLayout(layout) mainLayout.addWidget(self.hotkeyBox) self.introBox = QGroupBox(_("Animation")) layout = QFormLayout() self.cb_animation = QComboBox() animation = scctool.settings.config.parser.get("Intros", "animation") currentIdx = 0 idx = 0 options = dict() options['Fly-In'] = _("Fly-In") options['Slide'] = _("Slide") options['Fanfare'] = _("Fanfare") for key, item in options.items(): self.cb_animation.addItem(item, key) if(key == animation): currentIdx = idx idx += 1 self.cb_animation.setCurrentIndex(currentIdx) self.cb_animation.currentIndexChanged.connect(self.changed) label = QLabel(_("Animation:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_animation) self.sb_displaytime = QDoubleSpinBox() self.sb_displaytime.setRange(0, 10) self.sb_displaytime.setDecimals(1) self.sb_displaytime.setValue( scctool.settings.config.parser.getfloat("Intros", "display_time")) self.sb_displaytime.setSuffix(" " + _("Seconds")) self.sb_displaytime.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Display Duration:") + " "), self.sb_displaytime) self.sl_sound = QSlider(Qt.Horizontal) self.sl_sound.setMinimum(0) self.sl_sound.setMaximum(20) self.sl_sound.setValue( scctool.settings.config.parser.getint("Intros", "sound_volume")) self.sl_sound.setTickPosition(QSlider.TicksBothSides) self.sl_sound.setTickInterval(1) self.sl_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_sound) self.introBox.setLayout(layout) mainLayout.addWidget(self.introBox) self.ttsBox = QGroupBox(_("Text-to-Speech")) layout = QFormLayout() self.cb_tts_active = QCheckBox() self.cb_tts_active.setChecked( scctool.settings.config.parser.getboolean("Intros", "tts_active")) self.cb_tts_active.stateChanged.connect(self.changed) label = QLabel(_("Activate Text-to-Speech:") + " ") label.setMinimumWidth(120) layout.addRow(label, self.cb_tts_active) self.cb_tts_lang = QComboBox() currentIdx = 0 idx = 0 tts_langs = gtts.lang.tts_langs() tts_lang = scctool.settings.config.parser.get("Intros", "tts_lang") for key, name in tts_langs.items(): self.cb_tts_lang.addItem(name, key) if(key == tts_lang): currentIdx = idx idx += 1 self.cb_tts_lang.setCurrentIndex(currentIdx) self.cb_tts_lang.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Language:") + " "), self.cb_tts_lang) self.ttsBox.setStyleSheet("QComboBox { combobox-popup: 0; }") self.ttsBox.setLayout(layout) mainLayout.addWidget(self.ttsBox) self.cb_tts_scope = QComboBox() scope = scctool.settings.config.parser.get("Intros", "tts_scope") currentIdx = 0 idx = 0 options = dict() options['team_player'] = _("Team & Player") options['player'] = _("Player") for key, item in options.items(): self.cb_tts_scope.addItem(item, key) if(key == scope): currentIdx = idx idx += 1 self.cb_tts_scope.setCurrentIndex(currentIdx) self.cb_tts_scope.currentIndexChanged.connect(self.changed) layout.addRow(QLabel( _("Scope:") + " "), self.cb_tts_scope) self.sl_tts_sound = QSlider(Qt.Horizontal) self.sl_tts_sound.setMinimum(0) self.sl_tts_sound.setMaximum(20) self.sl_tts_sound.setValue( scctool.settings.config.parser.getint("Intros", "tts_volume")) self.sl_tts_sound.setTickPosition(QSlider.TicksBothSides) self.sl_tts_sound.setTickInterval(1) self.sl_tts_sound.valueChanged.connect(self.changed) layout.addRow(QLabel( _("Sound Volume:") + " "), self.sl_tts_sound) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupIntro.setLayout(mainLayout)