# -*- coding: utf-8 -*- # # Copyright © 2009-2011 Pierre Raybaut # Licensed under the terms of the MIT License # (copied from Spyder source code [spyderlib.qt]) # # Qt5 migration would not have been possible without # 2014-2015 Spyder Development Team work # (MIT License too, same parent project) """Qt utilities""" # winpython.qt becomes winpython._vendor.qtpy from winpython._vendor.qtpy.QtWidgets import (QAction, QStyle, QWidget, QApplication, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QMenu, QToolButton) from winpython._vendor.qtpy.QtGui import (QIcon, QKeyEvent, QKeySequence, QPixmap) from winpython._vendor.qtpy.QtCore import (Signal, QObject, Qt, QLocale, QTranslator, QLibraryInfo, QEvent, Slot) from winpython._vendor.qtpy.compat import to_qvariant, from_qvariant import os import re import os.path as osp import sys # Local import from winpython import config from winpython.py3compat import is_text_string, to_text_string def get_icon(name): """Return QIcon from icon name""" return QIcon(osp.join(config.IMAGE_PATH, name)) class MacApplication(QApplication): """Subclass to be able to open external files with our Mac app""" open_external_file = Signal(str) def __init__(self, *args): QApplication.__init__(self, *args) def event(self, event): if event.type() == QEvent.FileOpen: fname = str(event.file()) # PyQt4 old SIGNAL: self.emit(SIGNAL('open_external_file(QString)'), fname) self.open_external_file.emit(fname) return QApplication.event(self, event) def qapplication(translate=True): """Return QApplication instance Creates it if it doesn't already exist""" if sys.platform == "darwin" and 'Spyder.app' in __file__: SpyderApplication = MacApplication else: SpyderApplication = QApplication app = SpyderApplication.instance() if not app: # Set Application name for Gnome 3 # https://groups.google.com/forum/#!topic/pyside/24qxvwfrRDs app = SpyderApplication(['Spyder']) if translate: install_translator(app) return app def file_uri(fname): """Select the right file uri scheme according to the operating system""" if os.name == 'nt': # Local file if re.search(r'^[a-zA-Z]:', fname): return 'file:///' + fname # UNC based path else: return 'file://' + fname else: return 'file://' + fname QT_TRANSLATOR = None def install_translator(qapp): """Install Qt translator to the QApplication instance""" global QT_TRANSLATOR if QT_TRANSLATOR is None: qt_translator = QTranslator() if qt_translator.load("qt_"+QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath)): QT_TRANSLATOR = qt_translator # Keep reference alive if QT_TRANSLATOR is not None: qapp.installTranslator(QT_TRANSLATOR) def keybinding(attr): """Return keybinding""" ks = getattr(QKeySequence, attr) return from_qvariant(QKeySequence.keyBindings(ks)[0], str) def _process_mime_path(path, extlist): if path.startswith(r"file://"): if os.name == 'nt': # On Windows platforms, a local path reads: file:///c:/... # and a UNC based path reads like: file://server/share if path.startswith(r"file:///"): # this is a local path path = path[8:] else: # this is a unc path path = path[5:] else: path = path[7:] if osp.exists(path): if extlist is None or osp.splitext(path)[1] in extlist: return path def mimedata2url(source, extlist=None): """ Extract url list from MIME data extlist: for example ('.py', '.pyw') """ pathlist = [] if source.hasUrls(): for url in source.urls(): path = _process_mime_path(to_text_string(url.toString()), extlist) if path is not None: pathlist.append(path) elif source.hasText(): for rawpath in to_text_string(source.text()).splitlines(): path = _process_mime_path(rawpath, extlist) if path is not None: pathlist.append(path) if pathlist: return pathlist def action2button(action, autoraise=True, text_beside_icon=False, parent=None): """Create a QToolButton directly from a QAction object""" if parent is None: parent = action.parent() button = QToolButton(parent) button.setDefaultAction(action) button.setAutoRaise(autoraise) if text_beside_icon: button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) return button def toggle_actions(actions, enable): """Enable/disable actions""" if actions is not None: for action in actions: if action is not None: action.setEnabled(enable) def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction""" action = QAction(text, parent) if triggered is not None: # PyQt4 old SIGNAL: parent.connect(action, SIGNAL("triggered()"), triggered) action.triggered.connect(triggered) if toggled is not None: # PyQt4 old SIGNAL: parent.connect(action, SIGNAL("toggled(bool)"), toggled) action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: if is_text_string(icon): icon = get_icon(icon) action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) # TODO: Hard-code all shortcuts and choose context=Qt.WidgetShortcut # (this will avoid calling shortcuts from another dockwidget # since the context thing doesn't work quite well with these widgets) action.setShortcutContext(context) return action def add_actions(target, actions, insert_before=None): """Add actions to a menu""" previous_action = None target_actions = list(target.actions()) if target_actions: previous_action = target_actions[-1] if previous_action.isSeparator(): previous_action = None for action in actions: if (action is None) and (previous_action is not None): if insert_before is None: target.addSeparator() else: target.insertSeparator(insert_before) elif isinstance(action, QMenu): if insert_before is None: target.addMenu(action) else: target.insertMenu(insert_before, action) elif isinstance(action, QAction): if insert_before is None: target.addAction(action) else: target.insertAction(insert_before, action) previous_action = action def get_std_icon(name, size=None): """Get standard platform icon Call 'show_std_icons()' for details""" if not name.startswith('SP_'): name = 'SP_'+name icon = QWidget().style().standardIcon(getattr(QStyle, name)) if size is None: return icon else: return QIcon(icon.pixmap(size, size))