File indexing completed on 2024-11-03 04:29:23

0001 /*
0002  * SPDX-FileCopyrightText: 2022 Jean-Baptiste Mardelle <jb.kdenlive@org>
0003  * SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004  */
0005 #include "markercategorybutton.h"
0006 #include "../bin/model/markerlistmodel.hpp"
0007 #include "core.h"
0008 
0009 #include <KLocalizedString>
0010 #include <QMenu>
0011 
0012 MarkerCategoryButton::MarkerCategoryButton(QWidget *parent)
0013     : QToolButton(parent)
0014     , m_markerListModel(nullptr)
0015     , m_allowAll(true)
0016     , m_onlyUsed(false)
0017 {
0018     setCheckable(false);
0019     setIcon(QIcon::fromTheme(QLatin1String("view-filter")));
0020     setPopupMode(QToolButton::InstantPopup);
0021     m_menu = new QMenu(this);
0022     setMenu(m_menu);
0023     if (pCore) {
0024         refresh();
0025     }
0026     connect(m_menu, &QMenu::triggered, this, &MarkerCategoryButton::categorySelected);
0027     connect(this, &MarkerCategoryButton::changed, this, &MarkerCategoryButton::refresh);
0028 }
0029 
0030 void MarkerCategoryButton::enableFilterMode()
0031 {
0032     setCheckable(true);
0033     setPopupMode(QToolButton::MenuButtonPopup);
0034 }
0035 
0036 void MarkerCategoryButton::categorySelected(QAction *ac)
0037 {
0038     int index = ac->data().toInt();
0039     QList<QAction *> actions = m_menu->actions();
0040     if (index == -1) {
0041         if (!ac->isChecked()) {
0042             // Don't allow unselecting all categories
0043             ac->setChecked(true);
0044             if (isCheckable()) {
0045                 setChecked(false);
0046             }
0047             return;
0048         }
0049         // All categories selected, unselect any other
0050         for (auto &action : actions) {
0051             if (action != ac && action->isChecked()) {
0052                 action->setChecked(false);
0053             }
0054         }
0055         Q_EMIT categoriesChanged({-1});
0056         if (isCheckable()) {
0057             setChecked(false);
0058         }
0059         return;
0060     } else {
0061         // If a category is selected, ensure "all categories" is unchecked
0062         if (!ac->isChecked()) {
0063             bool categorySelected = false;
0064             for (auto &action : actions) {
0065                 if (action->data().toInt() != -1 && action->isChecked()) {
0066                     categorySelected = true;
0067                     break;
0068                 }
0069             }
0070             if (!categorySelected) {
0071                 for (auto &action : actions) {
0072                     if (action->data().toInt() == -1) {
0073                         action->setChecked(true);
0074                         break;
0075                     }
0076                 }
0077             }
0078         } else {
0079             // A category is checked, ensure "all categories is unchecked
0080             for (auto &action : actions) {
0081                 if (action->data().toInt() == -1) {
0082                     action->setChecked(false);
0083                     break;
0084                 }
0085             }
0086         }
0087     }
0088     QList<int> selection;
0089     for (auto &action : actions) {
0090         if (action->isChecked()) {
0091             selection << action->data().toInt();
0092         }
0093     }
0094     Q_EMIT categoriesChanged(selection);
0095     if (isCheckable()) {
0096         setChecked(selection != (QList<int>() << -1));
0097     }
0098 }
0099 
0100 void MarkerCategoryButton::refresh()
0101 {
0102     QList<int> selected;
0103     // remember selected categories
0104     QList<QAction *> actions = m_menu->actions();
0105     for (auto &ac : actions) {
0106         if (ac->isChecked()) {
0107             selected << ac->data().toInt();
0108         }
0109     }
0110     m_menu->clear();
0111     // Set up guide categories
0112     QPixmap pixmap(32, 32);
0113     QMapIterator<int, Core::MarkerCategory> i(pCore->markerTypes);
0114     while (i.hasNext()) {
0115         i.next();
0116         if (m_onlyUsed && m_markerListModel && m_markerListModel->getAllMarkers(i.key()).isEmpty()) {
0117             continue;
0118         }
0119         pixmap.fill(i.value().color);
0120         QIcon colorIcon(pixmap);
0121         QAction *ac = new QAction(colorIcon, i.value().displayName, m_menu);
0122         ac->setData(i.key());
0123         ac->setCheckable(true);
0124         ac->setChecked(selected.contains(i.key()));
0125         m_menu->addAction(ac);
0126     }
0127     if (m_menu->actions().count() == 0 && !m_allowAll) {
0128         setEnabled(false);
0129         setText(i18n("Nothing to select"));
0130         return;
0131     }
0132     setEnabled(true);
0133     if (m_allowAll) {
0134         QAction *ac = new QAction(i18n("All Categories"), m_menu);
0135         ac->setData(-1);
0136         ac->setCheckable(true);
0137         if (m_menu->actions().isEmpty()) {
0138             m_menu->addAction(ac);
0139         } else {
0140             m_menu->insertAction(m_menu->actions().first(), ac);
0141         }
0142         if (selected.isEmpty() || selected.contains(-1)) {
0143             ac->setChecked(true);
0144         }
0145     }
0146 }
0147 
0148 void MarkerCategoryButton::setCurrentCategories(QList<int> categories)
0149 {
0150     QList<QAction *> actions = m_menu->actions();
0151     if (categories.contains(-1)) {
0152         for (auto &ac : actions) {
0153             if (ac->data().toInt() == -1) {
0154                 ac->setChecked(true);
0155             } else {
0156                 ac->setChecked(false);
0157             }
0158         }
0159     } else {
0160         for (auto &ac : actions) {
0161             int categoryIndex = ac->data().toInt();
0162             if (categoryIndex == -1) {
0163                 ac->setChecked(false);
0164             } else {
0165                 ac->setChecked(categories.contains(categoryIndex));
0166             }
0167         }
0168     }
0169 }
0170 
0171 QList<int> MarkerCategoryButton::currentCategories()
0172 {
0173     QList<int> selected;
0174     QList<QAction *> actions = m_menu->actions();
0175     for (auto &ac : actions) {
0176         if (ac->isChecked()) {
0177             selected << ac->data().toInt();
0178         }
0179     }
0180     if (selected.contains(-1)) {
0181         return {-1};
0182     }
0183     return selected;
0184 }
0185 
0186 void MarkerCategoryButton::setMarkerModel(const MarkerListModel *model)
0187 {
0188     m_markerListModel = model;
0189     connect(m_markerListModel, &MarkerListModel::categoriesChanged, this, &MarkerCategoryButton::changed);
0190     Q_EMIT changed();
0191 }
0192 
0193 void MarkerCategoryButton::setAllowAll(bool allowAll)
0194 {
0195     m_allowAll = allowAll;
0196     Q_EMIT changed();
0197 }
0198 
0199 void MarkerCategoryButton::setOnlyUsed(bool onlyUsed)
0200 {
0201     m_onlyUsed = onlyUsed;
0202     if (m_onlyUsed) {
0203         connect(m_menu, &QMenu::aboutToShow, this, &MarkerCategoryButton::changed);
0204     }
0205     Q_EMIT changed();
0206 }