source: orange/Orange/OrangeCanvas/main.py @ 11299:0d7f328b766a

Revision 11299:0d7f328b766a, 9.0 KB checked in by Ales Erjavec <ales.erjavec@…>, 15 months ago (diff)

PyQt4 < 4.8.3 QSettings compatibility class (type parameter for value method).

Always use the type parameter instead of QVariant transformations.

Line 
1"""
2Orange Canvas main entry point
3
4"""
5
6import os
7import sys
8import gc
9import re
10import logging
11import optparse
12import cPickle
13from contextlib import nested
14
15import pkg_resources
16
17from PyQt4.QtGui import QFont, QColor
18from PyQt4.QtCore import Qt, QRect, QDir
19
20from Orange import OrangeCanvas
21from Orange.OrangeCanvas.application.application import CanvasApplication
22from Orange.OrangeCanvas.application.canvasmain import CanvasMainWindow
23from Orange.OrangeCanvas.application.outputview import TextStream, ExceptHook
24
25from Orange.OrangeCanvas.gui.splashscreen import SplashScreen, QPixmap
26from Orange.OrangeCanvas.config import cache_dir
27from Orange.OrangeCanvas import config
28from Orange.OrangeCanvas.utils.redirect import redirect_stdout, redirect_stderr
29from Orange.OrangeCanvas.utils.qtcompat import QSettings
30
31from Orange.OrangeCanvas.registry import qt
32from Orange.OrangeCanvas.registry import WidgetRegistry, set_global_registry
33from Orange.OrangeCanvas.registry import cache
34
35log = logging.getLogger(__name__)
36
37
38def running_in_ipython():
39    try:
40        __IPYTHON__
41        return True
42    except NameError:
43        return False
44
45
46def main(argv=None):
47    if argv is None:
48        argv = sys.argv[1:]
49
50    usage = "usage: %prog [options] [scheme_file]"
51    parser = optparse.OptionParser(usage=usage)
52
53    parser.add_option("--no-discovery",
54                      action="store_true",
55                      help="Don't run widget discovery "
56                           "(use full cache instead)")
57
58    parser.add_option("--force-discovery",
59                      action="store_true",
60                      help="Force full widget discovery "
61                           "(invalidate cache)")
62    parser.add_option("--no-welcome",
63                      action="store_true",
64                      help="Don't show welcome dialog.")
65    parser.add_option("--no-splash",
66                      action="store_true",
67                      help="Don't show splash screen.")
68    parser.add_option("-l", "--log-level",
69                      help="Logging level (0, 1, 2, 3, 4)",
70                      type="int", default=1)
71    parser.add_option("--no-redirect",
72                      action="store_true",
73                      help="Do not redirect stdout/err to canvas output view.")
74    parser.add_option("--style",
75                      help="QStyle to use",
76                      type="str", default=None)
77    parser.add_option("--stylesheet",
78                      help="Application level CSS style sheet to use",
79                      type="str", default="orange.qss")
80    parser.add_option("--qt",
81                      help="Additional arguments for QApplication",
82                      type="str", default=None)
83
84    (options, args) = parser.parse_args(argv)
85
86    levels = [logging.CRITICAL,
87              logging.ERROR,
88              logging.WARN,
89              logging.INFO,
90              logging.DEBUG]
91
92    logging.basicConfig(level=levels[options.log_level])
93
94    log.info("Starting 'Orange Canvas' application.")
95
96    qt_argv = ["orange-canvas"]
97
98    if options.style is not None:
99        qt_argv += ["-style", options.style]
100
101    if options.qt is not None:
102        qt_argv += options.qt.split()
103
104    log.debug("Starting CanvasApplicaiton with argv = %r.", qt_argv)
105    app = CanvasApplication(qt_argv)
106
107    # Note: config.init must be called after the QApplication constructor
108    config.init()
109    settings = QSettings()
110
111    stylesheet = options.stylesheet
112    stylesheet_string = None
113
114    if stylesheet != "none":
115        if os.path.isfile(stylesheet):
116            stylesheet_string = open(stylesheet, "rb").read()
117        else:
118            if not os.path.splitext(stylesheet)[1]:
119                # no extension
120                stylesheet = os.path.extsep.join([stylesheet, "qss"])
121
122            pkg_name = OrangeCanvas.__name__
123            resource = "styles/" + stylesheet
124
125            if pkg_resources.resource_exists(pkg_name, resource):
126                stylesheet_string = \
127                    pkg_resources.resource_string(pkg_name, resource)
128
129                base = pkg_resources.resource_filename(pkg_name, "styles")
130
131                pattern = re.compile(
132                    r"^\s@([a-zA-Z0-9_]+?)\s*:\s*([a-zA-Z0-9_/]+?);\s*$",
133                    flags=re.MULTILINE
134                )
135
136                matches = pattern.findall(stylesheet_string)
137
138                for prefix, search_path in matches:
139                    QDir.addSearchPath(prefix, os.path.join(base, search_path))
140                    log.info("Adding search path %r for prefix, %r",
141                             search_path, prefix)
142
143                stylesheet_string = pattern.sub("", stylesheet_string)
144
145            else:
146                log.info("%r style sheet not found.", stylesheet)
147
148    if stylesheet_string is not None:
149        app.setStyleSheet(stylesheet_string)
150
151    # Add the default canvas_icons search path
152    dirpath = os.path.abspath(os.path.dirname(OrangeCanvas.__file__))
153    QDir.addSearchPath("canvas_icons", os.path.join(dirpath, "icons"))
154
155    canvas_window = CanvasMainWindow()
156    canvas_window.resize(1024, 650)
157
158    if not options.force_discovery:
159        reg_cache = cache.registry_cache()
160    else:
161        reg_cache = None
162
163    widget_discovery = qt.QtWidgetDiscovery(cached_descriptions=reg_cache)
164
165    widget_registry = qt.QtWidgetRegistry()
166
167    widget_discovery.found_category.connect(
168        widget_registry.register_category
169    )
170    widget_discovery.found_widget.connect(
171        widget_registry.register_widget
172    )
173
174    want_splash = \
175        settings.value("startup/show-splash-screen", True, type=bool) and \
176        not options.no_splash
177
178    if want_splash:
179        pm = QPixmap(pkg_resources.resource_filename(
180                        __name__, "icons/orange-splash-screen.png")
181                     )
182        # Text rectangle in which to fit the message.
183        rect = QRect(88, 193, 200, 20)
184        splash_screen = SplashScreen(pixmap=pm, textRect=rect)
185        splash_screen.setFont(QFont("Helvetica", 12))
186        color = QColor("#FFD39F")
187
188        def show_message(message):
189            splash_screen.showMessage(message, color=color)
190
191        widget_discovery.discovery_start.connect(splash_screen.show)
192        widget_discovery.discovery_process.connect(show_message)
193        widget_discovery.discovery_finished.connect(splash_screen.hide)
194
195    log.info("Running widget discovery process.")
196
197    cache_filename = os.path.join(cache_dir(), "widget-registry.pck")
198    if options.no_discovery:
199        widget_registry = cPickle.load(open(cache_filename, "rb"))
200        widget_registry = qt.QtWidgetRegistry(widget_registry)
201    else:
202        widget_discovery.run(config.widgets_entry_points())
203        # Store cached descriptions
204        cache.save_registry_cache(widget_discovery.cached_descriptions)
205        cPickle.dump(WidgetRegistry(widget_registry),
206                     open(cache_filename, "wb"))
207    set_global_registry(widget_registry)
208    canvas_window.set_widget_registry(widget_registry)
209    canvas_window.show()
210
211    want_welcome = \
212        settings.value("startup/show-welcome-screen", True, type=bool) \
213        and not options.no_welcome
214
215    canvas_window.raise_()
216
217    if want_welcome and not args:
218        # Process events to make sure the canvas_window layout has
219        # a chance to activate (the welcome dialog is modal and will
220        # block the event queue)
221        app.processEvents()
222        canvas_window.welcome_dialog()
223
224    elif args:
225        log.info("Loading a scheme from the command line argument %r",
226                 args[0])
227        canvas_window.load_scheme(args[0])
228
229    stdout_redirect = \
230        settings.value("output/redirect-stdout", True, type=bool)
231
232    stderr_redirect = \
233        settings.value("output/redirect-stderr", True, type=bool)
234
235    # cmd line option overrides settings / no redirect is possible
236    # under ipython
237    if options.no_redirect or running_in_ipython():
238        stderr_redirect = stdout_redirect = False
239
240    output_view = canvas_window.output_view()
241
242    if stdout_redirect:
243        stdout = TextStream()
244        stdout.stream.connect(output_view.write)
245        # also connect to original fd
246        stdout.stream.connect(sys.stdout.write)
247    else:
248        stdout = sys.stdout
249
250    if stderr_redirect:
251        error_writer = output_view.formated(color=Qt.red)
252        stderr = TextStream()
253        stderr.stream.connect(error_writer.write)
254        # also connect to original fd
255        stderr.stream.connect(sys.stderr.write)
256    else:
257        stderr = sys.stderr
258
259    if stderr_redirect:
260        sys.excepthook = ExceptHook()
261        sys.excepthook.handledException.connect(output_view.parent().show)
262
263    with nested(redirect_stdout(stdout), redirect_stderr(stderr)):
264        log.info("Entering main event loop.")
265        try:
266            status = app.exec_()
267        except BaseException:
268            log.error("Error in main event loop.", exc_info=True)
269
270    canvas_window.deleteLater()
271    app.processEvents()
272    app.flush()
273    del canvas_window
274
275    # Collect any cycles before deleting the QApplication instance
276    gc.collect()
277
278    del app
279    return status
280
281
282if __name__ == "__main__":
283    sys.exit(main())
Note: See TracBrowser for help on using the repository browser.