From 10076cc52cce774a9d16498db7115f07bfb08112 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 Jul 2015 21:43:19 +0200 Subject: [PATCH 1/1] move QtFrontend to the Qt dialogue --- gui.py | 24 +-------- qt_dialogue.py | 102 -------------------------------------- qt_frontend.py | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 125 deletions(-) delete mode 100644 qt_dialogue.py create mode 100644 qt_frontend.py diff --git a/gui.py b/gui.py index 62decc6..4847668 100644 --- a/gui.py +++ b/gui.py @@ -28,34 +28,12 @@ def setup(internalResolutions, externalResolutions): 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 sys import collections +from qt_frontend import QtFrontend from cli_frontend import CLIFrontend from zenity_frontend import ZenityFrontend -# 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 # list of available frontends frontends = collections.OrderedDict() diff --git a/qt_dialogue.py b/qt_dialogue.py deleted file mode 100644 index 26f6717..0000000 --- a/qt_dialogue.py +++ /dev/null @@ -1,102 +0,0 @@ -# DSL - easy Display Setup for Laptops -# 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 -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import os -from screen import RelativeScreenPosition, ScreenSetup -from PyQt4 import QtCore, QtGui, uic - -class PositionSelection(QtGui.QDialog): - def __init__(self, situation): - # set up main window - super(PositionSelection, self).__init__() - self._situation = situation - uifile = os.path.join(os.path.dirname(__file__), 'qt_dialogue.ui') - uic.loadUi(uifile, self) - - # fill relative position box - for pos in RelativeScreenPosition: - self.relPos.addItem(pos.text, pos) - - # keep resolutions in sync when in mirror mode - def syncIfMirror(source, target): - def _slot(idx): - if self.isMirror: - target.setCurrentIndex(idx) - source.currentIndexChanged.connect(_slot) - syncIfMirror(self.intRes, self.extRes) - syncIfMirror(self.extRes, self.intRes) - - # connect the update function, and make sure we are in a correct state - self.intEnabled.toggled.connect(self.updateEnabledControls) - self.extEnabled.toggled.connect(self.updateEnabledControls) - self.relPos.currentIndexChanged.connect(self.updateEnabledControls) - self.updateEnabledControls() - - def getRelativeScreenPosition(self): - idx = self.relPos.currentIndex() - return self.relPos.itemData(idx) - - def fillResolutionBox(self, box, resolutions): - # if the count did not change, update in-place (this avoids flicker) - if box.count() == len(resolutions): - for idx, res in enumerate(resolutions): - box.setItemText(idx, str(res)) - box.setItemData(idx, res) - else: - # first clear it - while box.count() > 0: - box.removeItem(0) - # then fill it - for res in resolutions: - box.addItem(str(res), res) - - def updateEnabledControls(self): - intEnabled = self.intEnabled.isChecked() - extEnabled = self.extEnabled.isChecked() - bothEnabled = intEnabled and extEnabled - self.isMirror = bothEnabled and self.getRelativeScreenPosition() == RelativeScreenPosition.MIRROR # only if both are enabled, we can really mirror - # configure screen controls - self.intRes.setEnabled(intEnabled) - self.intPrimary.setEnabled(intEnabled and not self.isMirror) - self.extRes.setEnabled(extEnabled) - self.extPrimary.setEnabled(extEnabled and not self.isMirror) - if not intEnabled and extEnabled: - self.extPrimary.setChecked(True) - elif not extEnabled and intEnabled: - self.intPrimary.setChecked(True) - # which resolutions do we offer? - if self.isMirror: - commonRes = self._situation.commonResolutions() - self.fillResolutionBox(self.intRes, commonRes) - self.fillResolutionBox(self.extRes, commonRes) - self.intRes.setCurrentIndex(self.extRes.currentIndex()) - else: - self.fillResolutionBox(self.intRes, self._situation.internalResolutions()) - self.fillResolutionBox(self.extRes, self._situation.externalResolutions()) - # configure position control - self.posGroup.setEnabled(bothEnabled) - self.posLabel1.setEnabled(bothEnabled) - self.posLabel2.setEnabled(bothEnabled) - self.relPos.setEnabled(bothEnabled) - # avoid having no screen - self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(intEnabled or extEnabled) - - def run(self): - self.exec_() - if not self.result(): return None - intRes = self.intRes.itemData(self.intRes.currentIndex()) if self.intEnabled.isChecked() else None - extRes = self.extRes.itemData(self.extRes.currentIndex()) if self.extEnabled.isChecked() else None - return ScreenSetup(intRes, extRes, self.getRelativeScreenPosition(), self.extPrimary.isChecked()) diff --git a/qt_frontend.py b/qt_frontend.py new file mode 100644 index 0000000..62e3b84 --- /dev/null +++ b/qt_frontend.py @@ -0,0 +1,130 @@ +# DSL - easy Display Setup for Laptops +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +import sys, os +from screen import RelativeScreenPosition, ScreenSetup + +try: + # Be fine with PyQt4 not being installed + from PyQt4 import QtCore, QtGui, uic + + class PositionSelection(QtGui.QDialog): + def __init__(self, situation): + # set up main window + super(PositionSelection, self).__init__() + self._situation = situation + uifile = os.path.join(os.path.dirname(__file__), 'qt_dialogue.ui') + uic.loadUi(uifile, self) + + # fill relative position box + for pos in RelativeScreenPosition: + self.relPos.addItem(pos.text, pos) + + # keep resolutions in sync when in mirror mode + def syncIfMirror(source, target): + def _slot(idx): + if self.isMirror: + target.setCurrentIndex(idx) + source.currentIndexChanged.connect(_slot) + syncIfMirror(self.intRes, self.extRes) + syncIfMirror(self.extRes, self.intRes) + + # connect the update function, and make sure we are in a correct state + self.intEnabled.toggled.connect(self.updateEnabledControls) + self.extEnabled.toggled.connect(self.updateEnabledControls) + self.relPos.currentIndexChanged.connect(self.updateEnabledControls) + self.updateEnabledControls() + + def getRelativeScreenPosition(self): + idx = self.relPos.currentIndex() + return self.relPos.itemData(idx) + + def fillResolutionBox(self, box, resolutions): + # if the count did not change, update in-place (this avoids flicker) + if box.count() == len(resolutions): + for idx, res in enumerate(resolutions): + box.setItemText(idx, str(res)) + box.setItemData(idx, res) + else: + # first clear it + while box.count() > 0: + box.removeItem(0) + # then fill it + for res in resolutions: + box.addItem(str(res), res) + + def updateEnabledControls(self): + intEnabled = self.intEnabled.isChecked() + extEnabled = self.extEnabled.isChecked() + bothEnabled = intEnabled and extEnabled + self.isMirror = bothEnabled and self.getRelativeScreenPosition() == RelativeScreenPosition.MIRROR # only if both are enabled, we can really mirror + # configure screen controls + self.intRes.setEnabled(intEnabled) + self.intPrimary.setEnabled(intEnabled and not self.isMirror) + self.extRes.setEnabled(extEnabled) + self.extPrimary.setEnabled(extEnabled and not self.isMirror) + if not intEnabled and extEnabled: + self.extPrimary.setChecked(True) + elif not extEnabled and intEnabled: + self.intPrimary.setChecked(True) + # which resolutions do we offer? + if self.isMirror: + commonRes = self._situation.commonResolutions() + self.fillResolutionBox(self.intRes, commonRes) + self.fillResolutionBox(self.extRes, commonRes) + self.intRes.setCurrentIndex(self.extRes.currentIndex()) + else: + self.fillResolutionBox(self.intRes, self._situation.internalResolutions()) + self.fillResolutionBox(self.extRes, self._situation.externalResolutions()) + # configure position control + self.posGroup.setEnabled(bothEnabled) + self.posLabel1.setEnabled(bothEnabled) + self.posLabel2.setEnabled(bothEnabled) + self.relPos.setEnabled(bothEnabled) + # avoid having no screen + self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(intEnabled or extEnabled) + + def run(self): + self.exec_() + if not self.result(): return None + intRes = self.intRes.itemData(self.intRes.currentIndex()) if self.intEnabled.isChecked() else None + extRes = self.extRes.itemData(self.extRes.currentIndex()) if self.extEnabled.isChecked() else None + return ScreenSetup(intRes, extRes, self.getRelativeScreenPosition(), self.extPrimary.isChecked()) +except ImportError: + pass + +# 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): + return PositionSelection(situation).run() + + @staticmethod + def isAvailable(): + try: + import PyQt4 + return True + except ImportError: + return False + -- 2.30.2