I felt that a "user-friendly" configuration dialog for uRSSus was not a good way to spend effort, because I expect options to change often for a while, and I didn't want an outdated dialog, either. The solution? Autogenerate a mediocre configuration dialog!
First, define what options uRSSus supports (Update: suggestion by Alejandro Cura, using tuples works much better!):
options = (
('ui',
(
('alwaysShowFeed', ('bool', False, "Always show a link to the post's feed when diplaying a post")),
('hideOnTrayClick', ('bool', True, "Hide the main window when clicking on the tray icon")),
)
),
('options',
(
('defaultRefresh' , ('int', 1800, "How often feeds should be refreshed by default (in seconds).", 300, None )),
('maxPostsDisplayed' , ('int', 1000, "Limit the display to this many posts. If set too high, opening 'All Feeds' may take forever", 0, None)),
('defaultExpiration' , ('int', 7, "How long should articles be kept by default. (In days)", 0, 9999)),
)
),
('twitter',
(
('username', ('string', None, 'Your Twitter user name.' )),
('password', ('password', None, 'Your Twitter password.' )),
)
)
)
Then a little magic, and this comes out:
How magic? This magic:
class ConfigDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
# Set up the UI from designer
self.ui=UI_ConfigDialog()
self.ui.setupUi(self)
pages=[]
sections=[]
self.values={}
for sectionName, options in config.options:
# Create a page widget/layout for this section:
page=QtGui.QScrollArea()
layout=QtGui.QGridLayout()
row=-2
for optionName, definition in options:
row+=2
if definition[0]=='bool':
cb=QtGui.QCheckBox(optionName)
cb.setChecked(config.getValue(sectionName, optionName, definition[1]))
layout.addWidget(cb, row, 0, 1, 2)
self.values[sectionName+'/'+optionName]=[cb, lambda(cb): cb.isChecked()]
elif definition[0]=='int':
label=QtGui.QLabel(optionName+":")
label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
spin=QtGui.QSpinBox()
if definition[3] is not None:
spin.setMinimum(definition[3])
else:
spin.setMinimum(-99999)
if definition[4] is not None:
spin.setMaximum(definition[4])
else:
spin.setMaximum(99999)
spin.setValue(config.getValue(sectionName, optionName, definition[1]))
layout.addWidget(label, row, 0, 1, 1)
layout.addWidget(spin, row, 1, 1, 1)
self.values[sectionName+'/'+optionName]=[spin, lambda(spin): spin.value()]
elif definition[0]=='string':
label=QtGui.QLabel(optionName+":")
label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
text=QtGui.QLineEdit()
text.setText(config.getValue(sectionName, optionName, definition[1]))
layout.addWidget(label, row, 0, 1, 1)
layout.addWidget(text, row, 1, 1, 1)
self.values[sectionName+'/'+optionName]=[text, lambda(text): unicode(text.text())]
elif definition[0]=='password':
label=QtGui.QLabel(optionName+":")
label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
text=QtGui.QLineEdit()
text.setEchoMode(QtGui.QLineEdit.Password)
text.setText(config.getValue(sectionName, optionName, definition[1]))
layout.addWidget(label, row, 0, 1, 1)
layout.addWidget(text, row, 1, 1, 1)
self.values[sectionName+'/'+optionName]=[text, lambda(text): unicode(text.text())]
help=QtGui.QLabel(definition[2])
help.setWordWrap(True)
layout.addWidget(help, row, 2, 1, 1)
separator=QtGui.QFrame()
separator.setFrameStyle(QtGui.QFrame.HLine|QtGui.QFrame.Plain)
layout.addWidget(separator, row+1, 0, 1, 3)
page.setLayout(layout)
pages.append(page)
sections.append(sectionName)
for page, name in zip(pages,sections) :
# Make a tab out of it
self.ui.tabs.addTab(page, name)
self.ui.tabs.setCurrentIndex(1)
self.ui.tabs.removeTab(0)
My first ever thing that I just don't see how it would work without a lambda ;-)