source: orange/Orange/OrangeCanvas/gui/utils.py @ 11232:c56bdc4a90a6

Revision 11232:c56bdc4a90a6, 7.0 KB checked in by Ales Erjavec <ales.erjavec@…>, 16 months ago (diff)

Workaround for QDockWidget's minimumSize.

Line 
1"""
2Helper utilities
3
4"""
5import os
6import sys
7import traceback
8
9from contextlib import contextmanager
10
11from PyQt4.QtGui import (
12    QWidget, QMessageBox, QGradient, QLinearGradient, QRadialGradient, QBrush,
13    QPainter, QStyleOption, QStyle
14)
15
16import sip
17
18QWIDGETSIZE_MAX = ((1 << 24) - 1)
19
20
21@contextmanager
22def updates_disabled(widget):
23    """Disable QWidget updates (using QWidget.setUpdatesEnabled)
24    """
25    old_state = widget.updatesEnabled()
26    widget.setUpdatesEnabled(False)
27    try:
28        yield
29    finally:
30        widget.setUpdatesEnabled(old_state)
31
32
33@contextmanager
34def signals_disabled(qobject):
35    """Disables signals on an instance of QObject.
36    """
37    old_state = qobject.signalsBlocked()
38    qobject.blockSignals(True)
39    try:
40        yield
41    finally:
42        qobject.blockSignals(old_state)
43
44
45@contextmanager
46def disabled(qobject):
47    """Disables a disablable QObject instance.
48    """
49    if not (hasattr(qobject, "setEnabled") and hasattr(qobject, "isEnabled")):
50        raise TypeError("%r does not have 'enabled' property" % qobject)
51
52    old_state = qobject.isEnabled()
53    qobject.setEnabled(False)
54    try:
55        yield
56    finally:
57        qobject.setEnabled(old_state)
58
59
60def StyledWidget_paintEvent(self, event):
61    """A default styled QWidget subclass  paintEvent function.
62    """
63    opt = QStyleOption()
64    opt.init(self)
65    painter = QPainter(self)
66    self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)
67
68
69class StyledWidget(QWidget):
70    """
71    """
72    paintEvent = StyledWidget_paintEvent
73
74
75def is_transparency_supported():
76    """Is window transparency supported by the current windowing system.
77
78    """
79    if sys.platform == "win32":
80        return is_dwm_compositing_enabled()
81    elif sys.platform == "cygwin":
82        return False
83    elif sys.platform == "darwin":
84        try:
85            # Test if Qt was build against X11.
86            from PyQt4.QtGui import QX11Info
87            return QX11Info.isCompositingManagerRunning()
88        except ImportError:
89            # Assuming Quartz compositor is running.
90            return True
91    elif sys.platform.startswith("linux"):
92        # TODO: wayland??
93        return is_x11_compositing_enabled()
94    elif sys.platform.startswith("freebsd"):
95        return is_x11_compositing_enabled()
96    elif os.name == "":
97        # Any other system (Win, OSX) is assumed to support it
98        return True
99
100
101def is_x11_compositing_enabled():
102    """Is X11 compositing manager running.
103    """
104    try:
105        from PyQt4.QtGui import QX11Info
106    except ImportError:
107        return False
108
109    return QX11Info.isCompositingManagerRunning()
110
111
112def is_dwm_compositing_enabled():
113    """Is Desktop Window Manager compositing (Aero) enabled.
114    """
115    import ctypes
116
117    enabled = ctypes.c_bool()
118    try:
119        DwmIsCompositionEnabled = ctypes.windll.dwmapi.DwmIsCompositionEnabled
120    except AttributeError:
121        # dwmapi or DwmIsCompositionEnabled is not present
122        return False
123
124    rval = DwmIsCompositionEnabled(ctypes.byref(enabled))
125
126    return rval == 0 and enabled.value
127
128
129def gradient_darker(grad, factor):
130    """Return a copy of the QGradient darkened by factor.
131
132    .. note:: Only QLinearGradeint and QRadialGradient are supported.
133
134    """
135    if type(grad) is QGradient:
136        if grad.type() == QGradient.LinearGradient:
137            grad = sip.cast(grad, QLinearGradient)
138        elif grad.type() == QGradient.RadialGradient:
139            grad = sip.cast(grad, QRadialGradient)
140
141    if isinstance(grad, QLinearGradient):
142        new_grad = QLinearGradient(grad.start(), grad.finalStop())
143    elif isinstance(grad, QRadialGradient):
144        new_grad = QRadialGradient(grad.center(), grad.radius(),
145                                   grad.focalPoint())
146    else:
147        raise TypeError
148
149    new_grad.setCoordinateMode(grad.coordinateMode())
150
151    for pos, color in grad.stops():
152        new_grad.setColorAt(pos, color.darker(factor))
153
154    return new_grad
155
156
157def brush_darker(brush, factor):
158    """Return a copy of the brush darkened by factor.
159    """
160    grad = brush.gradient()
161    if grad:
162        return QBrush(gradient_darker(grad, factor))
163    else:
164        brush = QBrush(brush)
165        brush.setColor(brush.color().darker(factor))
166        return brush
167
168
169def message_critical(text, title=None, informative_text=None, details=None,
170                     buttons=None, default_button=None, exc_info=False,
171                     parent=None):
172    """Show a critical message.
173    """
174    if not text:
175        text = "An unexpected error occurred."
176
177    if title is None:
178        title = "Error"
179
180    return message(QMessageBox.Critical, text, title, informative_text,
181                   details, buttons, default_button, exc_info, parent)
182
183
184def message_warning(text, title=None, informative_text=None, details=None,
185                    buttons=None, default_button=None, exc_info=False,
186                    parent=None):
187    """Show a warning message.
188    """
189    if not text:
190        import random
191        text_candidates = ["Death could come at any moment.",
192                           "Murphy lurks about. Remember to save frequently."
193                           ]
194        text = random.choice(text_candidates)
195
196    if title is not None:
197        title = "Warning"
198
199    return message(QMessageBox.Warning, text, title, informative_text,
200                   details, buttons, default_button, exc_info, parent)
201
202
203def message_information(text, title=None, informative_text=None, details=None,
204                        buttons=None, default_button=None, exc_info=False,
205                        parent=None):
206    """Show an information message box.
207    """
208    if title is None:
209        title = "Information"
210    if not text:
211        text = "I am not a number."
212
213    return message(QMessageBox.Information, text, title, informative_text,
214                   details, buttons, default_button, exc_info, parent)
215
216
217def message_question(text, title, informative_text=None, details=None,
218                     buttons=None, default_button=None, exc_info=False,
219                     parent=None):
220    """Show an message box asking the user to select some
221    predefined course of action (set by buttons argument).
222
223    """
224    return message(QMessageBox.Question, text, title, informative_text,
225                   details, buttons, default_button, exc_info, parent)
226
227
228def message(icon, text, title=None, informative_text=None, details=None,
229            buttons=None, default_button=None, exc_info=False, parent=None):
230    """Show a message helper function.
231    """
232    if title is None:
233        title = "Message"
234    if not text:
235        text = "I am neither a postman nor a doctor."
236
237    if buttons is None:
238        buttons = QMessageBox.Ok
239
240    if details is None and exc_info:
241        details = traceback.format_exc(limit=20)
242
243    mbox = QMessageBox(icon, title, text, buttons, parent)
244
245    if informative_text:
246        mbox.setInformativeText(informative_text)
247
248    if details:
249        mbox.setDetailedText(details)
250
251    if default_button is not None:
252        mbox.setDefaultButton(default_button)
253
254    return mbox.exec_()
Note: See TracBrowser for help on using the repository browser.