# ###########################################################################
#
# This file is part of Taurus
#
# http://taurus-scada.org
#
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
#
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Taurus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus. If not, see <http://www.gnu.org/licenses/>.
#
# ###########################################################################
"""
This module provides an icon catalog widget
"""
import os
import click
import hashlib
from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.input import GraphicalChoiceWidget
from taurus.qt.qtgui.icon import REGISTERED_PREFIXES, getCachedPixmap
from taurus.external.qt import Qt
class QIconCatalogPage(GraphicalChoiceWidget):
"""A widget that shows all icons available under a given searchPath
prefix"""
def __init__(self, prefix, iconSize=24, columns=10):
choices, pixmaps = self.__build_catalog(prefix, columns=columns)
GraphicalChoiceWidget.__init__(
self,
choices=choices,
pixmaps=pixmaps,
iconSize=iconSize,
defaultPixmap=None,
)
spacer = Qt.QSpacerItem(
0, 0, Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding
)
self.gridLayout.addItem(
spacer, self.gridLayout.rowCount(), self.gridLayout.columnCount()
)
def __build_catalog(self, prefix, columns=10):
"""explores paths registered under the given prefix and selects unique
pixmaps (performs an md5 check to discard duplicated icon files)
"""
pixmaps_hashed = {}
hashes = {}
for path in Qt.QDir.searchPaths(prefix):
if not os.path.exists(path):
print(" %s not found. Skipping.!" % path)
continue
for fname in os.listdir(path):
abs_fname = os.path.join(path, fname)
if not os.path.isfile(abs_fname):
continue
md5 = self.__md5(abs_fname)
choice = "%s:%s" % (prefix, fname)
if md5 in hashes:
hashes[md5] += "\n%s\t(%s)" % (choice, abs_fname)
else:
hashes[md5] = "%s\t(%s)" % (choice, abs_fname)
pixmap = getCachedPixmap(choice)
if not pixmap.isNull():
pixmaps_hashed[md5] = pixmap
pixmaps = {}
choices = []
row = []
for md5, choice in hashes.items():
try:
pixmaps[choice] = pixmaps_hashed[md5]
except KeyError:
continue
row.append(choice)
if len(row) > columns:
choices.append(row)
row = []
if len(row) > 0:
choices.append(row)
return choices, pixmaps
def __md5(self, fname):
"""
Extracts md5 sum of a file
:param fname: path to file
:type fname: str
:return: md5 hash
"""
hash_md5 = hashlib.md5()
with open(fname, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def onClick(self):
"""Reimplemented :class:`GraphicalChoiceWidget`"""
# From all alternatives, extract the one with the shortest name
# -------------------------------------------------------
# Work around for https://bugs.kde.org/show_bug.cgi?id=345023
# TODO: make better solution for this
# self._chosen = str(self.sender().text())
# it fails due to added "&"
chosen = self.sender()._id # <-- this was monkey-patched
# -------------------------------------------------------
alts = chosen.splitlines()
alts = sorted(alts, key=lambda s: len(s.split()[0]))
name, absname = alts[0].split()
# Store chosen name and emit signal using name
self._chosen = name
self.choiceMade.emit(name)
# show a message dialob with more info on the selected icon
dlg = Qt.QMessageBox()
dlg.setWindowTitle(name)
text = "You can access the selected icon as:\n%s\n\n" % name
text += "Or, by absolute name:\n%s\n\n" % absname
if len(alts) > 1:
text += "Other alternative names:\n\n" + "\n\n".join(alts[1:])
dlg.setText(text)
dlg.setIconPixmap(getCachedPixmap(name, size=128))
dlg.exec_()
[docs]
class QIconCatalog(Qt.QTabWidget):
"""A widget that shows a tab for each registered search path prefix. In
each tab, all icons available for the corresponding prefix are displayed.
Clicking on an icon provides info on how to use it from a taurus
application."""
iconSelected = Qt.pyqtSignal("QString")
def __init__(self, parent=None):
Qt.QTabWidget.__init__(self)
nprefix = len(REGISTERED_PREFIXES)
progress = Qt.QProgressDialog(
"Building icon catalog...", None, 0, nprefix, self
)
progress.setWindowModality(Qt.Qt.WindowModal)
for i, prefix in enumerate(sorted(REGISTERED_PREFIXES)):
progress.setValue(i)
page = QIconCatalogPage(prefix)
page.choiceMade.connect(self.iconSelected)
self.addTab(page, prefix)
progress.setValue(nprefix)
@click.command("icons")
def icons_cmd():
"""Show the Taurus icon catalog"""
import sys
app = TaurusApplication(cmd_line_parser=None)
w = QIconCatalog()
w.setWindowTitle("Taurus Icon Catalog")
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
icons_cmd()