mirror of
https://github.com/pyapp-kit/superqt.git
synced 2026-01-05 20:01:28 +01:00
Add font icons (#24)
* working kinda well * rearrange * add back init * change entrypoints * add mi4 * example * more improvements * add animations * more changes * add feather, improve seticon * update example * refactor * broken wip * use iconfontmeta instead of enum * mostly working * misc * more tweaks * docs * adding tests * remove napari example * more docs * more docs * update examples * more docs * typing * working on icon options * updates * update * update example * update tests * add comment * docs * fix annotation * try set false first * fix py37 * more test fixes * fix qt6 test * ignore old deprecation warning * extend test
This commit is contained in:
20
examples/fonticon1.py
Normal file
20
examples/fonticon1.py
Normal file
@@ -0,0 +1,20 @@
|
||||
try:
|
||||
from fonticon_fa5 import FA5S
|
||||
except ImportError as e:
|
||||
raise type(e)(
|
||||
"This example requires the fontawesome fontpack:\n\n"
|
||||
"pip install git+https://github.com/tlambert03/fonticon-fontawesome5.git"
|
||||
)
|
||||
|
||||
from superqt.fonticon import icon, pulse
|
||||
from superqt.qtcompat.QtCore import QSize
|
||||
from superqt.qtcompat.QtWidgets import QApplication, QPushButton
|
||||
|
||||
app = QApplication([])
|
||||
|
||||
btn2 = QPushButton()
|
||||
btn2.setIcon(icon(FA5S.spinner, animation=pulse(btn2)))
|
||||
btn2.setIconSize(QSize(225, 225))
|
||||
btn2.show()
|
||||
|
||||
app.exec()
|
||||
20
examples/fonticon2.py
Normal file
20
examples/fonticon2.py
Normal file
@@ -0,0 +1,20 @@
|
||||
try:
|
||||
from fonticon_fa5 import FA5S
|
||||
except ImportError as e:
|
||||
raise type(e)(
|
||||
"This example requires the fontawesome fontpack:\n\n"
|
||||
"pip install git+https://github.com/tlambert03/fonticon-fontawesome5.git"
|
||||
)
|
||||
|
||||
from superqt.fonticon import setTextIcon
|
||||
from superqt.qtcompat.QtWidgets import QApplication, QPushButton
|
||||
|
||||
app = QApplication([])
|
||||
|
||||
|
||||
btn4 = QPushButton()
|
||||
btn4.resize(275, 275)
|
||||
setTextIcon(btn4, FA5S.hamburger)
|
||||
btn4.show()
|
||||
|
||||
app.exec()
|
||||
40
examples/fonticon3.py
Normal file
40
examples/fonticon3.py
Normal file
@@ -0,0 +1,40 @@
|
||||
try:
|
||||
from fonticon_fa5 import FA5S
|
||||
except ImportError as e:
|
||||
raise type(e)(
|
||||
"This example requires the fontawesome fontpack:\n\n"
|
||||
"pip install git+https://github.com/tlambert03/fonticon-fontawesome5.git"
|
||||
)
|
||||
|
||||
from superqt.fonticon import IconOpts, icon, pulse, spin
|
||||
from superqt.qtcompat.QtCore import QSize
|
||||
from superqt.qtcompat.QtWidgets import QApplication, QPushButton
|
||||
|
||||
app = QApplication([])
|
||||
|
||||
btn = QPushButton()
|
||||
btn.setIcon(
|
||||
icon(
|
||||
FA5S.smile,
|
||||
color="blue",
|
||||
states={
|
||||
"active": IconOpts(
|
||||
glyph_key=FA5S.spinner,
|
||||
color="red",
|
||||
scale_factor=0.5,
|
||||
animation=pulse(btn),
|
||||
),
|
||||
"disabled": {"color": "green", "scale_factor": 0.8, "animation": spin(btn)},
|
||||
},
|
||||
)
|
||||
)
|
||||
btn.setIconSize(QSize(256, 256))
|
||||
btn.show()
|
||||
|
||||
|
||||
@btn.clicked.connect
|
||||
def toggle_state():
|
||||
btn.setChecked(not btn.isChecked())
|
||||
|
||||
|
||||
app.exec()
|
||||
377
examples/icon_explorer.py
Normal file
377
examples/icon_explorer.py
Normal file
@@ -0,0 +1,377 @@
|
||||
from superqt.fonticon._plugins import loaded
|
||||
from superqt.qtcompat import QtCore, QtGui, QtWidgets
|
||||
from superqt.qtcompat.QtCore import Qt
|
||||
|
||||
P = loaded(load_all=True)
|
||||
if not P:
|
||||
print("you have no font packs loaded!")
|
||||
|
||||
|
||||
class GlyphDelegate(QtWidgets.QItemDelegate):
|
||||
def createEditor(self, parent, option, index):
|
||||
if index.column() < 2:
|
||||
edit = QtWidgets.QLineEdit(parent)
|
||||
edit.editingFinished.connect(self.emitCommitData)
|
||||
return edit
|
||||
comboBox = QtWidgets.QComboBox(parent)
|
||||
if index.column() == 2:
|
||||
comboBox.addItem("Normal")
|
||||
comboBox.addItem("Active")
|
||||
comboBox.addItem("Disabled")
|
||||
comboBox.addItem("Selected")
|
||||
elif index.column() == 3:
|
||||
comboBox.addItem("Off")
|
||||
comboBox.addItem("On")
|
||||
|
||||
comboBox.activated.connect(self.emitCommitData)
|
||||
return comboBox
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
if index.column() < 2:
|
||||
editor.setText(index.model().data(index))
|
||||
return
|
||||
comboBox = editor
|
||||
if comboBox:
|
||||
pos = comboBox.findText(
|
||||
index.model().data(index), Qt.MatchFlag.MatchExactly
|
||||
)
|
||||
comboBox.setCurrentIndex(pos)
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
if editor:
|
||||
text = editor.text() if index.column() < 2 else editor.currentText()
|
||||
model.setData(index, text)
|
||||
|
||||
def emitCommitData(self):
|
||||
self.commitData.emit(self.sender())
|
||||
|
||||
|
||||
class IconPreviewArea(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
mainLayout = QtWidgets.QGridLayout()
|
||||
self.setLayout(mainLayout)
|
||||
|
||||
self.icon = QtGui.QIcon()
|
||||
self.size = QtCore.QSize()
|
||||
self.stateLabels = []
|
||||
self.modeLabels = []
|
||||
self.pixmapLabels = []
|
||||
|
||||
self.stateLabels.append(self.createHeaderLabel("Off"))
|
||||
self.stateLabels.append(self.createHeaderLabel("On"))
|
||||
self.modeLabels.append(self.createHeaderLabel("Normal"))
|
||||
self.modeLabels.append(self.createHeaderLabel("Active"))
|
||||
self.modeLabels.append(self.createHeaderLabel("Disabled"))
|
||||
self.modeLabels.append(self.createHeaderLabel("Selected"))
|
||||
|
||||
for j, label in enumerate(self.stateLabels):
|
||||
mainLayout.addWidget(label, j + 1, 0)
|
||||
|
||||
for i, label in enumerate(self.modeLabels):
|
||||
mainLayout.addWidget(label, 0, i + 1)
|
||||
|
||||
self.pixmapLabels.append([])
|
||||
for j in range(len(self.stateLabels)):
|
||||
self.pixmapLabels[i].append(self.createPixmapLabel())
|
||||
mainLayout.addWidget(self.pixmapLabels[i][j], j + 1, i + 1)
|
||||
|
||||
def setIcon(self, icon):
|
||||
self.icon = icon
|
||||
self.updatePixmapLabels()
|
||||
|
||||
def setSize(self, size):
|
||||
if size != self.size:
|
||||
self.size = size
|
||||
self.updatePixmapLabels()
|
||||
|
||||
def createHeaderLabel(self, text):
|
||||
label = QtWidgets.QLabel("<b>%s</b>" % text)
|
||||
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
return label
|
||||
|
||||
def createPixmapLabel(self):
|
||||
label = QtWidgets.QLabel()
|
||||
label.setEnabled(False)
|
||||
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
label.setFrameShape(QtWidgets.QFrame.Box)
|
||||
label.setSizePolicy(
|
||||
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
|
||||
)
|
||||
label.setBackgroundRole(QtGui.QPalette.Base)
|
||||
label.setAutoFillBackground(True)
|
||||
label.setMinimumSize(132, 132)
|
||||
return label
|
||||
|
||||
def updatePixmapLabels(self):
|
||||
for i in range(len(self.modeLabels)):
|
||||
if i == 0:
|
||||
mode = QtGui.QIcon.Mode.Normal
|
||||
elif i == 1:
|
||||
mode = QtGui.QIcon.Mode.Active
|
||||
elif i == 2:
|
||||
mode = QtGui.QIcon.Mode.Disabled
|
||||
else:
|
||||
mode = QtGui.QIcon.Mode.Selected
|
||||
|
||||
for j in range(len(self.stateLabels)):
|
||||
state = {True: QtGui.QIcon.State.Off, False: QtGui.QIcon.State.On}[
|
||||
j == 0
|
||||
]
|
||||
pixmap = self.icon.pixmap(self.size, mode, state)
|
||||
self.pixmapLabels[i][j].setPixmap(pixmap)
|
||||
self.pixmapLabels[i][j].setEnabled(not pixmap.isNull())
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.centralWidget = QtWidgets.QWidget()
|
||||
self.setCentralWidget(self.centralWidget)
|
||||
|
||||
self.createPreviewGroupBox()
|
||||
self.createGlyphBox()
|
||||
self.createIconSizeGroupBox()
|
||||
|
||||
mainLayout = QtWidgets.QGridLayout()
|
||||
mainLayout.addWidget(self.previewGroupBox, 0, 0, 1, 2)
|
||||
mainLayout.addWidget(self.glyphGroupBox, 1, 0)
|
||||
mainLayout.addWidget(self.iconSizeGroupBox, 1, 1)
|
||||
self.centralWidget.setLayout(mainLayout)
|
||||
|
||||
self.setWindowTitle("Icons")
|
||||
self.otherRadioButton.click()
|
||||
|
||||
self.resize(self.minimumSizeHint())
|
||||
|
||||
def changeSize(self):
|
||||
if self.otherRadioButton.isChecked():
|
||||
extent = self.otherSpinBox.value()
|
||||
else:
|
||||
if self.smallRadioButton.isChecked():
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_SmallIconSize
|
||||
elif self.largeRadioButton.isChecked():
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_LargeIconSize
|
||||
elif self.toolBarRadioButton.isChecked():
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_ToolBarIconSize
|
||||
elif self.listViewRadioButton.isChecked():
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_ListViewIconSize
|
||||
elif self.iconViewRadioButton.isChecked():
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_IconViewIconSize
|
||||
else:
|
||||
metric = QtWidgets.QStyle.PixelMetric.PM_TabBarIconSize
|
||||
|
||||
extent = QtWidgets.QApplication.style().pixelMetric(metric)
|
||||
|
||||
self.previewArea.setSize(QtCore.QSize(extent, extent))
|
||||
self.otherSpinBox.setEnabled(self.otherRadioButton.isChecked())
|
||||
|
||||
def changeIcon(self):
|
||||
from superqt import fonticon
|
||||
|
||||
icon = None
|
||||
for row in range(self.glyphTable.rowCount()):
|
||||
item0 = self.glyphTable.item(row, 0)
|
||||
item1 = self.glyphTable.item(row, 1)
|
||||
item2 = self.glyphTable.item(row, 2)
|
||||
item3 = self.glyphTable.item(row, 3)
|
||||
|
||||
if item0.checkState() != Qt.CheckState.Checked:
|
||||
continue
|
||||
key = item0.text()
|
||||
if not key:
|
||||
continue
|
||||
|
||||
if item2.text() == "Normal":
|
||||
mode = QtGui.QIcon.Mode.Normal
|
||||
elif item2.text() == "Active":
|
||||
mode = QtGui.QIcon.Mode.Active
|
||||
elif item2.text() == "Disabled":
|
||||
mode = QtGui.QIcon.Mode.Disabled
|
||||
else:
|
||||
mode = QtGui.QIcon.Mode.Selected
|
||||
|
||||
color = item1.text() or None
|
||||
state = (
|
||||
QtGui.QIcon.State.On if item3.text() == "On" else QtGui.QIcon.State.Off
|
||||
)
|
||||
try:
|
||||
if icon is None:
|
||||
icon = fonticon.icon(key, color=color)
|
||||
else:
|
||||
icon.addState(state, mode, glyph_key=key, color=color)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
continue
|
||||
if icon:
|
||||
self.previewArea.setIcon(icon)
|
||||
|
||||
def createPreviewGroupBox(self):
|
||||
self.previewGroupBox = QtWidgets.QGroupBox("Preview")
|
||||
|
||||
self.previewArea = IconPreviewArea()
|
||||
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
layout.addWidget(self.previewArea)
|
||||
self.previewGroupBox.setLayout(layout)
|
||||
|
||||
def createGlyphBox(self):
|
||||
self.glyphGroupBox = QtWidgets.QGroupBox("Glpyhs")
|
||||
self.glyphGroupBox.setMinimumSize(480, 200)
|
||||
self.glyphTable = QtWidgets.QTableWidget()
|
||||
self.glyphTable.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||
self.glyphTable.setItemDelegate(GlyphDelegate(self))
|
||||
|
||||
self.glyphTable.horizontalHeader().setDefaultSectionSize(100)
|
||||
self.glyphTable.setColumnCount(4)
|
||||
self.glyphTable.setHorizontalHeaderLabels(("Glyph", "Color", "Mode", "State"))
|
||||
self.glyphTable.horizontalHeader().setSectionResizeMode(
|
||||
0, QtWidgets.QHeaderView.Stretch
|
||||
)
|
||||
self.glyphTable.horizontalHeader().setSectionResizeMode(
|
||||
1, QtWidgets.QHeaderView.Fixed
|
||||
)
|
||||
self.glyphTable.horizontalHeader().setSectionResizeMode(
|
||||
2, QtWidgets.QHeaderView.Fixed
|
||||
)
|
||||
self.glyphTable.horizontalHeader().setSectionResizeMode(
|
||||
3, QtWidgets.QHeaderView.Fixed
|
||||
)
|
||||
self.glyphTable.verticalHeader().hide()
|
||||
|
||||
self.glyphTable.itemChanged.connect(self.changeIcon)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
layout.addWidget(self.glyphTable)
|
||||
self.glyphGroupBox.setLayout(layout)
|
||||
self.changeIcon()
|
||||
|
||||
p0 = list(P)[-1]
|
||||
key = f"{p0}.{list(P[p0])[1]}"
|
||||
for _ in range(4):
|
||||
row = self.glyphTable.rowCount()
|
||||
self.glyphTable.setRowCount(row + 1)
|
||||
|
||||
item0 = QtWidgets.QTableWidgetItem()
|
||||
item1 = QtWidgets.QTableWidgetItem()
|
||||
|
||||
if _ == 0:
|
||||
item0.setText(key)
|
||||
# item0.setFlags(item0.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||
|
||||
item2 = QtWidgets.QTableWidgetItem("Normal")
|
||||
item3 = QtWidgets.QTableWidgetItem("Off")
|
||||
|
||||
self.glyphTable.setItem(row, 0, item0)
|
||||
self.glyphTable.setItem(row, 1, item1)
|
||||
self.glyphTable.setItem(row, 2, item2)
|
||||
self.glyphTable.setItem(row, 3, item3)
|
||||
self.glyphTable.openPersistentEditor(item2)
|
||||
self.glyphTable.openPersistentEditor(item3)
|
||||
|
||||
item0.setCheckState(Qt.CheckState.Checked)
|
||||
|
||||
def createIconSizeGroupBox(self):
|
||||
self.iconSizeGroupBox = QtWidgets.QGroupBox("Icon Size")
|
||||
|
||||
self.smallRadioButton = QtWidgets.QRadioButton()
|
||||
self.largeRadioButton = QtWidgets.QRadioButton()
|
||||
self.toolBarRadioButton = QtWidgets.QRadioButton()
|
||||
self.listViewRadioButton = QtWidgets.QRadioButton()
|
||||
self.iconViewRadioButton = QtWidgets.QRadioButton()
|
||||
self.tabBarRadioButton = QtWidgets.QRadioButton()
|
||||
self.otherRadioButton = QtWidgets.QRadioButton("Other:")
|
||||
|
||||
self.otherSpinBox = QtWidgets.QSpinBox()
|
||||
self.otherSpinBox.setRange(8, 128)
|
||||
self.otherSpinBox.setValue(64)
|
||||
|
||||
self.smallRadioButton.toggled.connect(self.changeSize)
|
||||
self.largeRadioButton.toggled.connect(self.changeSize)
|
||||
self.toolBarRadioButton.toggled.connect(self.changeSize)
|
||||
self.listViewRadioButton.toggled.connect(self.changeSize)
|
||||
self.iconViewRadioButton.toggled.connect(self.changeSize)
|
||||
self.tabBarRadioButton.toggled.connect(self.changeSize)
|
||||
self.otherRadioButton.toggled.connect(self.changeSize)
|
||||
self.otherSpinBox.valueChanged.connect(self.changeSize)
|
||||
|
||||
otherSizeLayout = QtWidgets.QHBoxLayout()
|
||||
otherSizeLayout.addWidget(self.otherRadioButton)
|
||||
otherSizeLayout.addWidget(self.otherSpinBox)
|
||||
otherSizeLayout.addStretch()
|
||||
|
||||
layout = QtWidgets.QGridLayout()
|
||||
layout.addWidget(self.smallRadioButton, 0, 0)
|
||||
layout.addWidget(self.largeRadioButton, 1, 0)
|
||||
layout.addWidget(self.toolBarRadioButton, 2, 0)
|
||||
layout.addWidget(self.listViewRadioButton, 0, 1)
|
||||
layout.addWidget(self.iconViewRadioButton, 1, 1)
|
||||
layout.addWidget(self.tabBarRadioButton, 2, 1)
|
||||
layout.addLayout(otherSizeLayout, 3, 0, 1, 2)
|
||||
layout.setRowStretch(4, 1)
|
||||
self.iconSizeGroupBox.setLayout(layout)
|
||||
self.changeStyle()
|
||||
|
||||
def changeStyle(self, style=None):
|
||||
style = style or QtWidgets.QApplication.style().objectName()
|
||||
style = QtWidgets.QStyleFactory.create(style)
|
||||
if not style:
|
||||
return
|
||||
|
||||
QtWidgets.QApplication.setStyle(style)
|
||||
|
||||
self.setButtonText(
|
||||
self.smallRadioButton,
|
||||
"Small (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_SmallIconSize,
|
||||
)
|
||||
self.setButtonText(
|
||||
self.largeRadioButton,
|
||||
"Large (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_LargeIconSize,
|
||||
)
|
||||
self.setButtonText(
|
||||
self.toolBarRadioButton,
|
||||
"Toolbars (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_ToolBarIconSize,
|
||||
)
|
||||
self.setButtonText(
|
||||
self.listViewRadioButton,
|
||||
"List views (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_ListViewIconSize,
|
||||
)
|
||||
self.setButtonText(
|
||||
self.iconViewRadioButton,
|
||||
"Icon views (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_IconViewIconSize,
|
||||
)
|
||||
self.setButtonText(
|
||||
self.tabBarRadioButton,
|
||||
"Tab bars (%d x %d)",
|
||||
style,
|
||||
QtWidgets.QStyle.PixelMetric.PM_TabBarIconSize,
|
||||
)
|
||||
|
||||
self.changeSize()
|
||||
|
||||
@staticmethod
|
||||
def setButtonText(button, label, style, metric):
|
||||
metric_value = style.pixelMetric(metric)
|
||||
button.setText(label % (metric_value, metric_value))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import sys
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
mainWin = MainWindow()
|
||||
mainWin.show()
|
||||
sys.exit(app.exec_())
|
||||
Reference in New Issue
Block a user