def __init__(self, title="Janus", splash=None): Object.__init__(self) QApplication.__init__(self, sys.argv) self.setApplicationName(title) self.janus.application = self self.path = os.path.realpath(os.path.dirname(sys.argv[0])) QDir.addSearchPath("icons", \ os.path.realpath(os.path.dirname(__file__)) + "/widgets/icons") self.splash = None if splash is not None: if os.access(self.path + splash, os.R_OK): self.splash = QPixmap(self.path + splash) self.janus.utils = dict() self.janus.devices = dict() self.janus.widgets = dict() self.janus.actions = dict() self.janus.controllers = dict() self.aboutToQuit.connect(self.on_exit)
def __init__(self, *args, **kwargs): config = args[1] pkg_root_dir = os.path.join(os.path.dirname(__file__), '..') icons_dir = os.path.join(pkg_root_dir, 'gui/assets/icons') QDir.addSearchPath('icons', icons_dir) QGuiApplication.setWindowIcon(QIcon(QPixmap('icons:feeluown.png'))) # Set desktopFileName so that the window icon is properly shown under wayland. # I don't know if this setting brings other benefits or not. # https://github.com/pyfa-org/Pyfa/issues/1607#issuecomment-392099878 QApplication.setDesktopFileName('FeelUOwn') QApplication.instance().setQuitOnLastWindowClosed( not config.ENABLE_TRAY) QApplication.instance().setApplicationName('FeelUOwn') QWidget.__init__(self) App.__init__(self, *args, **kwargs) GuiApp.__q_app = QApplication.instance() self.setObjectName('app') # GUI 的一些辅助管理模块 self.coll_mgr = CollectionManager(self) self.theme_mgr = ThemeManager(self) self.tips_mgr = TipsManager(self) self.hotkey_mgr = HotkeyManager(self) self.img_mgr = ImgManager(self) # GUI 组件的数据管理模块 self.pvd_uimgr = ProviderUiManager(self) self.pl_uimgr = PlaylistUiManager(self) self.mymusic_uimgr = MyMusicUiManager(self) self.coll_uimgr = CollectionUiManager(self) self.browser = Browser(self) self.ui = Ui(self) if self.config.ENABLE_TRAY: self.tray = Tray(self) self.show_msg = self.ui.toolbar.status_line.get_item( 'notify').widget.show_msg
def __init__ ( self ): assert ( EditorApp._singleton == None ) EditorApp._singleton = self QDir.addSearchPath ( "icons", ":/resources/icons" ) self.qtApp = QApplication ( [ '-graphicssystem', 'opengl' ] ) self.qtApp.setStyleSheet ( open ( '/Users/Kanbaru/GitWorkspace/CandyEditor/resources/theme/CryEngineVStyleSheet.qss' ).read () ) # self.qtApp.setStyleSheet ( open ( 'C:/Users/Administrator/OneDrive/文档/CandyEditor/resources/theme/CryEngineVStyleSheet.qss' ).read () ) # self.qtApp.setStyleSheet ( open ( 'D:/OneDrive/文档/CandyEditor/resources/theme/CryEngineVStyleSheet.qss' ).read () ) # Init game engine editorImpl = CEditorImpl () editorImpl.init () window = CEditorMainFrame ( None ) window.postLoad () window.show () window.raise_ () self.mainWindow = window sys.exit ( self.qtApp.exec_ () )
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ import os from pkg_resources import resource_filename, resource_string from PyQt5.QtGui import QPixmap, QIcon, QFontDatabase from PyQt5.QtSvg import QSvgWidget from PyQt5.QtCore import QDir # Add resource directories to the search path. QDir.addSearchPath('images', resource_filename(__name__, 'images')) QDir.addSearchPath('css', resource_filename(__name__, 'css')) def path(name: str, resource_dir: str = "images/") -> str: """ Return the filename for the referenced image. Qt uses unix path conventions. """ return resource_filename(__name__, resource_dir + name) def load_font(font_folder_name: str) -> None: directory = resource_filename(__name__, 'fonts/') + font_folder_name for filename in os.listdir(directory):
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ from pkg_resources import resource_filename, resource_string from PyQt5.QtGui import QPixmap, QIcon from PyQt5.QtCore import QDir # The following lines add the images and css directories to the search path. QDir.addSearchPath('images', resource_filename(__name__, 'images')) QDir.addSearchPath('css', resource_filename(__name__, 'css')) def path(name): """Return the filename for the referenced image.""" return resource_filename(__name__, "images/" + name) def load_icon(name): """Load an icon from the resources directory.""" return QIcon(path(name)) def load_pixmap(name): """Load a pixmap from the resources directory."""
(at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ from pkg_resources import resource_filename, resource_string from PyQt5.QtGui import QPixmap, QIcon from PyQt5.QtCore import QDir # The following lines add the images and css directories to the search path. QDir.addSearchPath("images", resource_filename(__name__, "images")) QDir.addSearchPath("css", resource_filename(__name__, "css")) def path(name, resource_dir="images/"): """Return the filename for the referenced image.""" return resource_filename(__name__, resource_dir + name) def load_icon(name): """Load an icon from the resources directory.""" return QIcon(path(name)) def load_pixmap(name): """Load a pixmap from the resources directory."""
from PyQt5.QtWidgets import QDialog except: from PyQt4 import QtGui, uic from PyQt4.QtCore import QDir from PyQt4.QtGui import QDialog try: from .fnc4ADXF2Shape import * except: from fnc4ADXF2Shape import * d = os.path.dirname(__file__) QDir.addSearchPath( "AnotherDXF2Shape", d ) uiAboutBase = uic.loadUiType( os.path.join( d, 'uiAbout.ui' ) )[0] FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'uiAbout.ui')) class uiAbout(QDialog, FORM_CLASS): def __init__(self, parent=None): super(uiAbout, self).__init__(parent)
def create_app(config): mode = config.MODE if mode & App.GuiMode: from PyQt5.QtCore import Qt, QDir from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtWidgets import QApplication, QWidget try: # HELP: QtWebEngineWidgets must be imported before a # QCoreApplication instance is created # TODO: add a command line option to control this import import PyQt5.QtWebEngineWidgets # noqa except ImportError: logger.info('import QtWebEngineWidgets failed') from feeluown.utils.compat import QEventLoop pkg_root_dir = os.path.dirname(__file__) icons_dir = os.path.join(pkg_root_dir, 'icons') q_app = QApplication(sys.argv) QDir.addSearchPath('icons', icons_dir) q_app.setQuitOnLastWindowClosed(not config.ENABLE_TRAY) q_app.setApplicationName('FeelUOwn') app_event_loop = QEventLoop(q_app) asyncio.set_event_loop(app_event_loop) class GuiApp(QWidget): mode = App.GuiMode def __init__(self): super().__init__() self.setObjectName('app') QApplication.setWindowIcon(QIcon( QPixmap('icons:feeluown.png'))) def closeEvent(self, _): if not self.config.ENABLE_TRAY: self.exit() def mouseReleaseEvent(self, e): if not self.rect().contains(e.pos()): return if e.button() == Qt.BackButton: self.browser.back() elif e.button() == Qt.ForwardButton: self.browser.forward() class FApp(App, GuiApp): def __init__(self, config): App.__init__(self, config) GuiApp.__init__(self) def exit_player(self): # If mpv use render api to show video, we should # free resource explicitly if not self.player.use_opengl_cb: mpv_render_ctx = self.ui.mpv_widget.ctx if mpv_render_ctx is not None: mpv_render_ctx.free() self.ui.mpv_widget.close() self.player.shutdown() def exit(self): QApplication.exit() else: FApp = App Signal.setup_aio_support() Resolver.setup_aio_support() app = FApp(config) attach_attrs(app) if mode & App.GuiMode: q_app.aboutToQuit.connect(app.about_to_exit) Resolver.library = app.library return app
from PyQt5.QtWidgets import QDialog except: from PyQt4 import QtGui, uic from PyQt4.QtCore import QDir from PyQt4.QtGui import QDialog try: from .fnc4ADXF2Shape import * except: from fnc4ADXF2Shape import * d = os.path.dirname(__file__) QDir.addSearchPath( "AnotherDXF2Shape", d ) uiAboutBase = uic.loadUiType( os.path.join( d, 'uiAbout.ui' ) )[0] FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'uiAbout.ui')) class uiAbout(QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(uiAbout, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect
def main(argv=None): # PREVENTS MESSAGING FROM THREADING PROBLEMS IN MATPLOTLIB: # The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec(). # Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug. # # This problem cause the continous appearing of Popup Windows "Python Quit Unexpectedly", with no reason. # if platform.system() == "Darwin": crash_report = os.popen( "defaults read com.apple.CrashReporter DialogType").read().strip() os.system("defaults write com.apple.CrashReporter DialogType none") try: if argv is None: argv = sys.argv usage = "usage: %prog [options] [workflow_file]" parser = optparse.OptionParser(usage=usage) parser.add_option("--no-discovery", action="store_true", help="Don't run widget discovery " "(use full cache instead)") parser.add_option("--force-discovery", action="store_true", help="Force full widget discovery " "(invalidate cache)") parser.add_option("--clear-widget-settings", action="store_true", help="Remove stored widget setting") parser.add_option("--no-welcome", action="store_true", help="Don't show welcome dialog.") parser.add_option("--no-splash", action="store_true", help="Don't show splash screen.") parser.add_option("-l", "--log-level", help="Logging level (0, 1, 2, 3, 4)", type="int", default=1) parser.add_option( "--no-redirect", action="store_true", help="Do not redirect stdout/err to canvas output view.") parser.add_option("--style", help="QStyle to use", type="str", default="Fusion") parser.add_option("--stylesheet", help="Application level CSS style sheet to use", type="str", default="orange.qss") parser.add_option("--qt", help="Additional arguments for QApplication", type="str", default=None) (options, args) = parser.parse_args(argv[1:]) levels = [ logging.CRITICAL, logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG ] # Fix streams before configuring logging (otherwise it will store # and write to the old file descriptors) fix_win_pythonw_std_stream() # Try to fix fonts on OSX Mavericks fix_osx_10_9_private_font() # File handler should always be at least INFO level so we need # the application root level to be at least at INFO. root_level = min(levels[options.log_level], logging.INFO) rootlogger = logging.getLogger(orangecanvas.__name__) rootlogger.setLevel(root_level) oasyslogger = logging.getLogger("oasys") oasyslogger.setLevel(root_level) # Standard output stream handler at the requested level stream_handler = logging.StreamHandler() stream_handler.setLevel(level=levels[options.log_level]) rootlogger.addHandler(stream_handler) oasyslogger.addHandler(stream_handler) config.set_default(conf.oasysconf) log.info("Starting 'OASYS' application.") qt_argv = argv[:1] # if options.style is not None: qt_argv += ["-style", options.style] if options.qt is not None: qt_argv += shlex.split(options.qt) qt_argv += args if options.clear_widget_settings: log.debug("Clearing widget settings") shutil.rmtree(config.widget_settings_dir(), ignore_errors=True) log.debug("Starting CanvasApplicaiton with argv = %r.", qt_argv) app = CanvasApplication(qt_argv) # NOTE: config.init() must be called after the QApplication constructor config.init() file_handler = logging.FileHandler(filename=os.path.join( config.log_dir(), "canvas.log"), mode="w") file_handler.setLevel(root_level) rootlogger.addHandler(file_handler) # intercept any QFileOpenEvent requests until the main window is # fully initialized. # NOTE: The QApplication must have the executable ($0) and filename # arguments passed in argv otherwise the FileOpen events are # triggered for them (this is done by Cocoa, but QApplicaiton filters # them out if passed in argv) open_requests = [] def onrequest(url): log.info("Received an file open request %s", url) open_requests.append(url) app.fileOpenRequest.connect(onrequest) settings = QSettings() stylesheet = options.stylesheet stylesheet_string = None if stylesheet != "none": if os.path.isfile(stylesheet): stylesheet_string = open(stylesheet, "rb").read() else: if not os.path.splitext(stylesheet)[1]: # no extension stylesheet = os.path.extsep.join([stylesheet, "qss"]) pkg_name = orangecanvas.__name__ resource = "styles/" + stylesheet if pkg_resources.resource_exists(pkg_name, resource): stylesheet_string = \ pkg_resources.resource_string(pkg_name, resource).decode() base = pkg_resources.resource_filename(pkg_name, "styles") pattern = re.compile( r"^\s@([a-zA-Z0-9_]+?)\s*:\s*([a-zA-Z0-9_/]+?);\s*$", flags=re.MULTILINE) matches = pattern.findall(stylesheet_string) for prefix, search_path in matches: QDir.addSearchPath(prefix, os.path.join(base, search_path)) log.info("Adding search path %r for prefix, %r", search_path, prefix) stylesheet_string = pattern.sub("", stylesheet_string) else: log.info("%r style sheet not found.", stylesheet) # Add the default canvas_icons search path dirpath = os.path.abspath(os.path.dirname(orangecanvas.__file__)) QDir.addSearchPath("canvas_icons", os.path.join(dirpath, "icons")) canvas_window = OASYSMainWindow() canvas_window.setWindowIcon(config.application_icon()) if stylesheet_string is not None: canvas_window.setStyleSheet(stylesheet_string) if not options.force_discovery: reg_cache = cache.registry_cache() else: reg_cache = None widget_registry = qt.QtWidgetRegistry() widget_discovery = config.widget_discovery( widget_registry, cached_descriptions=reg_cache) menu_registry = conf.menu_registry() want_splash = \ settings.value("startup/show-splash-screen", True, type=bool) and \ not options.no_splash if want_splash: pm, rect = config.splash_screen() splash_screen = SplashScreen(pixmap=pm, textRect=rect) splash_screen.setFont(QFont("Helvetica", 12)) color = QColor("#FFD39F") def show_message(message): splash_screen.showMessage(message, color=color) widget_registry.category_added.connect(show_message) log.info("Running widget discovery process.") cache_filename = os.path.join(config.cache_dir(), "widget-registry.pck") if options.no_discovery: widget_registry = pickle.load(open(cache_filename, "rb")) widget_registry = qt.QtWidgetRegistry(widget_registry) else: if want_splash: splash_screen.show() widget_discovery.run(config.widgets_entry_points()) if want_splash: splash_screen.hide() splash_screen.deleteLater() # Store cached descriptions cache.save_registry_cache(widget_discovery.cached_descriptions) with open(cache_filename, "wb") as f: pickle.dump(WidgetRegistry(widget_registry), f) set_global_registry(widget_registry) canvas_window.set_widget_registry(widget_registry) canvas_window.set_menu_registry(menu_registry) # automatic save automatic_saver_thread = QThread() automatic_saver = SaveWorkspaceObj(canvas_window, ) automatic_saver.moveToThread(automatic_saver_thread) automatic_saver.finished.connect(automatic_saver_thread.quit) automatic_saver_thread.started.connect(automatic_saver.long_running) automatic_saver_thread.finished.connect(app.exit) automatic_saver_thread.start() canvas_window.show() canvas_window.raise_() want_welcome = True or \ settings.value("startup/show-welcome-screen", True, type=bool) \ and not options.no_welcome app.setStyle(QStyleFactory.create('Fusion')) #app.setStyle(QStyleFactory.create('Macintosh')) #app.setStyle(QStyleFactory.create('Windows')) # Process events to make sure the canvas_window layout has # a chance to activate (the welcome dialog is modal and will # block the event queue, plus we need a chance to receive open file # signals when running without a splash screen) app.processEvents() app.fileOpenRequest.connect(canvas_window.open_scheme_file) close_app = False if open_requests: if "pydevd.py" in str( open_requests[0].path()): # PyCharm Debugger on open_requests = [] if want_welcome and not args and not open_requests: if not canvas_window.welcome_dialog(): log.info("Welcome screen cancelled; closing application") close_app = True elif args: log.info("Loading a scheme from the command line argument %r", args[0]) canvas_window.load_scheme(args[0]) elif open_requests: log.info("Loading a scheme from an `QFileOpenEvent` for %r", open_requests[-1]) canvas_window.load_scheme(open_requests[-1].toLocalFile()) stdout_redirect = \ settings.value("output/redirect-stdout", True, type=bool) stderr_redirect = \ settings.value("output/redirect-stderr", True, type=bool) # cmd line option overrides settings / no redirect is possible # under ipython if options.no_redirect or running_in_ipython(): stderr_redirect = stdout_redirect = False output_view = canvas_window.output_view() if stdout_redirect: stdout = TextStream() stdout.stream.connect(output_view.write) if sys.stdout is not None: # also connect to original fd stdout.stream.connect(sys.stdout.write) else: stdout = sys.stdout if stderr_redirect: error_writer = output_view.formated(color=Qt.red) stderr = TextStream() stderr.stream.connect(error_writer.write) if sys.stderr is not None: # also connect to original fd stderr.stream.connect(sys.stderr.write) else: stderr = sys.stderr if stderr_redirect: sys.excepthook = ExceptHook() sys.excepthook.handledException.connect(output_view.parent().show) if not close_app: with redirect_stdout(stdout), redirect_stderr(stderr): log.info("Entering main event loop.") try: status = app.exec_() except BaseException: log.error("Error in main event loop.", exc_info=True) canvas_window.deleteLater() app.processEvents() app.flush() del canvas_window else: status = False if automatic_saver_thread.isRunning(): automatic_saver_thread.deleteLater() # Collect any cycles before deleting the QApplication instance gc.collect() del app # RESTORE INITIAL USER SETTINGS if platform.system() == "Darwin": os.system("defaults write com.apple.CrashReporter DialogType " + crash_report) return status except Exception as e: # RESTORE INITIAL USER SETTINGS if platform.system() == "Darwin": os.system("defaults write com.apple.CrashReporter DialogType " + crash_report) raise e
# This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # See http://www.gnu.org/licenses/ for more information. """ Resources for styling some widgets. """ from PyQt5.QtCore import QDir QDir.addSearchPath('css', __path__[0]) lcd_screen = """ * { border-width: 4 3 2 4; border-image: url('css:lcd-borders.png') repeat; background-image: url('css:lcd-background.png') repeat; color: #151B19; } """
from PyQt5.QtCore import QDir from PyQt5.QtWidgets import QDialog except: from PyQt4 import QtGui, uic from PyQt4.QtCore import QDir from PyQt4.QtGui import QDialog try: from fnc4all import * from fnc4CaigosConnector import * except: from .fnc4all import * from .fnc4CaigosConnector import * d = os.path.dirname(__file__) QDir.addSearchPath( "CaigosConnector", d ) uiAboutBase = uic.loadUiType( os.path.join( d, 'uiAbout.ui' ) )[0] FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'uiAbout.ui')) class uiAbout(QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(uiAbout, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect
# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # See http://www.gnu.org/licenses/ for more information. """ Resources for styling some widgets. """ from PyQt5.QtCore import QDir QDir.addSearchPath('css', __path__[0]) lcd_screen = """ * { border-width: 4 3 2 4; border-image: url('css:lcd-borders.png') repeat; background-image: url('css:lcd-background.png') repeat; color: #151B19; } """
from PyQt5.QtCore import QDir from PyQt5.QtWidgets import QDialog except: from PyQt4 import QtGui, uic from PyQt4.QtCore import QDir from PyQt4.QtGui import QDialog try: from fnc4all import * from fnc4SaxonyCadastralParcels import * except: from .fnc4all import * from .fnc4SaxonyCadastralParcels import * d = os.path.dirname(__file__) QDir.addSearchPath("SaxonyCadastralParcels", d) uiAboutBase = uic.loadUiType(os.path.join(d, 'uiAbout.ui'))[0] FORM_CLASS, _ = uic.loadUiType( os.path.join(os.path.dirname(__file__), 'uiAbout.ui')) class uiAbout(QDialog, FORM_CLASS): def __init__(self, parent=None): super(uiAbout, self).__init__(parent) self.setupUi(self) s = self.lblLink.text() s = s.replace(
def main(argv=None): if argv is None: argv = sys.argv usage = "usage: %prog [options] [workflow_file]" parser = optparse.OptionParser(usage=usage) parser.add_option("--no-discovery", action="store_true", help="Don't run widget discovery " "(use full cache instead)") parser.add_option("--force-discovery", action="store_true", help="Force full widget discovery " "(invalidate cache)") parser.add_option("--clear-widget-settings", action="store_true", help="Remove stored widget setting") parser.add_option("--no-welcome", action="store_true", help="Don't show welcome dialog.") parser.add_option("--no-splash", action="store_true", help="Don't show splash screen.") parser.add_option("-l", "--log-level", help="Logging level (0, 1, 2, 3, 4)", type="int", default=1) parser.add_option("--no-redirect", action="store_true", help="Do not redirect stdout/err to canvas output view.") parser.add_option("--style", help="QStyle to use", type="str", default=None) parser.add_option("--stylesheet", help="Application level CSS style sheet to use", type="str", default="orange.qss") parser.add_option("--qt", help="Additional arguments for QApplication", type="str", default=None) parser.add_option("--config", help="Configuration namespace", type="str", default="orangecanvas.example") # -m canvas orange.widgets # -m canvas --config orange.widgets (options, args) = parser.parse_args(argv[1:]) levels = [ logging.CRITICAL, logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG ] # Fix streams before configuring logging (otherwise it will store # and write to the old file descriptors) fix_win_pythonw_std_stream() # Try to fix fonts on OSX Mavericks/Yosemite, ... fix_osx_private_font() # File handler should always be at least INFO level so we need # the application root level to be at least at INFO. root_level = min(levels[options.log_level], logging.INFO) rootlogger = logging.getLogger(__package__) rootlogger.setLevel(root_level) # Standard output stream handler at the requested level stream_hander = logging.StreamHandler() stream_hander.setLevel(level=levels[options.log_level]) rootlogger.addHandler(stream_hander) if options.config is not None: try: cfg = utils.name_lookup(options.config) except (ImportError, AttributeError): pass else: # config.default = cfg config.set_default(cfg) log.info("activating %s", options.config) log.info("Starting 'Orange Canvas' application.") qt_argv = argv[:1] if options.style is not None: qt_argv += ["-style", options.style] if options.qt is not None: qt_argv += shlex.split(options.qt) qt_argv += args if options.clear_widget_settings: log.debug("Clearing widget settings") shutil.rmtree(config.widget_settings_dir(), ignore_errors=True) log.debug("Starting CanvasApplicaiton with argv = %r.", qt_argv) app = CanvasApplication(qt_argv) # NOTE: config.init() must be called after the QApplication constructor config.init() file_handler = logging.FileHandler(filename=os.path.join( config.log_dir(), "canvas.log"), mode="w") file_handler.setLevel(root_level) rootlogger.addHandler(file_handler) # intercept any QFileOpenEvent requests until the main window is # fully initialized. # NOTE: The QApplication must have the executable ($0) and filename # arguments passed in argv otherwise the FileOpen events are # triggered for them (this is done by Cocoa, but QApplicaiton filters # them out if passed in argv) open_requests = [] def onrequest(url): log.info("Received an file open request %s", url) open_requests.append(url) app.fileOpenRequest.connect(onrequest) settings = QSettings() stylesheet = options.stylesheet stylesheet_string = None if stylesheet != "none": if os.path.isfile(stylesheet): stylesheet_string = io.open(stylesheet, "r").read() else: if not os.path.splitext(stylesheet)[1]: # no extension stylesheet = os.path.extsep.join([stylesheet, "qss"]) pkg_name = __package__ resource = "styles/" + stylesheet if pkg_resources.resource_exists(pkg_name, resource): stylesheet_string = \ pkg_resources.resource_string(pkg_name, resource).decode("utf-8") base = pkg_resources.resource_filename(pkg_name, "styles") pattern = re.compile( r"^\s@([a-zA-Z0-9_]+?)\s*:\s*([a-zA-Z0-9_/]+?);\s*$", flags=re.MULTILINE) matches = pattern.findall(stylesheet_string) for prefix, search_path in matches: QDir.addSearchPath(prefix, os.path.join(base, search_path)) log.info("Adding search path %r for prefix, %r", search_path, prefix) stylesheet_string = pattern.sub("", stylesheet_string) else: log.info("%r style sheet not found.", stylesheet) # Add the default canvas_icons search path dirpath = os.path.abspath(os.path.dirname(__file__)) QDir.addSearchPath("canvas_icons", os.path.join(dirpath, "icons")) canvas_window = CanvasMainWindow() canvas_window.setWindowIcon(config.application_icon()) if stylesheet_string is not None: canvas_window.setStyleSheet(stylesheet_string) if not options.force_discovery: reg_cache = cache.registry_cache() else: reg_cache = None widget_registry = qt.QtWidgetRegistry() widget_discovery = config.widget_discovery(widget_registry, cached_descriptions=reg_cache) want_splash = \ settings.value("startup/show-splash-screen", True, type=bool) and \ not options.no_splash if want_splash: pm, rect = config.splash_screen() splash_screen = SplashScreen(pixmap=pm, textRect=rect) splash_screen.setAttribute(Qt.WA_DeleteOnClose) splash_screen.setFont(QFont("Helvetica", 12)) color = QColor("#FFD39F") def show_message(message): splash_screen.showMessage(message, color=color) widget_registry.category_added.connect(show_message) show_splash = splash_screen.show close_splash = splash_screen.close else: show_splash = close_splash = lambda: None log.info("Running widget discovery process.") cache_filename = os.path.join(config.cache_dir(), "widget-registry.pck") if options.no_discovery: widget_registry = pickle.load(open(cache_filename, "rb")) widget_registry = qt.QtWidgetRegistry(widget_registry) else: show_splash() widget_discovery.run(config.widgets_entry_points()) close_splash() # Store cached descriptions cache.save_registry_cache(widget_discovery.cached_descriptions) with open(cache_filename, "wb") as f: pickle.dump(WidgetRegistry(widget_registry), f) set_global_registry(widget_registry) canvas_window.set_widget_registry(widget_registry) canvas_window.show() canvas_window.raise_() want_welcome = \ settings.value("startup/show-welcome-screen", True, type=bool) \ and not options.no_welcome # Process events to make sure the canvas_window layout has # a chance to activate (the welcome dialog is modal and will # block the event queue, plus we need a chance to receive open file # signals when running without a splash screen) app.processEvents() app.fileOpenRequest.connect(canvas_window.open_scheme_file) if want_welcome and not args and not open_requests: canvas_window.welcome_dialog() elif args: log.info("Loading a scheme from the command line argument %r", args[0]) canvas_window.load_scheme(args[0]) elif open_requests: log.info("Loading a scheme from an `QFileOpenEvent` for %r", open_requests[-1]) canvas_window.load_scheme(open_requests[-1].toLocalFile()) stdout_redirect = \ settings.value("output/redirect-stdout", True, type=bool) stderr_redirect = \ settings.value("output/redirect-stderr", True, type=bool) # cmd line option overrides settings / no redirect is possible # under ipython if options.no_redirect or running_in_ipython(): stderr_redirect = stdout_redirect = False output_view = canvas_window.output_view() if stdout_redirect: stdout = TextStream() stdout.stream.connect(output_view.write) if sys.stdout is not None: # also connect to original fd stdout.stream.connect(sys.stdout.write) else: stdout = sys.stdout if stderr_redirect: error_writer = output_view.formated(color=Qt.red) stderr = TextStream() stderr.stream.connect(error_writer.write) if sys.stderr is not None: # also connect to original fd stderr.stream.connect(sys.stderr.write) else: stderr = sys.stderr if stderr_redirect: sys.excepthook = ExceptHook() sys.excepthook.handledException.connect(output_view.parent().show) with ExitStack() as stack: stack.enter_context(redirect_stdout(stdout)) stack.enter_context(redirect_stderr(stderr)) log.info("Entering main event loop.") try: status = app.exec_() except BaseException: log.error("Error in main event loop.", exc_info=True) canvas_window.deleteLater() app.processEvents() app.flush() del canvas_window # Collect any cycles before deleting the QApplication instance gc.collect() del app return status