File indexing completed on 2025-03-09 03:57:08
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-05-22 0007 * Description : a control widget for the AdvancedRename utility 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 "advancedrenamewidget.h" 0016 0017 // Qt includes 0018 0019 #include <QAction> 0020 #include <QApplication> 0021 #include <QGridLayout> 0022 #include <QIcon> 0023 #include <QMenu> 0024 #include <QPushButton> 0025 #include <QStyle> 0026 #include <QToolButton> 0027 0028 // KDE includes 0029 0030 #include <kconfiggroup.h> 0031 #include <klocalizedstring.h> 0032 #include <ksharedconfig.h> 0033 0034 // Local includes 0035 0036 #include "dexpanderbox.h" 0037 #include "advancedrenameinput.h" 0038 #include "defaultrenameparser.h" 0039 #include "dynamiclayout.h" 0040 #include "tooltipcreator.h" 0041 #include "tooltipdialog.h" 0042 0043 namespace Digikam 0044 { 0045 0046 class Q_DECL_HIDDEN AdvancedRenameWidget::Private 0047 { 0048 typedef AdvancedRenameWidget::ControlWidgets CWMask; 0049 typedef AdvancedRenameWidget::LayoutStyle LStyle; 0050 0051 public: 0052 0053 explicit Private() : 0054 configExpandedStateDefault (true), 0055 tooltipToggleButton (nullptr), 0056 modifiersToolButton (nullptr), 0057 optionsButton (nullptr), 0058 modifiersButton (nullptr), 0059 btnContainer (nullptr), 0060 tooltipDialog (nullptr), 0061 renameInput (nullptr), 0062 parser (nullptr), 0063 optionsLabel (nullptr), 0064 controlWidgetsMask (AdvancedRenameWidget::DefaultControls), 0065 layoutStyle (AdvancedRenameWidget::LayoutNormal) 0066 { 0067 } 0068 0069 static const QString configGroupName; 0070 static const QString configExpandedStateEntry; 0071 0072 bool configExpandedStateDefault; 0073 0074 QToolButton* tooltipToggleButton; 0075 QToolButton* modifiersToolButton; 0076 0077 QPushButton* optionsButton; 0078 QPushButton* modifiersButton; 0079 0080 QWidget* btnContainer; 0081 0082 TooltipDialog* tooltipDialog; 0083 AdvancedRenameInput* renameInput; 0084 Parser* parser; 0085 DLabelExpander* optionsLabel; 0086 0087 CWMask controlWidgetsMask; 0088 LStyle layoutStyle; 0089 }; 0090 0091 const QString AdvancedRenameWidget::Private::configGroupName(QLatin1String("AdvancedRename Widget")); 0092 const QString AdvancedRenameWidget::Private::configExpandedStateEntry(QLatin1String("Options are expanded")); 0093 0094 // -------------------------------------------------------- 0095 0096 AdvancedRenameWidget::AdvancedRenameWidget(QWidget* const parent) 0097 : QWidget(parent), 0098 d (new Private) 0099 { 0100 setupWidgets(); 0101 } 0102 0103 AdvancedRenameWidget::~AdvancedRenameWidget() 0104 { 0105 writeSettings(); 0106 delete d; 0107 } 0108 0109 QString AdvancedRenameWidget::parseString() const 0110 { 0111 return d->renameInput->text(); 0112 } 0113 0114 void AdvancedRenameWidget::setParseString(const QString& text) 0115 { 0116 d->renameInput->setText(text); 0117 } 0118 0119 void AdvancedRenameWidget::setParseTimerDuration(int milliseconds) 0120 { 0121 d->renameInput->setParseTimerDuration(milliseconds); 0122 } 0123 0124 void AdvancedRenameWidget::clearParseString() 0125 { 0126 d->renameInput->slotClearText(); 0127 } 0128 0129 void AdvancedRenameWidget::clear() 0130 { 0131 d->renameInput->slotClearTextAndHistory(); 0132 } 0133 0134 QString AdvancedRenameWidget::parse(ParseSettings& settings) const 0135 { 0136 if (!d->parser) 0137 { 0138 return QString(); 0139 } 0140 0141 settings.parseString = d->renameInput->text(); 0142 0143 QString parsed; 0144 parsed = d->parser->parse(settings); 0145 0146 return parsed; 0147 } 0148 0149 void AdvancedRenameWidget::createToolTip() 0150 { 0151 d->tooltipDialog->clearTooltip(); 0152 0153 if (d->parser) 0154 { 0155 d->tooltipDialog->setTooltip(TooltipCreator::getInstance().tooltip(d->parser)); 0156 } 0157 } 0158 0159 void AdvancedRenameWidget::slotToolTipButtonToggled(bool checked) 0160 { 0161 Q_UNUSED(checked) 0162 0163 if (!d->tooltipDialog->isVisible()) 0164 { 0165 d->tooltipDialog->show(); 0166 } 0167 0168 d->tooltipDialog->raise(); 0169 } 0170 0171 void AdvancedRenameWidget::setLayoutStyle(LayoutStyle style) 0172 { 0173 d->layoutStyle = style; 0174 calculateLayout(); 0175 } 0176 0177 void AdvancedRenameWidget::setControlWidgets(ControlWidgets mask) 0178 { 0179 d->controlWidgetsMask = mask; 0180 0181 // we need a parser and at least one renaming option to successfully use 0182 // this widget. 0183 0184 bool enable = d->parser && !(d->parser->options().isEmpty()); 0185 0186 // enable the modifier toolbutton if environment has been set up correctly 0187 0188 bool enableModBtn = enable && !(d->parser->modifiers().isEmpty()); 0189 0190 d->renameInput->setEnabled(enable); 0191 d->tooltipToggleButton->setVisible(enable && (mask & ToolTipButton)); 0192 0193 // layout specific 0194 0195 if (d->layoutStyle == LayoutNormal) 0196 { 0197 d->optionsLabel->setVisible(enable && (mask & TokenButtons)); 0198 d->modifiersToolButton->setVisible(enableModBtn && (mask & ModifierToolButton)); 0199 } 0200 else 0201 { 0202 d->optionsButton->setVisible(enableModBtn && (mask & TokenButtons)); 0203 d->modifiersButton->setVisible(enableModBtn && (mask & ModifierToolButton)); 0204 } 0205 } 0206 0207 QMenu* AdvancedRenameWidget::createControlsMenu(QWidget* const parent, const RulesList& rules) 0208 { 0209 QMenu* const menu = new QMenu(parent); 0210 QAction* action = nullptr; 0211 0212 Q_FOREACH (Rule* const rule, rules) 0213 { 0214 action = rule->registerMenu(menu); 0215 0216 if (!action) 0217 { 0218 continue; 0219 } 0220 0221 connect(rule, SIGNAL(signalTokenTriggered(QString)), 0222 d->renameInput, SLOT(slotAddToken(QString))); 0223 } 0224 0225 return menu; 0226 } 0227 0228 void AdvancedRenameWidget::registerParserControls() 0229 { 0230 if (d->parser) 0231 { 0232 setupWidgets(); 0233 0234 RulesList optionsList = d->parser->options(); 0235 RulesList modifiersList = d->parser->modifiers(); 0236 0237 if (d->layoutStyle == LayoutNormal) 0238 { 0239 // register options 0240 0241 QPushButton* btn = nullptr; 0242 const int cmargin = qMin(style()->pixelMetric(QStyle::PM_LayoutLeftMargin), 0243 qMin(style()->pixelMetric(QStyle::PM_LayoutTopMargin), 0244 qMin(style()->pixelMetric(QStyle::PM_LayoutRightMargin), 0245 style()->pixelMetric(QStyle::PM_LayoutBottomMargin)))); 0246 0247 DynamicLayout* const layout = new DynamicLayout(cmargin, cmargin); 0248 0249 Q_FOREACH (Rule* const p, d->parser->options()) 0250 { 0251 btn = p->registerButton(this); 0252 0253 if (!btn) 0254 { 0255 continue; 0256 } 0257 0258 // set button tooltip 0259 0260 btn->setToolTip(p->description()); 0261 0262 layout->addWidget(btn); 0263 0264 connect(p, SIGNAL(signalTokenTriggered(QString)), 0265 d->renameInput, SLOT(slotAddToken(QString))); 0266 } 0267 0268 d->btnContainer->setLayout(layout); 0269 setMinimumWidth(d->btnContainer->layout()->sizeHint().width()); 0270 0271 // register modifiers 0272 0273 QMenu* const modifiersMenu = createControlsMenu(d->modifiersToolButton, modifiersList); 0274 d->modifiersToolButton->setMenu(modifiersMenu); 0275 } 0276 else // LayoutCompact 0277 { 0278 // register options 0279 0280 QMenu* const optionsMenu = createControlsMenu(d->optionsButton, optionsList); 0281 d->optionsButton->setMenu(optionsMenu); 0282 0283 // register modifiers 0284 0285 QMenu* const modifiersMenu = createControlsMenu(d->modifiersButton, modifiersList); 0286 d->modifiersButton->setMenu(modifiersMenu); 0287 } 0288 0289 // -------------------------------------------------------- 0290 0291 d->renameInput->setParser(d->parser); 0292 createToolTip(); 0293 } 0294 } 0295 0296 Parser* AdvancedRenameWidget::parser() const 0297 { 0298 return d->parser; 0299 } 0300 0301 void AdvancedRenameWidget::setParser(Parser* parser) 0302 { 0303 if (!parser) 0304 { 0305 return; 0306 } 0307 0308 d->parser = parser; 0309 0310 calculateLayout(); 0311 } 0312 0313 void AdvancedRenameWidget::calculateLayout() 0314 { 0315 registerParserControls(); 0316 setControlWidgets(d->controlWidgetsMask); 0317 } 0318 0319 void AdvancedRenameWidget::setupWidgets() 0320 { 0321 /* 0322 * This methods needs to delete all main widgets, do not remove the delete lines! 0323 * If a new parser is set or the layout has changed, we need to call setupWidgets() again. 0324 * So any widget that is created in here needs to be removed first, to avoid memory leaks and 0325 * duplicate signal/slot connections. 0326 */ 0327 delete d->tooltipDialog; 0328 delete d->renameInput; 0329 delete d->tooltipToggleButton; 0330 delete d->optionsButton; 0331 delete d->modifiersButton; 0332 delete d->btnContainer; 0333 delete d->optionsLabel; 0334 delete d->modifiersToolButton; 0335 0336 // -------------------------------------------------------- 0337 0338 d->tooltipDialog = new TooltipDialog(this); 0339 d->tooltipDialog->resize(650, 530); 0340 0341 d->renameInput = new AdvancedRenameInput; 0342 d->renameInput->setToolTip(i18n("<p>Enter your renaming pattern here. Use the access buttons to quickly add renaming " 0343 "options and modifiers. For further explanation, use the information button.</p>")); 0344 0345 // -------------------------------------------------------- 0346 0347 d->tooltipToggleButton = new QToolButton; 0348 d->tooltipToggleButton->setIcon(QIcon::fromTheme(QLatin1String("dialog-information"))); 0349 d->tooltipToggleButton->setToolTip(i18n("Show a list of all available options")); 0350 0351 // -------------------------------------------------------- 0352 0353 QString modifiersStr = i18n("Modifiers"); 0354 QIcon modifiersIcon = QIcon::fromTheme(QLatin1String("document-edit")); 0355 QString modifiersTooltip = i18n("<p>Add a modifier to a renaming option. " 0356 "To activate this button, place the cursor behind a renaming option " 0357 "or an already assigned modifier.</p>"); 0358 0359 // -------------------------------------------------------- 0360 0361 delete layout(); 0362 QGridLayout* const mainLayout = new QGridLayout; 0363 0364 if (d->layoutStyle == LayoutNormal) 0365 { 0366 d->btnContainer = new QWidget(this); 0367 0368 d->optionsLabel = new DLabelExpander(this); 0369 d->optionsLabel->setText(i18n("Renaming Options")); 0370 d->optionsLabel->setWidget(d->btnContainer); 0371 d->optionsLabel->setLineVisible(false); 0372 0373 d->modifiersToolButton = new QToolButton; 0374 d->modifiersToolButton->setPopupMode(QToolButton::InstantPopup); 0375 d->modifiersToolButton->setText(modifiersStr); 0376 d->modifiersToolButton->setIcon(modifiersIcon); 0377 d->modifiersToolButton->setToolTip(modifiersTooltip); 0378 0379 mainLayout->addWidget(d->renameInput, 0, 0, 1, 1); 0380 mainLayout->addWidget(d->modifiersToolButton, 0, 1, 1, 1); 0381 mainLayout->addWidget(d->tooltipToggleButton, 0, 2, 1, 1); 0382 mainLayout->addWidget(d->optionsLabel, 1, 0, 1, -1); 0383 mainLayout->setColumnStretch(0, 10); 0384 } 0385 else 0386 { 0387 d->optionsButton = new QPushButton; 0388 d->optionsButton->setText(i18n("Options")); 0389 d->optionsButton->setIcon(QIcon::fromTheme(QLatin1String("configure"))); 0390 d->optionsButton->setToolTip(i18n("<p>Add renaming options to the parse string.</p>")); 0391 0392 // -------------------------------------------------------- 0393 0394 d->modifiersButton = new QPushButton; 0395 d->modifiersButton->setText(modifiersStr); 0396 d->modifiersButton->setIcon(modifiersIcon); 0397 d->modifiersButton->setToolTip(modifiersTooltip); 0398 0399 mainLayout->addWidget(d->renameInput, 0, 0, 1, -1); 0400 mainLayout->addWidget(d->optionsButton, 1, 0, 1, 1); 0401 mainLayout->addWidget(d->modifiersButton, 1, 1, 1, 1); 0402 mainLayout->addWidget(d->tooltipToggleButton, 1, 3, 1, 1); 0403 mainLayout->setColumnStretch(2, 10); 0404 } 0405 0406 const int cmargin = qMin(style()->pixelMetric(QStyle::PM_LayoutLeftMargin), 0407 qMin(style()->pixelMetric(QStyle::PM_LayoutTopMargin), 0408 qMin(style()->pixelMetric(QStyle::PM_LayoutRightMargin), 0409 style()->pixelMetric(QStyle::PM_LayoutBottomMargin)))); 0410 0411 mainLayout->setSpacing(cmargin); 0412 mainLayout->setContentsMargins(QMargins(cmargin, cmargin, cmargin, cmargin)); 0413 setLayout(mainLayout); 0414 0415 // -------------------------------------------------------- 0416 0417 connect(d->tooltipToggleButton, SIGNAL(clicked(bool)), 0418 this, SLOT(slotToolTipButtonToggled(bool))); 0419 0420 connect(d->renameInput, SIGNAL(signalTextChanged(QString)), 0421 this, SIGNAL(signalTextChanged(QString))); 0422 0423 connect(d->renameInput, SIGNAL(signalTokenMarked(bool)), 0424 this, SLOT(slotTokenMarked(bool))); 0425 0426 connect(d->renameInput, SIGNAL(signalReturnPressed()), 0427 this, SIGNAL(signalReturnPressed())); 0428 0429 slotTokenMarked(false); 0430 readSettings(); 0431 } 0432 0433 void AdvancedRenameWidget::slotTokenMarked(bool marked) 0434 { 0435 bool enable = marked && d->parser; 0436 bool enableMod = enable && !(d->parser->modifiers().isEmpty()); 0437 0438 if (d->layoutStyle == LayoutNormal) 0439 { 0440 d->modifiersToolButton->setEnabled(enableMod); 0441 } 0442 else 0443 { 0444 d->modifiersButton->setEnabled(enableMod); 0445 } 0446 } 0447 0448 void AdvancedRenameWidget::focusLineEdit() 0449 { 0450 d->renameInput->slotSetFocus(); 0451 } 0452 0453 void AdvancedRenameWidget::highlightLineEdit() 0454 { 0455 d->renameInput->slotHighlightLineEdit(); 0456 } 0457 0458 void AdvancedRenameWidget::highlightLineEdit(const QString& word) 0459 { 0460 d->renameInput->slotHighlightLineEdit(word); 0461 } 0462 0463 void AdvancedRenameWidget::readSettings() 0464 { 0465 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0466 KConfigGroup group = config->group(d->configGroupName); 0467 0468 if (d->layoutStyle == LayoutNormal) 0469 { 0470 d->optionsLabel->setExpanded(group.readEntry(d->configExpandedStateEntry, d->configExpandedStateDefault)); 0471 } 0472 } 0473 0474 void AdvancedRenameWidget::writeSettings() 0475 { 0476 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0477 KConfigGroup group = config->group(d->configGroupName); 0478 0479 if (d->layoutStyle == LayoutNormal) 0480 { 0481 group.writeEntry(d->configExpandedStateEntry, d->optionsLabel ? d->optionsLabel->isExpanded() 0482 : d->configExpandedStateDefault); 0483 } 0484 } 0485 0486 } // namespace Digikam 0487 0488 #include "moc_advancedrenamewidget.cpp"