#!/usr/bin/env python # Copyright (c) 2004 Michael Pyne # Distributed under the terms of the GNU GPL v2, or any later version. # Script to auto-generate the configuration for kdesvn-build to use. # See http://grammarian.homelinux.net/kdesvn-build/ from qt import *; from re import split; import re; import sys; import os; defaultQtCopyOpts = "-system-zlib -qt-gif -system-libjpeg -system-libpng -plugin-imgfmt-mng -thread -no-exceptions -debug -fast -dlopen-opengl" modules = { 'qt-copy': { 'order': 0, 'conf': { 'apply-qt-patches': 'true', 'use-qt-builddir-hack': 'true' } }, 'arts': { 'order': 1, 'conf': { } }, 'kdesupport': { 'order': 2, 'conf': { } }, 'kdemultimedia': { 'order': 4, 'conf': { } }, 'kdelibs': { 'order': 2, 'conf': { } }, 'kdebase': { 'order': 3, 'conf': { } }, 'kdepim': { 'order': 4, 'conf': { } }, 'kdegraphics': { 'order': 4, 'conf': { } }, 'kdeaddons': { 'order': 4, 'conf': { } }, 'kdenetwork': { 'order': 4, 'conf': { } }, 'kdegames': { 'order': 4, 'conf': { } }, 'kdeadmin': { 'order': 4, 'conf': { } }, 'kdeartwork': { 'order': 4, 'conf': { } }, 'kdeutils': { 'order': 4, 'conf': { } }, 'kdetoys': { 'order': 4, 'conf': { } }, 'kdeedu': { 'order': 4, 'conf': { } }, 'kdeaccessibility': { 'order': 4, 'conf': { } }, 'valgrind': { 'order': 3, 'conf': { } }, 'kdevelop': { 'order': 4, 'conf': { } }, 'kde-common': { 'order': 2, 'conf': { } }, 'kde-i18n': { 'order': 3, 'conf': { } }, 'kdewebdev': { 'order': 4, 'conf': { } }, 'koffice': { 'order': 4, 'conf': { } }, 'kdebindings': { 'order': 4, 'conf': { } }, #'kdenonbeta': { 'order': 4, 'conf': { } }, 'kdesdk': { 'order': 5, 'conf': { } }, } globals = { 'binpath': { 'description': 'Binary path', 'whatsthis': """This is the path that you can find your development toolchain in, including the g++ and make programs. This is specified by using colon (:) separated directories. Do not include any KDE or Qt paths, as kdesvn-build will add those automatically as appropriate.""", 'default': '/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin' }, 'source-dir': { 'description': 'Directory to hold KDE sources', 'whatsthis': """This is the directory to download the KDE sources into. You may use the tilde (~) to stand for your home directory.""", 'default': '~/kdesvn' }, 'kdedir': { 'description': 'Directory to install KDE into', 'whatsthis': """This is the directory that KDE will be installed to. You may use the tilde (~) to stand for your home directory. If you choose to install into a system directory, then you will probably need to adjust the make-install-prefix option using sudo. """, 'default': '~/kde' # We probably don't want to default to KDEDIR }, 'qtdir': { 'description': 'Directory to Qt installation', 'whatsthis': """This is the directory of your Qt installation. If you would like to use qt-copy from KDE Subversion, check the Use KDE's qt-copy instead of system Qt checkbox.""", 'default': os.environ.get('QTDIR', '~/kdesvn/build/qt-copy') }, 'svn-server': { 'description': 'Subversion Server to use', 'whatsthis': "This is the server to download the KDE sources from", 'default': 'svn://svn.kde.org/home/kde' }, 'conf-flags': { 'description': 'Default configure flags', 'whatsthis': """This is what configure flags you would like to pass to every Subversion module (except for qt-copy). Use this to specify settings you want every module to have, such as --enable-debug""", 'default': '--enable-debug' }, 'cxxflags': { 'description': 'Your CXXFLAGS', 'whatsthis': """These flags control various gcc options, such as the amount of optimization to perform. She the gcc manual for more information. Whatever you do, don't put excessive CXXFLAGS here, as higher levels of optimization tend to introduce errors sometimes.""", 'default': '-g -pipe -march=i686' } } version = '0.93' class BoldLabel(QLabel): def __init__(self, label, parent): QLabel.__init__(self, "

" + label + "

