Warning, file /office/skrooge/skgbasegui/skgshow.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /***************************************************************************
0002  * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
0003  * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  ***************************************************************************/
0006 /** @file
0007  * A widget to select what to show.
0008  *
0009  * @author Stephane MANKOWSKI / Guillaume DE BURE
0010  */
0011 #include "skgshow.h"
0012 
0013 #include <klocalizedstring.h>
0014 #include <qdom.h>
0015 #include <qicon.h>
0016 #include <qwidgetaction.h>
0017 
0018 #include "skgperiodedit.h"
0019 #include "skgservices.h"
0020 
0021 SKGShow::SKGShow(QWidget* iParent)
0022     : QToolButton(iParent), m_mode(OR), m_inTrigger(false), m_displayTitle(true)
0023 {
0024     setPopupMode(QToolButton::InstantPopup);
0025     setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
0026     setAutoRaise(true);
0027 
0028     m_menu = new SKGMenu(this);
0029     setMenu(m_menu);
0030 
0031     // Time to emit stateChanged
0032     m_timer.setSingleShot(true);
0033     connect(&m_timer, &QTimer::timeout, this, &SKGShow::stateChanged, Qt::QueuedConnection);
0034 
0035     hide();
0036 }
0037 
0038 SKGShow::~SKGShow()
0039 {
0040     m_menu = nullptr;
0041 }
0042 
0043 SKGShow::OperatorMode SKGShow::getMode()
0044 {
0045     return m_mode;
0046 }
0047 
0048 void SKGShow::setMode(SKGShow::OperatorMode iMode)
0049 {
0050     if (m_mode != iMode) {
0051         m_mode = iMode;
0052         Q_EMIT modified();
0053     }
0054 }
0055 
0056 QString SKGShow::getState()
0057 {
0058     QStringList itemsChecked;
0059     if (m_menu != nullptr) {
0060         QList<QAction*> actionsList = m_menu->actions();
0061         int nb = actionsList.count();
0062         itemsChecked.reserve(nb);
0063         for (int i = 0; i < nb; ++i) {
0064             QAction* act = actionsList.at(i);
0065             if (act != nullptr) {
0066                 auto* wact = qobject_cast<QWidgetAction*>(act);
0067                 if (wact != nullptr) {
0068                     auto* pedit = qobject_cast<SKGPeriodEdit*>(wact->defaultWidget());
0069                     itemsChecked.push_back(act->data().toString() % ":" % pedit->getState());
0070                 } else {
0071                     if (act->isChecked()) {
0072                         itemsChecked.push_back(act->data().toString());
0073                     }
0074                 }
0075             }
0076         }
0077     }
0078     return SKGServices::stringsToCsv(itemsChecked);
0079 }
0080 
0081 void SKGShow::setDefaultState(const QString& iState)
0082 {
0083     m_defaultState = iState;
0084     setState(m_defaultState);
0085 }
0086 
0087 void SKGShow::setState(const QString& iState)
0088 {
0089     if (m_menu != nullptr) {
0090         QStringList itemsChecked = SKGServices::splitCSVLine(iState.isEmpty() ? m_defaultState : iState);
0091 
0092         int nb = m_actions.count();
0093         for (int i = 0; i < nb; ++i) {
0094             QAction* act = m_actions.at(i);
0095             if (act != nullptr) {
0096                 QString identifier = m_actions.at(i)->data().toString();
0097                 auto* wact = qobject_cast<QWidgetAction*>(act);
0098                 if (wact != nullptr) {
0099                     auto* pedit = qobject_cast<SKGPeriodEdit*>(wact->defaultWidget());
0100                     for (const auto& item : qAsConst(itemsChecked)) {
0101                         if (item.startsWith(identifier % ":")) {
0102                             pedit->setState(item.right(item.length() - identifier.length() - 1));
0103                             break;
0104                         }
0105                     }
0106                 } else {
0107                     act->setChecked(itemsChecked.contains(identifier));
0108                 }
0109             }
0110         }
0111 
0112         // Change tooltip
0113         setToolTip(getTitle());
0114 
0115         // Emit event
0116         emit stateChanged();
0117     }
0118 }
0119 
0120 QString SKGShow::getWhereClause() const
0121 {
0122     QString wc;
0123     if (m_menu != nullptr) {
0124         QList<QAction*> actionsList = m_menu->actions();
0125         int nb = actionsList.count();
0126         bool noCheck = true;
0127         for (int i = 0; i < nb; ++i) {
0128             QAction* act = actionsList.at(i);
0129 
0130             if (act != nullptr) {
0131                 auto* wact = qobject_cast<QWidgetAction*>(act);
0132                 if (wact != nullptr) {
0133                     auto* pedit = qobject_cast<SKGPeriodEdit*>(wact->defaultWidget());
0134                     if (!wc.isEmpty()) {
0135                         wc += (m_mode == OR ? QStringLiteral(" OR ") : QStringLiteral(" AND "));
0136                     }
0137                     wc += '(' % pedit->getWhereClause() % ')';
0138                     noCheck = false;
0139 
0140                 } else {
0141                     if (act->isChecked()) {
0142                         if (!wc.isEmpty()) {
0143                             wc += (m_mode == OR ? QStringLiteral(" OR ") : QStringLiteral(" AND "));
0144                         }
0145                         wc += '(' % m_whereclause.value(act) % ')';
0146                         noCheck = false;
0147 
0148                         if (m_whereclause.value(act).isEmpty()) {
0149                             wc = QLatin1String("");
0150                             break;
0151                         }
0152                     }
0153                 }
0154             }
0155         }
0156         if ((nb != 0) && noCheck) {
0157             wc = QStringLiteral("1=0");
0158         }
0159     }
0160     return wc;
0161 }
0162 
0163 QString SKGShow::getTitle() const
0164 {
0165     QString wc;
0166     if (m_menu != nullptr) {
0167         int nb = m_actions.count();
0168         for (int i = 0; i < nb; ++i) {
0169             QAction* act = m_actions.at(i);
0170             if (act != nullptr) {
0171                 auto* wact = qobject_cast<QWidgetAction*>(act);
0172                 if (wact != nullptr) {
0173                     auto* pedit = qobject_cast<SKGPeriodEdit*>(wact->defaultWidget());
0174                     if (!wc.isEmpty()) {
0175                         wc += (m_mode == OR ? QStringLiteral(" + ") : QStringLiteral(" , "));
0176                     }
0177                     wc += pedit->text();
0178                 } else {
0179                     if (act->isChecked()) {
0180                         if (!wc.isEmpty()) {
0181                             wc += (m_mode == OR ? QStringLiteral(" + ") : QStringLiteral(" , "));
0182                         }
0183                         wc += act->toolTip();
0184                     }
0185                 }
0186             }
0187         }
0188     }
0189     return wc;
0190 }
0191 
0192 void SKGShow::clear()
0193 {
0194     m_check_to_check.clear();
0195     m_uncheck_to_check.clear();
0196     m_check_to_uncheck.clear();
0197     m_uncheck_to_uncheck.clear();
0198     m_actions.clear();
0199     m_icons.clear();
0200     m_whereclause.clear();
0201     m_defaultState.clear();
0202     m_menu->clear();
0203 }
0204 
0205 int SKGShow::count()
0206 {
0207     return m_check_to_check.count();
0208 }
0209 
0210 int SKGShow::addGroupedItem(const QString& iIdentifier, const QString& iText, const QString& iIcon,
0211                             const QString& iWhereClose, const QString& iGroup, const QKeySequence& iShortcut)
0212 {
0213     if (m_menu != nullptr) {
0214         QActionGroup* groupAction = m_groups.value(iGroup);
0215         if (groupAction == nullptr) {
0216             groupAction = new QActionGroup(this);
0217             m_groups[iGroup] = groupAction;
0218         }
0219 
0220         QString name = iText;
0221         name = name.replace('&', QStringLiteral("&&"));
0222         QAction* act = m_menu->addAction(name);
0223         if (act != nullptr) {
0224             act->setToolTip(name);
0225             act->setIcon(SKGServices::fromTheme(iIcon));
0226             act->setData(iIdentifier);
0227             act->setCheckable(true);
0228             if (!iShortcut.isEmpty()) {
0229                 act->setShortcuts(QList<QKeySequence>() << iShortcut << QKeySequence::fromString("Ctrl+Alt+" % iShortcut.toString()));
0230             }
0231 
0232             m_check_to_check[act] = QLatin1String("");
0233             m_check_to_uncheck[act] = QLatin1String("");
0234             m_uncheck_to_check[act] = QLatin1String("");
0235             m_uncheck_to_uncheck[act] = QLatin1String("");
0236             m_actions.push_back(act);
0237             m_icons.push_back(iIcon);
0238 
0239             m_whereclause[act] = iWhereClose;
0240 
0241             connect(act, &QAction::toggled, this, &SKGShow::trigger);
0242 
0243             groupAction->addAction(act);
0244         }
0245 
0246         show();
0247 
0248         return (m_actions.count() - 1);
0249     }
0250     return -1;
0251 }
0252 
0253 int SKGShow::addPeriodItem(const QString& iIdentifier)
0254 {
0255     if (m_menu != nullptr) {
0256         auto m_periodEdit1 = new SKGPeriodEdit(this);
0257 
0258         // Set default
0259         QDomDocument doc(QStringLiteral("SKGML"));
0260         QDomElement root = doc.createElement(QStringLiteral("parameters"));
0261         doc.appendChild(root);
0262         root.setAttribute(QStringLiteral("period"), SKGServices::intToString(static_cast<int>(SKGPeriodEdit::ALL)));
0263         m_periodEdit1->setState(doc.toString());
0264 
0265         // Add widget in menu
0266         auto act = new QWidgetAction(this);
0267         if (act != nullptr) {
0268             act->setData(iIdentifier);
0269             act->setDefaultWidget(m_periodEdit1);
0270 
0271             m_check_to_check[act] = QLatin1String("");
0272             m_check_to_uncheck[act] = QLatin1String("");
0273             m_uncheck_to_check[act] = QLatin1String("");
0274             m_uncheck_to_uncheck[act] = QLatin1String("");
0275             m_actions.push_back(act);
0276             m_icons.push_back(QLatin1String(""));
0277 
0278             m_whereclause[act] = QLatin1String("");
0279 
0280             connect(m_periodEdit1, &SKGPeriodEdit::changed, this, &SKGShow::triggerRefreshOnly);
0281 
0282             m_menu->addAction(act);
0283         }
0284 
0285         show();
0286 
0287         return (m_actions.count() - 1);
0288     }
0289     return -1;
0290 }
0291 
0292 int SKGShow::addItem(const QString& iIdentifier, const QString& iText, const QString& iIcon,
0293                      const QString& iWhereClose,
0294                      const QString& iListIdToCheckWhenChecked,
0295                      const QString& iListIdToUncheckWhenChecked,
0296                      const QString& iListIdToCheckWhenUnchecked,
0297                      const QString& iListIdToUncheckWhenUnchecked,
0298                      const QKeySequence& iShortcut
0299                     )
0300 {
0301     if (m_menu != nullptr) {
0302         QString name = iText;
0303         name = name.replace('&', QStringLiteral("&&"));
0304         QAction* act = m_menu->addAction(name);
0305         if (act != nullptr) {
0306             act->setToolTip(name);
0307             act->setIcon(SKGServices::fromTheme(iIcon));
0308             act->setData(iIdentifier);
0309             act->setCheckable(true);
0310             if (!iShortcut.isEmpty()) {
0311                 act->setShortcuts(QList<QKeySequence>() << iShortcut << QKeySequence::fromString("Ctrl+Alt+" % iShortcut.toString()));
0312             }
0313 
0314             m_check_to_check[act] = iListIdToCheckWhenChecked;
0315             m_check_to_uncheck[act] = iListIdToUncheckWhenChecked;
0316             m_uncheck_to_check[act] = iListIdToCheckWhenUnchecked;
0317             m_uncheck_to_uncheck[act] = iListIdToUncheckWhenUnchecked;
0318             m_actions.push_back(act);
0319             m_icons.push_back(iIcon);
0320 
0321             m_whereclause[act] = iWhereClose;
0322 
0323             connect(act, &QAction::toggled, this, &SKGShow::trigger);
0324         }
0325 
0326         show();
0327 
0328         return (m_actions.count() - 1);
0329     }
0330     return -1;
0331 }
0332 
0333 void SKGShow::setListIdToCheckWhenChecked(int iIndex, const QString& iIds)
0334 {
0335     m_check_to_check[m_actions.at(iIndex)] = iIds;
0336 }
0337 
0338 void SKGShow::setListIdToCheckWhenUnchecked(int iIndex, const QString& iIds)
0339 {
0340     m_uncheck_to_check[m_actions.at(iIndex)] = iIds;
0341 }
0342 
0343 void SKGShow::setListIdToUncheckWhenChecked(int iIndex, const QString& iIds)
0344 {
0345     m_check_to_uncheck[m_actions.at(iIndex)] = iIds;
0346 }
0347 
0348 void SKGShow::setListIdToUncheckWhenUnchecked(int iIndex, const QString& iIds)
0349 {
0350     m_uncheck_to_uncheck[m_actions.at(iIndex)] = iIds;
0351 }
0352 
0353 void SKGShow::addSeparator()
0354 {
0355     if (m_menu != nullptr) {
0356         m_menu->addSeparator();
0357     }
0358 }
0359 
0360 void SKGShow::trigger()
0361 {
0362     auto* act = qobject_cast<QAction*>(sender());
0363     if ((act != nullptr) && !m_inTrigger) {
0364         m_inTrigger = true;
0365 
0366         // Apply rules
0367         QStringList over;
0368         if (act->isChecked()) {
0369             {
0370                 // Check items
0371                 QStringList items = SKGServices::splitCSVLine(m_check_to_check.value(act));
0372                 int nb = items.count();
0373                 for (int i = 0; i < nb; ++i) {
0374                     QAction* act2 = getAction(items.at(i));
0375                     if ((act2 != nullptr) && act2 != act) {
0376                         act2->setChecked(true);
0377                     }
0378                 }
0379             }
0380 
0381             {
0382                 // Uncheck items
0383                 QStringList items = SKGServices::splitCSVLine(m_check_to_uncheck.value(act));
0384                 int nb = items.count();
0385                 for (int i = 0; i < nb; ++i) {
0386                     QAction* act2 = getAction(items.at(i));
0387                     if ((act2 != nullptr) && act2 != act) {
0388                         act2->setChecked(false);
0389                     }
0390                 }
0391             }
0392         } else {
0393             {
0394                 // Check items
0395                 QStringList items = SKGServices::splitCSVLine(m_uncheck_to_check.value(act));
0396                 int nb = items.count();
0397                 for (int i = 0; i < nb; ++i) {
0398                     QAction* act2 = getAction(items.at(i));
0399                     if ((act2 != nullptr) && act2 != act) {
0400                         act2->setChecked(true);
0401                     }
0402                 }
0403             }
0404 
0405             {
0406                 // Uncheck items
0407                 QStringList items = SKGServices::splitCSVLine(m_uncheck_to_uncheck.value(act));
0408                 int nb = items.count();
0409                 for (int i = 0; i < nb; ++i) {
0410                     QAction* act2 = getAction(items.at(i));
0411                     if ((act2 != nullptr) && act2 != act) {
0412                         act2->setChecked(false);
0413                     }
0414                 }
0415             }
0416         }
0417 
0418         // Change tooltip
0419         setToolTip(getTitle());
0420 
0421         // Change icon
0422         QStringList icons;
0423         QString mainIcon;
0424         if (m_menu != nullptr) {
0425             int nb = m_actions.count();
0426             icons.reserve(nb);
0427             for (int i = 0; i < nb; ++i) {
0428                 QAction* act2 = m_actions.at(i);
0429                 if ((act2 != nullptr) && act2->isChecked()) {
0430                     if (!m_icons.at(i).isEmpty()) {
0431                         if (mainIcon.isEmpty()) {
0432                             mainIcon = m_icons.at(i);
0433                         } else {
0434                             icons.push_back(m_icons.at(i));
0435                         }
0436                     } else {
0437                         if (mainIcon.isEmpty()) {
0438                             mainIcon = QStringLiteral("show-menu");
0439                         }
0440                     }
0441                 }
0442             }
0443         }
0444         if (mainIcon.isEmpty()) {
0445             mainIcon = QStringLiteral("show-menu");
0446         }
0447         setIcon(SKGServices::fromTheme(mainIcon, icons));
0448 
0449         triggerRefreshOnly();
0450 
0451         m_inTrigger = false;
0452     }
0453 }
0454 
0455 void SKGShow::triggerRefreshOnly()
0456 {
0457     // Emit event
0458     m_timer.start(300);
0459 
0460     // Change title
0461     refreshTitle();
0462 }
0463 
0464 
0465 bool SKGShow::getDisplayTitle()
0466 {
0467     return m_displayTitle;
0468 }
0469 
0470 void SKGShow::setDisplayTitle(bool iDisplay)
0471 {
0472     if (m_displayTitle != iDisplay) {
0473         m_displayTitle = iDisplay;
0474         refreshTitle();
0475         Q_EMIT modified();
0476     }
0477 }
0478 
0479 void SKGShow::refreshTitle()
0480 {
0481     if (m_displayTitle) {
0482         setText(i18n("Show: %1", getTitle()));
0483     } else {
0484         setText(i18n("Show"));
0485     }
0486 }
0487 
0488 QAction* SKGShow::getAction(const QString& iIdentifier) const
0489 {
0490     QAction* output = nullptr;
0491     if (m_menu != nullptr) {
0492         QList<QAction*> actionsList = m_menu->actions();
0493         int nb = actionsList.count();
0494         for (int i = 0; (output == nullptr) && i < nb; ++i) {
0495             QAction* act = actionsList.at(i);
0496             if ((act != nullptr) && act->data().toString() == iIdentifier) {
0497                 output = act;
0498             }
0499         }
0500     }
0501     return output;
0502 }
0503 
0504