96c04a73e74c6e3f9a6e2205d5b1c7a47a8da727
[lilass.git] / qt_dialogue.py
1 # DSL - easy Display Setup for Laptops
2 # Copyright (C) 2012-2015 Ralf Jung <post@ralfj.de>
3 #
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.
8 #
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.
13 #
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.
17 import os
18 from screen import RelativeScreenPosition, ScreenSetup
19 from PyQt4 import QtCore, QtGui, uic
20
21 relPosNames = {
22     RelativeScreenPosition.LEFT: "left of",
23     RelativeScreenPosition.RIGHT: "right of",
24     RelativeScreenPosition.ABOVE: "above",
25     RelativeScreenPosition.BELOW: "below",
26     RelativeScreenPosition.MIRROR: "same as",
27 }
28
29
30 class PositionSelection(QtGui.QDialog):
31     def __init__(self, situation):
32         # set up main window
33         super(PositionSelection, self).__init__()
34         self._situation = situation
35         uifile = os.path.join(os.path.dirname(__file__), 'qt_dialogue.ui')
36         uic.loadUi(uifile, self)
37         
38         # fill relative position box
39         for pos in RelativeScreenPosition:
40             self.relPos.addItem(relPosNames[pos], pos)
41         
42         # keep resolutions in sync when in mirror mode
43         def syncIfMirror(source, target):
44             def _slot(idx):
45                 if self.isMirror:
46                     target.setCurrentIndex(idx)
47             source.currentIndexChanged.connect(_slot)
48         syncIfMirror(self.intRes, self.extRes)
49         syncIfMirror(self.extRes, self.intRes)
50
51         # connect the update function, and make sure we are in a correct state
52         self.intEnabled.toggled.connect(self.updateEnabledControls)
53         self.extEnabled.toggled.connect(self.updateEnabledControls)
54         self.relPos.currentIndexChanged.connect(self.updateEnabledControls)
55         self.updateEnabledControls()
56     
57     def getRelativeScreenPosition(self):
58         idx = self.relPos.currentIndex()
59         return self.relPos.itemData(idx)
60     
61     def fillResolutionBox(self, box, resolutions):
62         # if the count did not change, update in-place (this avoids flicker)
63         if box.count() == len(resolutions):
64             for idx, res in enumerate(resolutions):
65                 box.setItemText(idx, str(res))
66                 box.setItemData(idx, res)
67         else:
68             # first clear it
69             while box.count() > 0:
70                 box.removeItem(0)
71             # then fill it
72             for res in resolutions:
73                 box.addItem(str(res), res)
74     
75     def updateEnabledControls(self):
76         intEnabled = self.intEnabled.isChecked()
77         extEnabled = self.extEnabled.isChecked()
78         bothEnabled = intEnabled and extEnabled
79         self.isMirror = bothEnabled and self.getRelativeScreenPosition() == RelativeScreenPosition.MIRROR # only if both are enabled, we can really mirror
80         # configure screen controls
81         self.intRes.setEnabled(intEnabled)
82         self.intPrimary.setEnabled(intEnabled and not self.isMirror)
83         self.extRes.setEnabled(extEnabled)
84         self.extPrimary.setEnabled(extEnabled and not self.isMirror)
85         if not intEnabled and extEnabled:
86             self.extPrimary.setChecked(True)
87         elif not extEnabled and intEnabled:
88             self.intPrimary.setChecked(True)
89         # which resolutions do we offer?
90         if self.isMirror:
91             commonRes = self._situation.commonResolutions()
92             self.fillResolutionBox(self.intRes, commonRes)
93             self.fillResolutionBox(self.extRes, commonRes)
94             self.intRes.setCurrentIndex(self.extRes.currentIndex())
95         else:
96             self.fillResolutionBox(self.intRes, self._situation.internalResolutions())
97             self.fillResolutionBox(self.extRes, self._situation.externalResolutions())
98         # configure position control
99         self.posGroup.setEnabled(bothEnabled)
100         self.posLabel1.setEnabled(bothEnabled)
101         self.posLabel2.setEnabled(bothEnabled)
102         self.relPos.setEnabled(bothEnabled)
103         # avoid having no screen
104         self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(intEnabled or extEnabled)
105     
106     def run(self):
107         self.exec_()
108         if not self.result(): return None
109         intRes = self.intRes.itemData(self.intRes.currentIndex()) if self.intEnabled.isChecked() else None
110         extRes = self.extRes.itemData(self.extRes.currentIndex()) if self.extEnabled.isChecked() else None
111         return ScreenSetup(intRes, extRes, self.getRelativeScreenPosition(), self.extPrimary.isChecked())