", parent) class WizardPage(QVBox): def __init__(self, wizard, title): QVBox.__init__(self, wizard) self.wizard = wizard self.title = title self.label = BoldLabel(title, self) self.setSpacing(10) wizard.addPage(self, title) self.connect(wizard, SIGNAL("selected(const QString &)"), self.pageSelected) def pageSelected(self, title): if str(title) == self.title: self.preparePage() def preparePage(self): pass class IntroPage(WizardPage): def __init__(self, wizard): WizardPage.__init__(self, wizard, "Introduction to kdesvn-build-wizard") self.body = QLabel("""
This wizard will help you setup a basic configuration file for kdesvn-build. To continue, please click the Next button.
""", self) class DistributedPage(WizardPage): def __init__(self, wizard): WizardPage.__init__(self, wizard, "Distributed compilation options") text = """On this page you can configure whether or not you want to enable some options for distributed compilation. You would want this if you have a SMP computer, or if you are using distributed build tools such as distcc, TeamBuilder, or icecream. """ formBox = QVBox(self) formBox.setSpacing(12) self.explanation = QLabel(text, formBox) self.usedcCheck = QCheckBox("Enable distributed compilation", formBox) self.connect(self.usedcCheck, SIGNAL("toggled(bool)"), self.setDCEnabled) self.usedcCheck.setChecked(False) self.setStretchFactor(self.explanation, 1) self.optionsPage = DistributedOptionsPage(self.wizard) self.wizard.setAppropriate(self.optionsPage, False) def setDCEnabled(self, enable): if enable: self.wizard.setAppropriate(self.optionsPage, True) else: self.wizard.setAppropriate(self.optionsPage, False) class DistributedOptionsPage(WizardPage): def __init__(self, wizard): WizardPage.__init__(self, wizard, "Distributed Compilation Options") self.options = QGroupBox(2, Qt.Vertical, "Distributed compilation options", self) box = QHBox(self.options) label = QLabel("Number of simultaneous jobs", box) edit = QSpinBox(1, 128, 1, box) edit.setValue(4) self.connect(edit, SIGNAL("valueChanged(int)"), self.jobsChanged) check = QCheckBox("Use unsermake instead of automake", self.options) self.connect(check, SIGNAL("toggled(bool)"), self.unsermakeChecked) def preparePage(self): if not globals.has_key('use-unsermake'): globals['use-unsermake'] = { 'value': 'false' } if not globals.has_key('make-options'): globals['make-options'] = { 'value': '-j4' } def jobsChanged(self, number): globals['make-options']['value'] = '-j' + str(number) def unsermakeChecked(self, enabled): if enabled: globals['use-unsermake']['value'] = 'true' else: globals['use-unsermake']['value'] = 'false' # Reimplemented in order to shade the text background when an item is selected class CheckItem(QCheckListItem): def __init__(self, parent, text): QCheckListItem.__init__(self, parent, text, QCheckListItem.CheckBox) self.moduleName = text self.listView().palette().setColor(QPalette.Disabled, QColorGroup.Text, Qt.darkGray) def stateChange(self, status): self.repaint() modules[self.moduleName]['checked'] = self.state() if not modules[self.moduleName].has_key('option-box'): return if self.state(): modules[self.moduleName]['option-box'].show() else: modules[self.moduleName]['option-box'].hide() def paintCell(self, painter, cg, col, width, align): newCg = QColorGroup(cg) color = QColor(196, 223, 255) if self.state() == QCheckListItem.On: if self.listView().viewport().backgroundMode() != Qt.FixedColor: newCg.setColor(QColorGroup.Base, color) else: newCg.setColor(QColorGroup.Background, color) newCg.setColor(QColorGroup.Text, Qt.black) QCheckListItem.paintCell(self, painter, newCg, col, width, align) class GlobalSettingsPage(WizardPage): class TextChangeProxy(QObject): def __init__(self, parent, name): QObject.__init__(self, parent) self.name = name def textChanged(self, value): globals[self.name]['value'] = str(value) def preparePage(self): if modules['qt-copy']['checked'] == QCheckListItem.On: self.toggleCheckBox.setChecked(True) else: self.toggleCheckBox.setChecked(False) def qtCopyToggled(self, enable): self.qtcopyLine.setEnabled(not enable) modules['qt-copy']['checked'] = QCheckListItem.Off if enable: self.qtcopyLine.setText("~/kdesvn/build/qt-copy") modules['qt-copy']['checked'] = QCheckListItem.On def addGridLine(self, label): templabel = QLabel(globals[label]['description'], self.layoutWidget) editor = QLineEdit(globals[label]['default'], self.layoutWidget) if label == 'qtdir': self.qtcopyLine = editor toggleQtCopy = QCheckBox("Use KDE's qt-copy instead of system Qt", self) toggleQtCopy.setChecked(True) self.qtCopyToggled(True) self.connect(toggleQtCopy, SIGNAL("toggled(bool)"), self.qtCopyToggled) self.toggleCheckBox = toggleQtCopy QWhatsThis.add(toggleQtCopy, """

