Skip to content

Commit

Permalink
in Qt 6.1+ the QFont constructor requires a QStringList for families
Browse files Browse the repository at this point in the history
  • Loading branch information
jborbely committed Jun 2, 2021
1 parent a900072 commit 96e2a1a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 27 deletions.
64 changes: 45 additions & 19 deletions msl/qt/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def to_qfont(*args):
The argument(s) to convert to a :class:`QtGui.QFont`.
* If :class:`int` or :class:`float` then the point size.
* If :class:`str` then the font family name.
* If :class:`str` then the font family name(s).
* If :class:`QtGui.QFont` then returns a copy.
* If multiple arguments then
- family name, point size
- family name(s), point size
- family name, point size, weight
- family name(s), point size, weight
- family name, point size, weight, is italic
- family name(s), point size, weight, is italic
Returns
-------
Expand All @@ -62,28 +62,54 @@ def to_qfont(*args):
--------
>>> font = to_qfont(48)
>>> font = to_qfont(23.4)
>>> font = to_qfont('Papyrus')
>>> font = to_qfont('Ariel')
>>> font = to_qfont('Ariel', 16)
>>> font = to_qfont('Ariel', 16, QtGui.QFont.Bold)
>>> font = to_qfont('Ariel', 16, 50, True)
If you are using Qt 6.1+ then you can specify multiple family names
>>> font = to_qfont('Ariel', 'Papyrus')
>>> font = to_qfont('Ariel', 'Papyrus', 'Helvetica [Cronyx]', 16)
>>> font = to_qfont('Ariel', 'Helvetica', 16, QtGui.QFont.Bold)
>>> font = to_qfont('Ariel', 'Papyrus', 'Times', 16, QtGui.QFont.Bold, True)
"""
if not args:
return QtGui.QFont()

def filter_families(options=None):
# as of version 6.1 the QFont constructor uses
# QStringList &families
# instead of
# QString &family
if options is None:
options = args
families = []
rest = []
for option in options:
if isinstance(option, str):
families.append(option)
else:
rest.append(option)
if families and binding.qt_version_info[:2] < (6, 1):
return families[0], rest
return families, rest

def parse_tuple(a):
if not isinstance(a[0], str):
raise TypeError('The first argument must be the family name (as a string)')

if len(a) == 1:
return QtGui.QFont(a[0])
elif len(a) == 2:
return QtGui.QFont(a[0], pointSize=int(a[1]))
elif len(a) == 3:
return QtGui.QFont(a[0], pointSize=int(a[1]), weight=int(a[2]))
families, rest = filter_families(a)
if not families:
raise TypeError('The first argument(s) must be family name(s)')

if not rest:
return QtGui.QFont(families)
elif len(rest) == 1:
return QtGui.QFont(families, pointSize=int(rest[0]))
elif len(rest) == 2:
return QtGui.QFont(families, pointSize=int(rest[0]), weight=int(rest[1]))
else:
return QtGui.QFont(a[0], pointSize=int(a[1]), weight=int(a[2]), italic=bool(a[3]))
return QtGui.QFont(families, pointSize=int(rest[0]), weight=int(rest[1]), italic=bool(rest[2]))

if not args:
return QtGui.QFont()
elif len(args) == 1:
if len(args) == 1:
value = args[0]
if isinstance(value, QtGui.QFont):
return QtGui.QFont(value)
Expand All @@ -96,7 +122,7 @@ def parse_tuple(a):
f.setPointSizeF(value)
return f
elif isinstance(value, str):
return QtGui.QFont(value)
return QtGui.QFont(filter_families()[0])
elif isinstance(value, (list, tuple)):
return parse_tuple(value)
else:
Expand Down
53 changes: 45 additions & 8 deletions tests/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest

from msl.qt import application, QtWidgets, QtCore, QtGui, Qt, convert
from msl.qt import application, QtWidgets, QtCore, QtGui, Qt, convert, binding

app = application()

Expand Down Expand Up @@ -238,7 +238,7 @@ def test_to_qfont():

# the second item in the list will be cast to an integer
# also test that one can pass in a tuple or a list
for obj in [('Comic Sans MS', 36), ['Comic Sans MS', 36.6], ('Comic Sans MS', '36')]:
for obj in [('Comic Sans MS', 36), ['Comic Sans MS', 36.6]]:
f = convert.to_qfont(obj)
assert f.family() == 'Comic Sans MS'
assert f.pointSize() == 36
Expand All @@ -252,9 +252,9 @@ def test_to_qfont():

# the first item in the list must be a string
for obj in [None, 1, 23.4, 5j, True, [1]]:
with pytest.raises(TypeError, match=r'(as a string)'):
with pytest.raises(TypeError, match=r'The first argument\(s\) must be family name\(s\)'):
convert.to_qfont(obj, 12)
with pytest.raises(TypeError, match=r'(as a string)'):
with pytest.raises(TypeError, match=r'The first argument\(s\) must be family name\(s\)'):
convert.to_qfont((obj, 12))

# the first argument is not a QFont, int, float or string
Expand All @@ -263,12 +263,49 @@ def test_to_qfont():
convert.to_qfont(obj)

# the second item cannot be cast to an integer
with pytest.raises(ValueError):
convert.to_qfont(['Ariel', 'xxx'])
with pytest.raises(TypeError):
convert.to_qfont(['Ariel', {}])

# the third item cannot be cast to an integer
with pytest.raises(ValueError):
convert.to_qfont('Ariel', 12, 'xxx')
with pytest.raises(TypeError):
convert.to_qfont('Ariel', 12, {})


@pytest.mark.skipif(binding.qt_version_info[:2] < (6, 1), reason='QFont constructor uses obsolete &family')
def test_to_qfont_families():
f = convert.to_qfont('Papyrus', 'Ariel')
assert f.family() == 'Papyrus'
assert f.families() == ['Papyrus', 'Ariel']

f = convert.to_qfont('Ariel', 'Papyrus', 48)
assert f.family() == 'Ariel'
assert f.families() == ['Ariel', 'Papyrus']
assert f.pointSize() == 48
assert f.weight() == QtGui.QFont.Normal
assert not f.italic()

# family names can occur in any position
f = convert.to_qfont('Papyrus', 48, 'Ariel', QtGui.QFont.Bold)
assert f.family() == 'Papyrus'
assert f.families() == ['Papyrus', 'Ariel']
assert f.pointSize() == 48
assert f.weight() == QtGui.QFont.Bold
assert not f.italic()

f = convert.to_qfont(48, 'Helvetica [Cronyx]', QtGui.QFont.Bold, True, 'Papyrus', 'Ariel')
assert f.family() == 'Helvetica [Cronyx]'
assert f.families() == ['Helvetica [Cronyx]', 'Papyrus', 'Ariel']
assert f.pointSize() == 48
assert f.weight() == QtGui.QFont.Bold
assert f.italic()

f = convert.to_qfont(['Papyrus', 'Ariel', 'Helvetica [Cronyx]'])
assert f.family() == 'Papyrus'
assert f.families() == ['Papyrus', 'Ariel', 'Helvetica [Cronyx]']

with pytest.raises(TypeError, match=r'The first argument\(s\) must be family name\(s\)'):
# cannot mix a list of family names with other positional arguments
convert.to_qfont(['Papyrus'], 48)


def test_to_qcolor():
Expand Down

0 comments on commit 96e2a1a

Please sign in to comment.