Source code for vimtk.cplat

# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
from collections import OrderedDict
from vimtk import util
import sys
import logging
logger = logging.getLogger(__name__)


try:
    import pyperclip
except (ImportError, Exception) as ex:
    msg = ('Warning: Python cannot import pyperclip: '
           'python version={}, prefix={}, ex={!r}').format(
               sys.version_info, sys.prefix, ex)
    logger.warn(msg)
    pyperclip = None
    # raise

__PyQt__ = None


[docs] class _PyQtWraper(object): """ Lazy import of PyQt 4 or 5 CommandLine: python -m vimtk.cplat _PyQtWraper Example: >>> # xdoctest: +REQUIRES(module:PyQt5) >>> PyQt = import_pyqt() >>> app1 = PyQt.ensure_app() >>> app2 = PyQt.ensure_app() >>> assert app1 is app2 """ def __init__(PyQt): logger.debug('Constructing PyQt Wrapper') try: from PyQt5 import QtWidgets # NOQA from PyQt5 import QtCore # NOQA except ImportError as ex5: logger.debug('Could not find PyQt5') try: from PyQt4 import QtGui as QtWidgets from PyQt4 import QtCore except ImportError: logger.debug('Could not find PyQt4 or PyQt5') raise ex5 else: logger.debug('Using PyQt4') else: logger.debug('Using PyQt5') PyQt.QtWidgets = QtWidgets PyQt.QtCore = QtCore PyQt.app = None
[docs] def ensure_app(PyQt): if PyQt.app is None: # ensure we have a qt application app = PyQt.QtCore.QCoreApplication.instance() if app is None: # if not in qtconsole app = PyQt.QtWidgets.QApplication(sys.argv) PyQt.app = app return PyQt.app
[docs] def import_pyqt(): global __PyQt__ if __PyQt__ is None: __PyQt__ = _PyQtWraper() __PyQt__.ensure_app() return __PyQt__
[docs] def lorium_ipsum(): """ Standard testing string """ ipsum_str = ''' Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ''' return ipsum_str
[docs] def _ensure_clipboard_backend(): """ CommandLine: pip install pyperclip sudo apt-get install xclip sudo apt-get install xsel pip install PyQt5 # for windows conda install pyqt References: http://stackoverflow.com/questions/11063458/-text-to-clipboard http://stackoverflow.com/questions/579687using-python Benchmark: import pyperclip import timerit ti = timerit.Timerit(verbose=2, unit='ms') # Qt is by far the fastest, followed by xsel, and then xclip backend_order = ['xclip', 'xsel', 'qt', 'gtk'] backend_order = ['qt', 'xsel', 'xclip', 'gtk'] for be in backend_order: print('-----') print('be = %r' % (be,)) try: pyperclip.set_clipboard(be) ti.reset('test-copy').call(lambda: pyperclip.copy('a line of reasonable length text')) ti.reset('test-paste').call(lambda: pyperclip.paste()) except Exception: print('Backend failed: {}'.format(be)) CommandLine: python -m vimtk.xctrl _ensure_clipboard_backend Example: >>> from vimtk.xctrl import * # NOQA >>> import pytest >>> import pyperclip >>> result = _ensure_clipboard_backend() >>> try: >>> prev = get_clipboard() >>> except pyperclip.PyperclipException: >>> pytest.skip('no appropriate backend for pyperclip') >>> text1 = 'foobar' >>> text2 = 'bazbiz' >>> copy_text_to_clipboard(text1) >>> pasted1 = get_clipboard() >>> copy_text_to_clipboard(text2) >>> pasted2 = get_clipboard() >>> assert pasted1 == text1 >>> assert pasted2 == text2 >>> copy_text_to_clipboard(prev) """ if getattr(pyperclip, '_vimtk_monkey_backend', 'no') != 'no': return def _check_clipboard_backend(backend): if backend == 'windows': return sys.platform.startswith('win32') if backend == 'qt': return (util.modname_to_modpath('PyQt5') or util.modname_to_modpath('PyQt4')) elif backend == 'gtk': return util.modname_to_modpath('gtk') else: return pyperclip._executable_exists(backend) if util.WIN32: backend_order = ['windows', 'qt'] else: backend_order = ['xclip', 'xsel', 'qt', 'gtk'] #raise NotImplementedError('not on windows yet') for backend in backend_order: if _check_clipboard_backend(backend): if pyperclip is None: raise Exception( 'pyperclip is not appear to be installed. ' 'See also: https://github.com/Erotemic/vimtk/issues/5') pyperclip.set_clipboard(backend) pyperclip._vimtk_monkey_backend = backend return else: print('warning %r not installed' % (backend,))
[docs] def copy_text_to_clipboard(text): """ Copies text to the clipboard """ _ensure_clipboard_backend() if pyperclip is None: raise Exception( 'pyperclip is not appear to be installed. ' 'See also: https://github.com/Erotemic/vimtk/issues/5') pyperclip.copy(text)
[docs] def get_clipboard(): """ References: http://stackoverflow.com/questions/11063458/python-script-to-copy-text-to-clipboard """ _ensure_clipboard_backend() if pyperclip is None: raise Exception( 'pyperclip is not appear to be installed. ' 'See also: https://github.com/Erotemic/vimtk/issues/5') text = pyperclip.paste() return text
[docs] def _get_number_of_monitors(): PyQt = import_pyqt() desktop = PyQt.QtWidgets.QDesktopWidget() if hasattr(desktop, 'numScreens'): n = desktop.numScreens() else: n = desktop.screenCount() return n
[docs] def get_resolution_info(monitor_num=0): r""" Args: monitor_num (int): (default = 0) Returns: dict: info CommandLine: python -m vimtk.xctrl get_resolution_info Example: >>> # xdoctest: +REQUIRES(module:PyQt5) >>> import ubelt as ub >>> monitor_num = 1 >>> for monitor_num in range(_get_number_of_monitors()): >>> info = get_resolution_info(monitor_num) >>> print('monitor(%d).info = %s' % (monitor_num, ub.urepr(info, precision=3))) """ # screen_resolution = app.desktop().screenGeometry() # width, height = screen_resolution.width(), screen_resolution.height() # print('height = %r' % (height,)) # print('width = %r' % (width,)) PyQt = import_pyqt() desktop = PyQt.QtWidgets.QDesktopWidget() screen = desktop.screen(monitor_num) ppi_x = screen.logicalDpiX() ppi_y = screen.logicalDpiY() dpi_x = screen.physicalDpiX() dpi_y = screen.physicalDpiY() # This call is not rotated correctly # rect = screen.screenGeometry() # This call has bad offsets rect = desktop.screenGeometry(screen=monitor_num) # This call subtracts offsets weirdly # desktop.availableGeometry(screen=monitor_num) pixels_w = rect.width() # for num in range(desktop.screenCount()): # pass pixels_h = rect.height() # + rect.y() """ I have two monitors (screens), after rotation effects they have the geometry: (for example) S1 = {x: 0, y=300, w: 1920, h:1080} S2 = {x=1920, y=0, w: 1080, h:1920} Here is a pictoral example G--------------------------------------C------------------- | | | A--------------------------------------| | | | | | | | | | | | S1 | | | | S2 | | | | | | | | | | |--------------------------------------B | | | | | | | ----------------------------------------------------------D Desired Info G = (0, 0) A = (S1.x, S1.y) B = (S1.x + S1.w, S1.y + S1.h) C = (S2.x, S2.y) D = (S2.x + S1.w, S2.y + S2.h) from PyQt4 import QtGui, QtCore app = QtCore.QCoreApplication.instance() if app is None: import sys app = QtGui.QApplication(sys.argv) desktop = QtGui.QDesktopWidget() rect1 = desktop.screenGeometry(screen=0) rect2 = desktop.screenGeometry(screen=1) """ off_x = rect.x() off_y = rect.y() inches_w = (pixels_w / dpi_x) inches_h = (pixels_h / dpi_y) inches_diag = (inches_w ** 2 + inches_h ** 2) ** .5 MM_PER_INCH = 25.4 mm_w = inches_w * MM_PER_INCH mm_h = inches_h * MM_PER_INCH mm_diag = inches_diag * MM_PER_INCH ratio = min(mm_w, mm_h) / max(mm_w, mm_h) #pixel_density = dpi_x / ppi_x info = OrderedDict([ ('monitor_num', monitor_num), ('off_x', off_x), ('off_y', off_y), ('ratio', ratio), ('ppi_x', ppi_x), ('ppi_y', ppi_y), ('dpi_x', dpi_x), ('dpi_y', dpi_y), #'pixel_density', pixel_density), ('inches_w', inches_w), ('inches_h', inches_h), ('inches_diag', inches_diag), ('mm_w', mm_w), ('mm_h', mm_h), ('mm_diag', mm_diag), ('pixels_w', pixels_w), ('pixels_h', pixels_h), ]) return info
if __name__ == '__main__': r""" CommandLine: python -m vimtk.cplat """ import xdoctest xdoctest.doctest_module(__file__)