File indexing completed on 2025-03-09 03:57:05

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-05-01
0007  * Description : an abstract rule class
0008  *
0009  * SPDX-FileCopyrightText: 2009-2012 by Andi Clemens <andi dot clemens at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "rule.h"
0016 
0017 // Qt includes
0018 
0019 #include <QAction>
0020 #include <QMenu>
0021 #include <QPushButton>
0022 #include <QRegularExpression>
0023 #include <QString>
0024 #include <QIcon>
0025 #include <QApplication>
0026 #include <QStyle>
0027 
0028 namespace Digikam
0029 {
0030 
0031 class Q_DECL_HIDDEN Rule::Private
0032 {
0033 public:
0034 
0035     explicit Private()
0036         : useTokenMenu(false)
0037     {
0038     }
0039 
0040     bool                    useTokenMenu;
0041 
0042     QString                 description;
0043     QString                 iconName;
0044     QRegularExpression      regExp;
0045 
0046     TokenList               tokens;
0047 };
0048 
0049 Rule::Rule(const QString& name)
0050     : QObject(nullptr),
0051       d(new Private)
0052 {
0053     setObjectName(name);
0054 }
0055 
0056 Rule::Rule(const QString& name, const QString& icon)
0057     : QObject(nullptr),
0058       d(new Private)
0059 {
0060     setObjectName(name);
0061     setIcon(icon);
0062 }
0063 
0064 Rule::~Rule()
0065 {
0066     qDeleteAll(d->tokens);
0067     d->tokens.clear();
0068 
0069     delete d;
0070 }
0071 
0072 void Rule::setIcon(const QString& iconName)
0073 {
0074     d->iconName = iconName;
0075 }
0076 
0077 QPixmap Rule::icon(Rule::IconType type) const
0078 {
0079     QPixmap icon;
0080 
0081     switch (type)
0082     {
0083         case Dialog:
0084             icon = QIcon::fromTheme(d->iconName).pixmap(48);
0085             break;
0086 
0087         default:
0088             icon = QIcon::fromTheme(d->iconName).pixmap(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize));
0089             break;
0090     }
0091 
0092     return icon;
0093 }
0094 
0095 void Rule::setDescription(const QString& desc)
0096 {
0097     d->description = desc;
0098 }
0099 
0100 QString Rule::description() const
0101 {
0102     return d->description;
0103 }
0104 
0105 QRegularExpression& Rule::regExp() const
0106 {
0107     return d->regExp;
0108 }
0109 
0110 void Rule::setRegExp(const QRegularExpression& regExp)
0111 {
0112     d->regExp = regExp;
0113 }
0114 
0115 QPushButton* Rule::createButton(const QString& name, const QIcon& icon)
0116 {
0117     const int maxHeight       = 28;
0118     QPushButton* const button = new QPushButton;
0119     button->setText(name);
0120     button->setIcon(icon);
0121     button->setMinimumHeight(maxHeight);
0122     button->setMaximumHeight(maxHeight);
0123 
0124     return button;
0125 }
0126 
0127 QPushButton* Rule::registerButton(QWidget* parent)
0128 {
0129     QPushButton* button = createButton(objectName(), icon());
0130 
0131     QList<QAction*> actions;
0132 
0133     if (d->tokens.count() > 1 && d->useTokenMenu)
0134     {
0135         QMenu* const menu = new QMenu(button);
0136 
0137         Q_FOREACH (Token* const token, d->tokens)
0138         {
0139             actions << token->action();
0140         }
0141 
0142         menu->addActions(actions);
0143         button->setMenu(menu);
0144     }
0145     else if (!d->tokens.isEmpty())
0146     {
0147         Token* const token = d->tokens.first();
0148 
0149         connect(button, SIGNAL(clicked()),
0150                 token, SLOT(slotTriggered()));
0151     }
0152 
0153     button->setParent(parent);
0154 
0155     return button;
0156 }
0157 
0158 QAction* Rule::registerMenu(QMenu* parent)
0159 {
0160     QAction* action = nullptr;
0161 
0162     if (d->tokens.count() > 1 && d->useTokenMenu)
0163     {
0164         QMenu* const menu = new QMenu(parent);
0165         QList<QAction*> actions;
0166 
0167         Q_FOREACH (Token* const token, d->tokens)
0168         {
0169             actions << token->action();
0170         }
0171 
0172         menu->addActions(actions);
0173         action = parent->addMenu(menu);
0174     }
0175     else if (!d->tokens.isEmpty())
0176     {
0177         action = d->tokens.first()->action();
0178         parent->insertAction(nullptr, action);
0179     }
0180 
0181     if (action)
0182     {
0183         action->setText(objectName());
0184         action->setIcon(icon());
0185     }
0186 
0187     return action;
0188 }
0189 
0190 bool Rule::addToken(const QString& id, const QString& description, const QString& actionName)
0191 {
0192     if (id.isEmpty() || description.isEmpty())
0193     {
0194         return false;
0195     }
0196 
0197     Token* const token = new Token(id, description);
0198 
0199     if (!actionName.isEmpty())
0200     {
0201         token->action()->setText(actionName);
0202     }
0203 
0204     connect(token, SIGNAL(signalTokenTriggered(QString)),
0205             this, SLOT(slotTokenTriggered(QString)));
0206 
0207     d->tokens << token;
0208 
0209     return true;
0210 }
0211 
0212 void Rule::setUseTokenMenu(bool value)
0213 {
0214     d->useTokenMenu = value;
0215 }
0216 
0217 bool Rule::useTokenMenu() const
0218 {
0219     return d->useTokenMenu;
0220 }
0221 
0222 TokenList& Rule::tokens() const
0223 {
0224     return d->tokens;
0225 }
0226 
0227 void Rule::slotTokenTriggered(const QString& token)
0228 {
0229     Q_EMIT signalTokenTriggered(token);
0230 }
0231 
0232 bool Rule::isValid() const
0233 {
0234     return (!d->tokens.isEmpty() && !d->regExp.pattern().isEmpty() && d->regExp.isValid());
0235 }
0236 
0237 void Rule::reset()
0238 {
0239 }
0240 
0241 QString Rule::escapeToken(const QString& token)
0242 {
0243     QString escaped = token;
0244 
0245     // replace special characters for renaming options
0246 
0247     escaped.replace(QLatin1Char('['), QLatin1String("\\["));
0248     escaped.replace(QLatin1Char(']'), QLatin1String("\\]"));
0249 
0250     // replace special characters for modifiers
0251 
0252     escaped.replace(QLatin1Char('{'), QLatin1String("\\{"));
0253     escaped.replace(QLatin1Char('}'), QLatin1String("\\}"));
0254 
0255     return escaped;
0256 }
0257 
0258 ParseResults Rule::parse(ParseSettings& settings)
0259 {
0260     ParseResults parsedResults;
0261     const QRegularExpression& reg = regExp();
0262     const QString& parseString    = settings.parseString;
0263     QRegularExpressionMatch         match;
0264 
0265     int pos = 0;
0266 
0267     while (pos > -1)
0268     {
0269         pos = parseString.indexOf(reg, pos, &match);
0270 
0271         if (pos > -1)
0272         {
0273             QString result = parseOperation(settings, match);
0274 
0275             ParseResults::ResultsKey   k(pos, match.captured(0).count());
0276             ParseResults::ResultsValue v(match.captured(0), result);
0277             parsedResults.addEntry(k, v);
0278             pos           += match.capturedLength();
0279         }
0280     }
0281 
0282     return parsedResults;
0283 }
0284 
0285 } // namespace Digikam
0286 
0287 #include "moc_rule.cpp"