#!/usr/bin/env python #**************************************************************************** # optiondlg.py, provides classes for option setting dialogs # # Copyright (C) 2005, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, Version 2. This program is # distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. #***************************************************************************** import sys from tmpcontrol import SpinBoxEx from qt import Qt, PYSIGNAL, SIGNAL, SLOT, QCheckBox, QDialog, \ QDoubleValidator, QGridLayout, QGroupBox, QHBoxLayout, \ QLabel, QLineEdit, QPushButton, QRadioButton, QSizePolicy, \ QSpacerItem, QValidator, QVBoxLayout, QVButtonGroup stdFlags = Qt.WStyle_Customize | Qt.WStyle_NormalBorder | Qt.WStyle_Title | \ Qt.WStyle_SysMenu class OptionDlg(QDialog): """Works with Option class to provide a dialog for pref/options""" def __init__(self, option, parent=None, name=None, modal=0, flags=stdFlags): QDialog.__init__(self, parent, name, modal, flags) self.option = option topLayout = QVBoxLayout(self, 8) self.columnLayout = QHBoxLayout(topLayout) self.gridLayout = QGridLayout(self.columnLayout, 0, 2) self.oldLayout = self.gridLayout ctrlLayout = QHBoxLayout(topLayout) ctrlLayout.insertStretch(0) okButton = QPushButton(_('&OK'), self) ctrlLayout.addWidget(okButton) self.connect(okButton, SIGNAL('clicked()'), self, SLOT('accept()')) cancelButton = QPushButton(_('&Cancel'), self) ctrlLayout.addWidget(cancelButton) self.connect(cancelButton, SIGNAL('clicked()'), self, SLOT('reject()')) caption = _('Preferences') if sys.platform == 'win32': caption += ' (PyQt)' self.setCaption(caption) self.itemList = [] self.curGroup = None def addItem(self, dlgItem, widget, label=None): """Add a control with optional label, called by OptionDlgItem""" row = self.gridLayout.numRows() if label: self.gridLayout.addWidget(label, row, 0) self.gridLayout.addWidget(widget, row, 1) else: self.gridLayout.addMultiCellWidget(widget, row, row, 0, 1) self.itemList.append(dlgItem) def startGroupBox(self, title, intSpace=5): """Use a group box for next added items""" self.curGroup = QGroupBox(title, self) row = self.oldLayout.numRows() self.oldLayout.addMultiCellWidget(self.curGroup, row, row, 0, 1) self.gridLayout = QGridLayout(self.curGroup, 0, 2, 10, intSpace) spacer = QSpacerItem(1, 10, QSizePolicy.Fixed) # fix title spacing self.gridLayout.addMultiCell(spacer, 0, 0, 0, 1) def endGroupBox(self): """Cancel group box for next added items""" self.gridLayout = self.oldLayout self.curGroup = None def startNewColumn(self): """Cancel any group box and start a second column""" self.curGroup = None spacer = QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding) row = self.oldLayout.numRows() self.oldLayout.addMultiCell(spacer, row, row, 0, 1) self.gridLayout = QGridLayout(self.columnLayout, 0, 2) self.oldLayout = self.gridLayout def parentGroup(self): """Return parent for new widgets""" if self.curGroup: return self.curGroup return self def accept(self): """Called by dialog when OK button pressed""" for item in self.itemList: item.updateData() QDialog.accept(self) class OptionDlgItem: """Base class for items to add to dialog""" def __init__(self, dlg, key, writeChg): self.dlg = dlg self.key = key self.writeChg = writeChg self.control = None class OptionDlgBool(OptionDlgItem): """Holds widget for bool checkbox""" def __init__(self, dlg, key, menuText, writeChg=1): OptionDlgItem.__init__(self, dlg, key, writeChg) self.control = QCheckBox(menuText, dlg.parentGroup()) self.control.setChecked(dlg.option.boolData(key)) dlg.addItem(self, self.control) def updateData(self): """Update Option class based on checkbox status""" if self.control.isChecked() != self.dlg.option.boolData(self.key): if self.control.isChecked(): self.dlg.option.changeData(self.key, 'yes', self.writeChg) else: self.dlg.option.changeData(self.key, 'no', self.writeChg) class OptionDlgInt(OptionDlgItem): """Holds widget for int spinbox""" def __init__(self, dlg, key, menuText, min, max, writeChg=1, step=1, \ wrap=0, zeroDigits=0, suffix=''): OptionDlgItem.__init__(self, dlg, key, writeChg) label = QLabel(menuText, dlg.parentGroup()) self.control = SpinBoxEx(min, max, step, zeroDigits, dlg.parentGroup()) self.control.setWrapping(wrap) self.control.setSuffix(suffix) self.control.setValue(dlg.option.intData(key, min, max)) dlg.addItem(self, self.control, label) def updateData(self): """Update Option class based on spinbox status""" self.control.updateValue() if self.control.value() != int(self.dlg.option.numData(self.key)): self.dlg.option.changeData(self.key, `self.control.value()`, \ self.writeChg) class OptionDlgDbl(OptionDlgItem): """Holds widget for double line edit""" def __init__(self, dlg, key, menuText, min, max, writeChg=1): OptionDlgItem.__init__(self, dlg, key, writeChg) label = QLabel(menuText, dlg.parentGroup()) self.control = QLineEdit(str(dlg.option.numData(key, min, max)), \ dlg.parentGroup()) valid = QDoubleValidator( min, max, 6, self.control) self.control.setValidator(valid) dlg.addItem(self, self.control, label) def updateData(self): """Update Option class based on edit status""" text = self.control.text() tmp = 0 if self.control.validator().validate(text, tmp)[0] != \ QValidator.Acceptable: return num = float(str(text)) if num != self.dlg.option.numData(self.key): self.dlg.option.changeData(self.key, `num`, self.writeChg) class OptionDlgStr(OptionDlgItem): """Holds widget for string line edit""" def __init__(self, dlg, key, menuText, writeChg=1): OptionDlgItem.__init__(self, dlg, key, writeChg) label = QLabel(menuText, dlg.parentGroup()) self.control = QLineEdit(dlg.option.strData(key, 1), dlg.parentGroup()) dlg.addItem(self, self.control, label) def updateData(self): """Update Option class based on edit status""" newStr = unicode(self.control.text()) if newStr != self.dlg.option.strData(self.key, 1): self.dlg.option.changeData(self.key, newStr, self.writeChg) class OptionDlgRadio(OptionDlgItem): """Holds widget for exclusive radio button group""" def __init__(self, dlg, key, headText, textList, writeChg=1): # textList is list of tuples: optionText, labelText OptionDlgItem.__init__(self, dlg, key, writeChg) self.strList = [x[0] for x in textList] self.control = QVButtonGroup(headText, dlg.parentGroup()) str = dlg.option.strData(key) for textGroup in textList: button = QRadioButton(textGroup[1], self.control) if textGroup[0] == str: button.setChecked(1) dlg.addItem(self, self.control) def updateData(self): """Update Option class based on button status""" data = self.strList[self.control.id(self.control.selected())] if data != self.dlg.option.strData(self.key): self.dlg.option.changeData(self.key, data, self.writeChg) class OptionDlgPush(OptionDlgItem): """Holds widget for extra misc. push button""" def __init__(self, dlg, text, cmd): OptionDlgItem.__init__(self, dlg, '', 0) self.control = QPushButton(text, dlg.parentGroup()) self.control.connect(self.control, SIGNAL('clicked()'), cmd) dlg.addItem(self, self.control) def updateData(self): """Dummy update function""" pass