# -*- coding: utf-8 -*-
import sys
import utool as ut
import numpy as np
try:
import wbia.guitool as gt
from wbia.guitool.__PYQT__ import QtWidgets
from wbia.guitool.__PYQT__ import QtCore
except ImportError:
try:
from PyQt4 import QtGui as QtWidgets
from PyQt4 import QtCore
except ImportError:
pass
try:
from PyQt5 import QtWidgets # NOQA
from PyQt5 import QtCore # NOQA
except ImportError:
pass
print('Warning: guitool did not import correctly')
# (print, print_, printDBG, rrr, profile) = ut.inject(__name__, '[screeninfo]', DEBUG=True)
ut.noinject(__name__, '[screeninfo]')
DEFAULT_MAX_ROWS = 3
# Win7 Areo
WIN7_SIZES = {
'os_border_x': 20,
'os_border_y': 35,
'os_border_h': 30,
'win_border_x': 17,
'win_border_y': 10,
'mpl_toolbar_y': 10,
}
# Ubuntu (Medeterrainian Dark)
GNOME3_SIZES = {
'os_border_x': 0,
'os_border_y': 35, # for gnome3 title bar
'os_border_h': 0,
'win_border_x': 5,
'win_border_y': 30,
'mpl_toolbar_y': 0,
}
for key in GNOME3_SIZES:
GNOME3_SIZES[key] += 5
[docs]def infer_monitor_specs(res_w, res_h, inches_diag):
"""
monitors = [
dict(name='work1', inches_diag=23, res_w=1920, res_h=1080),
dict(name='work2', inches_diag=24, res_w=1920, res_h=1200),
dict(name='hp-129', inches_diag=25, res_w=1920, res_h=1080),
dict(name='?-26', inches_diag=26, res_w=1920, res_h=1080),
dict(name='?-27', inches_diag=27, res_w=1920, res_h=1080),
]
for info in monitors:
name = info['name']
inches_diag = info['inches_diag']
res_h = info['res_h']
res_w = info['res_w']
print('---')
print(name)
inches_w = inches_diag * res_w / np.sqrt(res_h**2 + res_w**2)
inches_h = inches_diag * res_h / np.sqrt(res_h**2 + res_w**2)
print('inches diag = %.2f' % (inches_diag))
print('inches WxH = %.2f x %.2f' % (inches_w, inches_h))
#inches_w = inches_diag * res_w/sqrt(res_h**2 + res_w**2)
"""
import sympy
# Build a system of equations and solve it
inches_w, inches_h = sympy.symbols(
'inches_w inches_h'.split(), real=True, positive=True
)
res_w, res_h = sympy.symbols('res_w res_h'.split(), real=True, positive=True)
(inches_diag,) = sympy.symbols('inches_diag'.split(), real=True, positive=True)
equations = [
sympy.Eq(inches_diag, (inches_w ** 2 + inches_h ** 2) ** 0.5),
sympy.Eq(res_w / res_h, inches_w / inches_h),
]
print('Possible solutions:')
query_vars = [inches_w, inches_h]
for solution in sympy.solve(equations, query_vars):
print('Solution:')
reprstr = ut.repr3(
ut.odict(zip(query_vars, solution)), explicit=True, nobr=1, with_comma=False
)
print(ut.indent(ut.autopep8_format(reprstr)))
# (inches_diag*res_w/sqrt(res_h**2 + res_w**2), inches_diag*res_h/sqrt(res_h**2 + res_w**2))
[docs]def get_resolution_info(monitor_num=0):
r"""
Args:
monitor_num (int): (default = 0)
Returns:
dict: info
CommandLine:
python -m wbia.plottool.screeninfo get_resolution_info --show
xrandr | grep ' connected'
grep "NVIDIA" /var/log/Xorg.0.log
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.plottool.screeninfo import * # NOQA
>>> 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, ut.repr3(info, precision=3)))
"""
import wbia.guitool as gt
app = gt.ensure_qtapp()[0] # NOQA
# screen_resolution = app.desktop().screenGeometry()
# width, height = screen_resolution.width(), screen_resolution.height()
# print('height = %r' % (height,))
# print('width = %r' % (width,))
desktop = 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)
"""
# I want to get the relative positions of my monitors
# pt = screen.pos()
# pt = screen.mapToGlobal(pt)
# pt = screen.mapToGlobal(screen.pos())
# Screen offsets seem bugged
# off_x = pt.x()
# off_y = pt.y()
# print(pt.x())
# print(pt.y())
# pt = screen.mapToGlobal(QtCore.QPoint(0, 0))
# print(pt.x())
# print(pt.y())
off_x = rect.x()
off_y = rect.y()
# pt.x(), pt.y()
inches_w = pixels_w / dpi_x
inches_h = pixels_h / dpi_y
inches_diag = (inches_w ** 2 + inches_h ** 2) ** 0.5
mm_w = inches_w * ut.MM_PER_INCH
mm_h = inches_h * ut.MM_PER_INCH
mm_diag = inches_diag * ut.MM_PER_INCH
ratio = min(mm_w, mm_h) / max(mm_w, mm_h)
# pixel_density = dpi_x / ppi_x
info = ut.odict(
[
('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
[docs]def get_number_of_monitors():
gt.ensure_qtapp()
desktop = QtWidgets.QDesktopWidget()
if hasattr(desktop, 'numScreens'):
n = desktop.numScreens()
else:
n = desktop.screenCount()
return n
[docs]def get_monitor_geom(monitor_num=0):
r"""
Args:
monitor_num (int): (default = 0)
Returns:
tuple: geom
CommandLine:
python -m wbia.plottool.screeninfo get_monitor_geom --show
Example:
>>> # DISABLE_DOCTEST
>>> from wbia.plottool.screeninfo import * # NOQA
>>> monitor_num = 0
>>> geom = get_monitor_geom(monitor_num)
>>> result = ('geom = %s' % (ut.repr2(geom),))
>>> print(result)
"""
gt.ensure_qtapp()
desktop = QtWidgets.QDesktopWidget()
rect = desktop.availableGeometry(screen=monitor_num)
geom = (rect.x(), rect.y(), rect.width(), rect.height())
return geom
[docs]def get_monitor_geometries():
gt.ensure_qtapp()
monitor_geometries = {}
desktop = QtWidgets.QDesktopWidget()
if hasattr(desktop, 'numScreens'):
n = desktop.numScreens()
else:
n = desktop.screenCount()
for screenx in range(n):
rect = desktop.availableGeometry(screen=screenx)
geom = (rect.x(), rect.y(), rect.width(), rect.height())
monitor_geometries[screenx] = geom
return monitor_geometries
[docs]def get_stdpxls():
if sys.platform.startswith('win32'):
stdpxls = WIN7_SIZES
elif sys.platform.startswith('linux'):
stdpxls = GNOME3_SIZES
else:
stdpxls = GNOME3_SIZES
return stdpxls
[docs]def get_xywh_pads():
stdpxls = get_stdpxls()
w_pad = stdpxls['win_border_x']
y_pad = stdpxls['win_border_y'] + stdpxls['mpl_toolbar_y']
# Pads are applied to all windows
x_pad = stdpxls['os_border_x']
y_pad = stdpxls['os_border_y']
return (x_pad, y_pad, w_pad, y_pad)
[docs]def get_avail_geom(monitor_num=None, percent_w=1.0, percent_h=1.0):
stdpxls = get_stdpxls()
if monitor_num is None:
monitor_num = 0
monitor_geometries = get_monitor_geometries()
try:
(startx, starty, availw, availh) = monitor_geometries[monitor_num]
except KeyError:
(startx, starty, availw, availh) = next(monitor_geometries.values())
available_geom = (
startx,
starty,
availw * percent_w,
(availh - stdpxls['os_border_h']) * percent_h,
)
return available_geom
[docs]def get_valid_fig_positions(
num_wins,
max_rows=None,
row_first=True,
monitor_num=None,
percent_w=1.0,
percent_h=1.0,
):
"""
Returns a list of bounding boxes where figures can be placed on the screen
"""
if percent_h is None:
percent_h = 1.0
if percent_w is None:
percent_w = 1.0
if max_rows is None:
max_rows = DEFAULT_MAX_ROWS
available_geom = get_avail_geom(monitor_num, percent_w=percent_w, percent_h=percent_h)
# print('available_geom = %r' % (available_geom,))
startx, starty, avail_width, avail_height = available_geom
nRows = num_wins if num_wins < max_rows else max_rows
nCols = int(np.ceil(num_wins / nRows))
win_height = avail_height / nRows
win_width = avail_width / nCols
(x_pad, y_pad, w_pad, h_pad) = get_xywh_pads()
# print('startx, startx = %r, %r' % (startx, starty))
# print('avail_width, avail_height = %r, %r' % (avail_width, avail_height))
# print('win_width, win_height = %r, %r' % (win_width, win_height))
# print('nRows, nCols = %r, %r' % (nRows, nCols))
def get_position_ix(ix):
if row_first:
rowx = ix % nRows
colx = int(ix // nRows)
else:
colx = ix % nCols
rowx = int(ix // nCols)
w = win_width - w_pad
h = win_height - h_pad
x = startx + colx * (win_width) + x_pad
y = starty + rowx * (win_height) + y_pad
return (x, y, w, h)
valid_positions = [get_position_ix(ix) for ix in range(num_wins)]
return valid_positions