source: orange/Orange/OrangeCanvas/gui/utils.py @ 11208:b2091aba2a49

Revision 11208:b2091aba2a49, 7.0 KB checked in by Ales Erjavec <ales.erjavec@…>, 17 months ago (diff)

Moved widget actions definitions into SchemeEditWidget.

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