from ConfigParserEdit import ConfigParser from os.path import exists from os import listdir, _exit import subprocess try: import Cocoa # mac except: pass from PyQt4 import QtGui, QtCore from constants import * import ini class Settings(QtGui.QDialog): def __init__(self, parent): super(Settings, self).__init__() self.setModal(True) self.gamewindow = parent self.parent = parent self.inifile = ConfigParser() self.setWindowTitle("AO2XP Settings") self.setFixedSize(480, 512) self.setWindowIcon(QtGui.QIcon("AO2XP.ico")) self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) self.hide() layMain = QtGui.QVBoxLayout(self) laySave = QtGui.QHBoxLayout() self.tabs = QtGui.QTabWidget() self.tabs.resize(320-16, 480-40) self.tabs.move(8, 8) tabGeneral = QtGui.QWidget() tabAudio = QtGui.QWidget() tabCallwords = QtGui.QWidget() layGeneral = QtGui.QVBoxLayout(tabGeneral) layGeneral.setAlignment(QtCore.Qt.AlignTop) layAudio = QtGui.QFormLayout(tabAudio) layAudio.setLabelAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) layAudio.setFormAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) layCallwords = QtGui.QVBoxLayout(tabCallwords) layCallwords.setAlignment(QtCore.Qt.AlignTop) self.btnSave = QtGui.QPushButton() self.btnSave.setText("Save") self.btnSave.clicked.connect(self.onSaveClicked) self.btnCancel = QtGui.QPushButton() self.btnCancel.setText("Cancel") self.btnCancel.clicked.connect(self.onCancelClicked) self.btnAbout = QtGui.QPushButton() self.btnAbout.setText("About...") self.btnAbout.clicked.connect(self.onAboutClicked) separators = [] for i in range(5): separator = QtGui.QFrame() separator.setFixedSize(separator.size().width(), 12) separators.append(separator) ###### General tab ###### layDefaultOOCName = QtGui.QHBoxLayout() lblDefaultOOCName = QtGui.QLabel("Default OOC name") self.defaultOOCName = QtGui.QLineEdit() layDefaultOOCName.addWidget(lblDefaultOOCName) layDefaultOOCName.addWidget(self.defaultOOCName) lblDefaultShowname = QtGui.QLabel("Default showname") self.defaultShowname = QtGui.QLineEdit() layDefaultOOCName.addWidget(lblDefaultShowname) layDefaultOOCName.addWidget(self.defaultShowname) laySaveToLog = QtGui.QHBoxLayout() self.cbSaveToLog = QtGui.QCheckBox() self.cbSaveToLog.setText("Save chat logs to a file") self.cbSaveToLog.setChecked(False) self.cbCombineLogs = QtGui.QCheckBox() self.cbCombineLogs.setText("Combine OOC and IC chat logs in the same file") self.cbCombineLogs.setChecked(False) laySaveToLog.addWidget(self.cbSaveToLog) laySaveToLog.addWidget(self.cbCombineLogs) laySaveDemos = QtGui.QHBoxLayout() self.cbSaveDemos = QtGui.QCheckBox() self.cbSaveDemos.setText("Record demo files") self.cbSaveDemos.setChecked(False) laySaveDemos.addWidget(self.cbSaveDemos) layTextStayTime = QtGui.QHBoxLayout() lblTextStayTime = QtGui.QLabel("Text stay time (milliseconds)") self.sbTextStayTime = QtGui.QSpinBox() self.sbTextStayTime.setMinimum(0) self.sbTextStayTime.setMaximum(10000) layTextStayTime.addWidget(lblTextStayTime) layTextStayTime.addWidget(self.sbTextStayTime) laySlide = QtGui.QHBoxLayout() self.cbEnableSlide = QtGui.QCheckBox() self.cbEnableSlide.setText("(Experimental) Display courtroom slide (pan-tilt) animations") self.cbEnableSlide.setChecked(True) laySlide.addWidget(self.cbEnableSlide) layTheme = QtGui.QHBoxLayout() lblTheme = QtGui.QLabel("Current theme") self.cbThemes = QtGui.QComboBox() self.themes = listdir(AO2XPpath + "ao2xp_themes") for theme in self.themes: if exists(AO2XPpath + "ao2xp_themes/"+theme+"/theme.py") or exists(AO2XPpath + "ao2xp_themes/"+theme+"/courtroom_design.ini"): self.cbThemes.addItem(theme) layTheme.addWidget(lblTheme) layTheme.addWidget(self.cbThemes) layAutoConnect = QtGui.QHBoxLayout() lblAutoConnect = QtGui.QLabel("Connect automatically to this server") self.cbServers = QtGui.QComboBox() layAutoConnect.addWidget(lblAutoConnect) layAutoConnect.addWidget(self.cbServers) self.cbServers.addItem("Always show server list") if exists('serverlist.txt'): with open('serverlist.txt') as file: for server in [line.rstrip().split(':') for line in file]: self.cbServers.addItem(server[-1]) layAutoPick = QtGui.QHBoxLayout() lblAutoPick = QtGui.QLabel("Pick this character automatically on join") self.cbCharacters = QtGui.QComboBox() for folder in listdir(unicode(AOpath + 'characters')): if exists(AOpath + 'characters/' + folder + '/char.ini'): self.cbCharacters.addItem(folder) self.cbCharacters.setEditable(1) layAutoPick.addWidget(lblAutoPick) layAutoPick.addWidget(self.cbCharacters) layAutoJoinArea = QtGui.QHBoxLayout() lblAutoJoinArea = QtGui.QLabel("Go to this area automatically on join") self.autoJoinArea = QtGui.QLineEdit() layAutoJoinArea.addWidget(lblAutoJoinArea) layAutoJoinArea.addWidget(self.autoJoinArea) lblDownloads = QtGui.QLabel() lblDownloads.setText("Automatically download or stream online from WebAO:") layDownloads = QtGui.QHBoxLayout() self.cbDownloadChars = QtGui.QCheckBox("Characters") self.cbDownloadSounds = QtGui.QCheckBox("Sounds") self.cbDownloadMusic = QtGui.QCheckBox("Music") self.cbDownloadEvidence = QtGui.QCheckBox("Evidence") layDownloads.addWidget(self.cbDownloadChars) layDownloads.addWidget(self.cbDownloadSounds) layDownloads.addWidget(self.cbDownloadMusic) layDownloads.addWidget(self.cbDownloadEvidence) layUpdate = QtGui.QHBoxLayout() self.cbCheckUpdates = QtGui.QCheckBox("Check for AO2XP updates on startup") self.btnCheckUpdatesNow = QtGui.QPushButton() self.btnCheckUpdatesNow.setText("Check now...") self.btnCheckUpdatesNow.clicked.connect(self.onUpdateClicked) layUpdate.addWidget(self.cbCheckUpdates) layUpdate.addWidget(self.btnCheckUpdatesNow) layGeneral.addLayout(layDefaultOOCName) layGeneral.addLayout(laySaveToLog) layGeneral.addLayout(laySaveDemos) layGeneral.addWidget(separators[0]) layGeneral.addLayout(layTextStayTime) layGeneral.addLayout(laySlide) layGeneral.addWidget(separators[1]) layGeneral.addLayout(layTheme) layGeneral.addLayout(layAutoConnect) layGeneral.addLayout(layAutoPick) layGeneral.addLayout(layAutoJoinArea) layGeneral.addWidget(separators[2]) layGeneral.addWidget(lblDownloads) layGeneral.addLayout(layDownloads) layGeneral.addWidget(separators[3]) layGeneral.addLayout(layUpdate) ###### Audio tab ###### lblAudioDevice = QtGui.QLabel("Audio device") self.cbDevices = QtGui.QComboBox() layAudio.setWidget(0, QtGui.QFormLayout.LabelRole, lblAudioDevice) layAudio.setWidget(0, QtGui.QFormLayout.FieldRole, self.cbDevices) layAudio.setWidget(1, QtGui.QFormLayout.FieldRole, separators[4]) lblMusicVolume = QtGui.QLabel("Music") lblSoundVolume = QtGui.QLabel("Sounds") lblBlipsVolume = QtGui.QLabel("Blips") self.sliMusicVolume = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.sliSoundVolume = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.sliBlipsVolume = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.sliMusicVolume.setRange(0, 100) self.sliSoundVolume.setRange(0, 100) self.sliBlipsVolume.setRange(0, 100) layAudio.setWidget(2, QtGui.QFormLayout.LabelRole, lblMusicVolume) layAudio.setWidget(2, QtGui.QFormLayout.FieldRole, self.sliMusicVolume) layAudio.setWidget(3, QtGui.QFormLayout.LabelRole, lblSoundVolume) layAudio.setWidget(3, QtGui.QFormLayout.FieldRole, self.sliSoundVolume) layAudio.setWidget(4, QtGui.QFormLayout.LabelRole, lblBlipsVolume) layAudio.setWidget(4, QtGui.QFormLayout.FieldRole, self.sliBlipsVolume) self.btnReloadAudioSystem = QtGui.QPushButton(text="Reload audio system") self.btnReloadAudioSystem.clicked.connect(self.onReloadAudioSystemClicked) layAudio.setWidget(5, QtGui.QFormLayout.FieldRole, self.btnReloadAudioSystem) for device in audio.getDevices(): self.cbDevices.addItem(device) ###### Callwords tab ###### self.callwords = QtGui.QTextEdit() cbCallwordsWordWrap = QtGui.QCheckBox("Word Wrap") cbCallwordsWordWrap.setChecked(True) cbCallwordsWordWrap.stateChanged.connect(self.callwordsWordWrapCheckbox) cbCallwordsInstructions = QtGui.QLabel() cbCallwordsInstructions.setText("Separate callwords with newlines (ENTER key).") layCallwords.addWidget(self.callwords) layCallwords.addWidget(cbCallwordsWordWrap, 0, QtCore.Qt.AlignRight) layCallwords.addWidget(cbCallwordsInstructions) ### Main settings window self.tabs.addTab(tabGeneral, "General") self.tabs.addTab(tabAudio, "Audio") self.tabs.addTab(tabCallwords, "Callwords") laySave.addWidget(self.btnSave, 100, QtCore.Qt.AlignRight) laySave.addWidget(self.btnCancel, 0, QtCore.Qt.AlignRight) laySave.addWidget(self.btnAbout, 0, QtCore.Qt.AlignLeft) layMain.addWidget(self.tabs) layMain.addLayout(laySave) self.btnSave.setFocus() # If they're different from the respective checkbox on save, tell the # gui to start/stop logging self.saveLogsState = False self.combineLogsState = False self.saveDemosState = False self.themeState = "" def showSettings(self): if exists("AO2XP.ini"): self.inifile.read("AO2XP.ini") self.cbSaveToLog.setChecked(ini.read_ini_bool(self.inifile, "General", "save logs", False)) self.cbCombineLogs.setChecked(ini.read_ini_bool(self.inifile, "General", "combined logs", False)) self.cbSaveDemos.setChecked(ini.read_ini_bool(self.inifile, "General", "record demos", False)) try: self.defaultOOCName.setText(ini.read_ini(self.inifile, "General", "OOC name").decode("utf-8")) except: self.defaultOOCName.setText(ini.read_ini(self.inifile, "General", "OOC name")) try: self.defaultShowname.setText(ini.read_ini(self.inifile, "General", "showname").decode("utf-8")) except: self.defaultShowname.setText(ini.read_ini(self.inifile, "General", "showname")) self.cbEnableSlide.setChecked(ini.read_ini_bool(self.inifile, "General", "slide", False)) self.cbDownloadChars.setChecked(ini.read_ini_bool(self.inifile, "General", "download characters", False)) self.cbDownloadSounds.setChecked(ini.read_ini_bool(self.inifile, "General", "download sounds", False)) self.cbDownloadMusic.setChecked(ini.read_ini_bool(self.inifile, "General", "download music")) self.cbDownloadEvidence.setChecked(ini.read_ini_bool(self.inifile, "General", "download evidence", False)) self.cbThemes.setCurrentIndex(self.themes.index(ini.read_ini(self.inifile, "General", "theme", "default"))) self.cbServers.setCurrentIndex(ini.read_ini_int(self.inifile, "General", "auto connect", -1) + 1) self.cbCharacters.setEditText(ini.read_ini(self.inifile, "General", "auto pick").decode('utf-8')) self.autoJoinArea.setText(ini.read_ini(self.inifile, "General", "auto join area").decode('utf-8')) self.sbTextStayTime.setValue(ini.read_ini_int(self.inifile, "General", "text stay time", 200)) self.cbCheckUpdates.setChecked(ini.read_ini_bool(self.inifile, "General", "install updates", False)) # Automatic updates are opt-in! self.cbDevices.setCurrentIndex(ini.read_ini_int(self.inifile, "Audio", "device", audio.getCurrDevice())) self.sliMusicVolume.setValue(ini.read_ini_int(self.inifile, "Audio", "Music volume", 100)) self.sliSoundVolume.setValue(ini.read_ini_int(self.inifile, "Audio", "Sound volume", 100)) self.sliBlipsVolume.setValue(ini.read_ini_int(self.inifile, "Audio", "Blip volume", 100)) else: self.cbSaveToLog.setChecked(False) self.cbCombineLogs.setChecked(False) self.cbSaveDemos.setChecked(False) self.defaultOOCName.setText("") self.defaultShowname.setText("") self.cbEnableSlide.setChecked(False) self.cbDownloadSounds.setChecked(True) self.cbDownloadMusic.setChecked(True) self.cbDownloadEvidence.setChecked(True) self.cbThemes.setCurrentIndex(self.themes.index("default")) self.cbCheckUpdates.setChecked(False) self.sbTextStayTime.setValue(200) self.cbCharacters.setEditText("") self.autoJoinArea.setText("") self.cbDevices.setCurrentIndex(audio.getCurrDevice()) self.sliMusicVolume.setValue(100) self.sliSoundVolume.setValue(100) self.sliBlipsVolume.setValue(100) self.callwords.clear() if exists(AO2XPpath + "callwords.ini"): with open(AO2XPpath + "callwords.ini") as f: for line in f: self.callwords.append(line.rstrip().decode("utf-8")) self.saveLogsState = self.cbSaveToLog.isChecked() self.combineLogsState = self.cbCombineLogs.isChecked() self.saveDemosState = self.cbSaveDemos.isChecked() self.themeState = self.cbThemes.currentText() self.tabs.setCurrentIndex(0) self.show() def callwordsWordWrapCheckbox(self, newstate): if newstate: self.callwords.setWordWrapMode(QtGui.QTextOption.WrapAtWordBoundaryOrAnywhere) else: self.callwords.setWordWrapMode(0) def onSaveClicked(self): if not self.inifile.has_section("General"): self.inifile.add_section("General") if not self.inifile.has_section("Audio"): self.inifile.add_section("Audio") self.inifile.set("General", "save logs", self.cbSaveToLog.isChecked()) self.inifile.set("General", "combined logs", self.cbCombineLogs.isChecked()) self.inifile.set("General", "record demos", self.cbSaveDemos.isChecked()) self.inifile.set("General", "OOC name", self.defaultOOCName.text().toUtf8()) self.inifile.set("General", "showname", self.defaultShowname.text().toUtf8()) self.inifile.set("General", "text stay time", self.sbTextStayTime.value()) self.inifile.set("General", "slide", self.cbEnableSlide.isChecked()) self.inifile.set("General", "download characters", self.cbDownloadChars.isChecked()) self.inifile.set("General", "download sounds", self.cbDownloadSounds.isChecked()) self.inifile.set("General", "download music", self.cbDownloadMusic.isChecked()) self.inifile.set("General", "download evidence", self.cbDownloadEvidence.isChecked()) self.inifile.set("General", "theme", self.cbThemes.currentText()) self.inifile.set("General", "auto connect", self.cbServers.currentIndex() - 1) self.inifile.set("General", "auto pick", self.cbCharacters.currentText().toUtf8()) self.inifile.set("General", "auto join area", self.autoJoinArea.text().toUtf8()) self.inifile.set("General", "install updates", self.cbCheckUpdates.isChecked()) self.inifile.set("Audio", "device", self.cbDevices.currentIndex()) self.inifile.set("Audio", "Music volume", self.sliMusicVolume.value()) self.inifile.set("Audio", "Sound volume", self.sliSoundVolume.value()) self.inifile.set("Audio", "Blip volume", self.sliBlipsVolume.value()) with open("AO2XP.ini", "wb") as f: self.inifile.write(f) with open(AO2XPpath + "callwords.ini", "w") as f: f.write(self.callwords.toPlainText().toUtf8()) self.gamewindow.gamewidget.textWaitTime = self.sbTextStayTime.value() slideEnabled = self.cbEnableSlide.isChecked() self.gamewindow.gamewidget.slideEnabled = slideEnabled self.gamewindow.gamewidget.cbSlide.setEnabled(slideEnabled) if not slideEnabled: self.gamewindow.gamewidget.cbSlide.setChecked(False) if not self.themeState == self.cbThemes.currentText(): self.gamewindow.gamewidget.loadTheme(True) if not self.gamewindow.gamewidget.demoPlaying: if not (self.saveLogsState == self.cbSaveToLog.isChecked() and self.combineLogsState == self.cbCombineLogs.isChecked()): self.gamewindow.gamewidget.OOCLog.setLogFiles() self.gamewindow.gamewidget.ICLog.setLogFiles(self.gamewindow.gamewidget.OOCLog.logfile) if not self.saveDemosState == self.cbSaveDemos.isChecked(): if self.cbSaveDemos.isChecked(): self.gamewindow.gamewidget.startDemoRecorder() else: self.gamewindow.gamewidget.demoRecorder = None self.hide() def onCancelClicked(self): self.hide() def onAboutClicked(self): self.gamewindow.aboutgui.exec_() def onUpdateClicked(self): import updater code = updater.checkForUpdates() if code == 0: subprocess.Popen(["./AO2XPupdat"]) _exit(0) def onReloadAudioSystemClicked(self): audio.free() audio.init() print "[audio] Reloaded audio system"