source: orange/Orange/OrangeCanvas/main.py @ 11175:0b3c92e4cb52

Revision 11175:0b3c92e4cb52, 7.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 18 months ago (diff)

Ensure main window's layout can activate before blocking it with a modal dialog.

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