Check this box if you'd like to use the qt-copy module in KDE instead of the system Qt.

qt-copy is the latest version of Qt, optionally with some patches applied to fix bugs and improve performance.

""") globals[label]['value'] = globals[label]['default'] if globals[label].has_key('whatsthis'): QWhatsThis.add(templabel, "" + globals[label]['whatsthis'] + "") QWhatsThis.add(editor, "" + globals[label]['whatsthis'] + "") proxy = self.TextChangeProxy(self, label) proxy.connect(editor, SIGNAL("textChanged(const QString&)"), proxy.textChanged) return editor def __init__(self, wizard): WizardPage.__init__(self, wizard, "Global Settings") self.layoutWidget = QGrid(2, self) self.layoutWidget.setSpacing(4) self.setStretchFactor(self.layoutWidget, 1) for x in globals.keys(): temp = self.addGridLine(x) # Abstract class, please subclass this class ModulesPage(WizardPage): def __init__(self, wizard, moduleDict, label, banner): WizardPage.__init__(self, wizard, label) defaultModules = [ 'arts', 'kdelibs', 'kdebase', 'kdesupport', 'kdepim', 'kdegraphics', 'kdeaddons', 'kdenetwork', 'kdegames', 'kdeartwork', 'kdeutils', 'qt-copy', 'kdemultimedia', 'kdetoys', 'kdeedu' ] requiredModules = [ 'arts', 'kdelibs' ] self.listview = QListView(self) listview = self.listview listview.setResizeMode(QListView.LastColumn) for x in ['Module', 'Description']: listview.addColumn(x) self.moduleItems = { } for x in moduleDict.keys(): self.moduleItems[x] = CheckItem(listview, x) self.moduleItems[x].setText(1, moduleDict[x]) modules[x]['checked'] = QCheckListItem.Off if x in defaultModules: self.moduleItems[x].setState(QCheckListItem.On) if x in requiredModules: self.moduleItems[x].setEnabled(False) listview.setColumnWidthMode(0, QListView.Manual) def preparePage(self): for x in self.moduleItems.keys(): self.moduleItems[x].setState(modules[x]['checked']) def showEvent(self, event): self.listview.adjustColumn(1) self.listview.adjustColumn(0) def resizeEvent(self, event): self.listview.adjustColumn(0) class BaseModulesPage(ModulesPage): def __init__(self, wizard): moduleDict = { 'arts': 'KDE Audio engine', 'qt-copy': 'Copy of the current Qt library, with bugfixes and optimizations', 'kdesupport': 'Support libraries for some KDE programs. Currently required for juk and amarok', 'kdemultimedia': 'KDE\'s multimedia software collection', 'kdelibs': 'Core KDE libraries, needed for all KDE apps', 'kdebase': 'Base KDE application distribution, includes konqueror', 'kdepim': 'Personal information management applications (e-mail, organizer)', 'kdegraphics': 'Programs to manage your images', 'kdeaddons': 'Useful addons to various KDE programs including kicker and konqueror', 'kdenetwork': 'Network utilities for KDE', 'kdegames': 'Simple games to make your KDE installation more fun!', 'kdeadmin': 'System administration tools for KDE', 'kdeartwork': 'More artwork and styles for KDE. Includes Plastik and dotNET', 'kdeutils': 'Useful utilities, including klipper and kgpg', 'kdetoys': 'Amusing doo-dads to ornament your desktop', 'kdeedu': 'Educational programs for KDE', 'kdeaccessibility': 'Accessibility-related programs for KDE' } ModulesPage.__init__(self, wizard, moduleDict, 'Base Modules', 'Base Module Selection') class ExtraModulesPage(ModulesPage): def __init__(self, wizard): moduleDict = { 'valgrind': 'Excellent program optimization/memory-leak-checker', 'kdevelop': 'Powerful Integrated Development Environment for developers', 'kde-common': 'Code and data common to all of KDE', 'kde-i18n': 'Language translations for KDE. This module is VERY LARGE', 'kdewebdev': 'Applications useful for web site developers. Includes Quanta and Kommander', 'koffice': 'KDE Office Suite, includes word processor, spreadsheet, and more', 'kdebindings': 'Bindings to allow programming Qt and/or KDE in languages other than C++', 'kdesdk': 'Collection of applications to ease the job of KDE developers' } ModulesPage.__init__(self, wizard, moduleDict, 'Extra Modules', 'Extra Module Selection') class ExtragearModulesPage(ModulesPage): def __init__(self, wizard): moduleDict = { 'addons': 'Addon programs not part of KDE', 'graphics': 'Graphics programs not part of KDE', 'libs': 'Libraries needed by other extragear modules', 'multimedia': 'Multimedia programs not part of KDE', 'network': 'Network/Internet programs not part of KDE', 'office': 'Office productivity applications not part of KDE', 'pim': 'Personal information management applications not part of KDE', 'security': 'Computer security applications not part of KDE', 'sysadmin': 'System administration tools not part of KDE', 'toys': 'Fun/silly programs not part of KDE', 'utils': 'Utility programs, or programs that don\'t fit a different category.' } dict = { } for x in moduleDict.keys(): dict["extragear/%s" % x] = moduleDict[x] ModulesPage.__init__(self, wizard, dict, 'Extragear Modules', 'Extragear Module Selection') caption = ''' You can select some modules from the Extragear project here. Extragear is a project that, although not part of KDE, contains a nice collection of KDE programs, including favorites like K3b and DigiKam.''' # Must be constructed after __init__() is called. label = QLabel(caption, self) class PlaygroundModulesPage(ModulesPage): def __init__(self, wizard): moduleDict = { 'artwork': 'Artwork/styles under development', 'base': 'General purpose programs under development', 'edu': 'Educational programs under development', 'games': 'Games under development', 'ioslaves': 'IOSlaves under development', 'multimedia': 'Multimedia programs under development', 'network': 'Network/Internet programs under development', 'pim': 'Personal Information Management programs under development', 'sysadmin': 'System administration tools under development', 'utils': 'Utility programs, or programs that don\'t fit a different category.' } dict = { } for x in moduleDict.keys(): dict["playground/%s" % x] = moduleDict[x] ModulesPage.__init__(self, wizard, dict, 'Playground Modules', 'Playground Module Selection') caption = ''' You can select some modules from the KDE Playground here. The Playground is a collection of modules holding programs that are currently in development. Some are closer to release quality than others.''' # Must be constructed after __init__() is called. label = QLabel(caption, self) class OptionsConfBox(QGroupBox): class TextChangeProxy(QObject): def __init__(self, parent, modName, key): QObject.__init__(self, parent) self.key = key self.modName = modName def textChanged(self, value): modules[self.modName]['conf'][self.key] = str(value) def __init__(self, title, parent): QGroupBox.__init__(self, 2, Qt.Horizontal, title, parent) self.moduleName = title checkoutOnlyRe = re.compile("^(playground|extragear|kde-i18n)") for x in ['conf-flags', 'checkout-only']: if x == 'checkout-only' and not checkoutOnlyRe.match(title): continue label = QLabel(x, self) edit = QLineEdit(self) if title == 'qt-copy' and x == 'conf-flags': edit.setText(defaultQtCopyOpts) modules['qt-copy']['conf']['conf-flags'] = defaultQtCopyOpts proxy = self.TextChangeProxy(self, title, x) proxy.textChanged(edit.text()) self.connect (edit, SIGNAL("textChanged(const QString &)"), proxy.textChanged) class OptionsPage(QScrollView): def __init__(self, wizard): QScrollView.__init__(self, wizard) self.setResizePolicy(self.AutoOneFit) self.container = QVBox(self.viewport()) self.container.setSpacing(7) self.addChild(self.container) label = BoldLabel("Module Options", self.container) self.wizard = wizard self.name = "Module Options" sortedModules = modules.keys() sortedModules.sort(cmpModuleOrder) for x in sortedModules: box = OptionsConfBox(x, self.container) if not modules.has_key(x): continue if not modules[x].has_key('checked'): continue if not modules[x]['checked']: box.hide() modules[x]['option-box'] = box wizard.addPage(self, self.name) def cmpModuleOrder(a,b): aa = modules[a]['order'] bb = modules[b]['order'] if aa == bb: return cmp(a, b) return cmp(aa, bb) class GeneratePage(WizardPage): def __init__(self, wizard): WizardPage.__init__(self, wizard, "Config file generation") self.textEdit = QTextEdit(self) self.textEdit.setFont(QFont('monospace')) self.textEdit.setReadOnly(True) self.textEdit.setWordWrap(QTextEdit.NoWrap) box = QHBox(self) box.setSpacing(6) label = QLabel("&Filename", box) self.browseLine = QLineEdit("~/.kdesvn-buildrc", box) label.setBuddy(self.browseLine) self.connect (self.browseLine, SIGNAL("textChanged(const QString &)"), self.wizard.setFileName) self.connect (self.browseLine, SIGNAL("returnPressed()"), self.wizard.accept) browseButton = QPushButton("&Save As...", box) self.connect (browseButton, SIGNAL("clicked()"), self.browseClicked) def browseClicked(self): fileName = re.sub('^~', os.environ['HOME'], str(self.browseLine.text())) fileName = QFileDialog.getSaveFileName(fileName, QString.null, self, "kdesvn-pywizard-filesave-dialog") if not fileName.isNull(): print "Setting filename to " + str(fileName) self.browseLine.setText(str(fileName)) self.wizard.setFileName(str(fileName)) def preparePage(self): self.textEdit.clear() te = self.textEdit.append te("### Generated by kdecvs-pywizard, version %s" % version) te("### Visit the homepage: http://grammarian.homelinux.net/kdesvn-build/") te("global\n") for x in globals.keys(): te("\t" + x + " " + globals[x]['value'] + "\n") te("end global\n\n") checkedFilter = lambda x: modules[x]['checked'] sortedCheckedModules = filter(checkedFilter, modules.keys()) sortedCheckedModules.sort(cmpModuleOrder) last = sortedCheckedModules[-1] for x in sortedCheckedModules: te("module " + x + "\n") mod = modules[x]['conf'] for y in mod.keys(): if mod[y] != "" and not (y == 'use-unsermake' and x == 'kdebindings'): te("\t" + y + " " + mod[y] + "\n") if x == 'kdebindings': te("\t# kdebindings hurts badly with unsermake\n") te("\tuse-unsermake false\n") if x == 'qt-copy': te("\t# unsermake makes no sense with qt-copy\n") te("\tuse-unsermake false\n") te("end module\n") if x != last: te("\n") self.wizard.setFinishEnabled(self, True) self.wizard.setFileName(self.browseLine.text()) self.wizard.setFileText(self.textEdit.text()) class ConfigWizard(QWizard): def __init__(self, parent=None): QWizard.__init__(self, parent) def showPage(self, page): QWizard.showPage(self, page) self.setHelpEnabled(page, 0) def setFileText(self, text): self.text = str(text) def setFileName(self, name): self.filename = str(name) def accept(self): filename = self.filename print "Saving " + filename name = re.sub('^~', os.environ['HOME'], self.filename) if os.access(name, os.F_OK): caption = "Overwrite file?" text = """ The file you have selected, %s, already exists. Do you want to overwrite %s?""" % (filename, filename) selection = QMessageBox.warning(self, caption, text, QMessageBox.Yes, QMessageBox.No | QMessageBox.Default | QMessageBox.Escape, 0) if selection != QMessageBox.Yes: return try: file = open(name, 'w') except IOError: QMessageBox.warning(self, "Unable to save", "Unable to save " + filename, QMessageBox.Ok | QMessageBox.Default, 0, 0) return file.write(self.text) file.close() QWizard.accept(self) def main(args): print "kdesvn-pywizard version %s" % version # extragear/ and playground have a shitload of modules, auto-generate some of # their entries here. playgroundMods = split('\s+', """artwork base edu games ioslaves multimedia network pim sysadmin utils""") extragearMods = split('\s+', """addons graphics libs multimedia network office pim security sysadmin toys utils""") for i in playgroundMods: modulename = "playground/%s" % i modules[modulename] = { 'order': 5, 'conf': { } } for i in extragearMods: modulename = "extragear/%s" % i modules[modulename] = { 'order': 5, 'conf': { } } a = QApplication(args) wizard = ConfigWizard() # I like bold fonts better font = wizard.titleFont() font.setBold(True) wizard.setTitleFont(font) # Add all of the pages to the wizard page1 = IntroPage(wizard) page2 = GlobalSettingsPage(wizard) page3 = DistributedPage(wizard) page4 = BaseModulesPage(wizard) page5 = ExtraModulesPage(wizard) page6 = ExtragearModulesPage(wizard) page7 = PlaygroundModulesPage(wizard) page8 = OptionsPage(wizard) page9 = GeneratePage(wizard) wizard.resize(QSize(640, 480)) # Start the show wizard.exec_loop() if __name__=="__main__": main(sys.argv) # vim: set noet sw=4 ts=4 tw=0: