# Source code for taurus.qt.qtgui.icon.catalog

    # ###########################################################################
    #
    # 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_()

    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()