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"