diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-13 05:43:39 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-13 05:43:39 +0000 |
commit | 19ae07d0d443ff8b777f46bcbe97119483356bfd (patch) | |
tree | dae169167c23ba7c61814101995de21d6abac2e8 /wineconfig | |
download | tde-guidance-19ae07d0d443ff8b777f46bcbe97119483356bfd.tar.gz tde-guidance-19ae07d0d443ff8b777f46bcbe97119483356bfd.zip |
Added KDE3 version of KDE Guidance utilities
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kde-guidance@1102646 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'wineconfig')
-rw-r--r-- | wineconfig/drivedetect.py | 122 | ||||
-rwxr-xr-x | wineconfig/firstrunwizard.py | 326 | ||||
-rw-r--r-- | wineconfig/kcm_wineconfig.cpp | 156 | ||||
-rw-r--r-- | wineconfig/wineconfig.desktop | 57 | ||||
-rwxr-xr-x | wineconfig/wineconfig.py | 3552 | ||||
-rw-r--r-- | wineconfig/wineread.py | 543 | ||||
-rw-r--r-- | wineconfig/winewrite.py | 489 |
7 files changed, 5245 insertions, 0 deletions
diff --git a/wineconfig/drivedetect.py b/wineconfig/drivedetect.py new file mode 100644 index 0000000..5916b18 --- /dev/null +++ b/wineconfig/drivedetect.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +########################################################################### +# wineread.py - description # +# ------------------------------ # +# begin : Fri Mar 26 2004 # +# copyright : (C) 2006 by Yuriy Kozlov # +# email : yuriy.kozlov@gmail.com # +# # +########################################################################### +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +########################################################################### + +import os +import wineread + +""" Reads a default set of drives from /etc/fstab """ + +fstabpath = "/etc/fstab" + +# Listed in winecfg +ignored_fs_types = set(["devpts", + "tmpfs", + "proc", + "sysfs", + "swap", + "usbdevfs", + "rpc_pipefs", + "binfmt_misc"]) + +# Listed in winecfg +ignored_mnt_pts = set(["/boot"]) + +cd_fs_types = set(["cdfs","udf","iso9660"]) + +# An incomplete listing, I don't know how winecfg does this. +# RAMFS is included here because I don't know what the correct type for it is in wine. +hd_fs_types = set(["ext4","ext3","ext2","ext","fat","fat32","fat16","ntfs","reiserfs","reiser4", + "jfs","xfs","ramfs","vfat","ufs","hfs","hfsplus"]) + +# Listed in winecfg +net_fs_types = set(["nfs","nfs4","smbfs","cifs","coda"]) + +def autodetect(drives=None): + """ Returns a set of drives found by scanning /etc/fstab, and an error code """ + if not drives: + drives = wineread.GetEmptyDrives() + mappings = set() + if not drives[2][2]: + drives[2][2] = "../drive_c" + drives[2][3] = "hd" + + for drive in drives: + mapping = drive[2] + if mapping: + mappings.add(mapping) + + driveid = 3 + fstab=open(fstabpath,'r') + + for driveline in fstab: + if driveline[0] == '#' or len(driveline.strip()) == 0: # Comment or empty line + continue + else: + driveprops = driveline.split() + fs = driveprops[0] + mnt = driveprops[1] + fstypes = set(driveprops[2].split(',')) + + ignore = False + for fstype in fstypes: + if fstype in ignored_fs_types: + ignore = True + break + + if mnt in ignored_mnt_pts or mnt in mappings: + ignore = True + + if not ignore: + while drives[driveid][2]: # Drive is in use, don't overwrite. + driveid += 1 + if driveid > 25: + return (1,drives) + drives[driveid][2] = mnt + if "/dev/fd" in fs or "floppy" in mnt: + drives[driveid][3] = "floppy" + elif fstype in cd_fs_types or "/dev/cdrom" in fs or "cdrom" in mnt: + drives[driveid][3] = "cdrom" + elif fstype in hd_fs_types: + drives[driveid][3] = "hd" + elif fstype in net_fs_types: + drives[driveid][3] = "network" + else: + drives[driveid][3] = "auto" + driveid += 1 + + fstab.close() + return (0,drives) + +def autodetectshelllinks(shelllinks = None): + """ Returns a default set of windows shell folder mappings """ + if not shelllinks: + shelllinks = wineread.GetEmptyShellLinks() + + for link in shelllinks: + if link[2]: + continue + else: + link[3] = "shellfolder" + #link[4] = wineread.winepath + "/dosdevices/c:/windows/profiles/" + os.environ['USER'] + "/" + link[1] + link[4] = wineread.defaultwinfolderspath + "\\" + link[1] + link[5] = wineread.defaultwinfolderspath + "\\" + link[1] + link[2] = os.environ['HOME'] + if link[1] == "Desktop": + link[2] = os.environ['HOME'] + "/Desktop" + + return shelllinks diff --git a/wineconfig/firstrunwizard.py b/wineconfig/firstrunwizard.py new file mode 100755 index 0000000..c6d3d67 --- /dev/null +++ b/wineconfig/firstrunwizard.py @@ -0,0 +1,326 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +########################################################################### +# wineconfig.py - description # +# ------------------------------ # +# begin : Fri Mar 26 2004 # +# copyright : (C) 2006 by Yuriy Kozlov # +# email : yuriy.kozlov@gmail.com # +# # +########################################################################### +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +########################################################################### + +from qt import * +from kdecore import * +from kdeui import * +from kfile import * +from kio import * +import os +import sys +import signal +import wineread +import winewrite +import drivedetect + +class FirstRunWizard(KWizard): + default_winepath = os.environ['HOME'] + "/.wine" + + def __init__(self, parent = None, name=None, modal=0, fl=0): + KWizard.__init__(self,parent,name,modal,fl) + + if not name: + self.setName("firstrunwizard") + + self.imagedir = unicode(KGlobal.dirs().findDirs("data","guidance/pics")[0]) + + self.setupPage1() + self.setupPageVersion() + self.setupPageExistingWine() + self.setupPageCreateWine() + self.slotCreateExistingToggled(0) + #self.connect(self,SIGNAL("selected(const QString &)"),self.slotPageChanged) + + #self.resize(QSize(600,480).expandedTo(self.minimumSizeHint())) + self.clearWState(Qt.WState_Polished) + + def setupPage1(self): + page1 = QHBox(self,"page1") + + self.kdewinepicture = QLabel(page1,"kdewinepicture") + self.kdewinepicture.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.kdewinepicture.sizePolicy().hasHeightForWidth())) + self.kdewinepicture.setMinimumSize(QSize(140,320)) + self.kdewinepicture.setPixmap(QPixmap(self.imagedir+"kdewinewizard.png")) + #self.kdewinepicture.setScaledContents(1) + + spacer = QWidget(page1) + spacer.setMinimumSize(QSize(6,300)) + + pagebody = QVBox(page1,"pagebody") + page1.setStretchFactor(pagebody,1) + + introtext = QLabel(pagebody,"introtext") + introtext.setText(i18n("It appears that you do not yet have a Windows drive set up.\n" +\ + "This wizard will help set it up so that you can run windows applications.\n")) + + spacer = QWidget(pagebody) + spacer.setMinimumSize(QSize(6,20)) + + self.createinstall = True + + createwinepathchoice = QRadioButton(i18n("Set up the fake windows installation " +\ + "in the following directory:"),pagebody) + + self.winepath = self.default_winepath + hbox = QHBox(pagebody) + hbox.setSpacing(KDialog.spacingHint()) + + self.winefolderedit = KLineEdit(self.winepath,hbox) + self.urlcompletion = KURLCompletion(KURLCompletion.DirCompletion) + self.winefolderedit.setCompletionObject(self.urlcompletion) + self.winefolderedit.setCompletionMode(KGlobalSettings.CompletionPopup) + self.connect(self.winefolderedit,SIGNAL("textChanged(const QString &)"),self.slotWineFolderEdited) + + self.browsecreatebutton = KPushButton(i18n("Browse"),hbox) + self.connect(self.browsecreatebutton,SIGNAL("clicked()"),self.slotBrowseClicked) + + spacer = QWidget(pagebody) + spacer.setMinimumSize(QSize(6,10)) + + existingwinepathchoice = QRadioButton(i18n("There is already a fake windows installation " +\ + "in the following directory:"),pagebody) + + hbox = QHBox(pagebody) + hbox.setSpacing(KDialog.spacingHint()) + + self.existingwinefolderedit = KLineEdit("",hbox) + self.urlcompletion = KURLCompletion(KURLCompletion.DirCompletion) + self.existingwinefolderedit.setCompletionObject(self.urlcompletion) + self.existingwinefolderedit.setCompletionMode(KGlobalSettings.CompletionPopup) + self.connect(self.existingwinefolderedit,SIGNAL("textChanged(const QString &)"),self.slotWineFolderEdited) + + self.browseexistingbutton = KPushButton(i18n("Browse"),hbox) + self.connect(self.browseexistingbutton,SIGNAL("clicked()"),self.slotBrowseClicked) + + self.createexistingchoicesgroup = QButtonGroup(pagebody,"createexistingchoicesgroup") + self.createexistingchoicesgroup.insert(createwinepathchoice,0) + self.createexistingchoicesgroup.insert(existingwinepathchoice,1) + self.createexistingchoicesgroup.setExclusive(True) + self.createexistingchoicesgroup.hide() + self.createexistingchoicesgroup.setButton(0) + self.connect(self.createexistingchoicesgroup,SIGNAL("clicked(int)"),self.slotCreateExistingToggled) + + bottomspacer = QWidget(pagebody) + pagebody.setStretchFactor(bottomspacer,1) + + self.addPage( page1, i18n("Setting up your windows drive") ) + + self.setBackEnabled( page1, False ) + self.setNextEnabled( page1, True ) + self.setHelpEnabled( page1, False ) + self.setFinishEnabled( page1, False ) + + def setupPageExistingWine(self): + self.pageexisting = QHBox(self,"pageexisting") + + self.kdewinepicture = QLabel(self.pageexisting,"kdewinepicture") + self.kdewinepicture.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.kdewinepicture.sizePolicy().hasHeightForWidth())) + self.kdewinepicture.setMinimumSize(QSize(140,320)) + self.kdewinepicture.setPixmap(QPixmap(self.imagedir+"kdewinewizard.png")) + #self.kdewinepicture.setScaledContents(1) + + spacer = QWidget(self.pageexisting) + spacer.setMinimumSize(QSize(6,300)) + + valid = wineread.VerifyWineDrive(self.winepath) + + pagebody = QVBox(self.pageexisting,"pagebody") + self.pageexisting.setStretchFactor(pagebody,1) + + existstext = QLabel(pagebody,"existstext") + if valid: + existstext.setText(i18n("A fake windows installation was found.")) + else: + existstext.setText(i18n("No fake windows installation was found in\n" +\ + self.winepath + "\nPlease go back and create one.")) + + bottomspacer = QWidget(pagebody) + pagebody.setStretchFactor(bottomspacer,1) + + self.addPage( self.pageexisting, i18n("Setting up your windows drive") ) + + self.setBackEnabled( self.pageexisting, True ) + self.setNextEnabled( self.pageexisting, True ) + self.setHelpEnabled( self.pageexisting, False ) + self.setFinishEnabled( self.pageexisting, True ) + + def setupPageCreateWine(self): + self.pagecreate = QHBox(self,"pagecreate") + + self.kdewinepicture = QLabel(self.pagecreate,"kdewinepicture") + self.kdewinepicture.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.kdewinepicture.sizePolicy().hasHeightForWidth())) + self.kdewinepicture.setMinimumSize(QSize(140,320)) + self.kdewinepicture.setPixmap(QPixmap(self.imagedir+"kdewinewizard.png")) + #self.kdewinepicture.setScaledContents(1) + + spacer = QWidget(self.pagecreate) + spacer.setMinimumSize(QSize(6,300)) + + pagebody = QVBox(self.pagecreate,"pagebody") + self.pagecreate.setStretchFactor(pagebody,1) + + self.createdtext = QLabel(pagebody,"existstext") + self.createdtext.setText(i18n("A fake windows installation was created for you in\n" +\ + self.winepath)) + + bottomspacer = QWidget(pagebody) + pagebody.setStretchFactor(bottomspacer,1) + + self.addPage( self.pagecreate, i18n("Setting up your windows drive") ) + + self.setBackEnabled( self.pagecreate, False ) + self.setNextEnabled( self.pagecreate, True ) + self.setHelpEnabled( self.pagecreate, False ) + self.setFinishEnabled( self.pagecreate, True ) + + def setupPageVersion(self): + self.pageversion = QHBox(self,"pageversion") + + self.kdewinepicture = QLabel(self.pageversion,"kdewinepicture") + self.kdewinepicture.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.kdewinepicture.sizePolicy().hasHeightForWidth())) + self.kdewinepicture.setMinimumSize(QSize(140,320)) + self.kdewinepicture.setPixmap(QPixmap(self.imagedir+"kdewinewizard.png")) + #self.kdewinepicture.setScaledContents(1) + + spacer = QWidget(self.pageversion) + spacer.setMinimumSize(QSize(6,300)) + + pagebody = QVBox(self.pageversion,"pagebody") + self.pageversion.setStretchFactor(pagebody,1) + + versiontext = QLabel(pagebody,"versiontext") + versiontext.setText(i18n("What windows version would you like to emulate?\n")) + + self.winversions = wineread.winversions + + self.verid=1 + self.versioncombo = KComboBox(0,pagebody,"versioncombo") + self.fillVersionCombo(self.versioncombo) + self.connect(self.versioncombo,SIGNAL("activated(int)"),self.slotVersionActivated) + self.__selectWinVer(self.verid) + + bottomspacer = QWidget(pagebody) + pagebody.setStretchFactor(bottomspacer,1) + + self.addPage( self.pageversion, i18n("Setting up your windows drive") ) + + self.setBackEnabled( self.pageversion, True ) + self.setNextEnabled( self.pageversion, True ) + self.setHelpEnabled( self.pageversion, False ) + self.setFinishEnabled( self.pageversion, False ) + + def fillVersionCombo(self,combo): + """ Fill the combobox with the values from our list """ + for version in self.winversions: + combo.insertItem(version[1]) + + def __selectWinVer(self,verid): + """ + Sets the current windows version and selects it in the combo box + """ + self.versioncombo.setCurrentItem(verid) + + def slotVersionActivated(self,verid): + self.verid = verid + + def slotFolderChanged(self,folder): + """ Change the directory when a new one is entered in the URL box """ + self.winepath = str(folder) + + def slotWineFolderEdited(self,folder): + """ Change the directory when a new one is entered manually in the URL box """ + self.urlcompletion.makeCompletion("") # Doesn't seem like this should be required. + self.slotFolderChanged(folder) + + def slotBrowseClicked(self): + """ Bring up a browse window to choose a directory """ + path = KFileDialog.getExistingDirectory(wineread.winepath,self,i18n("Windows Directory")) + if path: + self.winepath = str(path) + + #def slotPageChanged(self,pagename): + # if pagename == "pagecreate": + # self.CreateWindowsInstall() + + def slotCreateExistingToggled(self, buttonid): + """ Called when the choice to create a new windows drive or use an existing one is changed """ + if buttonid == 0: + self.createinstall = True + self.winefolderedit.setEnabled(True) + self.browsecreatebutton.setEnabled(True) + self.existingwinefolderedit.setEnabled(False) + self.browseexistingbutton.setEnabled(False) + self.setAppropriate(self.pageversion,True) + self.setAppropriate(self.pageexisting,False) + self.setAppropriate(self.pagecreate,True) + elif buttonid == 1: + self.createinstall = False + self.winefolderedit.setEnabled(False) + self.browsecreatebutton.setEnabled(False) + self.existingwinefolderedit.setEnabled(True) + self.browseexistingbutton.setEnabled(True) + self.setAppropriate(self.pageversion,False) + self.setAppropriate(self.pageexisting,True) + self.setAppropriate(self.pagecreate,False) + + def showPage(self,page): + if page == self.pagecreate: + self.CreateWindowsInstall() + + KWizard.showPage(self,page) + + def CreateWindowsInstall(self): + winewrite.CreateWineDrive(self.winepath) + wineread.SetWinePath(self.winepath) + + autodrives = drivedetect.autodetect() + autoshelllinks = drivedetect.autodetectshelllinks() + + if autodrives[0] == 1: + KMessageBox.sorry(self, \ + i18n("There were not enough letters to add all the autodetected drives.")) + drives = autodrives[1] + drives[26:] = autoshelllinks + + winewrite.SetDriveMappings(drives) + + winewrite.SetAudioDriver('alsa') + + dsoundsettings = {"HardwareAcceleration":"Full", + "DefaultSampleRate":"44100", + "DefaultBitsPerSample":"8", + "EmulDriver":"N"} + + winewrite.SetDSoundSettings(dsoundsettings) + + windowsettings = {"DXGrab":"N", + "DesktopDoubleBuffered":"Y", + "Managed":"Y", + "Desktop":""} + + winewrite.SetWindowSettings(windowsettings) + + d3dsettings = {"VertexShaderMode":"hardware", + "PixelShaderMode":"Y"} + + winewrite.SetD3DSettings(d3dsettings) + + winewrite.SetWinVersion(self.winversions[self.verid]) + + self.createdtext.setText(i18n("A fake windows installation was created for you in\n" +\ + self.winepath))
\ No newline at end of file diff --git a/wineconfig/kcm_wineconfig.cpp b/wineconfig/kcm_wineconfig.cpp new file mode 100644 index 0000000..bfd9217 --- /dev/null +++ b/wineconfig/kcm_wineconfig.cpp @@ -0,0 +1,156 @@ + +/* + * pykcm_launcher.cpp + * + * Launch Control Centre modules written in Python using an embedded Python + * interpreter. + * Based on David Boddie's PyKDE-components. + */ + +// pythonize.h must be included first. +#include <pythonize.h> +#include <kcmodule.h> +#include <kglobal.h> +#include <klocale.h> +#include <klibloader.h> +#include <kstandarddirs.h> +#include <ksimpleconfig.h> +#include <qstring.h> +#include <sip.h> + +#define MODULE_DIR "/opt/kde3/share/apps/guidance" +#define EXTRA_MODULE_DIR "/opt/kde3/share/python-support/kde-guidance-kde3" +#define EXTRA_MODULE_DIR_TWO "/opt/kde3/share/python-support/guidance-backends-kde3" +#define EXTRA_MODULE_DIR_THREE "/opt/kde3/share/python-support/kde-guidance-powermanager-kde3" +#define MODULE_NAME "wineconfig" +#define FACTORY "create_wineconfig" +#define CPP_FACTORY create_wineconfig +#define LIB_PYTHON "libpython2.5.so" +#define debug 1 + +static KCModule *report_error(char *msg) { + if (debug) printf ("error: %s\n", msg); + return NULL; +} + +static KCModule* return_instance( QWidget *parent, const char *name ) { + KCModule* kcmodule; + PyObject *pyKCModuleTuple; + PyObject *pyKCModule; + Pythonize *pyize; // Pythonize object to manage the Python interpreter. + int isErr; + + // Try to determine what py script we're loading. Note that "name" + // typically appears to be NULL. + QString script(MODULE_NAME); + + // Reload libpython, but this time tell the runtime linker to make the + // symbols global and available for later loaded libraries/module. + KLibLoader::self()->globalLibrary(LIB_PYTHON); + + // Start the interpreter. + pyize = initialize(); + if (!pyize) { + return report_error ("***Failed to start interpreter\n"); + } + + // Add the path to the python script to the interpreter search path. + QString path = QString(MODULE_DIR); + if(path == QString::null) { + return report_error ("***Failed to locate script path"); + } + if(!pyize->appendToSysPath (path.latin1 ())) { + return report_error ("***Failed to set sys.path\n"); + } + QString extrapath = QString(EXTRA_MODULE_DIR); + if(!pyize->appendToSysPath (extrapath.latin1 ())) { + return report_error ("***Failed to set extra sys.path\n"); + } + QString extrapath_two = QString(EXTRA_MODULE_DIR_TWO); + if(!pyize->appendToSysPath (extrapath_two.latin1 ())) { + return report_error ("***Failed to set extra 2 sys.path\n"); + } + QString extrapath_three = QString(EXTRA_MODULE_DIR_THREE); + if(!pyize->appendToSysPath (extrapath_three.latin1 ())) { + return report_error ("***Failed to set extra 3 sys.path\n"); + } + + // Load the Python script. + PyObject *pyModule = pyize->importModule ((char *)script.latin1 ()); + if(!pyModule) { + PyErr_Print(); + return report_error ("***failed to import module\n"); + } + + // Inject a helper function + QString bridge = QString("import sip\n" + "import qt\n" + "def kcontrol_bridge_" FACTORY "(parent,name):\n" + " if parent!=0:\n" +#if SIP_VERSION >= 0x040200 + " wparent = sip.wrapinstance(parent,qt.QWidget)\n" +#else + " wparent = sip.wrapinstance(parent,'QWidget')\n" +#endif + " else:\n" + " wparent = None\n" + " inst = " FACTORY "(wparent, name)\n" + " return (inst,sip.unwrapinstance(inst))\n"); + PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule)); + + // Get the Python module's factory function. + PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY); + if(!kcmFactory) { + return report_error ("***failed to find module factory\n"); + } + + // Call the factory function. Set up the args. + PyObject *pyParent = PyLong_FromVoidPtr(parent); + PyObject *pyName = PyString_FromString(MODULE_NAME); + // Using NN here is effect gives our references to the arguement away. + PyObject *args = Py_BuildValue ("NN", pyParent, pyName); + if(pyName && pyParent && args) { + // run the factory function + pyKCModuleTuple = pyize->runFunction(kcmFactory, args); + if(!pyKCModuleTuple) { + PyErr_Print(); + return report_error ("*** runFunction failure\n;"); + } + } else { + return report_error ("***failed to create args\n"); + } + // cleanup a bit + pyize->decref(args); + pyize->decref(kcmFactory); + + // Stop this from getting garbage collected. + Py_INCREF(PyTuple_GET_ITEM(pyKCModuleTuple,0)); + + // convert the KCModule PyObject to a real C++ KCModule *. + isErr = 0; + pyKCModule = PyTuple_GET_ITEM(pyKCModuleTuple,1); + kcmodule = (KCModule *)PyLong_AsVoidPtr(pyKCModule); + if(!kcmodule) { + return report_error ("***failed sip conversion to C++ pointer\n"); + } + pyize->decref(pyKCModuleTuple); + + // PyKDE can't run the module without this - Pythonize + // grabs the lock at initialization and we have to give + // it back before exiting. At this point, we no longer need + // it. + //pyize->releaseLock (); + + // take care of any translation info + KGlobal::locale()->insertCatalogue(script); + + // Return the pointer to our new KCModule + return kcmodule; +} + +extern "C" { + // Factory function that kcontrol will call. + KCModule* CPP_FACTORY(QWidget *parent, const char *name) { + return return_instance(parent, name); + } +} diff --git a/wineconfig/wineconfig.desktop b/wineconfig/wineconfig.desktop new file mode 100644 index 0000000..c485e65 --- /dev/null +++ b/wineconfig/wineconfig.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Categories=Qt;KDE;X-KDE-settings-system;X-KDE-systemsettings-advancedadministration; +Comment=Wine Configuration +Comment[el]=Ρυθμίσεις του Wine +Comment[es]=Configuración de wine +Comment[et]=Wine seadistamine +Comment[it]=Configurazione di Wine +Comment[ja]=Wine の設定 +Comment[nl]=Wine instellen +Comment[pt]=Configuração do Wine +Comment[pt_BR]=Configuração do Wine +Comment[sr]=Wine подешавања +Comment[sr@Latn]=Wine podešavanja +Comment[sv]=Inställning av Wine +Comment[xx]=xxWine Configurationxx +Encoding=UTF-8 +Exec=kcmshell System/wineconfig +GenericName=Wine Configuration Editor +GenericName[el]=Επεξεργαστής ρυθμίσεων του Wine +GenericName[es]=Editor de la configuración de wine +GenericName[et]=Wine seadistuste redaktor +GenericName[it]=Editor della configurazione di Wine +GenericName[ja]=Wine 設定エディタ +GenericName[nl]=Wine-configuratiemodule +GenericName[pt]=Editor de Configuração do Wine +GenericName[pt_BR]=Editor de Configurações do Wine +GenericName[sr]=Уређивач Wine подешавања +GenericName[sr@Latn]=Uređivač Wine podešavanja +GenericName[sv]=Editor för inställning av Wine +GenericName[xx]=xxWine Configuration Editorxx +Icon=wineconfig +MimeType= +Name=Windows Applications +Name[el]=Εφαρμογές Windows +Name[es]=Aplicaciones de Windows +Name[et]=Windowsi rakendused +Name[it]=Applicazioni Windows +Name[ja]=Windows アプリケーション +Name[nl]=Windows-programma's +Name[pt]=Aplicações do Windows +Name[pt_BR]=Aplicativos Windows +Name[sr]=Windows програми +Name[sr@Latn]=Windows programi +Name[sv]=Windows-program +Name[xx]=xxWindows Applicationsxx +Path= +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application +X-DCOP-ServiceType= +X-KDE-FactoryName=wineconfig +X-KDE-Library=wineconfig +X-KDE-ModuleType=Library +X-KDE-RootOnly=false +X-KDE-SubstituteUID=false +X-KDE-Username= diff --git a/wineconfig/wineconfig.py b/wineconfig/wineconfig.py new file mode 100755 index 0000000..d4c39ac --- /dev/null +++ b/wineconfig/wineconfig.py @@ -0,0 +1,3552 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +########################################################################### +# wineconfig.py - description # +# ------------------------------ # +# begin : Fri Mar 26 2004 # +# copyright : (C) 2006 by Yuriy Kozlov # +# email : yuriy.kozlov@gmail.com # +# # +########################################################################### +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +########################################################################### + +from qt import * +from kdecore import * +from kdeui import * +from kfile import * +from kio import * +#import string +#import math +import os +import shutil +#import select +import sys +#import struct +#import csv +#import time +import signal +#import shutil +import wineread +import winewrite +import drivedetect +import wineconfig + +programname = "Wine Configuration" +version = "0.7.1" + +default_winepath = os.environ['HOME'] + "/.wine" + +# Are we running as a separate standalone application or in KControl? +standalone = __name__=='__main__' + +# Editing application specific settings? For which application? +application = None + +# Running as the root user or not? Doesn't matter for wine +isroot = os.getuid()==0 + +############################################################################ +if standalone: + programbase = KDialogBase +else: + programbase = KCModule + +############################################################################ +class WineConfigApp(programbase): + ######################################################################## + def __init__(self,parent=None,name=None): + global standalone,kapp,default_winepath,application + KGlobal.locale().insertCatalogue("guidance") + + if standalone: + KDialogBase.__init__(self,KJanusWidget.Tabbed,"Wine Configuration",\ + KDialogBase.Apply|KDialogBase.User1|KDialogBase.User2|KDialogBase.Close, KDialogBase.Close) + self.setButtonText(KDialogBase.User1,i18n("Reset")) + self.setButtonText(KDialogBase.User2,i18n("About")) + args = KCmdLineArgs.parsedArgs() + if args.count() > 0: + application = args.arg(0) + else: + KCModule.__init__(self,parent,name) + self.setButtons(KCModule.Apply|KCModule.Reset) + self.aboutdata = MakeAboutData() + + # Create a configuration object. + self.config = KConfig("wineconfigrc") + + # Compact mode means that we have to make the GUI + # much smaller to fit on low resolution screens. + self.compact_mode = kapp.desktop().height()<=600 + + KGlobal.iconLoader().addAppDir("guidance") + + self.wineconfigchanged = False + + self.updatingGUI = True + + if not wineread.GetWineBuildPath(): + install = KMessageBox.questionYesNo(self, \ + i18n("It appears that you do not have Wine installed. Wine " + \ + "can be used to run some programs designed for Windows. " + \ + "Would you " + \ + "like to install it?\n" + \ + "You will need administrative privileges, and the " + \ + "community-maintained (universe) repository will be enabled."), \ + i18n("Windows Applications")) + if install == KMessageBox.Yes: + self.InstallWine() + + wineread.SetWineBuildPath(wineread.GetWineBuildPath()) + + if wineread.GetWineBuildPath(): + # wine doesn't set the WINEPREFIX globally, but just in case... + wineprefix = os.environ.get('WINEPREFIX',default_winepath) + newrc = not self.config.hasKey("ColorScheme") + firstrun = not wineread.VerifyWineDrive(wineprefix) + if firstrun: + KMessageBox.information(self, \ + i18n("It appears that you do not yet have a Windows drive set up. " + \ + "A fake Windows installation will be created for you in " + \ + wineprefix + "\nThis may take up to a minute."), \ + i18n("Setting up your Windows drive")) + self.CreateWindowsInstall() + + self._buildGUI() + + if firstrun and newrc: + self.appearancepage.slotColorSchemeActivated(1) + else: + self._buildGUI_noWine() + + self.aboutus = KAboutApplication(self) + + if standalone: + self.enableButton(KDialogBase.User1,False) # Reset button + self.enableButtonApply(False) # Apply button + + self.updatingGUI = False + + + def _buildGUI(self): + global standalone,application + if not standalone: + toplayout = QVBoxLayout( self, 0, KDialog.spacingHint() ) + tabcontrol = QTabWidget(self) + toplayout.addWidget(tabcontrol) + toplayout.setStretchFactor(tabcontrol,1) + + #--- General tab --- + tabname = i18n("General") + if standalone: + general1page = self.addGridPage(1,QGrid.Horizontal,tabname) + general1page.setSpacing(0) + self.generalpage = GeneralPage(general1page,self.compact_mode) + else: + self.generalpage = GeneralPage(tabcontrol,self.compact_mode) + self.generalpage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from GeneralPage Widget to appropriate actions. + self.connect(self.generalpage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.generalpage,tabname) + + #--- Drives tab --- + if not application: + tabname = i18n("Drives && Directories") + if standalone: + drives1page = self.addGridPage(1,QGrid.Horizontal,tabname) + drives1page.setSpacing(0) + self.drivespage = DrivesPage(drives1page,self.compact_mode) + else: + self.drivespage = DrivesPage(tabcontrol,self.compact_mode) + self.drivespage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from DrivesPage Widget to appropriate actions. + self.connect(self.drivespage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.drivespage,tabname) + + #--- Audio tab --- + tabname = i18n("Audio") + if standalone: + audio1page = self.addGridPage(1,QGrid.Horizontal,tabname) + self.audiopage = AudioPage(audio1page) + else: + self.audiopage = AudioPage(tabcontrol) + self.audiopage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from AudioPage Widget to appropriate actions. + self.connect(self.audiopage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.audiopage,tabname) + + #--- Graphics tab --- + tabname = i18n("Graphics") + if standalone: + graphics1page = self.addGridPage(1,QGrid.Horizontal,tabname) + self.graphicspage = GraphicsPage(graphics1page) + else: + self.graphicspage = GraphicsPage(tabcontrol) + self.graphicspage.setMargin(KDialog.marginHint()) + + + # Connect all PYSIGNALs from GraphicsPage Widget to appropriate actions. + self.connect(self.graphicspage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.graphicspage,tabname) + + #--- Appearance tab --- + if not application: + tabname = i18n("Appearance") + if standalone: + appearance1page = self.addGridPage(1,QGrid.Horizontal,tabname) + self.appearancepage = AppearancePage(appearance1page) + else: + self.appearancepage = AppearancePage(tabcontrol) + self.appearancepage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from DesktopPage Widget to appropriate actions. + self.connect(self.appearancepage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + self.graphicspage.connect(self.graphicspage.allowwmcheckbox, + SIGNAL("toggled(bool)"), + self.appearancepage.slotFillItemCombo) + self.connect(self.graphicspage.emudesktopcheckbox, + SIGNAL("toggled(bool)"), + self.appearancepage.slotFillItemComboDesktop) + + self.appearancepage.slotFillItemComboDesktop(\ + self.graphicspage.currentemudesktop) + + if not standalone: + tabcontrol.addTab(self.appearancepage,tabname) + + #--- Applications tab --- + if not application: + tabname = i18n("Applications") + if standalone: + apps1page = self.addGridPage(1,QGrid.Horizontal,tabname) + self.appspage = ApplicationsPage(apps1page) + else: + self.appspage = ApplicationsPage(tabcontrol) + self.appspage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from ApplicationsPage Widget to appropriate actions. + self.connect(self.appspage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.appspage,tabname) + + #--- Libraries tab --- + tabname = i18n("Libraries") + if standalone: + libs1page = self.addGridPage(1,QGrid.Horizontal,tabname) + self.libspage = LibrariesPage(libs1page) + else: + self.libspage = LibrariesPage(tabcontrol) + self.libspage.setMargin(KDialog.marginHint()) + + # Connect all PYSIGNALs from LibrariesPage Widget to appropriate actions. + self.connect(self.libspage,PYSIGNAL("changedSignal()"),self._sendChangedSignal) + + if not standalone: + tabcontrol.addTab(self.libspage,tabname) + + + def _buildGUI_noWine(self): + """ Displays an error that wine is not installed """ + global standalone + if not standalone: + toplayout = QVBoxLayout( self, 0, KDialog.spacingHint() ) + + if not standalone: + nowinewarning = QLabel(self,"nowinewarning") + toplayout.addWidget(nowinewarning) + else: + vbox = self.addVBoxPage ("Wine Not Installed") + nowinewarning = QLabel(vbox,"nowinewarning") + nowinewarning.setText(i18n("It appears that you do not have wine " +\ + "installed.\nwine " + \ + "can be used to run some programs designed for " + \ + "Windows.\nPlease " +\ + "install the wine package to get this functionality.")) + nowinewarning.setFrameStyle( QFrame.Box | QFrame.Raised ) + + def InstallWine(self): + """ Allows the user to enable the proper repositories and + install wine. + Currently Kubuntu specific, requires kdesudo, adept_batch + and software-properties-kde """ + if not isroot: + if os.system("kdesudo \"software-properties-kde --enable-component universe\""): + KMessageBox.error(self, i18n("There was a problem running " + \ + "software-properties-kde. Make sure " + \ + "software-properties-kde is installed.")) + elif os.system("kdesudo \"adept_batch install wine\""): + KMessageBox.error(self, i18n("There was a problem running " + \ + "adept_batch. Make sure " + \ + "Adept is installed.")) + else: + if os.system("software-properties-kde --enable-component=universe" + \ + " && adept_batch install wine"): + KMessageBox.error(self, i18n("There was a problem running " + \ + "software-properties-kde and adept_batch. Make sure " + \ + "Adept and software-properties-kde are installed.")) + + def CreateWindowsInstall(self,winepath = None): + if not winepath: + winepath = default_winepath + winewrite.CreateWineDrive(winepath) + wineread.SetWinePath(winepath) + + drives = wineread.LoadDrives() + autodrives = drivedetect.autodetect(drives) + autoshelllinks = drivedetect.autodetectshelllinks() + + if autodrives[0] == 1: + KMessageBox.sorry(self, \ + i18n("There were not enough letters to add all the autodetected drives.")) + drives = autodrives[1] + drives[26:] = autoshelllinks + + winewrite.SetDriveMappings(drives) + + winewrite.SetAudioDriver('alsa') + + dsoundsettings = {"HardwareAcceleration":"Full", + "DefaultSampleRate":"44100", + "DefaultBitsPerSample":"8", + "EmulDriver":"N"} + + winewrite.SetDSoundSettings(dsoundsettings) + + windowsettings = {"DXGrab":"N", + "DesktopDoubleBuffered":"Y", + "Managed":"Y", + "Desktop":""} + + winewrite.SetWindowSettings(windowsettings) + + d3dsettings = {"VertexShaderMode":"hardware", + "PixelShaderMode":"Y", + "UseGLSL":"enabled"} + + winewrite.SetD3DSettings(d3dsettings) + + winewrite.SetWinVersion(wineread.winversions[1]) + + # Removed pending a patch to winebrowser + #winewrite.SetFirstBrowser("kfmclient exec") + #winewrite.SetFirstMailer("kfmclient exec") + + def exec_loop(self,appname): + global application, programbase + if appname: + application = appname + KDialogBase.exec_loop(self) + else: + programbase.exec_loop(self) + + def save(self): # KCModule + # Find out what's changed + generalchanged = self.generalpage.isChanged() + driveschanged = not application and self.drivespage.isChanged() + audiochanged = self.audiopage.isChanged() + graphicschanged = self.graphicspage.isChanged() + appearancechanged = not application and self.appearancepage.isChanged() + applicationschanged = not application and self.appspage.isChanged() + libschanged = self.libspage.isChanged() + + # Apply changes for each tab + if generalchanged: + self.generalpage.applyChanges() + if driveschanged: + self.drivespage.applyChanges() + if audiochanged: + self.audiopage.applyChanges() + if graphicschanged: + self.graphicspage.applyChanges() + if appearancechanged: + self.appearancepage.applyChanges() + if applicationschanged: + self.appspage.applyChanges() + if libschanged: + self.libspage.applyChanges() + + self._sendChangedSignal() + + def slotApply(self): # KDialogBase + self.save() + + def slotClose(self): # KDialogBase + KDialogBase.slotClose(self) + + def load(self): # KCModule + self.__reset() + self._sendChangedSignal() + + def slotUser1(self): # Reset button, KDialogBase + self.load() + + def slotUser2(self): # About button, KDialogBase + self.aboutus.show() + + def __reset(self): + # Reset each configuration page + if not application: + self.drivespage.reset() + self.audiopage.reset() + self.graphicspage.reset() + self.appearancepage.reset() + if not application: + self.appspage.reset() + self.libspage.reset() + + # Kcontrol expects updates about whether the contents have changed. + # Also we fake the Apply and Reset buttons here when running outside kcontrol. + def _sendChangedSignal(self): + global standalone + + changed = False + changed = changed or (not application and self.drivespage.isChanged()) or \ + self.audiopage.isChanged() \ + or self.generalpage.isChanged() or \ + (not application and self.appspage.isChanged()) or \ + self.libspage.isChanged() or \ + (not application and self.appearancepage.isChanged()) + graphicschanged = self.graphicspage.isChanged() + changed = changed or graphicschanged + + if standalone: + self.enableButton(KDialogBase.User1,changed) # Reset button + self.enableButtonApply(changed) # Apply button + else: + self.emit(SIGNAL("changed(bool)"), (changed,) ) + +############################################################################ +''' Not used. +class ErrorPage(QWidget): + """ + Displayed when there is no fake Windows drive + """ + + def __init__(self,parent = None, name = None, parentapp = None, modal = 0,fl=0): + QWidget.__init__(self,parent) + + if not name: + self.setName("ErrorPage") + + self.parent = parentapp + + self.top_layout = QVBoxLayout(self,0,0,"ErrorPageLayout") + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + self.top_layout.addWidget(vbox) + + errortext = QLabel(vbox,"errortext") + errortext.setText(i18n("You need to set up a " +\ + "fake Windows drive\n before you can edit settings or run " +\ + "Windows applications.")) + + self.createbutton = KPushButton(i18n("Create Fake Windows Drive"),vbox) + self.connect(self.createbutton,SIGNAL("clicked()"),self.slotCreateClicked) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + self.top_layout.addItem(bottomspacer) + + self.clearWState(Qt.WState_Polished) + + def slotCreateClicked(self): + self.parent.CreateWindowsInstall() + self.parent._buildGUI() + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + +''' + +############################################################################## + +class DrivesPage(QWidget): + """ + A TabPage with configuration for drive mappings + """ + + types = ( + (0,i18n("Autodetect"),"auto"), + (1,i18n("Local Hard Disk"),"hd"), + (2,i18n("Network Share"),"network"), + (3,i18n("Floppy Disk"),"floppy"), + (4,i18n("CD-ROM"),"cdrom")) + + typesdic = { + 'auto':0, + 'hd':1, + 'network':2, + 'floppy':3, + 'cdrom':4} + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + QWidget.__init__(self,parent) + + self.updatingGUI = True + + self.selecteddriveid = None + + if not name: + self.setName("DrivesTab") + + self.drives = wineread.LoadDrives() + self.drives[26:] = wineread.GetShellLinks() + + drives_tab_layout = QVBoxLayout(self,0,0,"DrivesTabLayout") + self.top_layout = drives_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + drives_tab_layout.addWidget(vbox) + + # -- Drive mappings group + self.mappings_group_box = QHGroupBox(vbox) + self.mappings_group_box.setTitle(i18n("Drive and Directory Mappings")) + self.mappings_group_box.setInsideSpacing(KDialog.spacingHint()) + self.mappings_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.mappings_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + spacer = QWidget(vbox2) + vbox2.setStretchFactor(spacer,1) + + self.driveslist = KListView(vbox2) + self.driveslist.addColumn(i18n("Directory")) + self.driveslist.addColumn(i18n("Links to")) + self.driveslist.setAllColumnsShowFocus(True) + self.driveslist.setSelectionMode(QListView.Single) + self.driveslist.setSorting(-1,True) + + self.connect(self.driveslist, SIGNAL("selectionChanged(QListViewItem *)"), self.slotListClicked) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.addbutton = KPushButton(i18n("Add Drive..."),hbox) + self.connect(self.addbutton,SIGNAL("clicked()"),self.slotAddClicked) + + self.removebutton = KPushButton(i18n("Remove Drive"),hbox) + self.connect(self.removebutton,SIGNAL("clicked()"),self.slotRemoveClicked) + + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + self.autobutton = KPushButton(i18n("Autodetect"),hbox) + self.connect(self.autobutton,SIGNAL("clicked()"),self.slotAutoClicked) + + hbox2 = QHBox(vbox2) + hbox2.setSpacing(KDialog.spacingHint()) + + pathtext = QLabel(hbox2,"pathtext") + pathtext.setText(i18n("Path:")) + + self.fsfolderedit = KLineEdit("/",hbox2) + self.urlcompletion = KURLCompletion(KURLCompletion.DirCompletion) + self.fsfolderedit.setCompletionObject(self.urlcompletion) + self.fsfolderedit.setCompletionMode(KGlobalSettings.CompletionPopup) + self.connect(self.fsfolderedit,SIGNAL("textChanged(const QString &)"),self.slotFolderEdited) + + self.browsebutton = KPushButton(i18n("Browse"),hbox2) + self.connect(self.browsebutton,SIGNAL("clicked()"),self.slotBrowseClicked) + + hbox2 = QHBox(vbox2) + hbox2.setSpacing(KDialog.spacingHint()) + + self.typetext = QLabel(hbox2,"typetext") + self.typetext.setText(i18n("Type:")) + + self.typecombo = KComboBox(0,hbox2,"typecombo") + self.fillTypeCombo(self.typecombo) + self.connect(self.typecombo,SIGNAL("activated(int)"),self.slotTypeActivated) + + spacer = QWidget(hbox2) + hbox2.setStretchFactor(spacer,1) + + hbox2 = QHBox(vbox2) + hbox2.setSpacing(KDialog.spacingHint()) + + self.infotext1 = QLabel(hbox2,"infotext1") + + hbox2 = QHBox(vbox2) + hbox2.setSpacing(KDialog.spacingHint()) + + self.infotext2 = QLabel(hbox2,"infotext2") + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + drives_tab_layout.addItem(bottomspacer) + + self.changed = False + + self.clearWState(Qt.WState_Polished) + + self.updatingGUI=False + + self.updateDrivesList() + + def reset(self): + self.drives = wineread.LoadDrives() + self.drives[26:] = wineread.GetShellLinks() + self.updatingGUI=True + self.updateDrivesList() + self.updatingGUI=False + self.changed = False + + def isChanged(self): + """ Check if something has changed since startup or last apply(). """ + return self.changed + + def applyChanges(self): + """ Apply the changes """ + winewrite.SetDriveMappings(self.drives) + self.reset() + + def updateChanges(self): + """ Update the GUI and send the signal that changes were made """ + self.updatingGUI=True + self.updateDrivesList() + self.updatingGUI=False + self.changed = True + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotListClicked(self,item): + """ Show the drive information and settings for the newly selected drive """ + if self.updatingGUI==False: + for driveid in self.drivesToListItems: + if self.drivesToListItems[driveid]==item: + self.updatingGUI = True + self.__selectDrive(driveid) + self.updatingGUI = False + return + + def slotFolderChanged(self,folder): + """ Change the directory mapping when a new one is entered in the URL box """ + self.drives[self.selecteddriveid][2] = unicode(folder) + self.updateChanges() + + def slotFolderEdited(self,folder): + """ Change the directory mapping when a new one is entered manually in the URL box """ + if not self.updatingGUI: + self.urlcompletion.makeCompletion("") # Doesn't seem like this should be required. + self.slotFolderChanged(folder) + + def slotBrowseClicked(self): + """ Bring up a browse window to choose a ndew mapping directory """ + mapping = KFileDialog.getExistingDirectory(wineread.winepath,self,i18n("Drive Mapping")) + if mapping: + mapping = unicode(mapping) + self.drives[self.selecteddriveid][2] = mapping + self.updateChanges() + + def slotAddClicked(self): + """ + Let the user choose a directory to map a new drive to. + Uses the next available drive letter. """ + # TODO: Maybe the user should choose the drive letter? + for drive in self.drives[2:26]: + if drive[2]: + continue + else: + mapping = KFileDialog.getExistingDirectory(wineread.winepath,self,i18n("Drive Mapping")) + if mapping: + mapping = unicode(mapping) + drive[2] = mapping + else: + return + self.selecteddriveid = drive[0] + break + else: + KMessageBox.sorry(self, \ + i18n("Can't add another drive. There can only be 26, for letters A-Z")) + return + + self.updateChanges() + + def slotRemoveClicked(self): + """ Removes the currently selected drive """ + if self.selecteddriveid == 2: # Drive C: + if KMessageBox.warningContinueCancel(self, \ + i18n("Are you sure you want to delete drive C:?\n\n"\ + "Most Windows applications expect drive C: to exist, "\ + "and will die messily if it doesn't. If you proceed "\ + "remember to recreate it!"),\ + i18n("Warning")) != KMessageBox.Continue: + return + self.drives[self.selecteddriveid][2:4] = ("","") + self.selecteddriveid -= 1 # Not quite correct, should select previous drive. + self.updateChanges() + + def slotAutoClicked(self): + """ + Autodetects a default set of drives from /etc/fstab + Allows the user to start with a fresh list of drives or append to the current one + """ + automethod = KMessageBox.questionYesNoCancel(self, \ + i18n("Would you like to remove the current set of drives?"),\ + i18n("Drive Autodetection")) + if automethod == KMessageBox.Yes: + autodrives = drivedetect.autodetect() + autoshelllinks = drivedetect.autodetectshelllinks() + elif automethod == KMessageBox.No: + autodrives = drivedetect.autodetect(self.drives[:26]) + autoshelllinks = drivedetect.autodetectshelllinks(self.drives[26:]) + else: + return + + if autodrives[0] == 1: + KMessageBox.sorry(self, \ + i18n("There were not enough letters to add all the autodetected drives.")) + self.drives[0:26] = autodrives[1] + self.drives[26:] = autoshelllinks + + self.updateChanges() + + def slotTypeActivated(self,index): + self.__selectType(self.types[index][2]) + self.updateChanges() + + def fillTypeCombo(self,combo): + """ Fill the combobox with the values from our list """ + for drivetype in self.types: + combo.insertItem(drivetype[1]) + + def __selectType(self,typename): + if typename: + typeid = self.typesdic[typename] + else: + typeid = self.typesdic['auto'] + self.drives[self.selecteddriveid][3] = typename + self.typecombo.setCurrentItem(typeid) + + def updateDrivesList(self): + """ Updates the displayed list of drives """ + self.driveslist.clear() + self.drivesToListItems = {} + firstselecteddriveid = None + lastdriveid = None + + for driveid, driveletter, mapping, drivetype, drivelabel, serial in reversed(self.drives): + if mapping or drivelabel: + lvi = QListViewItem(self.driveslist,driveletter,mapping) + self.drivesToListItems[driveid] = lvi + if self.selecteddriveid==driveid: + firstselecteddriveid = driveid + lastdriveid = driveid + else: + continue + + if firstselecteddriveid==None: + firstselecteddriveid = lastdriveid + + self.selecteddriveid = firstselecteddriveid + self.__selectDrive(self.selecteddriveid) + self.driveslist.ensureItemVisible(self.driveslist.currentItem()) + + def __selectDrive(self,driveid): + """ Updates the GUI for a newly selected drive """ + self.selecteddriveid = driveid + lvi = self.drivesToListItems[driveid] + self.driveslist.setSelected(lvi,True) + self.driveslist.setCurrentItem(lvi) + + self.fsfolderedit.setText(self.drives[driveid][2]) + if self.drives[driveid][3] == 'shellfolder': + self.typecombo.insertItem(i18n("Shell Folder")) + self.typecombo.setCurrentItem(5) + self.typecombo.setEnabled(False) + + self.removebutton.setEnabled(False) + + self.infotext1.setText(unicode(i18n("Windows path: ")) + self.drives[driveid][4]) + + # It seems some old versions of wine didn't store the shell folders in the same place + if self.drives[driveid][5] != self.drives[driveid][4]: + changeregistryshell = KMessageBox.warningYesNo(self, \ + i18n("The " + self.drives[driveid][1] + " folder is currently located in\n" + \ + self.drives[driveid][5] + "\nIt is recommended that it is put in the default " + \ + "location in\n" + wineread.defaultwinfolderspath + "\nWould you like to move it there?"),\ + i18n("Shell Folder Mapping")) + changeregistryshell = changeregistryshell == KMessageBox.Yes + + if changeregistryshell: + self.drives[driveid][5] = self.drives[driveid][4] + self.changed = True + self.emit(PYSIGNAL("changedSignal()"), ()) + + if self.drives[driveid][2] == wineread.profilesdirectory + self.drives[driveid][1]: + realfolderwarning = KMessageBox.information(self, \ + i18n(self.drives[driveid][1] + " is an actual folder and is not linked elsewhere." + \ + " Remapping it will create a backup of the directory in " + \ + wineread.profilesdirectory),\ + i18n("Shell Folder Mapping")) + else: + if self.typecombo.count() > 5: + self.typecombo.removeItem(5) + self.typecombo.setEnabled(True) + self.__selectType(self.drives[driveid][3]) + + self.removebutton.setEnabled(True) + + if self.drives[driveid][4]: + self.infotext1.setText(unicode(i18n("Label: ")) + self.drives[driveid][4]) + else: + self.infotext1.setText("") + if self.drives[driveid][5]: + self.infotext2.setText(unicode(i18n("Serial: ")) + self.drives[driveid][5]) + else: + self.infotext2.setText("") + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + +############################################################################ +class AudioPage(QWidget): + driversdic = { + "":i18n("None - Disable Sound"), + "alsa":"ALSA", + "arts":"aRts", + "esd":"EsounD", + "oss":"OSS", + "jack":"JACK", + "nas":"NAS", + "coreaudio":"CoreAudio"} + + drivers = ("","alsa","arts","esd","oss","jack","nas","coreaudio") + + accel = ( + (0,i18n("Full")), + (1,i18n("Standard")), + (2,i18n("Basic")), + (3,i18n("Emulation"))) + + samplerates = ( + (0,"48000",48000), + (1,"44100",44100), + (2,"22050",22050), + (3,"16000",16000), + (4,"11025",11025), + (5,"8000",8000)) + + bitspersample = ( + (0,"8",8), + (1,"16",16)) + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + global application + QWidget.__init__(self,parent) + + if not name: + self.setName("AudioTab") + + audio_tab_layout = QVBoxLayout(self,0,0,"AudioTabLayout") + self.top_layout = audio_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + audio_tab_layout.addWidget(vbox) + + if application: + appwarning = QLabel(vbox,"appwarning") + appwarning.setText(i18n("Application specific settings for <b>" +\ + application + "</b><p>Changing a setting here will permanently " +\ + "make that setting independent of settings for all other " +\ + "applications.</p>")) + appwarning.setFrameStyle( QFrame.Box | QFrame.Raised ) + + # -- Drivers group + self.driver_group_box = QHGroupBox(vbox) + self.driver_group_box.setTitle(i18n("Driver Selection")) + self.driver_group_box.setInsideSpacing(KDialog.spacingHint()) + self.driver_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.driver_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + drivertext = QLabel(hbox,"drivertext") + drivertext.setText(i18n("Audio Driver:")) + + self.drivercombo = KComboBox(0,hbox,"drivercombo") + self.fillDriverCombo(self.drivercombo) + self.connect(self.drivercombo,SIGNAL("activated(int)"),self.slotDriverActivated) + + QToolTip.add(hbox, i18n("Choose an audio driver. Not all audio " +\ + "drivers are available.")) + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + if application: + self.driver_group_box.hide() + + # -- DirectSound Settings group + self.dsound_group_box = QHGroupBox(vbox) + self.dsound_group_box.setTitle(i18n("DirectSound")) + self.dsound_group_box.setInsideSpacing(KDialog.spacingHint()) + self.dsound_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.dsound_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + acceltext = QLabel(hbox,"acceltext") + acceltext.setText(i18n("Hardware Acceleration:")) + + self.accelcombo = KComboBox(0,hbox,"accelcombo") + self.fillAccelCombo(self.accelcombo) + self.connect(self.accelcombo,SIGNAL("activated(int)"),self.slotAccelActivated) + + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.overridecheckbox = QCheckBox(i18n("Override KDE Sample Rate"),hbox) + hbox.setStretchFactor(self.overridecheckbox,0) + self.connect(self.overridecheckbox,SIGNAL("toggled(bool)"),self.slotOverrideKDESoundToggled) + self.overridecheckbox.hide() + + self.sampleratehbox = QHBox(vbox2) + self.sampleratehbox.setSpacing(KDialog.spacingHint()) + + sampletext = QLabel(self.sampleratehbox,"sampletext") + sampletext.setText(i18n("Default Sample Rate:")) + + self.samplecombo = KComboBox(0,self.sampleratehbox,"samplecombo") + self.fillSampleCombo(self.samplecombo) + self.connect(self.samplecombo,SIGNAL("activated(int)"),self.slotSampleActivated) + + bitstext = QLabel(self.sampleratehbox,"bitstext") + bitstext.setText(i18n("Default Bits Per Sample:")) + + self.bitscombo = KComboBox(0,self.sampleratehbox,"bitscombo") + self.fillBitsCombo(self.bitscombo) + self.connect(self.bitscombo,SIGNAL("activated(int)"),self.slotBitsActivated) + + spacer = QWidget(self.sampleratehbox) + self.sampleratehbox.setStretchFactor(spacer,1) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.drvemucheckbox = QCheckBox(i18n("Driver Emulation"),hbox) + hbox.setStretchFactor(self.drvemucheckbox,0) + self.connect(self.drvemucheckbox,SIGNAL("toggled(bool)"), self.slotDriverEmulToggled) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + audio_tab_layout.addItem(bottomspacer) + + self.reset() + + self.clearWState(Qt.WState_Polished) + + def fillDriverCombo(self,combo): + """ Fill the combobox with the values from our list """ + for driver in self.drivers: + combo.insertItem(self.driversdic[driver]) + + def fillAccelCombo(self,combo): + """ Fill the combobox with the values from our list """ + for accel in self.accel: + combo.insertItem(accel[1]) + + def fillSampleCombo(self,combo): + """ Fill the combobox with the values from our list """ + for rate in self.samplerates: + combo.insertItem(rate[1]) + + def fillBitsCombo(self,combo): + """ Fill the combobox with the values from our list """ + for bits in self.bitspersample: + combo.insertItem(bits[1]) + + def isChanged(self): + changed = False + changed = changed or (not application and self.currentdriver != self.originaldriver) + changed = changed or self.currentaccel != self.originalaccel + changed = changed or self.currentsamplerate != self.originalsamplerate + changed = changed or self.currentbitspersample != self.originalbitspersample + changed = changed or self.currentemuldriver != self.originalemuldriver + return changed + + def reset(self): + if not application: + self.currentdriver = wineread.GetAudioDriver() + self.originaldriver = self.currentdriver + self.__selectDriver(self.currentdriver) + + dsoundsettings = wineread.GetDSoundSettings(application) + globaldsoundsettings = wineread.GetDSoundSettings() + + self.currentaccel = dsoundsettings.get("HardwareAcceleration",\ + globaldsoundsettings.get("HardwareAcceleration", "Full")) + self.originalaccel = self.currentaccel + self.__selectAccel(self.currentaccel) + + self.currentsamplerate = dsoundsettings.get("DefaultSampleRate",\ + globaldsoundsettings.get("DefaultSampleRate", "44100")) + self.originalsamplerate = self.currentsamplerate + self.__selectSampleRate(self.currentsamplerate) + + self.currentbitspersample = dsoundsettings.get("DefaultBitsPerSample",\ + globaldsoundsettings.get("DefaultBitsPerSample","16")) + self.originalbitspersample = self.currentbitspersample + self.__selectBitsPerSample(self.currentbitspersample) + + self.currentemuldriver = dsoundsettings.get("EmulDriver",\ + globaldsoundsettings.get("EmulDriver", "N")) + self.originalemuldriver = self.currentemuldriver + self.__setDriverEmul(self.currentemuldriver) + + self.currentkdeoverride = True + self.originalkdeoverride = self.currentkdeoverride + self.__setOverrideKDESound(self.currentkdeoverride) + + def applyChanges(self): + if not application: + winewrite.SetAudioDriver(self.currentdriver) + + dsoundsettings = {"HardwareAcceleration":self.currentaccel, + "DefaultSampleRate":self.currentsamplerate, + "DefaultBitsPerSample":self.currentbitspersample, + "EmulDriver":self.currentemuldriver} + + winewrite.SetDSoundSettings(dsoundsettings, application) + + self.reset() + + def slotDriverActivated(self,driverid): + self.currentdriver = self.drivers[driverid] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotAccelActivated(self,accelid): + self.currentaccel = self.accel[accelid][1] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotSampleActivated(self,sampleid): + self.currentsamplerate = self.samplerates[sampleid][1] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotBitsActivated(self,bitsid): + self.currentbitspersample = self.bitspersample[bitsid][1] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotDriverEmulToggled(self,driveremul): + if driveremul: + self.currentemuldriver = 'Y' + else: + self.currentemuldriver = 'N' + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotOverrideKDESoundToggled(self,override): + self.__setOverrideKDESound(override) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def __selectDriver(self,drivername): + """ + Sets the current driver and selects it in the combo box + Assumes drivername is a valid driver + """ + driverid = 0 + for driver in self.drivers: + if driver == drivername: + break + else: + driverid += 1 + + self.currentdriver = drivername + self.drivercombo.setCurrentItem(driverid) + + def __selectAccel(self,accelmode): + """ + Sets the current acceleration mode and selects it in the combo box + Assumes accelmode i sa valid acceleration mode + """ + accelid = 0 + for accelmode1 in self.accel: + if accelmode1[1] == accelmode: + break + else: + accelid += 1 + + self.currentaccel = accelmode + self.accelcombo.setCurrentItem(accelid) + + def __selectSampleRate(self,samplerate): + """ + Sets the current acceleration mode and selects it in the combo box + Assumes samplerate is a valid sample rate + """ + sampleid = 0 + for samplerate1 in self.samplerates: + if samplerate1[1] == samplerate: + break + else: + sampleid += 1 + + self.currentsamplerate = samplerate + self.samplecombo.setCurrentItem(sampleid) + + def __selectBitsPerSample(self,bits): + """ + Sets the current acceleration mode and selects it in the combo box + Assumes bits is a valid value for bits per sample + """ + bitsid = 0 + for bits1 in self.bitspersample: + if bits1[1] == bits: + break + else: + bitsid += 1 + + self.currentbitspersample = bits + self.bitscombo.setCurrentItem(bitsid) + + def __setDriverEmul(self,driveremul): + """ Enables/disables the driver emulation mode """ + self.currentdriveremul = driveremul + driveremul = driveremul != 'N' + self.drvemucheckbox.setChecked(driveremul) + + def __setOverrideKDESound(self,override): + """ Enables/disables use of KDE's (aRts) sample rate settings """ + self.currentkdeoverride = override + self.sampleratehbox.setEnabled(override) + self.overridecheckbox.setChecked(override) + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + +############################################################################ +class GraphicsPage(QWidget): + + # Mapping values in seconds to human-readable labels. + vertexshadersupport = ( + (0,i18n("Hardware")), + (1,i18n("None")), + (2,i18n("Emulation"))) + + vertexshadersupportdic = { + "hardware":0, + "none":1, + "emulation":2} + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + global currentallowwm + QWidget.__init__(self,parent) + + if not name: + self.setName("GraphicsTab") + + graphics_tab_layout = QVBoxLayout(self,0,0,"GraphicsTabLayout") + self.top_layout = graphics_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + graphics_tab_layout.addWidget(vbox) + + if application: + appwarning = QLabel(vbox,"appwarning") + appwarning.setText(i18n("Application specific settings for <b>" +\ + application + "</b><p>Changing a setting here will permanently " +\ + "make that setting independent of settings for all other " +\ + "applications.</p>")) + appwarning.setFrameStyle( QFrame.Box | QFrame.Raised ) + + # -- Window settings group + self.windows_group_box = QHGroupBox(vbox) + self.windows_group_box.setTitle(i18n("Window Settings")) + self.windows_group_box.setInsideSpacing(KDialog.spacingHint()) + self.windows_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.windows_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + self.allowcursorcheckbox = QCheckBox(i18n("Allow DirectX applications to stop the mouse leaving their window"),vbox2) + self.connect(self.allowcursorcheckbox,SIGNAL("toggled(bool)"), self.slotAllowCursorToggled) + + self.dubbuffercheckbox = QCheckBox(i18n("Enable desktop double buffering"),vbox2) + self.connect(self.dubbuffercheckbox,SIGNAL("toggled(bool)"), self.slotDubBufferToggled) + + self.allowwmcheckbox = QCheckBox(i18n("Allow the window manager to control the windows"),vbox2) + self.connect(self.allowwmcheckbox,SIGNAL("toggled(bool)"), self.slotAllowWMToggled) + + QToolTip.add(self.allowwmcheckbox, \ + i18n("<p>If windows are managed by your window manager, then they" +\ + " will have the standard borders, they will respect your virtual" +\ + " desktop and appear in your window list.\n</p><p>" +\ + "If the windows are unmanaged, they will be disconnected from your" +\ + " window manager. This will mean the windows do not integrate as" +\ + " closely with your desktop, but the emulation will be more" +\ + " accurate so it can help some programs work better.</p>")) + + self.showdragcheckbox = QCheckBox(i18n("Display window contents while dragging"),vbox2) + self.connect(self.showdragcheckbox,SIGNAL("toggled(bool)"), self.slotShowDragToggled) + + self.emudesktopcheckbox = QCheckBox(i18n("Emulate a virtual desktop"),vbox2) + self.connect(self.emudesktopcheckbox,SIGNAL("toggled(bool)"), self.slotEmuDesktopToggled) + + self.desksizehbox = QHBox(vbox2) + self.desksizehbox.setSpacing(KDialog.spacingHint()) + + desksizetext = QLabel(self.desksizehbox,"desksizetext") + desksizetext.setText(i18n("Desktop size:")) + + self.xsizeedit = KLineEdit("640",self.desksizehbox) + self.xsizeedit.setValidator(QIntValidator(self.xsizeedit)) + self.connect(self.xsizeedit,SIGNAL("textChanged(const QString &)"),self.slotDesktopSizeChanged) + bytext = QLabel(self.desksizehbox,"bytext") + bytext.setText(i18n("x")) + self.ysizeedit = KLineEdit("480",self.desksizehbox) + self.ysizeedit.setValidator(QIntValidator(self.ysizeedit)) + self.connect(self.ysizeedit,SIGNAL("textChanged(const QString &)"),self.slotDesktopSizeChanged) + + spacer = QWidget(self.desksizehbox) + self.desksizehbox.setStretchFactor(spacer,1) + + QToolTip.add(self.emudesktopcheckbox, + i18n("<p>You can choose to emulate a Windows desktop, where all" +\ + " the windows are confined to one 'virtual screen', or you" +\ + " can have the windows placed on your standard desktop.</p>")) + QToolTip.add(self.desksizehbox, QToolTip.textFor(self.emudesktopcheckbox)) + + if application: + self.emudesktopcheckbox.hide() + self.desksizehbox.hide() + self.showdragcheckbox.hide() + + # -- Direct3D settings group + self.d3d_group_box = QHGroupBox(vbox) + self.d3d_group_box.setTitle(i18n("Direct3D")) + self.d3d_group_box.setInsideSpacing(KDialog.spacingHint()) + self.d3d_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.d3d_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + vertexshadertext = QLabel(hbox,"vertexshadertext") + vertexshadertext.setText(i18n("Vertex Shader Support:")) + + self.accelcombo = KComboBox(0,hbox,"accelcombo") + self.fillCombo(self.accelcombo) + self.connect(self.accelcombo,SIGNAL("activated(int)"),self.slotVertexShaderModeActivated) + + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.pixelshadercheckbox = QCheckBox(i18n("Allow Pixel Shader (if supported by hardware)"),hbox) + self.connect(self.pixelshadercheckbox,SIGNAL("toggled(bool)"), self.slotPixelShaderModeToggled) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.glslcheckbox = QCheckBox(i18n("Use GL Shader Language"),hbox) + self.connect(self.glslcheckbox,SIGNAL("toggled(bool)"), self.slotGLSLToggled) + + QToolTip.add(hbox, + i18n("<p>This enables the use of GL Shading Language for vertex" +\ + " and pixel shaders, as long as the hardware supports it." +\ + " This is experimental.</p>")) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + graphics_tab_layout.addItem(bottomspacer) + + self.reset() + + self.clearWState(Qt.WState_Polished) + + def fillCombo(self,combo): + """ Fill the combobox with the values from our list """ + for accel in self.vertexshadersupport: + combo.insertItem(accel[1]) + + def isChanged(self): + changed = False + changed = changed or self.originalallowcursor != self.currentallowcursor + changed = changed or self.originaldubbuffer != self.currentdubbuffer + changed = changed or self.originalallowwm != currentallowwm + changed = changed or (not application and \ + self.originalemudesktop != self.currentemudesktop) + changed = changed or self.originalvertexshadermode != self.currentvertexshadermode + changed = changed or self.originalpixelshadermode != self.currentpixelshadermode + changed = changed or self.originalglsl != self.currentglsl + changed = changed or (not application and \ + self.originalshowdrag != self.currentshowdrag) + return changed + + def reset(self): + """ Resets the settings to ones read from the registry """ + global currentallowwm + settings = wineread.GetWindowSettings(application) + globalsettings = wineread.GetWindowSettings() + + self.currentallowcursor = settings.get("DXGrab",\ + globalsettings.get("DXGrab",'N')) + self.originalallowcursor = self.currentallowcursor + self.__setAllowCursor(self.currentallowcursor) + + self.currentdubbuffer = settings.get("DesktopDoubleBuffered",\ + globalsettings.get("DesktopDoubleBuffered",'Y')) + self.originaldubbuffer = self.currentdubbuffer + self.__setDubBuffer(self.currentdubbuffer) + + currentallowwm = settings.get("Managed",\ + globalsettings.get("Managed",'Y')) + self.originalallowwm = currentallowwm + + if not application: + self.currentemudesktop = settings.get("Desktop","") + self.originalemudesktop = self.currentemudesktop + self.__setEmuDesktop(self.currentemudesktop) + self.__setAllowWM(currentallowwm) + + d3dsettings = wineread.GetD3DSettings(application) + globald3dsettings = wineread.GetD3DSettings() + + self.currentvertexshadermode = d3dsettings.get("VertexShaderMode",\ + globald3dsettings.get("VertexShaderMode","hardware")) + self.originalvertexshadermode = self.currentvertexshadermode + self.__selectVertexShaderMode(self.currentvertexshadermode) + + self.currentpixelshadermode = d3dsettings.get("PixelShaderMode",\ + globald3dsettings.get("PixelShaderMode","enabled")) + self.originalpixelshadermode = self.currentpixelshadermode + self.__setPixelShaderMode(self.currentpixelshadermode) + + self.currentglsl = d3dsettings.get("UseGLSL",\ + globald3dsettings.get("UseGLSL","disabled")) + self.originalglsl = self.currentglsl + self.__setGLSL(self.currentglsl) + + if not application: + cpdesktopsettings = wineread.GetDesktopSettings() + + self.currentshowdrag = cpdesktopsettings.get("DragFullWindows","0") + self.originalshowdrag = self.currentshowdrag + self.__setShowDrag(self.currentshowdrag) + + def applyChanges(self): + """ Applies the changes to wine's configuration """ + settings = {"DXGrab":self.currentallowcursor, + "DesktopDoubleBuffered":self.currentdubbuffer, + "Managed":currentallowwm} + + if not application: + settings["Desktop"] = self.currentemudesktop + + winewrite.SetWindowSettings(settings, application) + + d3dsettings = {"VertexShaderMode":self.currentvertexshadermode, + "PixelShaderMode":self.currentpixelshadermode, + "UseGLSL":self.currentglsl} + + winewrite.SetD3DSettings(d3dsettings, application) + + if not application: + cpdesktopsettings = {"DragFullWindows":self.currentshowdrag} + + winewrite.SetDesktopSettings(cpdesktopsettings) + + self.reset() + + def slotAllowCursorToggled(self,allow): + if allow: + self.currentallowcursor = 'Y' + else: + self.currentallowcursor = 'N' + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotDubBufferToggled(self,dub): + if dub: + self.currentdubbuffer = 'Y' + else: + self.currentdubbuffer = 'N' + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotAllowWMToggled(self,allow): + global currentallowwm + if allow: + currentallowwm = 'Y' + else: + currentallowwm = 'N' + if not application: + if allow and self.currentemudesktop == "": + self.showdragcheckbox.setEnabled(False) + else: + self.showdragcheckbox.setEnabled(True) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotShowDragToggled(self,show): + if show: + self.currentshowdrag = '2' + else: + self.currentshowdrag = '0' + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotEmuDesktopToggled(self,emudesktop): + if emudesktop: + self.currentemudesktop = unicode(self.xsizeedit.text()) + 'x' + str(self.ysizeedit.text()) + else: + self.currentemudesktop = "" + self.__setEmuDesktop(self.currentemudesktop) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotDesktopSizeChanged(self,size): + self.slotEmuDesktopToggled(True) + + def slotVertexShaderModeActivated(self,modeid): + mode = self.vertexshadersupport[modeid][1][0].lower() + self.vertexshadersupport[modeid][1][1:] + self.currentvertexshadermode = mode + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotPixelShaderModeToggled(self,mode): + if mode: + self.currentpixelshadermode = 'enabled' + else: + self.currentpixelshadermode = 'disabled' + + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotGLSLToggled(self,mode): + if mode: + self.currentglsl = 'enabled' + else: + self.currentglsl = 'disabled' + + self.emit(PYSIGNAL("changedSignal()"), ()) + + def __setAllowCursor(self, allow): + self.currentallowcursor = allow + allow = allow != 'N' + self.allowcursorcheckbox.setChecked(allow) + + def __setDubBuffer(self, dub): + self.currentdubbuffer = dub + dub = dub != 'N' + self.dubbuffercheckbox.setChecked(dub) + + def __setAllowWM(self, allow): + global currentallowwm + currentallowwm = allow + allow = allow != 'N' + self.allowwmcheckbox.setChecked(allow) + if not application: + if allow and self.currentemudesktop == "": + self.showdragcheckbox.setEnabled(False) + else: + self.showdragcheckbox.setEnabled(True) + + def __setEmuDesktop(self, emudesktop): + self.currentemudesktop = emudesktop + emudesktopbool = emudesktop != "" + self.emudesktopcheckbox.setChecked(emudesktopbool) + self.desksizehbox.setEnabled(emudesktopbool) + if emudesktopbool: + desktopsize = emudesktop.split('x') + self.xsizeedit.setText(desktopsize[0]) + self.ysizeedit.setText(desktopsize[1]) + self.showdragcheckbox.setEnabled(True) + elif currentallowwm: + self.showdragcheckbox.setEnabled(False) + + def __selectVertexShaderMode(self,mode): + self.currentvertexshadermode = mode + self.accelcombo.setCurrentItem(self.vertexshadersupportdic[mode]) + + def __setPixelShaderMode(self,mode): + self.currentpixelshadermode = mode + mode = mode == 'enabled' + self.pixelshadercheckbox.setChecked(mode) + + def __setGLSL(self,mode): + self.currentglsl = mode + mode = mode == 'enabled' + self.glslcheckbox.setChecked(mode) + + def __setShowDrag(self,show): + self.currentshowdrag = show + show = show != '0' + self.showdragcheckbox.setChecked(show) + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + +############################################################################ +class AppearancePage(QWidget): + + themes = [unicode(i18n("No Theme"))] + colorschemes = [unicode(i18n("Custom"))] + sizes = [("NormalSize",unicode(i18n("Normal"))), + ("LargeSize",unicode(i18n("Large Fonts"))), + ("ExtraLargeSize",unicode(i18n("Extra Large Fonts")))] + + # Items for the combo box reference a tuple of dictionaries for color + # and size values and translations for that item + # For example, the value of BorderWidth is + # customizableitems[str(i18n("Window Border"))][1]["BorderWidth"][1] + customizableitems = {"Window Border": + ({"ActiveBorder":[unicode(i18n("Active Color:")),QColor()], + "InactiveBorder":[unicode(i18n("Inactive Color:")),QColor()]}, + {"BorderWidth":[unicode(i18n("Width:")),1]}), #ActiveBorder, InactiveBorder, metrics: BorderWidth + "Title Bar": + ({"ActiveTitle":[unicode(i18n("Active Color:")),QColor()], + "GradientActiveTitle":[unicode(i18n("Gradient:")),QColor()], + "InactiveTitle":[unicode(i18n("Inactive Color:")),QColor()], + "GradientInactiveTitle":[unicode(i18n("Gradient:")),QColor()], + "TitleText":[unicode(i18n("Active Text:")),QColor()], + "InactiveTitleText":[unicode(i18n("Inactive Text:")),QColor()]}, + {}), #ActiveTitle, GradientActiveTitle, InactiveTitle, GradientInactiveTitle, TitleText, InactiveTitleText + "Application Workspace": + ({"AppWorkSpace":[unicode(i18n("Background Color:")),QColor()]}, + {}), #AppWorkSpace "Background" + "Buttons": + ({"ButtonFace":[unicode(i18n("Face:")),QColor()], + "ButtonHilight":[unicode(i18n("Hilight:")),QColor()], + "ButtonLight":[unicode(i18n("Light:")),QColor()], + "ButtonShadow":[unicode(i18n("Shadow:")),QColor()], + "ButtonText":[unicode(i18n("Text Color:")),QColor()], + "ButtonAlternateFace":[unicode(i18n("Alternate Face:")),QColor()], + "ButtonDkShadow":[unicode(i18n("Dark Shadow:")),QColor()], + "WindowFrame":[unicode(i18n("Frame:")),QColor()]}, + {}), #ButtonFace, ButtonHilight, ButtonLight, ButtonShadow, ButtonText, ButtonAlternateFace, ButtonDkShadow, WindowFrame + "Caption Buttons": + ({}, + {"CaptionHeight":[unicode(i18n("Height:")),1], + "CaptionWidth":[unicode(i18n("Width:")),1]}), #Metrics: CaptionHeight, CaptionWidth + "Desktop": + ({"Background":[unicode(i18n("Background:")),QColor()]}, + {}), #Background + "Menu": + ({"Menu":[unicode(i18n("Menu Background:")),QColor()], + "MenuBar":[unicode(i18n("Menu Bar Color:")),QColor()], + "MenuHilight":[unicode(i18n("Menu Hilight:")),QColor()], + "MenuText":[unicode(i18n("Text Color:")),QColor()]}, + {"MenuHeight":[unicode(i18n("Menu Bar Height:")),1]}), #Menu (Background), MenuBar, MenuHilight, MenuText, metrics: MenuHeight, MenuWidth (does nothing) + "Scrollbar": + ({"Scrollbar":[unicode(i18n("Color:")),QColor()]}, + {"ScrollWidth":[unicode(i18n("Width:")),1]}), #Scrollbar, metrics: ScrollHeight (does nothing), ScrollWidth + "Window": + ({"Window":[unicode(i18n("Background:")),QColor()], + "WindowText":[unicode(i18n("Text Color:")),QColor()]}, + {}), #Window "Background", WindowText + "Selected Items": + ({"Hilight":[unicode(i18n("Hilight Color:")),QColor()], + "HilightText":[unicode(i18n("Text Color:")),QColor()]}, + {})} #Hilight, HilightText + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + global imagedir + QWidget.__init__(self,parent) + + if not name: + self.setName("AppearanceTab") + + appearance_tab_layout = QVBoxLayout(self,0,0,"AppearanceTabLayout") + self.top_layout = appearance_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + appearance_tab_layout.addWidget(vbox) + + # -- Appearance group + self.appearance_group_box = QVGroupBox(vbox) + self.appearance_group_box.setTitle(i18n("Style and Colors")) + self.appearance_group_box.setInsideSpacing(KDialog.spacingHint()) + self.appearance_group_box.setInsideMargin(KDialog.marginHint()) + + themebox = QWidget(self.appearance_group_box) + + theme_layout = QGridLayout(themebox,3,3) + theme_layout.setSpacing(KDialog.spacingHint()) + theme_layout.setColStretch(1,1) + + styletext = QLabel(themebox,"styletext") + styletext.setText(i18n("Widget Style:")) + theme_layout.addWidget(styletext,0,0) + + self.themes = self.themes + wineread.GetThemesList() + self.themecombo = KComboBox(0,themebox,"themecombo") + self.fillThemeCombo(self.themecombo) + self.connect(self.themecombo,SIGNAL("activated(int)"),self.slotThemeActivated) + theme_layout.addWidget(self.themecombo,0,1) + + self.installbutton = KPushButton(i18n("Install style..."),themebox) + self.connect(self.installbutton,SIGNAL("clicked()"),self.slotInstallThemeClicked) + theme_layout.addWidget(self.installbutton,0,2) + + fontsizetext = QLabel(themebox,"fontsizetext") + fontsizetext.setText(i18n("Font Size:")) + theme_layout.addWidget(fontsizetext,1,0) + + self.fontsizecombo = KComboBox(0,themebox,"fontsizecombo") + self.fillFontSizeCombo(self.fontsizecombo) + self.connect(self.fontsizecombo,SIGNAL("activated(int)"),self.slotFontSizeActivated) + theme_layout.addWidget(self.fontsizecombo,1,1) + + colorschemetext = QLabel(themebox,"colorschemetext") + colorschemetext.setText(i18n("Color Scheme:")) + theme_layout.addWidget(colorschemetext,2,0) + + self.colorschemecombo = KComboBox(0,themebox,"colorschemecombo") + self.fillColorSchemeCombo(self.colorschemecombo) + self.connect(self.colorschemecombo,SIGNAL("activated(int)"),self.slotColorSchemeActivated) + theme_layout.addWidget(self.colorschemecombo,2,1) + + self.saveschemebutton = KPushButton(i18n("Save..."),themebox) + self.connect(self.saveschemebutton,SIGNAL("clicked()"),self.slotSaveSchemeClicked) + theme_layout.addWidget(self.saveschemebutton,2,2) + + # --- Custom Colors --- + hbox = QHBox(self.appearance_group_box) + hbox.setSpacing(KDialog.spacingHint()) + + self.sizehbox = hbox + self.leftspacer = QWidget(hbox) + + self.customcolorsvbox = QVBox(hbox) + self.customcolorsvbox.setSpacing(KDialog.spacingHint()) + + hbox = QHBox(self.customcolorsvbox) + hbox.setSpacing(KDialog.spacingHint()) + + itemtext = QLabel(hbox,"itemtext") + itemtext.setText(i18n("Item:")) + + self.itemcombo = KComboBox(0,hbox,"itemcombo") + self.fillItemCombo(self.itemcombo) + self.connect(self.itemcombo,SIGNAL("activated(int)"),self.slotItemActivated) + hbox.setStretchFactor(self.itemcombo,1) + + self.customcolorsgrid = QWidget(self.customcolorsvbox) + self.customcolorsgrid_layout = QGridLayout(self.customcolorsgrid,4,2) + self.customcolorsgrid_layout.setSpacing(KDialog.spacingHint()) + + # Box 1 of 8 + self.colorsizehbox1 = QWidget(self.customcolorsgrid,"colorsizehbox1") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox1,0,0) + self.colorsizehbox1_layout = QGridLayout(self.colorsizehbox1,1,2) + self.colorsizehbox1_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext1 = QLabel(self.colorsizehbox1,"colorsizetext1") + self.colorsizetext1.setText(i18n(":")) + self.colorsizehbox1_layout.addWidget(self.colorsizetext1,0,0,Qt.AlignRight) + + self.sizespinbox1 = QSpinBox(self.colorsizehbox1,"sizespinbox1") + self.sizespinbox1.setMinValue(0) + self.connect(self.sizespinbox1,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo1 = KColorCombo(self.colorsizehbox1,"colorcombo1") + self.connect(self.colorcombo1,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 2 of 8 + self.colorsizehbox2 = QWidget(self.customcolorsgrid,"colorsizehbox2") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox2,0,1) + self.colorsizehbox2_layout = QGridLayout(self.colorsizehbox2,1,2) + self.colorsizehbox2_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext2 = QLabel(self.colorsizehbox2,"colorsizetext2") + self.colorsizetext2.setText(i18n(":")) + self.colorsizehbox2_layout.addWidget(self.colorsizetext2,0,0,Qt.AlignRight) + + self.sizespinbox2 = QSpinBox(self.colorsizehbox2,"sizespinbox2") + self.sizespinbox2.setMinValue(0) + self.connect(self.sizespinbox2,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo2 = KColorCombo(self.colorsizehbox2,"colorcombo2") + self.connect(self.colorcombo2,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 3 of 8 + self.colorsizehbox3 = QWidget(self.customcolorsgrid,"colorsizehbox3") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox3,1,0) + self.colorsizehbox3_layout = QGridLayout(self.colorsizehbox3,1,2) + self.colorsizehbox3_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext3 = QLabel(self.colorsizehbox3,"colorsizetext3") + self.colorsizetext3.setText(i18n(":")) + self.colorsizehbox3_layout.addWidget(self.colorsizetext3,0,0,Qt.AlignRight) + + self.sizespinbox3 = QSpinBox(self.colorsizehbox3,"sizespinbox3") + self.sizespinbox3.setMinValue(0) + self.connect(self.sizespinbox3,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo3 = KColorCombo(self.colorsizehbox3,"colorcombo3") + self.connect(self.colorcombo3,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 4 of 8 + self.colorsizehbox4 = QWidget(self.customcolorsgrid,"colorsizehbox4") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox4,1,1) + self.colorsizehbox4_layout = QGridLayout(self.colorsizehbox4,1,2) + self.colorsizehbox4_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext4 = QLabel(self.colorsizehbox4,"colorsizetext4") + self.colorsizetext4.setText(i18n(":")) + self.colorsizehbox4_layout.addWidget(self.colorsizetext4,0,0,Qt.AlignRight) + + self.sizespinbox4 = QSpinBox(self.colorsizehbox4,"sizespinbox4") + self.sizespinbox4.setMinValue(0) + self.connect(self.sizespinbox4,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo4 = KColorCombo(self.colorsizehbox4,"colorcombo4") + self.connect(self.colorcombo4,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 5 of 8 + self.colorsizehbox5 = QWidget(self.customcolorsgrid,"colorsizehbox5") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox5,2,0) + self.colorsizehbox5_layout = QGridLayout(self.colorsizehbox5,1,2) + self.colorsizehbox5_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext5 = QLabel(self.colorsizehbox5,"colorsizetext5") + self.colorsizetext5.setText(i18n(":")) + self.colorsizehbox5_layout.addWidget(self.colorsizetext5,0,0,Qt.AlignRight) + + self.sizespinbox5 = QSpinBox(self.colorsizehbox5,"sizespinbox5") + self.sizespinbox5.setMinValue(0) + self.connect(self.sizespinbox5,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo5 = KColorCombo(self.colorsizehbox5,"colorcombo5") + self.connect(self.colorcombo5,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 6 of 8 + self.colorsizehbox6 = QWidget(self.customcolorsgrid,"colorsizehbox6") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox6,2,1) + self.colorsizehbox6_layout = QGridLayout(self.colorsizehbox6,1,2) + self.colorsizehbox6_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext6 = QLabel(self.colorsizehbox6,"colorsizetext6") + self.colorsizetext6.setText(i18n(":")) + self.colorsizehbox6_layout.addWidget(self.colorsizetext6,0,0,Qt.AlignRight) + + self.sizespinbox6 = QSpinBox(self.colorsizehbox6,"sizespinbox6") + self.sizespinbox6.setMinValue(0) + self.connect(self.sizespinbox6,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo6 = KColorCombo(self.colorsizehbox6,"colorcombo6") + self.connect(self.colorcombo6,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 7 of 8 + self.colorsizehbox7 = QWidget(self.customcolorsgrid,"colorsizehbox7") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox7,3,0) + self.colorsizehbox7_layout = QGridLayout(self.colorsizehbox7,1,2) + self.colorsizehbox7_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext7 = QLabel(self.colorsizehbox7,"colorsizetext7") + self.colorsizetext7.setText(i18n(":")) + self.colorsizehbox7_layout.addWidget(self.colorsizetext7,0,0,Qt.AlignRight) + + self.sizespinbox7 = QSpinBox(self.colorsizehbox7,"sizespinbox7") + self.sizespinbox7.setMinValue(0) + self.connect(self.sizespinbox7,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo7 = KColorCombo(self.colorsizehbox7,"colorcombo7") + self.connect(self.colorcombo7,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + # Box 8 of 8 + self.colorsizehbox8 = QWidget(self.customcolorsgrid,"colorsizehbox8") + self.customcolorsgrid_layout.addWidget(self.colorsizehbox8,3,1) + self.colorsizehbox8_layout = QGridLayout(self.colorsizehbox8,1,2) + self.colorsizehbox8_layout.setSpacing(KDialog.spacingHint()) + + self.colorsizetext8 = QLabel(self.colorsizehbox8,"colorsizetext8") + self.colorsizetext8.setText(i18n(":")) + self.colorsizehbox8_layout.addWidget(self.colorsizetext8,0,0,Qt.AlignRight) + + self.sizespinbox8 = QSpinBox(self.colorsizehbox8,"sizespinbox8") + self.sizespinbox8.setMinValue(0) + self.connect(self.sizespinbox8,SIGNAL("valueChanged(int)"),self.slotSizeActivated) + + self.colorcombo8 = KColorCombo(self.colorsizehbox8,"colorcombo8") + self.connect(self.colorcombo8,SIGNAL("activated(const QColor &)"),self.slotColorActivated) + + spacer = QWidget(self.customcolorsvbox) + self.customcolorsvbox.setStretchFactor(spacer,1) + self.customcolorsvbox.setMinimumHeight(itemtext.height()*4.5) + #self.customcolorsvbox.setStretchFactor(self.customcolorsgrid,1) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + appearance_tab_layout.addItem(bottomspacer) + + self.selecteditem = None + self.config = KConfig("wineconfigrc",False,False) + self.reset() + + self.clearWState(Qt.WState_Polished) + + def isChanged(self): + changed = False + changed = changed or self.currenttheme != self.originaltheme\ + or self.currentthemecolorscheme != self.originalthemecolorscheme\ + or self.currentfontsize != self.originalfontsize\ + or self.customizableItemsChanged() + return changed + + def customizableItemsChanged(self): + """ Returns true if any custom setting was changed """ + colors = wineread.GetColorSettings() + metrics = wineread.GetWindowMetrics() + + changed = False + custom = False # For a little efficiency + for item in self.customizableitems.keys(): + for key in self.customizableitems[item][0].keys(): + color = colors.get(key,"0 0 0") + color = color.split() + color = QColor(int(color[0]),int(color[1]),int(color[2])) + if not custom and self.customizableitems[item][0][key][1] !=\ + self.config.readColorEntry(key,QColor(0,0,0)): + self.__selectColorScheme(0) + custom = True + if self.customizableitems[item][0][key][1] != color: + if custom: + return True + else: + changed = True + for key in self.customizableitems[item][1].keys(): + size = int(metrics.get(key,1)) + if not custom and self.customizableitems[item][1][key][1] !=\ + self.config.readNumEntry(key,1): + self.__selectColorScheme(0) + custom = True + if self.customizableitems[item][1][key][1] != size: + if custom: + return True + else: + changed = True + return changed + + def reset(self): + self.fillItemCombo(self.itemcombo) + self.config.setGroup("") + self.currentcustomcolorscheme = unicode(self.config.readEntry("ColorScheme",i18n("Custom"))) + self.originalcustomcolorscheme = self.currentcustomcolorscheme + schemeslist = self.config.readListEntry("ColorSchemes") + self.colorschemes = [unicode(i18n("Custom")), + unicode(i18n("Get KDE Colors"))] + list(schemeslist) + self.config.setGroup(self.currentcustomcolorscheme) + + for preset in self.presets: + if preset[0] not in schemeslist: + self.saveColorScheme(preset[0],preset[1]) + self.colorschemes.append(preset[0]) + + self.fillColorSchemeCombo(self.colorschemecombo) + + theme = wineread.GetCurrentTheme() + if not theme: + self.currenttheme = self.themes[0] + self.originaltheme = self.currenttheme + self.__selectTheme(0) + + self.currentthemecolorscheme = "NormalColor" + self.originalthemecolorscheme = self.currentthemecolorscheme + + self.currentfontsize = self.sizes[0][0] + self.originalfontsize = self.currentfontsize + for i,sizename in enumerate(self.sizes): + if sizename[0] == self.currentfontsize: + self.__selectFontSize(i) + break + else: + self.currenttheme = theme[0] + self.originaltheme = self.currenttheme + for i,themename in enumerate(self.themes): + if themename == self.currenttheme: + self.__selectTheme(i) + break + self.currentthemecolorscheme = theme[1] + self.originalthemecolorscheme = self.currentthemecolorscheme + + self.currentfontsize = theme[2] + self.originalfontsize = self.currentfontsize + for i,sizename in enumerate(self.sizes): + if sizename[0] == self.currentfontsize: + self.__selectFontSize(i) + break + + colors = wineread.GetColorSettings() + metrics = wineread.GetWindowMetrics() + + for item in self.customizableitems.keys(): + for key in self.customizableitems[item][0].keys(): + color = colors.get(key,"0 0 0") + color = color.split() + color = QColor(int(color[0]),int(color[1]),int(color[2])) + if color != self.config.readColorEntry(key,QColor(0,0,0)): + self.currentcustomcolorscheme = self.colorschemes[0] + self.customizableitems[item][0][key][1] = color + for key in self.customizableitems[item][1].keys(): + size = int(metrics.get(key,1)) + if size != self.config.readNumEntry(key,1): + self.currentcustomcolorscheme = self.colorschemes[0] + self.customizableitems[item][1][key][1] = size + + for i,colorname in enumerate(self.colorschemes): + if colorname == self.currentcustomcolorscheme: + self.__selectColorScheme(i) + break + + self.desktopsettings = wineread.GetDesktopSettings() + + def applyChanges(self): + """ Applies the changes to wine's configuration """ + if self.currenttheme == self.themes[0]: + winewrite.SetCurrentTheme(None) + else: + winewrite.SetCurrentTheme((self.currenttheme, + self.currentthemecolorscheme, + self.currentfontsize)) + + colorsettings = {} + metricssettings = {} + for item in self.customizableitems.keys(): + for key in self.customizableitems[item][0].keys(): + color = self.customizableitems[item][0][key][1] + color = str(color.red()) + " " + str(color.green()) +\ + " " + str(color.blue()) + colorsettings[key] = color + for key in self.customizableitems[item][1].keys(): + size = self.customizableitems[item][1][key][1] + + metricssettings[key] = str(size) + + winewrite.SetColorSettings(colorsettings) + winewrite.SetWindowMetrics(metricssettings) + + self.config.setGroup("") + if self.currentcustomcolorscheme == self.colorschemes[1]: + self.currentcustomcolorscheme = self.colorschemes[0] + self.config.writeEntry("ColorScheme",self.currentcustomcolorscheme) + self.config.sync() + + if self.customizableitems["Title Bar"][0]["ActiveTitle"][1]\ + !=\ + self.customizableitems["Title Bar"][0]["GradientActiveTitle"][1]\ + or\ + self.customizableitems["Title Bar"][0]["InactiveTitle"][1]\ + !=\ + self.customizableitems["Title Bar"][0]["GradientInactiveTitle"][1]: + prefmask = self.desktopsettings["UserPreferencemask"] + prefmask = prefmask[:4] + "1" + prefmask[5:] + self.desktopsettings["UserPreferencemask"] = prefmask + else: + prefmask = self.desktopsettings["UserPreferencemask"] + prefmask = prefmask[:4] + "0" + prefmask[5:] + self.desktopsettings["UserPreferencemask"] = prefmask + + winewrite.SetDesktopSettings(self.desktopsettings) + + self.reset() + + def fillThemeCombo(self,combo): + """ Fill the combo box with the list of themes """ + for theme in self.themes: + combo.insertItem(theme) + + def fillColorSchemeCombo(self,combo): + """ Fill the combo box with the list of color schemes """ + combo.clear() + for color in self.colorschemes: + combo.insertItem(color) + + def fillFontSizeCombo(self,combo): + """ Fill the combo box with the list of font sizes """ + for size in self.sizes: + combo.insertItem(size[1]) + + def slotFillItemCombo(self,allowwm): + """ + Fill the combo box with the list of customizable items + Called when window managing is changed + """ + combo = self.itemcombo + combo.clear() + items = self.customizableitems.keys() + items.sort() + for item in items: + if not (allowwm and (item == "Window Border" \ + or item == "Title Bar" or \ + item == "Caption Buttons")): + combo.insertItem(unicode(i18n(item))) + + def slotFillItemComboDesktop(self,desktop): + """ + Fill the combo box with the list of customizable items + Called when virtual desktop is changed + """ + self.slotFillItemCombo(not desktop) + + def fillItemCombo(self,combo = None): + """ Fill the combo box with the list of customizable items """ + if not combo: + combo = self.itemcombo + combo.clear() + items = self.customizableitems.keys() + items.sort() + self.currentitems = [] + for item in items: + if not (currentallowwm == 'Y' and (item == "Window Border" \ + or item == "Title Bar" or \ + item == "Caption Buttons")): + combo.insertItem(unicode(i18n(item))) + self.currentitems.append(item) + + def slotThemeActivated(self,themeid): + """ Picks an already installed theme """ + self.__selectTheme(themeid) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotInstallThemeClicked(self): + """ Opens up a dialog to install a new theme """ + themepath = unicode(KFileDialog.getOpenFileName(os.environ['HOME'],\ + "*.msstyles|" + str(i18n("Windows Styles (*.msstyles)")),self,i18n("Install Style"))) + if themepath: + themename = themepath.split('/') + themename = themename[-1] + themename = themename.split('.') + themename = themename[0] + themedir = wineread.winepath +\ + "/dosdevices/c:/windows/Resources/Themes/" +\ + themename + if not os.path.exists(themedir): + os.mkdir(themedir) + shutil.copy(themepath, themedir) + self.themes.append(str(i18n(themename))) + self.themecombo.insertItem(self.themes[-1]) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotSaveSchemeClicked(self): + """ Lets the user save the current color scheme """ + schemename = KInputDialog.getText(i18n("Save Color Scheme"),\ + i18n("Name: "),\ + i18n("CustomScheme"),\ + self,"schemenameinput") + + while schemename[1] and schemename[0] == "" or \ + schemename[0] == self.colorschemes[0] or \ + schemename[0] == self.colorschemes[1]: + KMessageBox.information(self, \ + i18n("Please enter a unique name for the color scheme."), \ + i18n("Save Color Scheme")) + schemename = KInputDialog.getText(i18n("Save Color Scheme"),\ + i18n("Name: "),\ + i18n("CustomScheme"),\ + self,"schemenameinput") + + if schemename[1]: + schemename = str(schemename[0]) + self.saveColorScheme(schemename) + if schemename not in self.colorschemes: + self.colorschemes.append(schemename) + self.colorschemecombo.insertItem(schemename) + for i,colorname in enumerate(self.colorschemes): + if colorname == schemename: + self.__selectColorScheme(i) + break + + def saveColorScheme(self,name,schemesettings = None): + """ Saves the colorscheme """ + if not schemesettings: + schemesettings = self.customizableitems + self.config.setGroup("") + if name != self.colorschemes[1]: + self.config.writeEntry("ColorScheme",name) + schemeslist = self.config.readListEntry("ColorSchemes") + if name not in schemeslist and name != self.colorschemes[0] and \ + name != self.colorschemes[1]: + schemeslist.append(name) + self.config.writeEntry("ColorSchemes",schemeslist) + self.config.setGroup(name) + for item in self.customizableitems.keys(): + for key in schemesettings[item][0].keys(): + self.config.writeEntry(key,schemesettings[item][0][key][1]) + for key in schemesettings[item][1].keys(): + self.config.writeEntry(key,schemesettings[item][1][key][1]) + self.config.sync() + + def GetKdeColorScheme(self): + """ Sets the current color scheme settings to those currently set in KDE """ + # Create a configuration object. + config = KConfig("kdesktoprc") + + config.setGroup("General") + self.customizableitems["Application Workspace"][0]["AppWorkSpace"][1] =\ + config.readColorEntry("background",QColor(100,100,100)) + self.customizableitems["Buttons"][0]["ButtonFace"][1] =\ + config.readColorEntry("background",QColor(230,230,230)) + self.customizableitems["Buttons"][0]["ButtonHilight"][1] =\ + config.readColorEntry("windowBackground",QColor(240,240,240)) + self.customizableitems["Buttons"][0]["ButtonLight"][1] =\ + config.readColorEntry("selectBackground",QColor(200,200,200)).light(135) + self.customizableitems["Buttons"][0]["ButtonShadow"][1] =\ + config.readColorEntry("background",QColor(100,100,100)).dark(180) + self.customizableitems["Buttons"][0]["ButtonText"][1] =\ + config.readColorEntry("buttonForeground",QColor(0,0,0)) + self.customizableitems["Buttons"][0]["ButtonAlternateFace"][1] =\ + config.readColorEntry("background",QColor(230,230,230)) + self.customizableitems["Buttons"][0]["ButtonDkShadow"][1] =\ + config.readColorEntry("selectBackground",QColor(0,0,0)).dark(146) + self.customizableitems["Buttons"][0]["WindowFrame"][1] =\ + config.readColorEntry("selectBackground",QColor(0,0,0)) + self.customizableitems["Menu"][0]["Menu"][1] =\ + config.readColorEntry("background",QColor(230,230,230)).light(105) + self.customizableitems["Menu"][0]["MenuBar"][1] =\ + config.readColorEntry("background",QColor(230,230,230)) + self.customizableitems["Menu"][0]["MenuHilight"][1] =\ + config.readColorEntry("selectBackground",QColor(0,0,0)) + self.customizableitems["Menu"][0]["MenuText"][1] =\ + config.readColorEntry("foreground",QColor(0,0,0)) + self.customizableitems["Scrollbar"][0]["Scrollbar"][1] =\ + config.readColorEntry("background",QColor(230,230,230)) + self.customizableitems["Window"][0]["Window"][1] =\ + config.readColorEntry("windowBackground",QColor(255,255,255)) + self.customizableitems["Window"][0]["WindowText"][1] =\ + config.readColorEntry("foreground",QColor(0,0,0)) + self.customizableitems["Selected Items"][0]["Hilight"][1] =\ + config.readColorEntry("selectBackground",QColor(0,0,0)) + self.customizableitems["Selected Items"][0]["HilightText"][1] =\ + config.readColorEntry("selectForeground",QColor(255,255,255)) + + config.setGroup("WM") + self.customizableitems["Title Bar"][0]["ActiveTitle"][1] =\ + config.readColorEntry("activeBackground",QColor(10,10,100)) + self.customizableitems["Title Bar"][0]["GradientActiveTitle"][1] =\ + config.readColorEntry("activeBlend",QColor(10,10,200)).light(110) + self.customizableitems["Title Bar"][0]["InactiveTitle"][1] =\ + config.readColorEntry("inactiveBackground",QColor(100,100,100)) + self.customizableitems["Title Bar"][0]["GradientInactiveTitle"][1] =\ + config.readColorEntry("inactiveBlend",QColor(100,100,200)) + self.customizableitems["Title Bar"][0]["TitleText"][1] =\ + config.readColorEntry("activeForeground",QColor(255,255,255)) + self.customizableitems["Title Bar"][0]["InactiveTitleText"][1] =\ + config.readColorEntry("inactiveForeground",QColor(250,250,250)) + self.customizableitems["Window Border"][0]["ActiveBorder"][1] =\ + config.readColorEntry("frame",QColor(10,10,100)) + self.customizableitems["Window Border"][0]["InactiveBorder"][1] =\ + config.readColorEntry("frame",QColor(100,100,200)) + + config.setGroup("Desktop0") + self.customizableitems["Desktop"][0]["Background"][1] =\ + config.readColorEntry("Color1",QColor(50,150,85)) + + self.saveColorScheme(self.colorschemes[1]) + + def slotColorSchemeActivated(self,colorid): + """ Picks a color scheme """ + self.__selectColorScheme(colorid) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotFontSizeActivated(self,fontid): + """ Picks a font size """ + self.__selectFontSize(fontid) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotItemActivated(self,itemid): + """ Picks an item to customize """ + items = self.customizableitems.keys() + items.sort() + for i,item in enumerate(self.currentitems): + if i == itemid: + if item != self.selecteditem: + self.__selectItem(item) + + def slotColorActivated(self,color): + """ Picks a color for the currently selected item """ + key = self.sender().name() + self.customizableitems[self.selecteditem][0][key][1] = color + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotSizeActivated(self,sizevalue): + """ Sets the size value from the spin box """ + key = self.sender().name() + self.customizableitems[self.selecteditem][1][key][1] = sizevalue + self.emit(PYSIGNAL("changedSignal()"), ()) + + def __selectTheme(self,themeid): + """ Selects the browser in the combobox """ + self.currenttheme = self.themes[themeid] + + self.themecombo.setCurrentItem(themeid) + + #if themeid == 0: + # self.colorfontbox.setEnabled(False) + #else: + # self.colorfontbox.setEnabled(True) + + def __selectColorScheme(self,colorid): + """ Selects a color scheme in the combo box """ + self.currentcustomcolorscheme = self.colorschemes[colorid] + + self.colorschemecombo.setCurrentItem(colorid) + + if colorid > 1: + self.config.setGroup("") + self.config.writeEntry("ColorScheme",self.colorschemes[colorid]) + self.config.setGroup(self.colorschemes[colorid]) + for item in self.customizableitems.keys(): + for key in self.customizableitems[item][0].keys(): + color = self.config.readColorEntry(key,QColor(0,0,0)) + self.customizableitems[item][0][key][1] = color + for key in self.customizableitems[item][1].keys(): + size = self.config.readNumEntry(key,1) + self.customizableitems[item][1][key][1] = size + elif colorid == 1: + self.GetKdeColorScheme() + + if not self.selecteditem: + self.__selectItem("Desktop") + else: + self.__selectItem(self.selecteditem) + + def __selectColorSchemeByName(self,name): + """ Finds the index of name in colorschemes and calls the above function """ + for i,colorname in enumerate(self.colorschemes): + if colorname == name: + self.__selectColorScheme(i) + break + + def __selectFontSize(self,sizeid): + """ Selects a font size in the combo box """ + self.currentfontsize = self.sizes[sizeid][0] + + self.fontsizecombo.setCurrentItem(sizeid) + + def __selectItem(self,item): + """ Sets the color and size settings boxes to those for item """ + self.selecteditem = item + + for i,item1 in enumerate(self.currentitems): + if item1 == item: + self.itemcombo.setCurrentItem(i) + + if item == "Application Workspace": + key = "AppWorkSpace" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + self.colorsizehbox2.hide() + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Buttons": + key = "ButtonFace" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "WindowFrame" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + key = "ButtonShadow" + self.colorsizehbox3.show() + self.colorsizetext3.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox3.hide() + self.colorsizehbox3_layout.remove(self.sizespinbox3) + self.colorsizehbox3_layout.addWidget(self.colorcombo3,0,1) + self.colorcombo3.show() + self.colorcombo3.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo3.setName(key) + + key = "ButtonDkShadow" + self.colorsizehbox4.show() + self.colorsizetext4.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox4.hide() + self.colorsizehbox4_layout.remove(self.sizespinbox4) + self.colorsizehbox4_layout.addWidget(self.colorcombo4,0,1) + self.colorcombo4.show() + self.colorcombo4.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo4.setName(key) + + key = "ButtonLight" + self.colorsizehbox5.show() + self.colorsizetext5.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox5.hide() + self.colorsizehbox5_layout.remove(self.sizespinbox5) + self.colorsizehbox5_layout.addWidget(self.colorcombo5,0,1) + self.colorcombo5.show() + self.colorcombo5.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo5.setName(key) + + key = "ButtonHilight" + self.colorsizehbox6.show() + self.colorsizetext6.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox6.hide() + self.colorsizehbox6_layout.remove(self.sizespinbox6) + self.colorsizehbox6_layout.addWidget(self.colorcombo6,0,1) + self.colorcombo6.show() + self.colorcombo6.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo6.setName(key) + + key = "ButtonAlternateFace" + self.colorsizehbox7.show() + self.colorsizetext7.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox7.hide() + self.colorsizehbox7_layout.remove(self.sizespinbox7) + self.colorsizehbox7_layout.addWidget(self.colorcombo7,0,1) + self.colorcombo7.show() + self.colorcombo7.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo7.setName(key) + + key = "ButtonText" + self.colorsizehbox8.show() + self.colorsizetext8.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox8.hide() + self.colorsizehbox8_layout.remove(self.sizespinbox8) + self.colorsizehbox8_layout.addWidget(self.colorcombo8,0,1) + self.colorcombo8.show() + self.colorcombo8.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo8.setName(key) + elif item == "Caption Buttons": + key = "CaptionHeight" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][1][key][0]) + self.colorcombo1.hide() + self.colorsizehbox1_layout.remove(self.colorcombo1) + self.colorsizehbox1_layout.addWidget(self.sizespinbox1,0,1) + self.sizespinbox1.show() + self.sizespinbox1.setName(key) + self.sizespinbox1.setValue(\ + self.customizableitems[item][1][key][1]) + self.sizespinbox1.setMinValue(8) + self.sizespinbox1.setMaxValue(100) + + key = "CaptionWidth" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][1][key][0]) + self.colorcombo2.hide() + self.colorsizehbox2_layout.remove(self.colorcombo2) + self.colorsizehbox2_layout.addWidget(self.sizespinbox2,0,1) + self.sizespinbox2.show() + self.sizespinbox2.setName(key) + self.sizespinbox2.setValue(\ + self.customizableitems[item][1][key][1]) + self.sizespinbox2.setMinValue(8) + self.sizespinbox2.setMaxValue(100) + + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Desktop": + key = "Background" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + self.colorsizehbox2.hide() + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Menu": + key = "Menu" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "MenuBar" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + key = "MenuHilight" + self.colorsizehbox3.show() + self.colorsizetext3.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox3.hide() + self.colorsizehbox3_layout.remove(self.sizespinbox3) + self.colorsizehbox3_layout.addWidget(self.colorcombo3,0,1) + self.colorcombo3.show() + self.colorcombo3.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo3.setName(key) + + key = "MenuText" + self.colorsizehbox4.show() + self.colorsizetext4.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox4.hide() + self.colorsizehbox4_layout.remove(self.sizespinbox4) + self.colorsizehbox4_layout.addWidget(self.colorcombo4,0,1) + self.colorcombo4.show() + self.colorcombo4.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo4.setName(key) + + key = "MenuHeight" + self.colorsizehbox5.show() + self.colorsizetext5.setText(\ + self.customizableitems[item][1][key][0]) + self.colorcombo5.hide() + self.colorsizehbox5_layout.remove(self.colorcombo5) + self.colorsizehbox5_layout.addWidget(self.sizespinbox5,0,1) + self.sizespinbox5.show() + self.sizespinbox5.setName(key) + self.sizespinbox5.setValue(\ + self.customizableitems[item][1][key][1]) + self.sizespinbox5.setMinValue(15) + self.sizespinbox5.setMaxValue(100) + + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Scrollbar": + key = "Scrollbar" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "ScrollWidth" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][1][key][0]) + self.colorcombo2.hide() + self.colorsizehbox2_layout.remove(self.colorcombo2) + self.colorsizehbox2_layout.addWidget(self.sizespinbox2,0,1) + self.sizespinbox2.show() + self.sizespinbox2.setName(key) + self.sizespinbox2.setValue(\ + self.customizableitems[item][1][key][1]) + self.sizespinbox2.setMinValue(8) + self.sizespinbox2.setMaxValue(100) + + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Selected Items": + key = "Hilight" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "HilightText" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Title Bar": + key = "ActiveTitle" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "GradientActiveTitle" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + key = "InactiveTitle" + self.colorsizehbox3.show() + self.colorsizetext3.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox3.hide() + self.colorsizehbox3_layout.remove(self.sizespinbox3) + self.colorsizehbox3_layout.addWidget(self.colorcombo3,0,1) + self.colorcombo3.show() + self.colorcombo3.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo3.setName(key) + + key = "GradientInactiveTitle" + self.colorsizehbox4.show() + self.colorsizetext4.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox4.hide() + self.colorsizehbox4_layout.remove(self.sizespinbox4) + self.colorsizehbox4_layout.addWidget(self.colorcombo4,0,1) + self.colorcombo4.show() + self.colorcombo4.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo4.setName(key) + + key = "TitleText" + self.colorsizehbox5.show() + self.colorsizetext5.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox5.hide() + self.colorsizehbox5_layout.remove(self.sizespinbox5) + self.colorsizehbox5_layout.addWidget(self.colorcombo5,0,1) + self.colorcombo5.show() + self.colorcombo5.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo5.setName(key) + + key = "InactiveTitleText" + self.colorsizehbox6.show() + self.colorsizetext6.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox6.hide() + self.colorsizehbox6_layout.remove(self.sizespinbox6) + self.colorsizehbox6_layout.addWidget(self.colorcombo6,0,1) + self.colorcombo6.show() + self.colorcombo6.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo6.setName(key) + + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Window": + key = "Window" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "WindowText" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + elif item == "Window Border": + key = "ActiveBorder" + self.colorsizehbox1.show() + self.colorsizetext1.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox1.hide() + self.colorsizehbox1_layout.remove(self.sizespinbox1) + self.colorsizehbox1_layout.addWidget(self.colorcombo1,0,1) + self.colorcombo1.show() + self.colorcombo1.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo1.setName(key) + + key = "InactiveBorder" + self.colorsizehbox2.show() + self.colorsizetext2.setText(\ + self.customizableitems[item][0][key][0]) + self.sizespinbox2.hide() + self.colorsizehbox2_layout.remove(self.sizespinbox2) + self.colorsizehbox2_layout.addWidget(self.colorcombo2,0,1) + self.colorcombo2.show() + self.colorcombo2.setColor(\ + self.customizableitems[item][0][key][1]) + self.colorcombo2.setName(key) + + key = "BorderWidth" + self.colorsizehbox3.show() + self.colorsizetext3.setText(\ + self.customizableitems[item][1][key][0]) + self.colorcombo3.hide() + self.colorsizehbox3_layout.remove(self.colorcombo3) + self.colorsizehbox3_layout.addWidget(self.sizespinbox3,0,1) + self.sizespinbox3.show() + self.sizespinbox3.setName(key) + self.sizespinbox3.setValue(\ + self.customizableitems[item][1][key][1]) + self.sizespinbox3.setMinValue(1) + self.sizespinbox3.setMaxValue(50) + + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + else: + # Shouldn't happen. + self.colorsizehbox1.hide() + self.colorsizehbox2.hide() + self.colorsizehbox3.hide() + self.colorsizehbox4.hide() + self.colorsizehbox5.hide() + self.colorsizehbox6.hide() + self.colorsizehbox7.hide() + self.colorsizehbox8.hide() + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + # --- Some default color schemes, with names --- + preset1 = (unicode(i18n("Purple")), + {"Window Border": + ({"ActiveBorder":[unicode(i18n("Active Color:")),QColor(239,239,239)], + "InactiveBorder":[unicode(i18n("Inactive Color:")),QColor(239,239,239)]}, + {"BorderWidth":[unicode(i18n("Width:")),1]}), #ActiveBorder, InactiveBorder, metrics: BorderWidth + "Title Bar": + ({"ActiveTitle":[unicode(i18n("Active Color:")),QColor(91,86,168)], + "GradientActiveTitle":[unicode(i18n("Gradient:")),QColor(136,118,202)], + "InactiveTitle":[unicode(i18n("Inactive Color:")),QColor(223,225,230)], + "GradientInactiveTitle":[unicode(i18n("Gradient:")),QColor(157,170,186)], + "TitleText":[unicode(i18n("Active Text:")),QColor(255,255,255)], + "InactiveTitleText":[unicode(i18n("Inactive Text:")),QColor(168,168,168)]}, + {}), #ActiveTitle, GradientActiveTitle, InactiveTitle, GradientInactiveTitle, TitleText, InactiveTitleText + "Application Workspace": + ({"AppWorkSpace":[unicode(i18n("Background Color:")),QColor(90,90,90)]}, + {}), #AppWorkSpace "Background" + "Buttons": + ({"ButtonFace":[unicode(i18n("Face:")),QColor(238,239,242)], + "ButtonHilight":[unicode(i18n("Hilight:")),QColor(255,255,255)], + "ButtonLight":[unicode(i18n("Light:")),QColor(201,199,255)], + "ButtonShadow":[unicode(i18n("Shadow:")),QColor(132,132,134)], + "ButtonText":[unicode(i18n("Text Color:")),QColor(0,0,0)], + "ButtonAlternateFace":[unicode(i18n("Alternate Face:")),QColor(238,239,242)], + "ButtonDkShadow":[unicode(i18n("Dark Shadow:")),QColor(98,96,143)], + "WindowFrame":[unicode(i18n("Frame:")),QColor(144,140,209)]}, + {}), #ButtonFace, ButtonHilight, ButtonLight, ButtonShadow, ButtonText, ButtonAlternateFace, ButtonDkShadow, WindowFrame + "Caption Buttons": + ({}, + {"CaptionHeight":[unicode(i18n("Height:")),22], + "CaptionWidth":[unicode(i18n("Width:")),22]}), #Metrics: CaptionHeight, CaptionWidth + "Desktop": + ({"Background":[unicode(i18n("Background:")),QColor(146,127,188)]}, + {}), #Background + "Menu": + ({"Menu":[unicode(i18n("Menu Background:")),QColor(250,251,254)], + "MenuBar":[unicode(i18n("Menu Bar Color:")),QColor(238,239,242)], + "MenuHilight":[unicode(i18n("Menu Hilight:")),QColor(144,140,209)], + "MenuText":[unicode(i18n("Text Color:")),QColor(0,0,0)]}, + {"MenuHeight":[unicode(i18n("Menu Bar Height:")),22]}), #Menu (Background), MenuBar, MenuHilight, MenuText, metrics: MenuHeight, MenuWidth (does nothing) + "Scrollbar": + ({"Scrollbar":[unicode(i18n("Color:")),QColor(238,239,242)]}, + {"ScrollWidth":[unicode(i18n("Width:")),16]}), #Scrollbar, metrics: ScrollHeight (does nothing), ScrollWidth + "Window": + ({"Window":[unicode(i18n("Background:")),QColor(255,255,255)], + "WindowText":[unicode(i18n("Text Color:")),QColor(0,0,0)]}, + {}), #Window "Background", WindowText + "Selected Items": + ({"Hilight":[unicode(i18n("Hilight Color:")),QColor(144,140,209)], + "HilightText":[unicode(i18n("Text Color:")),QColor(255,255,255)]}, + {})}) #Hilight, HilightText + + preset2 = (unicode(i18n("Blue")), + {"Window Border": + ({"ActiveBorder":[unicode(i18n("Active Color:")),QColor(239,239,239)], + "InactiveBorder":[unicode(i18n("Inactive Color:")),QColor(239,239,239)]}, + {"BorderWidth":[unicode(i18n("Width:")),1]}), #ActiveBorder, InactiveBorder, metrics: BorderWidth + "Title Bar": + ({"ActiveTitle":[unicode(i18n("Active Color:")),QColor(0,113,201)], + "GradientActiveTitle":[unicode(i18n("Gradient:")),QColor(87,161,219)], + "InactiveTitle":[unicode(i18n("Inactive Color:")),QColor(191,191,191)], + "GradientInactiveTitle":[unicode(i18n("Gradient:")),QColor(171,171,171)], + "TitleText":[unicode(i18n("Active Text:")),QColor(255,255,255)], + "InactiveTitleText":[unicode(i18n("Inactive Text:")),QColor(95,95,95)]}, + {}), #ActiveTitle, GradientActiveTitle, InactiveTitle, GradientInactiveTitle, TitleText, InactiveTitleText + "Application Workspace": + ({"AppWorkSpace":[unicode(i18n("Background Color:")),QColor(90,90,90)]}, + {}), #AppWorkSpace "Background" + "Buttons": + ({"ButtonFace":[unicode(i18n("Face:")),QColor(239,239,239)], + "ButtonHilight":[unicode(i18n("Hilight:")),QColor(246,246,246)], + "ButtonLight":[unicode(i18n("Light:")),QColor(191,207,251)], + "ButtonShadow":[unicode(i18n("Shadow:")),QColor(148,148,153)], + "ButtonText":[unicode(i18n("Text Color:")),QColor(0,0,0)], + "ButtonAlternateFace":[unicode(i18n("Alternate Face:")),QColor(238,239,242)], + "ButtonDkShadow":[unicode(i18n("Dark Shadow:")),QColor(50,101,146)], + "WindowFrame":[unicode(i18n("Frame:")),QColor(74,149,214)]}, + {}), #ButtonFace, ButtonHilight, ButtonLight, ButtonShadow, ButtonText, ButtonAlternateFace, ButtonDkShadow, WindowFrame + "Caption Buttons": + ({}, + {"CaptionHeight":[unicode(i18n("Height:")),22], + "CaptionWidth":[unicode(i18n("Width:")),22]}), #Metrics: CaptionHeight, CaptionWidth + "Desktop": + ({"Background":[unicode(i18n("Background:")),QColor(44,109,189)]}, + {}), #Background + "Menu": + ({"Menu":[unicode(i18n("Menu Background:")),QColor(249,249,249)], + "MenuBar":[unicode(i18n("Menu Bar Color:")),QColor(239,239,239)], + "MenuHilight":[unicode(i18n("Menu Hilight:")),QColor(74,149,214)], + "MenuText":[unicode(i18n("Text Color:")),QColor(0,0,0)]}, + {"MenuHeight":[unicode(i18n("Menu Bar Height:")),22]}), #Menu (Background), MenuBar, MenuHilight, MenuText, metrics: MenuHeight, MenuWidth (does nothing) + "Scrollbar": + ({"Scrollbar":[unicode(i18n("Color:")),QColor(230,230,230)]}, + {"ScrollWidth":[unicode(i18n("Width:")),16]}), #Scrollbar, metrics: ScrollHeight (does nothing), ScrollWidth + "Window": + ({"Window":[unicode(i18n("Background:")),QColor(255,255,255)], + "WindowText":[unicode(i18n("Text Color:")),QColor(0,0,0)]}, + {}), #Window "Background", WindowText + "Selected Items": + ({"Hilight":[unicode(i18n("Hilight Color:")),QColor(74,149,214)], + "HilightText":[unicode(i18n("Text Color:")),QColor(255,255,255)]}, + {})}) #Hilight, HilightText + presets = [preset1,preset2] + +############################################################################ +class GeneralPage(QWidget): + + winversions = wineread.winversions + + verdic = { + "win2003":0, + "winxp":1, + "win2k":2, + "winme":3, + "win98":4, + "win95":5, + "nt40":6, + "nt351":7, + "win31":8, + "win30":9, + "win20":10} + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + global application + QWidget.__init__(self,parent) + + if not name: + self.setName("GeneralTab") + + general_tab_layout = QVBoxLayout(self,0,0,"GeneralTabLayout") + self.top_layout = general_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + general_tab_layout.addWidget(vbox) + + if application: + appwarning = QLabel(vbox,"appwarning") + appwarning.setText(i18n("Application specific settings for <b>" +\ + application + "</b><p>Changing a setting here will permanently " +\ + "make that setting independent of settings for all other " +\ + "applications.</p>")) + appwarning.setFrameStyle( QFrame.Box | QFrame.Raised ) + self.winversions = self.winversions + (( "global",\ + unicode(i18n("Use Global Setting")), 0, 0, 0, "", "", 0, 0, ""),) + self.verdic["global"]=11 + + hbox = QHBox(vbox) + hbox.setSpacing(KDialog.spacingHint()) + + versiontext = QLabel(hbox,"versiontext") + versiontext.setText(i18n("Windows version:")) + + self.versioncombo = KComboBox(0,hbox,"versioncombo") + self.fillVersionCombo(self.versioncombo) + self.connect(self.versioncombo,SIGNAL("activated(int)"),self.slotVersionActivated) + + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + general_tab_layout.addItem(bottomspacer) + + self.reset() + + self.clearWState(Qt.WState_Polished) + + def isChanged(self): + changed = False + changed = changed or self.currentwinverid != self.originalwinverid + return changed + + def reset(self): + settings = wineread.GetGeneralWineSettings(application) + + if application: + self.currentwinverid = self.verdic[settings.get("Version","global")] + else: + self.currentwinverid = self.verdic[settings.get("Version","winxp")] + self.originalwinverid = self.currentwinverid + self.__selectWinVer(self.currentwinverid) + + def applyChanges(self): + """ Applies the changes to wine's configuration """ + winewrite.SetWinVersion(self.winversions[self.currentwinverid], application) + + self.reset() + + def fillVersionCombo(self,combo): + """ Fill the combobox with the values from our list """ + for version in self.winversions: + combo.insertItem(version[1]) + + def slotVersionActivated(self,verid): + self.currentwinverid = verid + self.emit(PYSIGNAL("changedSignal()"), ()) + + def __selectWinVer(self,verid): + """ + Sets the current Windows version and selects it in the combo box + """ + self.versioncombo.setCurrentItem(verid) + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + +############################################################################ +class ApplicationsPage(QWidget): + + applications = [] + + browsers = [] + mailers = [] + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + QWidget.__init__(self,parent) + + if not name: + self.setName("ApplicationsTab") + + applications_tab_layout = QVBoxLayout(self,0,0,"ApplicationsTabLayout") + self.top_layout = applications_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + applications_tab_layout.addWidget(vbox) + + # -- Application Specific Settings group -- + self.perapp_group_box = QHGroupBox(vbox) + self.perapp_group_box.setTitle(i18n("Application specific settings")) + self.perapp_group_box.setInsideSpacing(KDialog.spacingHint()) + self.perapp_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.perapp_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + applicationstext = QLabel(vbox2,"applicationstext") + applicationstext.setText(i18n("Change application specific settings for:")) + + self.appslist = KListBox(vbox2) + self.connect(self.appslist, SIGNAL("selectionChanged(QListBoxItem *)"), self.slotListClicked) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.addbutton = KPushButton(i18n("Add Application..."),hbox) + self.connect(self.addbutton,SIGNAL("clicked()"),self.slotAddClicked) + + self.removebutton = KPushButton(i18n("Remove..."),hbox) + self.connect(self.removebutton,SIGNAL("clicked()"),self.slotRemoveClicked) + + spacer = QWidget(hbox) + hbox.setStretchFactor(spacer,1) + + self.settingsbutton = KPushButton(i18n("Settings"),hbox) + self.connect(self.settingsbutton,SIGNAL("clicked()"),self.slotSettingsClicked) + + # -- Native Applications Settings group -- + # Removed pending a patch to winebrowser + #self.nativeapp_group_box = QVGroupBox(vbox) + #self.nativeapp_group_box.setTitle(i18n("Native applications")) + #self.nativeapp_group_box.setInsideSpacing(KDialog.spacingHint()) + #self.nativeapp_group_box.setInsideMargin(KDialog.marginHint()) + + #vbox3 = QWidget(self.nativeapp_group_box) + + #native_apps_layout = QGridLayout(vbox3,2,3) + #native_apps_layout.setSpacing(KDialog.spacingHint()) + + #browsertext = QLabel(vbox3,"browsertext") + #browsertext.setText(i18n("Web Browser:")) + #native_apps_layout.addWidget(browsertext,0,0) + + #self.browsercombo = KComboBox(0,vbox3,"browsercombo") + #self.browsercombo.setEditable(False) + #self.connect(self.browsercombo,SIGNAL("activated(int)"),self.slotBrowserActivated) + #native_apps_layout.addWidget(self.browsercombo,0,1) + #native_apps_layout.setColStretch(1,1) + + #QToolTip.add(self.browsercombo, + #i18n("<p>Select the browser to be launched when clicking on a link" +\ + #" in a Windows application.</p>")) + + #self.browserbutton = KPushButton(i18n("..."),vbox3) + #self.connect(self.browserbutton,SIGNAL("clicked()"),self.slotBrowserClicked) + #native_apps_layout.addWidget(self.browserbutton,0,2) + + #mailertext = QLabel(vbox3,"mailertext") + #mailertext.setText(i18n("Mail Client:")) + #native_apps_layout.addWidget(mailertext,1,0) + + #self.mailercombo = KComboBox(0,vbox3,"mailercombo") + #self.connect(self.mailercombo,SIGNAL("activated(int)"),self.slotMailerActivated) + #native_apps_layout.addWidget(self.mailercombo,1,1) + + #QToolTip.add(self.mailercombo, + #i18n("<p>Select the mail client to be launched when clicking on" +\ + #" a mailto link in a Windows application.</p>")) + + #self.mailerbutton = KPushButton(i18n("..."),vbox3) + #self.connect(self.mailerbutton,SIGNAL("clicked()"),self.slotMailerClicked) + #native_apps_layout.addWidget(self.mailerbutton,1,2) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + applications_tab_layout.addItem(bottomspacer) + + self.changed = False + + # Removed pending a patch to winebrowser + #browsers = wineread.GetNativeBrowserList() + #if "kfmclient exec" not in browsers: + #browsers.append("kfmclient exec") + #self.currentbrowser = wineread.GetBrowser() + #self.browsers = self.createBrowserList(browsers,[self.currentbrowser]) + #self.fillCombo(self.browsercombo,self.browsers) + + #mailers = wineread.GetNativeMailerList() + #if "kfmclient exec" not in mailers: + #mailers.append("kfmclient exec") + #self.currentmailer = wineread.GetMailer() + #self.mailers = self.createMailerList(mailers,[self.currentmailer]) + #self.fillCombo(self.mailercombo,self.mailers) + + self.reset() + + self.clearWState(Qt.WState_Polished) + + def isChanged(self): + changed = False + changed = changed or self.applications != self.originalapplications + #changed = changed or self.currentbrowser != self.originalbrowser + #changed = changed or self.currentmailer != self.originalmailer + return changed + + def reset(self): + self.applications = wineread.GetApps() + self.originalapplications = self.applications[:] + self.updateAppsList() + + # Removed pending a patch to winebrowser + #self.currentbrowser = wineread.GetBrowser() + #self.__selectBrowser(self.currentbrowser) + #self.originalbrowser = self.currentbrowser + + #self.currentmailer = wineread.GetMailer() + #self.__selectMailer(self.currentmailer) + #self.originalmailer = self.currentmailer + + def applyChanges(self): + """ Applies the changes to wine's configuration """ + if self.applications != self.originalapplications: + winewrite.SetApps(self.applications) + # Removed pending a patch to winebrowser + #if self.currentbrowser != self.originalbrowser: + #winewrite.SetDefaultBrowser(self.currentbrowser) + #if self.currentmailer != self.originalmailer: + #winewrite.SetDefaultMailer(self.currentmailer) + self.reset() + + def createBrowserList(self,native,wine): + """ + Takes a list of native browsers and a list wine browsers + and creates a list of the commands with descriptions + """ + + browsers = [] + + for browser in native: + browserwords = browser.split() + if browserwords and browserwords[0] == "kfmclient": + browserkfmcmd = browser.split(' ') + if len(browserkfmcmd) > 2 and \ + browserkfmcmd[1] == 'openProfile': + browsertr = "Konqueror " + browserkfmcmd[2] +\ + str(i18n(" profile (Native)")) + elif len(browserkfmcmd) > 1 and \ + browserkfmcmd[1] == 'exec': + browsertr = str(i18n("Use KDE Default")) + else: + browsertr = str(i18n("Konqueror (Native)")) + else: + browsertr = browser.capitalize() + str(i18n(" (Native)")) + browsers.append((browser,browsertr)) + for browser in wine: + if browser and browser[1] == ':': + browser = browser.lower() + browsertr = browser[browser.rfind('\\\\')+2:browser.rfind('.exe')] + browsertr = browsertr.capitalize() + str(i18n(" (Windows, set by application)")) + else: # winebrowser + continue + browsers.append((browser,browsertr)) + + return browsers + + def createMailerList(self,native,wine): + """ + Takes a list of native mailers and a list wine mailers + and creates a list of the commands with descriptions + """ + + mailers = [] + + for mailer in native: + mailerwords = mailer.split() + if mailerwords and mailerwords[0] == "kfmclient": + mailerkfmcmd = mailer.split(' ') + if len(mailerkfmcmd) > 1 and \ + mailerkfmcmd[1] == 'exec': + mailertr = str(i18n("Use KDE Default")) + else: + mailertr = str(i18n("KDE (Native)")) + else: + mailertr = mailer.capitalize() + unicode(i18n(" (Native)")) + mailers.append((mailer,mailertr)) + for mailer in wine: + if mailer and mailer[1] == ':': + mailer = mailer.lower() + mailertr = mailer[mailer.rfind('\\\\')+2:mailer.rfind('.exe')] + mailertr = mailertr.capitalize() + unicode(i18n(" (Windows, set by application)")) + else: # winebrowser + continue + mailers.append((mailer,mailertr)) + + return mailers + + def slotListClicked(self,item): + """ Called when an application in the list is clicked """ + for appid,appname in enumerate(self.applications): + if appname==item.text(): + self.__selectApp(appid) + return + + def slotAddClicked(self): + """ + Let the user choose a new application to change settings for + """ + app = KFileDialog.getOpenFileName(wineread.winepath + \ + "/dosdevices/c:",\ + "*.exe|" + unicode(i18n("Windows Executables (*.exe)")),self,i18n("Application")) + if app: + app = str(app).split('/') + app = app[-1] + self.applications.append(app) + self.updateAppsList() + for appid,appname in enumerate(self.applications): + if appname==app: + self.__selectApp(appid) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotRemoveClicked(self): + """ Removes settings for selected application """ + if KMessageBox.warningContinueCancel(self, \ + i18n("This will remove all application specific settings for \n" +\ + self.applications[self.selectedappid] +"\n" +\ + "Do you want to proceed?"),\ + i18n("Warning")) == KMessageBox.Continue: + del self.applications[self.selectedappid] + self.updateAppsList() + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotSettingsClicked(self): + """ + Launches a new wineconfig window for the selected application + """ + os.system("wineconfig " + self.applications[self.selectedappid]) + + def slotBrowserEdited(self,browser): + """ Sets the first browser to use to the one selected in the combo box """ + self.currentbrowser = str(browser).strip() + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotBrowserActivated(self,browserid): + """ Sets the first browser to use to the one selected in the combo box """ + self.currentbrowser = self.browsers[browserid][0] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotBrowserClicked(self): + """ Sets the first browser to use to the one selected in the combo box """ + browserdlg = KOpenWithDlg(self) + browserdlg.hideNoCloseOnExit() + browserdlg.hideRunInTerminal() + if browserdlg.exec_loop():#i18n("Choose a Web Browser"),self.currentbrowser) + self.__selectBrowser(str(browserdlg.text())) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotMailerEdited(self,mailer): + """ Sets the first mailer to use to the one selected in the combo box """ + self.currentmailer = str(mailer).strip() + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotMailerActivated(self,mailerid): + """ Sets the first browser to use to the one selected in the combo box """ + self.currentmailer = self.mailers[mailerid][0] + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotMailerClicked(self): + """ Sets the first mailer to use to the one selected in the combo box """ + mailerdlg = KOpenWithDlg(self) + mailerdlg.hideNoCloseOnExit() + mailerdlg.hideRunInTerminal() + if mailerdlg.exec_loop():#i18n("Choose a Web Browser"),self.currentbrowser) + self.__selectMailer(str(mailerdlg.text())) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def fillCombo(self,combo,_list): + """ Fill the combobox with the values from our list + Uses the second value from each tuple """ + for item in _list: + combo.insertItem(item[1]) + + def updateAppsList(self): + """ Updates the displayed list of applications """ + self.appslist.clear() + + self.applications.sort() + + self.appslist.insertStringList(QStringList.fromStrList(self.applications)) + + self.__selectApp(None) + + def __selectBrowser(self,browsercommand): + """ Selects the browser in the combobox """ + self.currentbrowser = browsercommand + + for i,browser in enumerate(self.browsers): + if browser[0].lower() == browsercommand.lower(): + self.browsercombo.setCurrentItem(i) + break + else: + browserwords = browsercommand.split() + #if len(browserwords) > 1 and browserwords[0] != "kfmclient": + # browsercommand = browserwords[0] + self.browsers = self.browsers +\ + self.createBrowserList([browsercommand],[]) + self.browsercombo.insertItem(self.browsers[-1][1]) + self.__selectBrowser(browsercommand) + + def __selectMailer(self,mailercommand): + """ Selects the mailer in the combobox """ + self.currentmailer = mailercommand + + for i,mailer in enumerate(self.mailers): + if mailer[0] == mailercommand: + self.mailercombo.setCurrentItem(i) + break + else: + mailerwords = mailercommand.split() + #if len(mailerwords) > 1 and mailerwords[0] != "kfmclient": + # mailercommand = mailerwords[0] + self.mailers = self.mailers +\ + self.createBrowserList([mailercommand],[]) + self.mailercombo.insertItem(self.mailers[-1][1]) + self.__selectMailer(mailercommand) + + def __selectApp(self,appid): + """ Selects the application """ + if appid or appid == 0: + self.selectedappid = appid + self.appslist.setCurrentItem(appid) + self.removebutton.setEnabled(True) + self.settingsbutton.setEnabled(True) + else: + self.selectedappid = None + self.removebutton.setEnabled(False) + self.settingsbutton.setEnabled(False) + + def GetKdeDefaultBrowser(self): + """ Returns the default browser set in KDE """ + # Create a configuration object. + config = KConfig("wineconfigrc") + return str(config.lookupData(KEntryKey("General","BrowserApplication")).mValue).strip('!') + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + +############################################################################ +class LibrariesPage(QWidget): + + dlls = [""] + overriddendlls = {} + + orderoptions = ("builtin","native","builtin,native","native,builtin","") + orderoptionstr = [ + unicode(i18n("Built-in (Wine)")), + unicode(i18n("Native (Windows)")), + unicode(i18n("Built-in then Native")), + unicode(i18n("Native then Built-in")), + unicode(i18n("Disable"))] + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + QWidget.__init__(self,parent) + + if not name: + self.setName("LibrariesTab") + + libraries_tab_layout = QVBoxLayout(self,0,0,"LibrariesTabLayout") + self.top_layout = libraries_tab_layout + + vbox = QVBox(self) + vbox.setSpacing(KDialog.spacingHint()) + + libraries_tab_layout.addWidget(vbox) + + # -- DLL overrides group + self.overrides_group_box = QHGroupBox(vbox) + self.overrides_group_box.setTitle(i18n("DLL Overrides")) + self.overrides_group_box.setInsideSpacing(KDialog.spacingHint()) + self.overrides_group_box.setInsideMargin(KDialog.marginHint()) + + vbox2 = QVBox(self.overrides_group_box) + vbox2.setSpacing(KDialog.spacingHint()) + + spacer = QWidget(vbox2) + vbox2.setStretchFactor(spacer,1) + + newtext = QLabel(vbox2,"newtext") + newtext.setText(i18n("New override for library:")) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.dllcombo = KComboBox(0,hbox,"dllcombo") + self.dllcombo.setEditable(True) + hbox.setStretchFactor(self.dllcombo,3) + self.connect(self.dllcombo,SIGNAL("activated(int)"),self.slotDllComboActivated) + + QToolTip.add(self.dllcombo, + i18n("<p>Dynamic Link Libraries can be specified individually to" +\ + " be either builtin (provided by Wine) or native (taken from" +\ + " Windows or provided by the application).</p>")) + self.addbutton = KPushButton(i18n("Add"),hbox) + hbox.setStretchFactor(self.addbutton,1) + self.connect(self.addbutton,SIGNAL("clicked()"),self.slotAddClicked) + + existingtext = QLabel(vbox2,"existingtext") + existingtext.setText(i18n("Existing overrides:")) + + hbox = QHBox(vbox2) + hbox.setSpacing(KDialog.spacingHint()) + + self.dllslist = KListView(hbox) + self.dllslist.addColumn(i18n("Library")) + self.dllslist.addColumn(i18n("Load Order")) + self.dllslist.setAllColumnsShowFocus(True) + self.dllslist.setSelectionMode(QListView.Single) + self.dllslist.setSorting(-1,True) + hbox.setStretchFactor(self.dllslist,3) + + self.connect(self.dllslist, SIGNAL("selectionChanged(QListViewItem *)"), self.slotListClicked) + + vbox3 = QVBox(hbox) + vbox3.setSpacing(KDialog.spacingHint()) + hbox.setStretchFactor(vbox3,1) + + self.editbutton = KPushButton(i18n("Edit"),vbox3) + self.connect(self.editbutton,SIGNAL("clicked()"),self.slotEditClicked) + self.editbutton.setEnabled(False) + + self.removebutton = KPushButton(i18n("Remove"),vbox3) + self.connect(self.removebutton,SIGNAL("clicked()"),self.slotRemoveClicked) + self.removebutton.setEnabled(False) + + spacer = QWidget(vbox3) + vbox3.setStretchFactor(spacer,1) + + bottomspacer = QSpacerItem(51,160,QSizePolicy.Minimum,QSizePolicy.Expanding) + libraries_tab_layout.addItem(bottomspacer) + + self.changed = False + + self.reset() + + self.clearWState(Qt.WState_Polished) + + def isChanged(self): + changed = False + changed = changed or self.overriddendlls != self.originaloverriddendlls + return changed + + def reset(self): + self.dlls = wineread.GetDllsList() + self.fillCombo(self.dllcombo) + + self.overriddendlls = wineread.GetDllOverrides(application) + self.originaloverriddendlls = self.overriddendlls.copy() + self.selecteddll = None + self.updateDllOverridesList() + + def applyChanges(self): + """ Applies the changes to wine's configuration """ + winewrite.SetDllOverrides(self.overriddendlls,application) + self.reset() + + def slotListClicked(self,item): + """ Called when an application in the list is clicked """ + self.__selectOverriddenDll(item.text(0)) + + def slotAddClicked(self): + """ + Adds the selected library to the overrides list + """ + dll = self.dllcombo.currentText() + if dll: + self.overriddendlls[str(dll)]="native,builtin" + self.updateDllOverridesList() + self.__selectOverriddenDll(dll) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotRemoveClicked(self): + """ Removes override for selected library """ + del self.overriddendlls[str(self.selecteddll)] + self.updateDllOverridesList() + self.__selectOverriddenDll(None) + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotEditClicked(self): + """ + Gives a choice for the load order for the library + """ + if self.selecteddll: + order = KInputDialog.getItem(i18n("Edit Library Override"),\ + unicode(i18n("Load order for %s:")) % (unicode(self.selecteddll),), + QStringList.fromStrList(self.orderoptionstr),\ + False,0,self,"editdll") + + if order[1]: + self.overriddendlls[str(self.selecteddll)] = \ + self.orderoptions[self.orderoptionstr.index(str(order[0]))] + self.updateDllOverridesList() + self.emit(PYSIGNAL("changedSignal()"), ()) + + def slotDllComboActivated(self,dllid): + return + + def fillCombo(self,combo): + """ Fill the combobox with the values from our list """ + for dll in self.dlls: + combo.insertItem(dll) + + def updateDllOverridesList(self): + """ Updates the displayed list of drives """ + self.dllslist.clear() + self.dllsToListItems = {} + firstselecteddll = None + lastdll = None + + for dll,order in self.overriddendlls.iteritems(): + lvi = QListViewItem(self.dllslist,dll,order) + self.dllsToListItems[dll] = lvi + if self.selecteddll and self.selecteddll==dll: + firstselecteddll = dll + lastdll = dll + + self.dllslist.setSortColumn(0) + self.selecteddll = firstselecteddll + self.__selectOverriddenDll(self.selecteddll) + self.dllslist.ensureItemVisible(self.dllslist.currentItem()) + + def __selectOverriddenDll(self,dll): + """ Select a dll from the overridden list """ + self.selecteddll = dll + if dll: + self.dllslist.setSelected(self.dllsToListItems[str(dll)],True) + self.editbutton.setEnabled(True) + self.removebutton.setEnabled(True) + else: + self.editbutton.setEnabled(False) + self.removebutton.setEnabled(False) + + def setMargin(self,margin): + self.top_layout.setMargin(margin) + + def setSpacing(self,spacing): + self.top_layout.setSpacing(spacing) + + +############################################################################ +def create_wineconfig(parent,name): + """ Factory function for KControl """ + global kapp + kapp = KApplication.kApplication() + return WineConfigApp(parent, name) + +############################################################################ +def MakeAboutData(): + aboutdata = KAboutData("guidance",programname,version, \ + "Wine Configuration Tool", KAboutData.License_GPL, \ + "Copyright (C) 2006-2007 Yuriy Kozlov", \ + "Thanks go to Simon Edwards, Sebastian Kügler") + aboutdata.addAuthor("Yuriy Kozlov","Developer","yuriy.kozlov@gmail.com", \ + "http://www.yktech.us/") + aboutdata.addAuthor("Simon Edwards","Developer","simon@simonzone.com", \ + "http://www.simonzone.com/software/") + aboutdata.addAuthor("Sebastian Kügler","Developer","sebas@kde.org", \ + "http://vizZzion.org") + return aboutdata + +if standalone: + aboutdata = MakeAboutData() + KCmdLineArgs.init(sys.argv,aboutdata) + + # Can't do i18n? + options = [("+[appname]", str(i18n("Application to change settings for")))] + KCmdLineArgs.addCmdLineOptions( options ) + + kapp = KApplication() + + wineconfigapp = WineConfigApp() + wineconfigapp.exec_loop(None) diff --git a/wineconfig/wineread.py b/wineconfig/wineread.py new file mode 100644 index 0000000..c1fa3c5 --- /dev/null +++ b/wineconfig/wineread.py @@ -0,0 +1,543 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +########################################################################### +# wineread.py - description # +# ------------------------------ # +# begin : Fri Mar 26 2004 # +# copyright : (C) 2006 by Yuriy Kozlov # +# email : yuriy.kozlov@gmail.com # +# # +########################################################################### +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +########################################################################### + +import os + +""" Provides a set of functions for accessing wine's settings """ + +# Assumes the fake windows is installed in ~/.wine +default_winepath = os.environ['HOME'] + "/.wine" +winepath = default_winepath +defaultwinfolderspath = "c:\\windows\\profiles\\" + os.environ['USER'] + +# Where the dll's are +default_winebuildpath = "/usr/lib/wine" +default_winebuildpath2 = "/usr/lib32/wine" +default_winebuildpath3 = "/usr/local/lib/wine" + +winebuildpath = None + +def GetWineBuildPath(): + """ Returns the wine build path, None if not present """ + path = None + if winebuildpath: + path = winebuildpath + elif os.path.exists(default_winebuildpath): + path = default_winebuildpath + elif os.path.exists(default_winebuildpath2): + path = default_winebuildpath2 + elif os.path.exists(default_winebuildpath3): + path = default_winebuildpath3 + + return path + +def SetWineBuildPath(path): + """ Sets the winebuildpath to path """ + global winebuildpath + winebuildpath = path + +# drive = [index, letter, unixpath/mapping, type, label, serial] +empty_drives = ( + [0,"A:","","","",""], + [1,"B:","","","",""], + [2,"C:","","","",""], + [3,"D:","","","",""], + [4,"E:","","","",""], + [5,"F:","","","",""], + [6,"G:","","","",""], + [7,"H:","","","",""], + [8,"I:","","","",""], + [9,"J:","","","",""], + [10,"K:","","","",""], + [11,"L:","","","",""], + [12,"M:","","","",""], + [13,"N:","","","",""], + [14,"O:","","","",""], + [15,"P:","","","",""], + [16,"Q:","","","",""], + [17,"R:","","","",""], + [18,"S:","","","",""], + [19,"T:","","","",""], + [20,"U:","","","",""], + [21,"V:","","","",""], + [22,"W:","","","",""], + [23,"X:","","","",""], + [24,"Y:","","","",""], + [25,"Z:","","","",""]) + +def GetEmptyDrives(): + """ Returns a list of 26 empty drives """ + drives = [] + for drive in empty_drives: + drives.append(drive[:]) + return drives + +def LoadDrives(): + drives = GetEmptyDrives() + + driveletters = os.listdir(winepath + "/dosdevices") + for folder in driveletters: + if len(folder) > 2 or folder[1] != ':': + del folder + set(driveletters) + + drivetypes = GetDriveTypes() + + for drive in drives: + letter = drive[1].lower() + if letter in driveletters: + drive[2] = os.readlink(winepath + "/dosdevices/" + letter) + if drivetypes.has_key(drive[1]): + drive[3] = drivetypes[drive[1]] + return drives + +empty_shelllinks = ([26,"Desktop","","","",""], + [27,"My Documents","","","",""], + [28,"My Pictures","","","",""], + [29,"My Music","","","",""], + [30,"My Video","","","",""]) + +folder_nonexistent = "This folder does not exist, please map it." +profilesdirectory = winepath + "/dosdevices/c:/windows/profiles/" + os.environ['USER'] + +def GetEmptyShellLinks(): + """ Returns a list of important windows folders """ + shelllinks = [] + for link in empty_shelllinks: + shelllinks.append(link[:]) + return shelllinks + +def GetShellLinks(): + shelllinks = GetEmptyShellLinks() + + existingshelllinks = os.listdir(profilesdirectory) + set(existingshelllinks) + shellregistry = GetShellRegistry() + usershellregistry = GetUserShellRegistry() + + for link in shelllinks: + if link[1] in existingshelllinks: + linkpath = profilesdirectory + "/" + link[1] + if os.path.islink(linkpath): + link[2] = os.readlink(linkpath) + else: + link[2] = linkpath + link[3] = "shellfolder" + winpath = defaultwinfolderspath + "\\" + link[1] + link[4] = winpath + link[5] = shellregistry.get(link[1], defaultwinfolderspath + "\\" + link[1]) + link[5] = link[5].replace("\\\\","\\") + else: + link[3] = "shellfolder" + link[4] = folder_nonexistent + link[5] = shellregistry.get(link[1], folder_nonexistent) + link[5] = link[5].replace("\\\\","\\") + + return shelllinks + +def GetValue(key, value): + """ Returns a specific value, returns a blank string if the value is not there. """ + # Need 4 \'s to generate one because both python and the shell use it as an escape character + key = key.replace("\\","\\\\") + key = key.replace(" ","\\ ") + error = os.system("wine regedit /E .registryvalue.reg " + key) + if error != 0: + return "" + + file=open('.registryvalue.reg') + + for line in file: + if line and line[0] == '"' or line[0] == '@': + line = line.strip('\r\n') + line = line.split('=') + line = (line[0].strip('"'),line[1].strip('"@')) + if line[0] == value: + file.close() + os.remove(".registryvalue.reg") + return line[1] + else: + file.close() + os.remove(".registryvalue.reg") + return "" + +def GetKeyValues(key): + """ Returns a dictionary of all the values in the key + Returns an empty dictionary if the key does not exist + Does not read subkeys within the key """ + # Need 4 \'s to generate one because both python and the shell use it as an escape character + key = key.replace("\\","\\\\") + key = key.replace(" ","\\ ") + error = os.system("wine regedit /E .registrykey.reg " + key) + if error != 0: + return {} + + settings = {} + + file=open('.registrykey.reg') + + keycount = 0 + for line in file: + if keycount > 1: + break + elif line and line[0] == '[': + keycount += 1 + elif line and line[0] == '"': + line = line.split('=') + settings[line[0].strip('"')] = line[1].strip('"\r\n@') + + file.close() + os.remove(".registrykey.reg") + + return settings + +def GetUserShellRegistry(): + error = os.system("wine regedit /E .registryshelluser.reg HKEY_USERS\\\\.Default\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\User\\ Shell\\ Folders") + if error != 0: + return {} + + usershellfile=open('.registryshelluser.reg') + usershellfilelines = usershellfile.readlines() + usershellfile.close() + os.remove(".registryshelluser.reg") + + settings = {} + + del(usershellfilelines[:3]) + + for usershellline in usershellfilelines: + usershellline = usershellline.split('=') + settings[usershellline[0].strip('"')] = usershellline[1].strip('"\r\n') + + return settings + +def GetShellRegistry(): + error = os.system("wine regedit /E .registryshell.reg HKEY_USERS\\\\.Default\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Shell\\ Folders") + if error != 0: + return {} + + shellfile=open('.registryshell.reg') + shellfilelines = shellfile.readlines() + shellfile.close() + os.remove(".registryshell.reg") + + settings = {} + + del(shellfilelines[:3]) + + for shellline in shellfilelines: + shellline = shellline.split('=') + settings[shellline[0].strip('"')] = shellline[1].strip('"\r\n') + + return settings + +def GetDriveTypes(): + """ Returns a dictionary of the drive types """ + # Drive C: doesn't get stored in the registry + defaulttypes = {"C:":"hd"} + + types = GetKeyValues("HKEY_LOCAL_MACHINE\\Software\\Wine\\Drives") + types.update(defaulttypes) + + return types + +def GetAudioDriver(): + """ Returns the audio driver currently set in the registry """ + return GetValue("HKEY_CURRENT_USER\\Software\\Wine\\Drivers","Audio") + +def GetDSoundSettings(app = None): + """ Returns a dictionary of the settings for the DirectSound section """ + if not app: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\DirectSound") + else: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\DirectSound") + +def GetWindowSettings(app = None): + """ Returns a dictionary of the Window Settings """ + if not app: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\X11 Driver") + else: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\X11 Driver") + +def GetD3DSettings(app = None): + """ Returns a dictionary of the Direct3D Settings """ + if not app: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\Direct3D") + else: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\Direct3D") + +# Copied from winecfg +winversions = ( + ( "win2003", "Windows 2003", 5, 2, 0xECE, "VER_PLATFORM_WIN32_NT", "Service Pack 1", 1, 0, "ServerNT"), + ( "winxp", "Windows XP", 5, 1, 0xA28, "VER_PLATFORM_WIN32_NT", "Service Pack 2", 2, 0, "WinNT"), + ( "win2k", "Windows 2000", 5, 0, 0x893, "VER_PLATFORM_WIN32_NT", "Service Pack 4", 4, 0, "WinNT"), + ( "winme", "Windows ME", 4, 90, 0xBB8, "VER_PLATFORM_WIN32_WINDOWS", " ", 0, 0, ""), + ( "win98", "Windows 98", 4, 10, 0x8AE, "VER_PLATFORM_WIN32_WINDOWS", " A ", 0, 0, ""), + ( "win95", "Windows 95", 4, 0, 0x3B6, "VER_PLATFORM_WIN32_WINDOWS", "", 0, 0, ""), + ( "nt40", "Windows NT 4.0", 4, 0, 0x565, "VER_PLATFORM_WIN32_NT", "Service Pack 6a", 6, 0, "WinNT"), + ( "nt351", "Windows NT 3.5", 3, 51, 0x421, "VER_PLATFORM_WIN32_NT", "Service Pack 2", 0, 0, "WinNT"), + ( "win31", "Windows 3.1", 2, 10, 0, "VER_PLATFORM_WIN32s", "Win32s 1.3", 0, 0, ""), + ( "win30", "Windows 3.0", 3, 0, 0, "VER_PLATFORM_WIN32s", "Win32s 1.3", 0, 0, ""), + ( "win20", "Windows 2.0", 2, 0, 0, "VER_PLATFORM_WIN32s", "Win32s 1.3", 0, 0, "")) + +def GetGeneralWineSettings(app = None): + """ Returns a dictionary of the general wine Settings, including the windows version """ + if not app: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine") + else: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app) + +def GetApps(): + """ + Returns a list of the applications which have keys for application + specific settings. + """ + error = os.system("wine regedit /E .registryapps.reg HKEY_CURRENT_USER\\\\Software\\\\Wine\\\\AppDefaults") + if error != 0: + return [] + + settingsfile=open('.registryapps.reg') + settingsfilelines = settingsfile.readlines() + settingsfile.close() + os.remove('.registryapps.reg') + + apps = set([]) + + del(settingsfilelines[:3]) + + for line in settingsfilelines: + if line[0] == '[': + line = line.split('\\') + line[4] = line[4].strip(']\r\n') + apps.add(line[4]) + + apps = list(apps) + apps.sort() + + return apps + +builtin_only = set(("advapi32", + "capi2032", + "dbghelp", + "ddraw", + "gdi32", + "glu32", + "icmp", + "iphlpapi", + "joystick.drv", + "kernel32", + "mswsock", + "ntdll", + "opengl32", + "stdole2.tlb", + "stdole32.tlb", + "twain_32", + "unicows", + "user32", + "vdmdbg", + "w32skrnl", + "winealsa.drv", + "winearts.drv", + "wineaudioio.drv", + "wined3d", + "winedos", + "wineesd.drv", + "winejack.drv", + "winemp3.acm", + "winenas.drv", + "wineoss.drv", + "wineps", + "wineps.drv", + "winex11.drv", + "winmm", + "wintab32", + "wnaspi32", + "wow32", + "ws2_32", + "wsock32")) + +def GetDllsList(): + """ Returns a list of dlls that can be overridden """ + origdlls = os.listdir(GetWineBuildPath()) + dlls = [""] + + for dll in origdlls: + dll = dll.rstrip('.so') + dots = dll.count('.') + if dots != 1: + continue + dll, extension = dll.split('.') + if not (extension != "dll" or dll in builtin_only): + dlls.append(dll) + + dlls.sort() + return dlls + +def GetDllOverrides(app = None): + """ Returns a dictionary of overridden dlls """ + if not app: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides") + else: + return GetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\DllOverrides") + + +# --- Getting and Setting the Default browser --- + +# WineBrowser>Browsers +# List of browsers that Wine will attempt to launch when running winebrowser +# command or clicking on a link in a windows application. Default value is +default_browserlist = ["firefox","konqueror","mozilla","netscape","galeon","opera","dillo"] + +# WineBrowser>Mailers +# List of mail clients that Wine will attempt to launch when running winebrowser +# Default value is +default_mailerlist = ["mozilla-thunderbird","thunderbird","evolution","kmail"] + +#with firefox installed +browser_formats = ["CHROME","FirefoxHTML","HTML","htmlfile","FTP","GOPHER","http","https"] + +default_browser_formats = ["htmlfile","http","https"] # just "winebrowser" + +default_mailer_formats = ["mailto"] # "winebrowser %1" + +def GetBrowser(): + """ Returns the default browser """ + browser = GetValue("HKEY_LOCAL_MACHINE\\Software\\Classes\\http\\shell\\open\\command",'@') + + if browser == "winebrowser": + return GetWineBrowser() + else: + return browser + +def GetWineBrowser(): + """ Returns the first browser tried by winebrowser """ + browserlist = GetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Browsers") + if browserlist: + browser = browserlist.split(',')[0].strip() + return browser + else: + return default_browserlist[0] + +#def GetWinBrowserList(): + +def GetNativeBrowserList(): + """ Returns the list of browsers tried by winebrowser """ + browserlist = GetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Browsers") + if browserlist: + browserlist = list(set(browserlist.split(','))) + for i,item in enumerate(browserlist): + browserlist[i] = item.strip() + return browserlist + else: + return default_browserlist + +def GetMailer(): + """ Returns the default mail client """ + mailer = GetValue("HKEY_LOCAL_MACHINE\\Software\\Classes\\mailto\\shell\\open\\command",'@') + + if mailer == "winebrowser" or mailer == "winebrowser %1": + return GetWineMailer() + else: + return mailer + +def GetWineMailer(): + """ Returns the first mail client tried by winebrowser """ + mailerlist = GetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Mailers") + if mailerlist: + mailer = mailerlist.split(',')[0].strip() + return mailer + else: + # Default first mailer to try in wine is mozilla-thunderbird + return default_mailerlist[0] + +def GetNativeMailerList(): + """ Returns the list of mail clients tried by winebrowser """ + mailerlist = GetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Mailers") + if mailerlist: + mailerlist = list(set(mailerlist.split(','))) + for i,item in enumerate(mailerlist): + mailerlist[i] = item.strip() + return mailerlist + else: + return default_mailerlist + + +# ----- Theming ----- + +def GetThemesList(): + """ Returns a list of installed thiemes """ + if not os.path.exists(winepath + "/dosdevices/c:/windows/Resources/Themes"): + return [] + origthemes = os.listdir(winepath + "/dosdevices/c:/windows/Resources/Themes") + themes = [] + + for i,theme in enumerate(origthemes): + if os.path.exists(winepath +\ + "/dosdevices/c:/windows/Resources/Themes/" + theme +\ + "/" + theme + ".msstyles"): + themes.append(theme) + + themes.sort() + return themes + +def GetCurrentTheme(): + """ Returns the current (theme,color,size), None if none is set """ + themeinfo = GetKeyValues("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager") + + if not themeinfo or themeinfo["ThemeActive"] == "0": + return None + else: + # themename from themename.msstyles + themename = themeinfo["DllName"].split('\\\\')[-1].split('.')[0] + theme = (themename, themeinfo["ColorName"], themeinfo["SizeName"]) + return theme + +def GetColorSettings(): + """ Returns a dictionary of the set colors """ + return GetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Colors") + +def GetWindowMetrics(): + """ Returns a dictionary of the WindowMetrics settings """ + return GetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics") + +def GetDesktopSettings(): + """ Returns a dictionary of the control panel \ Desktop settings """ + return GetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Desktop") + +def SetWinePath(path): + """ Sets the winepath to path """ + global winepath + winepath = path + +def GetWinePath(): + return winepath + +def VerifyWineDrive(path = None): + """ Does a very basic check of if the given path is a valid fake windows installation + Returns False if there is no C: drive """ + if not path: + path = self.default_winepath + + return os.path.exists(path + "/dosdevices/c:/windows/profiles/" + os.environ['USER']) and \ + os.path.exists(path + "/dosdevices/c:/windows/system32") and \ + os.path.exists(path + "/system.reg") and os.path.exists(path + "/userdef.reg") and \ + os.path.exists(path + "/user.reg") diff --git a/wineconfig/winewrite.py b/wineconfig/winewrite.py new file mode 100644 index 0000000..0d0d365 --- /dev/null +++ b/wineconfig/winewrite.py @@ -0,0 +1,489 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +########################################################################### +# winewrite.py - description # +# ------------------------------ # +# begin : Fri Mar 26 2004 # +# copyright : (C) 2006 by Yuriy Kozlov # +# email : yuriy.kozlov@gmail.com # +# # +########################################################################### +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +########################################################################### + +import os +import wineread +import random + +""" Provides functions for changings settings in wine """ + +def SetDriveMappings(drives): + """ Sets wine's drive settings """ + driveletters = os.listdir(wineread.winepath + "/dosdevices") + set(driveletters) + + for drive in drives[:26]: + letter = drive[1].lower() + defineDrive = False + if letter in driveletters: # The drive exists + if drive[2]: # The drive is in use + # Compare for changes + changed = False + # Check if the mapping changed + if drive[2] != os.readlink(wineread.winepath + "/dosdevices/" + letter): + changed = True + + # If it's changed, it will be recreated + if changed: + os.unlink(wineread.winepath + "/dosdevices/" + letter) + defineDrive = True + else: + # Remove the drive + os.unlink(wineread.winepath + "/dosdevices/" + letter) + else: # The drive doesn't exist + if drive[2]: # The drive is in use + # Create it + defineDrive = True + else: + # Do nothing + continue + + if defineDrive: + os.symlink(drive[2], wineread.winepath + "/dosdevices/" + letter) + + SetDriveTypes(drives[:26]) + SetShellLinks(drives[26:]) + +def SetShellLinks(shelllinks): + existingshelllinks = os.listdir(wineread.winepath + "/dosdevices/c:/windows/profiles/" + os.environ['USER']) + set(existingshelllinks) + shellregistry = wineread.GetShellRegistry() + + for link in shelllinks: + createLink = False + if link[1] in existingshelllinks: # The link exists + linkpath = wineread.winepath + "/dosdevices/c:/windows/profiles/" + os.environ['USER'] + "/" + link[1] + if link[2]: # The folder is mapped + # Compare for changes + changed = False + # Check if the mapping changed + if os.path.islink(linkpath) and link[2] != os.readlink(linkpath): + changed = True + elif not os.path.islink(linkpath) and link[2] != linkpath: + changed = True + elif link[5] != shellregistry.get(link[1], wineread.defaultwinfolderspath + "\\" + link[1]): + changed = True + + # If it's changed, it will be recreated + if changed: + if os.path.islink(linkpath): + os.unlink(linkpath) + else: + os.rename(linkpath,linkpath + "-backup" + str(random.randint(1,1000000))) + createLink = True + else: + # Remove the link + os.unlink(linkpath) + else: # The link doesn't exist + if link[2]: # The folder is mapped + # Create it + createLink = True + else: + # Do nothing + continue + + if createLink: + os.symlink(link[2], wineread.winepath + "/dosdevices/c:/windows/profiles/" + os.environ['USER'] + "/" + link[1]) + if shellregistry.has_key(link[1]): + SetShellRegistry(link) + + +def SetShellRegistry(link): + shellfile=open('.registryshellw.reg','w') + shellfile.write("REGEDIT4\n\n[HKEY_USERS\\.Default\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders]\n") + + link[5] = link[5].replace("\\","\\\\") + shellfile.write('"' + link[1] + '"="' + link[5] + '"\n') + + shellfile.write("\n[HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders]\n") + + link[5] = link[5].replace("\\","\\\\") + shellfile.write('"' + link[1] + '"="' + link[5] + '"\n') + + shellfile.write("\n[HKEY_USERS\\.Default\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders]\n") + + shellfile.write('"' + link[1] + '"="' + "%USERPROFILE%\\\\" + link[1] + '"') + + shellfile.write("\n[HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders]\n") + + shellfile.write('"' + link[1] + '"="' + "%USERPROFILE%\\\\" + link[1] + '"') + shellfile.close() + + os.system("wine regedit .registryshellw.reg") + os.remove(".registryshellw.reg") + +def SetKeyValues(key,settings): + """ Sets all the values in key to those from the dictionary settings """ + file=open('.registrykey.reg','w') + file.write("REGEDIT4\n\n[" + key + "]\n") + + for setting in settings: + # Casting to a python string is necessary for older versions of pyQT + if str(settings[setting])[:4] == 'hex:': + file.write('"'+str(setting)+'"='+str(settings[setting])+'\n') + else: + file.write('"'+str(setting)+'"="'+str(settings[setting])+'"\n') + + file.close() + os.system("wine regedit .registrykey.reg") + os.remove(".registrykey.reg") + +def SetValue(key,value,data): + """ Sets the value in key to data """ + file=open('.registryvalue.reg','w') + file.write("REGEDIT4\n\n[" + key + "]\n") + file.write('"' + value + '"="' + data + '"') + file.close() + + os.system("wine regedit .registryvalue.reg") + os.remove(".registryvalue.reg") + +def SetDriveTypes(drives): + """ Sets the type for the drives in the registry """ + drivesfile=open('.registrydrives.reg','w') + drivesfile.write("REGEDIT4\n\n[HKEY_LOCAL_MACHINE\\Software\\Wine\\Drives]\n") + + for drive in drives: + mapping = drive[2] + if mapping: + drivesfile.write('"' + drive[1] + '"="' + drive[3] + '"\n') + + drivesfile.close() + + os.system("wine regedit .registrydrives.reg") + os.remove(".registrydrives.reg") + +def SetAudioDriver(driver): + """ Sets the audio driver in the registry """ + SetValue("HKEY_CURRENT_USER\\Software\\Wine\\Drivers","Audio",driver) + +def SetDSoundSettings(settings, app = None): + """ Sets the settings for Direct Sound in the registry """ + if not app: + SetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\DirectSound", settings) + else: + SetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\DirectSound", settings) + +def SetWindowSettings(settings, app = None): + """ Sets the window settings in the registry """ + windowsfile=open('.registrywindows.reg','w') + if not app: + windowsfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine\\X11 Driver]\n") + else: + windowsfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\X11 Driver]\n") + + # There is a bug in wine that doesn't allow removing of registry entries from + # a reg file, so unchecking emulate desktop can't be implemented this way yet. + + for setting in settings: + if settings[setting]: + windowsfile.write('"'+str(setting)+'"="'+str(settings[setting])+'"\n') + else: + # winecfg removes the value when the emulate desktop checkbox is unchecked + windowsfile.write('"'+str(setting)+'"=-\n') + + windowsfile.close() + os.system("wine regedit .registrywindows.reg") + os.remove(".registrywindows.reg") + +def SetD3DSettings(settings, app = None): + """ Sets the settings for Direct3D in the registry """ + if not app: + SetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\Direct3D", settings) + else: + SetKeyValues("HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\Direct3D", settings) + +def SetDesktopSettings(settings): + """ Sets the control panel \ Desktop settings in the registry """ + SetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Desktop", settings) + +def SetWinVersion(version, app = None): + """ + Sets the windows version in the registry + Sample format for version: + ( "winxp", "Windows XP", 5, 1, 0xA28, "VER_PLATFORM_WIN32_NT", "Service Pack 2", 2, 0, "WinNT") + """ + winverfile=open('.registrywinver.reg','w') + if not app: + winverfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine]\n") + winverfile.write('"Version"="' + version[0] + '"\n') + + Key9x = "\n[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion]\n" + KeyNT = "\n[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion]\n" + KeyProdNT = "\n[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\ProductOptions]\n" + KeyWindNT = "\n[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Windows\n" + KeyEnvNT = "\n[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment]\n" + + versionnumber9x = str(version[2]) + '.' + str(version[3]) + '.' + str(version[4]) + versionnumberNT = str(version[2]) + '.' + str(version[3]) + + if version[5] == "VER_PLATFORM_WIN32_WINDOWS": + winverfile.write(Key9x + '"VersionNumber"="' + versionnumber9x + '"\n') + winverfile.write(Key9x + '"SubVersionNumber"="' + str(version[6]) + '"\n') + + winverfile.write(KeyNT + '"CSDVersion"=-\n') + winverfile.write(KeyNT + '"CurrentVersion"=-\n') + winverfile.write(KeyNT + '"CurrentBuildNumber"=-\n') + winverfile.write(KeyProdNT + '"ProductType"=-\n') + winverfile.write(KeyWindNT + '"CSDVersion"=-\n') + winverfile.write(KeyEnvNT + '"OS"=-\n') + elif version[5] == "VER_PLATFORM_WIN32_NT": + winverfile.write(KeyNT + '"CurrentVersion"="' + versionnumberNT + '"\n') + winverfile.write(KeyNT + '"CSDVersion"="' + str(version[6]) + '"\n') + winverfile.write(KeyNT + '"CurrentBuildNumber"="' + str(version[4]) + '"\n') + winverfile.write(KeyProdNT + '"ProductType"="' + str(version[9]) + '"\n') + winverfile.write(KeyWindNT + '"CSDVersion"=dword:00000' + str(version[7]) + '00\n') + winverfile.write(KeyEnvNT + '"OS"="Windows_NT"\n') + + winverfile.write(Key9x + '"VersionNumber"=-\n') + winverfile.write(Key9x + '"SubVersionNumber"=-\n') + elif version[5] == "VER_PLATFORM_WIN32s": + winverfile.write(Key9x + '"VersionNumber"=-\n') + winverfile.write(Key9x + '"SubVersionNumber"=-\n') + winverfile.write(KeyNT + '"CSDVersion"=-\n') + winverfile.write(KeyNT + '"CurrentVersion"=-\n') + winverfile.write(KeyNT + '"CurrentBuildNumber"=-\n') + winverfile.write(KeyProdNT + '"ProductType"=-\n') + winverfile.write(KeyWindNT + '"CSDVersion"=-\n') + winverfile.write(KeyEnvNT + '"OS"=-\n') + else: + winverfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "]\n") + if version[0] == "global": + winverfile.write('"Version"=-\n') + else: + winverfile.write('"Version"="' + version[0] + '"\n') + + winverfile.close() + + os.system("wine regedit .registrywinver.reg") + os.remove(".registrywinver.reg") + +def SetApps(apps): + """ Adds and removes keys for app specific settings for apps """ + oldapps = wineread.GetApps() + newapps = [] + + # Add new app keys + for app in apps: + if app not in oldapps: + newapps.append(app) + AddApps(newapps) + + # Remove removed app keys + for app in oldapps: + if app not in apps: + RemoveApp(app) + +def RemoveApp(app): + """ Removes the key for settings for app """ + os.system("wine regedit /D HKEY_USERS\\\\S-1-5-4\\\\Software\\\\Wine\\\\AppDefaults\\\\" +\ + app) + +def AddApps(apps): + """ Adds a key for app """ + appsfile=open('.registryapps.reg','w') + appsfile.write("REGEDIT4\n\n") + + for app in apps: + appsfile.write('[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\' +\ + app + ']\n') + + appsfile.close() + os.system("wine regedit .registryapps.reg") + os.remove(".registryapps.reg") + +def SetDllOverrides(overrides, app = None): + """ Sets the dll override settings in the registry """ + dllfile=open('.registrydll.reg','w') + if not app: + dllfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides]\n") + else: + dllfile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\" +\ + app + "\\DllOverrides]\n") + + origoverrides = wineread.GetDllOverrides(app) + + for dll in overrides.keys(): + dllfile.write('"'+str(dll)+'"="'+str(overrides[dll])+'"\n') + + for dll in origoverrides.keys(): + if dll not in overrides: + dllfile.write('"'+str(dll)+'"=-\n') + + dllfile.close() + os.system("wine regedit .registrydll.reg") + os.remove(".registrydll.reg") + +def SetDefaultBrowser(browser): + """ + Sets the default browser to browser + Doesn't set windows browsers, leaves it for the program to do. + """ + file=open('.registrybrowser.reg','w') + file.write("REGEDIT4\n") + + if browser[1] == ':': + for format in wineread.default_browser_formats: + file.write("\n[HKEY_LOCAL_MACHINE\\Software\\Classes\\" +\ + format + "\\shell\\open\\command]\n") + file.write('@="' + browser + '"\n') + file.close() + + os.system("wine regedit .registrybrowser.reg") + os.remove(".registrybrowser.reg") + else: # winebrowser + for format in wineread.default_browser_formats: + file.write("\n[HKEY_LOCAL_MACHINE\\Software\\Classes\\" +\ + format + "\\shell\\open\\command]\n") + file.write('@="winebrowser"\n') + file.close() + + os.system("wine regedit .registrybrowser.reg") + os.remove(".registrybrowser.reg") + + SetFirstBrowser(browser) + +def SetDefaultMailer(mailer): + """ + Sets the default mailer to mailer + Doesn't set windows mailers, leaves it for the program to do. + """ + file=open('.registrymailer.reg','w') + file.write("REGEDIT4\n") + + if mailer[1] == ':': + for format in wineread.default_mailer_formats: + file.write("\n[HKEY_LOCAL_MACHINE\\Software\\Classes\\" +\ + format + "\\shell\\open\\command]\n") + file.write('@="' + mailer + '"\n') + file.close() + + os.system("wine regedit .registrymailer.reg") + os.remove(".registrymailer.reg") + else: # winebrowser + for format in wineread.default_mailer_formats: + file.write("\n[HKEY_LOCAL_MACHINE\\Software\\Classes\\" +\ + format + "\\shell\\open\\command]\n") + file.write('@="winebrowser %1"\n') + file.close() + + os.system("wine regedit .registrymailer.reg") + os.remove(".registrymailer.reg") + + SetFirstMailer(mailer) + +def SetFirstBrowser(browser): + """ Sets the first in the list of browsers for winebrowser to use to browser """ + originalbrowserlist = wineread.GetNativeBrowserList() + + if browser in originalbrowserlist: + originalbrowserlist.remove(browser) + browserlist = [browser] + originalbrowserlist + + browserlist = str(browserlist).strip('[]') + browserlist = browserlist.replace("'","") + browserlist = browserlist.replace(", ",",") + + SetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Browsers",browserlist) + +def SetFirstMailer(mailer): + """ Sets the first in the list of mailers for winebrowser to use to mailer """ + originalmailerlist = wineread.GetNativeMailerList() + + if mailer in originalmailerlist: + originalmailerlist.remove(mailer) + mailerlist = [mailer] + originalmailerlist + + mailerlist = str(mailerlist).strip('[]') + mailerlist = mailerlist.replace("'","") + mailerlist = mailerlist.replace(", ",",") + + SetValue("HKEY_CURRENT_USER\\Software\\Wine\\WineBrowser","Mailers",mailerlist) + +def CreateWineDrive(path = None): + """ + Creates a fake windows installation in path + """ + if not path: + path = wineread.default_winepath + + os.system("WINEPREFIX=" + path + " wineprefixcreate --wait") + +# ----- Theming ----- + +def SetCurrentTheme(theme): + """ + Sets the current theme + theme = (theme,color,size), None if none is set + """ + if not theme: + theme = ("", "", "") + + themesettings = {"ColorName":theme[1], + "SizeName":theme[2], + "ThemeActive":"1"} + + if not theme[0]: + themesettings["DllName"] = "" + themesettings["ThemeActive"] = "0" + else: + themesettings["DllName"] = "C:\\\\windows\\\\Resources\\\\Themes\\\\" +\ + theme[0] + "\\\\" + theme[0] +".msstyles" + + themefile=open('.registrytheme.reg','w') + themefile.write("REGEDIT4\n\n[HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager]\n") + for setting in themesettings: + if themesettings[setting]: + themefile.write('"'+str(setting)+'"="'+str(themesettings[setting])+'"\n') + else: + themefile.write('"'+str(setting)+'"=-\n') + + themefile.close() + os.system("wine regedit .registrytheme.reg") + os.remove(".registrytheme.reg") + +def SetColorSettings(colors): + """ Takes a dictionary of color settings and sets them in the registry """ + SetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Colors",colors) + SetKeyValues("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager\\Control Panel\\Colors",colors) + +def SetWindowMetrics(metrics): + """ + Takes a dictionary of WindowMetrics settings and sets them in the registry + """ + SetKeyValues("HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics",metrics) + +ports_translation = {"lp":"lpt","ttyS":"com"} + +def CreatePorts(ports = None): + """ + Creates links to ports in dosdevices + """ + if not ports: + # Find ports in /dev + ports = ["lp0"] + + for port in ports: + winport = ports_translation[port.rstrip("012345678")] +\ + str(int(port.lstrip("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")) + 1) + os.symlink("/dev/" + port, wineread.winepath + "/dosdevices/" + winport) +
\ No newline at end of file |