File indexing completed on 2025-04-27 03:58:35

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2011-02-14
0007  * Description : pick label widget
0008  *
0009  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "picklabelwidget.h"
0016 
0017 // Qt includes
0018 
0019 #include <QPainter>
0020 #include <QIcon>
0021 #include <QLayout>
0022 #include <QLabel>
0023 #include <QButtonGroup>
0024 #include <QWidgetAction>
0025 #include <QFontMetrics>
0026 #include <QFont>
0027 #include <QToolButton>
0028 #include <QApplication>
0029 
0030 // KDE includes
0031 
0032 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0033 #   pragma GCC diagnostic push
0034 #   pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0035 #endif
0036 
0037 #if defined(Q_CC_CLANG)
0038 #   pragma clang diagnostic push
0039 #   pragma clang diagnostic ignored "-Wdeprecated-declarations"
0040 #endif
0041 
0042 #include <klocalizedstring.h>
0043 #include <kactioncollection.h>
0044 
0045 // Restore warnings
0046 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0047 #   pragma GCC diagnostic pop
0048 #endif
0049 
0050 #if defined(Q_CC_CLANG)
0051 #   pragma clang diagnostic pop
0052 #endif
0053 
0054 // Local includes
0055 
0056 #include "dxmlguiwindow.h"
0057 #include "dexpanderbox.h"
0058 
0059 namespace Digikam
0060 {
0061 
0062 class Q_DECL_HIDDEN PickLabelWidget::Private
0063 {
0064 
0065 public:
0066 
0067     explicit Private()
0068       : pickBtns    (nullptr),
0069         desc        (nullptr),
0070         btnNone     (nullptr),
0071         btnRej      (nullptr),
0072         btnPndg     (nullptr),
0073         btnAccpt    (nullptr),
0074         descBox     (nullptr),
0075         shortcut    (nullptr)
0076     {
0077     }
0078 
0079     QButtonGroup*     pickBtns;
0080 
0081     QLabel*           desc;
0082 
0083     QToolButton*      btnNone;
0084     QToolButton*      btnRej;
0085     QToolButton*      btnPndg;
0086     QToolButton*      btnAccpt;
0087 
0088     DHBox*            descBox;
0089 
0090     DAdjustableLabel* shortcut;
0091 };
0092 
0093 PickLabelWidget::PickLabelWidget(QWidget* const parent)
0094     : DVBox(parent),
0095       d    (new Private)
0096 {
0097     setAttribute(Qt::WA_DeleteOnClose);
0098     setFocusPolicy(Qt::NoFocus);
0099 
0100     DHBox* const hbox = new DHBox(this);
0101     hbox->setContentsMargins(QMargins());
0102     hbox->setSpacing(0);
0103 
0104     d->btnNone = new QToolButton(hbox);
0105     d->btnNone->setCheckable(true);
0106     d->btnNone->setFocusPolicy(Qt::NoFocus);
0107     d->btnNone->setIcon(buildIcon(NoPickLabel));
0108     d->btnNone->installEventFilter(this);
0109 
0110     d->btnRej = new QToolButton(hbox);
0111     d->btnRej->setCheckable(true);
0112     d->btnRej->setFocusPolicy(Qt::NoFocus);
0113     d->btnRej->setIcon(buildIcon(RejectedLabel));
0114     d->btnRej->installEventFilter(this);
0115 
0116     d->btnPndg = new QToolButton(hbox);
0117     d->btnPndg->setCheckable(true);
0118     d->btnPndg->setFocusPolicy(Qt::NoFocus);
0119     d->btnPndg->setIcon(buildIcon(PendingLabel));
0120     d->btnPndg->installEventFilter(this);
0121 
0122     d->btnAccpt = new QToolButton(hbox);
0123     d->btnAccpt->setCheckable(true);
0124     d->btnAccpt->setFocusPolicy(Qt::NoFocus);
0125     d->btnAccpt->setIcon(buildIcon(AcceptedLabel));
0126     d->btnAccpt->installEventFilter(this);
0127 
0128     d->pickBtns = new QButtonGroup(hbox);
0129     d->pickBtns->addButton(d->btnNone,  NoPickLabel);
0130     d->pickBtns->addButton(d->btnRej,   RejectedLabel);
0131     d->pickBtns->addButton(d->btnPndg,  PendingLabel);
0132     d->pickBtns->addButton(d->btnAccpt, AcceptedLabel);
0133 
0134     d->descBox  = new DHBox(this);
0135     d->descBox->setContentsMargins(QMargins());
0136     d->descBox->setSpacing(0);
0137     d->desc     = new QLabel(d->descBox);
0138     d->shortcut = new DAdjustableLabel(d->descBox);
0139     QFont fnt = d->shortcut->font();
0140     fnt.setItalic(true);
0141     d->shortcut->setFont(fnt);
0142     d->shortcut->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
0143     d->shortcut->setWordWrap(false);
0144 
0145     setSpacing(0);
0146     setContentsMargins(QMargins());
0147     setPickLabels(QList<PickLabel>() << NoPickLabel);
0148     setDescriptionBoxVisible(true);
0149     setButtonsExclusive(true);
0150 
0151     // -------------------------------------------------------------
0152 
0153 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0154 
0155     connect(d->pickBtns, SIGNAL(idReleased(int)),
0156             this, SIGNAL(signalPickLabelChanged(int)));
0157 
0158 #else
0159 
0160     connect(d->pickBtns, SIGNAL(buttonReleased(int)),
0161             this, SIGNAL(signalPickLabelChanged(int)));
0162 
0163 #endif
0164 
0165 }
0166 
0167 PickLabelWidget::~PickLabelWidget()
0168 {
0169     delete d;
0170 }
0171 
0172 void PickLabelWidget::setDescriptionBoxVisible(bool b)
0173 {
0174     d->descBox->setVisible(b);
0175 
0176     if (!b)
0177     {
0178         Q_FOREACH (QAbstractButton* const btn, d->pickBtns->buttons())
0179         {
0180             PickLabel id = (PickLabel)(d->pickBtns->id(btn));
0181             btn->setToolTip(labelPickName(id));
0182         }
0183     }
0184 }
0185 
0186 void PickLabelWidget::setButtonsExclusive(bool b)
0187 {
0188     d->pickBtns->setExclusive(b);
0189 }
0190 
0191 void PickLabelWidget::updateDescription(PickLabel label)
0192 {
0193     d->desc->setText(labelPickName(label));
0194 
0195     DXmlGuiWindow* const app = dynamic_cast<DXmlGuiWindow*>(qApp->activeWindow());
0196 
0197     if (app)
0198     {
0199         QAction* const ac = app->actionCollection()->action(QString::fromLatin1("pickshortcut-%1").arg(label));
0200 
0201         if (ac)
0202         {
0203             d->shortcut->setAdjustedText(ac->shortcut().toString());
0204         }
0205     }
0206 }
0207 
0208 bool PickLabelWidget::eventFilter(QObject* obj, QEvent* ev)
0209 {
0210     if (obj == d->btnNone)
0211     {
0212         if (ev->type() == QEvent::Enter)
0213         {
0214             updateDescription(NoPickLabel);
0215             return false;
0216         }
0217     }
0218 
0219     if (obj == d->btnRej)
0220     {
0221         if (ev->type() == QEvent::Enter)
0222         {
0223             updateDescription(RejectedLabel);
0224             return false;
0225         }
0226     }
0227 
0228     if (obj == d->btnPndg)
0229     {
0230         if (ev->type() == QEvent::Enter)
0231         {
0232             updateDescription(PendingLabel);
0233             return false;
0234         }
0235     }
0236 
0237     if (obj == d->btnAccpt)
0238     {
0239         if (ev->type() == QEvent::Enter)
0240         {
0241             updateDescription(AcceptedLabel);
0242             return false;
0243         }
0244     }
0245 
0246     // pass the event on to the parent class
0247 
0248     return DVBox::eventFilter(obj, ev);
0249 }
0250 
0251 void PickLabelWidget::setPickLabels(const QList<PickLabel>& list)
0252 {
0253     Q_FOREACH (QAbstractButton* const btn, d->pickBtns->buttons())
0254     {
0255         PickLabel id = (PickLabel)(d->pickBtns->id(btn));
0256         btn->setChecked(list.contains(id));
0257         updateDescription(id);
0258     }
0259 }
0260 
0261 QList<PickLabel> PickLabelWidget::pickLabels() const
0262 {
0263     QList<PickLabel> list;
0264 
0265     Q_FOREACH (QAbstractButton* const btn, d->pickBtns->buttons())
0266     {
0267         if (btn && btn->isChecked())
0268             list.append((PickLabel)(d->pickBtns->id(btn)));
0269     }
0270 
0271     return list;
0272 }
0273 
0274 QIcon PickLabelWidget::buildIcon(PickLabel label)
0275 {
0276     switch (label)
0277     {
0278         case RejectedLabel:
0279         {
0280             return QIcon::fromTheme(QLatin1String("flag-red"));
0281         }
0282 
0283         case PendingLabel:
0284         {
0285             return QIcon::fromTheme(QLatin1String("flag-yellow"));
0286         }
0287 
0288         case AcceptedLabel:
0289         {
0290             return QIcon::fromTheme(QLatin1String("flag-green"));
0291         }
0292 
0293         default:
0294         {
0295             break;
0296         }
0297     }
0298 
0299     // default : NoPickLabel
0300 
0301     return QIcon::fromTheme(QLatin1String("flag-black"));
0302 }
0303 
0304 QString PickLabelWidget::labelPickName(PickLabel label)
0305 {
0306     QString name;
0307 
0308     switch (label)
0309     {
0310         case RejectedLabel:
0311         {
0312             name = i18nc("@info: pick label name", "Rejected");
0313             break;
0314         }
0315 
0316         case PendingLabel:
0317         {
0318             name = i18nc("@info: pick label name", "Pending");
0319             break;
0320         }
0321 
0322         case AcceptedLabel:
0323         {
0324             name = i18nc("@info: pick label name", "Accepted");
0325             break;
0326         }
0327 
0328         default:   // NoPickLabel
0329         {
0330             name = i18nc("@info: pick label name", "None");
0331             break;
0332         }
0333     }
0334 
0335     return name;
0336 }
0337 
0338 // -----------------------------------------------------------------------------
0339 
0340 class Q_DECL_HIDDEN PickLabelSelector::Private
0341 {
0342 
0343 public:
0344 
0345     explicit Private()
0346       : plw(nullptr)
0347     {
0348     }
0349 
0350     PickLabelWidget* plw;
0351 };
0352 
0353 PickLabelSelector::PickLabelSelector(QWidget* const parent)
0354     : QPushButton(parent),
0355       d          (new Private)
0356 {
0357     QMenu* const popup          = new QMenu(this);
0358     setMenu(popup);
0359 
0360     QWidgetAction* const action = new QWidgetAction(this);
0361     d->plw                      = new PickLabelWidget(this);
0362     action->setDefaultWidget(d->plw);
0363     popup->addAction(action);
0364     slotPickLabelChanged(NoPickLabel);
0365 
0366     connect(d->plw, SIGNAL(signalPickLabelChanged(int)),
0367             this, SLOT(slotPickLabelChanged(int)));
0368 }
0369 
0370 PickLabelSelector::~PickLabelSelector()
0371 {
0372     delete d;
0373 }
0374 
0375 PickLabelWidget* PickLabelSelector::pickLabelWidget() const
0376 {
0377     return d->plw;
0378 }
0379 
0380 void PickLabelSelector::setPickLabel(PickLabel label)
0381 {
0382     d->plw->setPickLabels(QList<PickLabel>() << label);
0383     slotPickLabelChanged(label);
0384 }
0385 
0386 PickLabel PickLabelSelector::pickLabel()
0387 {
0388     QList<PickLabel> list = d->plw->pickLabels();
0389 
0390     if (!list.isEmpty())
0391     {
0392         return list.first();
0393     }
0394 
0395     return NoPickLabel;
0396 }
0397 
0398 void PickLabelSelector::slotPickLabelChanged(int id)
0399 {
0400     setText(QString());
0401     setIcon(d->plw->buildIcon((PickLabel)id));
0402     setToolTip(i18nc("@info: pick lablel selector", "Pick Label: %1", d->plw->labelPickName((PickLabel)id)));
0403     menu()->close();
0404 
0405     Q_EMIT signalPickLabelChanged(id);
0406 }
0407 
0408 // -----------------------------------------------------------------------------
0409 
0410 PickLabelMenuAction::PickLabelMenuAction(QMenu* const parent)
0411     : QMenu(parent)
0412 {
0413     setTitle(i18nc("@title: pick label menu", "Pick"));
0414     QWidgetAction* const wa    = new QWidgetAction(this);
0415     PickLabelWidget* const plw = new PickLabelWidget(parent);
0416     wa->setDefaultWidget(plw);
0417     addAction(wa);
0418 
0419     connect(plw, SIGNAL(signalPickLabelChanged(int)),
0420             this, SIGNAL(signalPickLabelChanged(int)));
0421 
0422     connect(plw, SIGNAL(signalPickLabelChanged(int)),
0423             parent, SLOT(close()));
0424 }
0425 
0426 PickLabelMenuAction::~PickLabelMenuAction()
0427 {
0428 }
0429 
0430 } // namespace Digikam
0431 
0432 #include "moc_picklabelwidget.cpp"