X-Git-Url: https://git.ralfj.de/lilass.git/blobdiff_plain/6895277c1f24aa9381822a0cbb20259b97cd075f..38ae85f1535d8301498b94649ed100c88dc377a6:/gui.py diff --git a/gui.py b/gui.py index b6906e1..998783f 100644 --- a/gui.py +++ b/gui.py @@ -1,5 +1,5 @@ # DSL - easy Display Setup for Laptops -# Copyright (C) 2012 Ralf Jung +# Copyright (C) 2012-2015 Ralf Jung # # 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 @@ -12,25 +12,98 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program (gpl.txt); if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# This file bstracts GUI stuff away, so that the actual dsl.py does not have to deal with it +# This file abstracts GUI stuff away, so that the actual dsl.py does not have to deal with it import sys -from PyQt4 import QtGui -from qt_dialogue import PositionSelection -app = QtGui.QApplication(sys.argv) + +''' +This module implements two functions: def error(message): - '''Displays a fatal error to the user''' - QtGui.QMessageBox.critical(None, 'Fatal error', message) - -def getDialogue(externalName, internalResolutions, externalResolutions): - '''Returns a class implementing the following functions: - * run() opens the dialogue. returns True if it was accepted, False otherwise - * getRelativeScreenPosition() returns one of the RelativeScreenPosition values (see dsl.py) - * getIntResolutionIndex() returns the index of an element in the internalResolutions list - * getExtResolutionIndex() returns the index of an element in the externalResolutions list - * externalIsPrimary() returns whether the external screen is the primary one (True) or the internal one (False) - ''' - return PositionSelection(externalName, internalResolutions, externalResolutions) + This function displays the error message to the user in some appropriate fassion + +def setup(internalResolutions, externalResolutions): + Both arguments are lists of (width, height) tuples of resolutions. You can use dsl.res2user to obtain a user-readable representation of a resolution tuple. + The user should be asked about his display setup preferences. + The function returns None if the user cancelled, and an instance of dsl.ScreenSetup otherwise. +''' +import subprocess, collections + +# Qt frontend +class QtFrontend: + def __init__(self): + from PyQt4 import QtGui + self.app = QtGui.QApplication(sys.argv) + print("Qt loaded") + + def error(self, message): + from PyQt4 import QtGui + QtGui.QMessageBox.critical(None, 'Fatal error', message) + + def setup(self, situation): + from qt_dialogue import PositionSelection + return PositionSelection(situation).run() + + @staticmethod + def isAvailable(): + try: + import PyQt4 + return True + except ImportError: + return False + + +# Zenity frontend +class ZenityFrontend: + def error(message): + '''Displays a fatal error to the user''' + subprocess.check_call(["zenity", "--error", "--text="+message]) + + def setup(self, situation): + from zenity_dialogue import run + return run(situation.internalResolutions(), situation.externalResolutions()) + + @staticmethod + def isAvailable(): + try: + from screen import processOutputIt + processOutputIt("zenity", "--version") + return True + except Exception: + return False + + +# CLI frontend +class CLIFrontend: + def error(self, message): + print(message, file=sys.stderr) + + def setup(self, internalResolutions, externalResolutions, commonRes): + raise Exception("Choosing the setup interactively is not supported with the CLI frontend") + + @staticmethod + def isAvailable(): + return True + +# list of available frontends +frontends = collections.OrderedDict() +frontends["qt"] = QtFrontend +frontends["zenity"] = ZenityFrontend +frontends["cli"] = CLIFrontend + +# get a frontend +def getFrontend(name = None): + # by name + if name is not None: + if name in frontends: + if frontends[name].isAvailable(): + return frontends[name]() # call constructor + # frontend not found or not available + raise Exception("Frontend %s not found or not available" % name) + # auto-detect + for frontend in frontends.values(): + if frontend.isAvailable(): + return frontend() # call constructor + raise Exception("No frontend is available - this should not happen")