1 # DSL - easy Display Setup for Laptops
2 # Copyright (C) 2012-2015 Ralf Jung <post@ralfj.de>
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # This file abstracts GUI stuff away, so that the actual dsl.py does not have to deal with it
22 This module implements two functions:
25 This function displays the error message to the user in some appropriate fassion
27 def setup(internalResolutions, externalResolutions):
28 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.
29 The user should be asked about his display setup preferences.
30 The function returns None if the user cancelled, and an instance of dsl.ScreenSetup otherwise.
32 import subprocess, collections
34 from question_frontend import QuestionFrontend
35 from screen import processOutputIt
40 from PyQt4 import QtGui
41 self.app = QtGui.QApplication(sys.argv)
44 def error(self, message):
45 from PyQt4 import QtGui
46 QtGui.QMessageBox.critical(None, 'Fatal error', message)
48 def setup(self, situation):
49 from qt_dialogue import PositionSelection
50 return PositionSelection(situation).run()
62 class ZenityFrontend(QuestionFrontend):
63 def error(self, message):
64 '''Displays a fatal error to the user'''
65 subprocess.check_call(["zenity", "--error", "--text="+message])
66 def userChoose (self, title, choices, returns, fallback):
67 assert len(choices) == len(returns)
68 args = ["zenity", "--list", "--text="+title, "--column="]+choices
69 switch = dict (list(zip (choices,returns)))
71 for line in processOutputIt(*args):
72 return switch.get(line.strip(), fallback)
74 # on user cancel, the return code of zenity is nonzero
76 # if the output was empty
80 processOutputIt("zenity", "--version")
82 except FileNotFoundError:
84 except PermissionError:
88 class CLIFrontend(QuestionFrontend):
89 def error(self, message):
90 print(message, file=sys.stderr)
92 def userChoose (self, title, choices, returns, fallback):
96 for i in range(len(choices)):
97 print("%d. %s"%(i,choices[i]))
98 print("Enter 'c' to cancel.")
105 answerint = int(answer)
106 if answerint >= 0 and answerint < len(choices):
107 return returns[answerint]
110 # if we are here something invalid was entered
111 print("INVALID ANSWER: '%s'" % answer)
117 # list of available frontends
118 frontends = collections.OrderedDict()
119 frontends["qt"] = QtFrontend
120 frontends["zenity"] = ZenityFrontend
121 frontends["cli"] = CLIFrontend
124 def getFrontend(name = None):
127 if name in frontends:
128 if frontends[name].isAvailable():
129 return frontends[name]() # call constructor
131 raise Exception("Frontend %s not available" % name)
133 raise Exception("Frontend %s not found" % name)
135 for frontend in frontends.values():
136 if frontend.isAvailable():
137 return frontend() # call constructor
138 raise Exception("No frontend is available - this should not happen")