File indexing completed on 2024-05-26 04:24:43

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #define DEBUG_KP_EFFECTS_DIALOG 0
0030 
0031 
0032 #include "kpEffectsDialog.h"
0033 
0034 #include "kpDefs.h"
0035 #include "document/kpDocument.h"
0036 #include "widgets/imagelib/effects/kpEffectBalanceWidget.h"
0037 #include "widgets/imagelib/effects/kpEffectBlurSharpenWidget.h"
0038 #include "widgets/imagelib/effects/kpEffectEmbossWidget.h"
0039 #include "widgets/imagelib/effects/kpEffectFlattenWidget.h"
0040 #include "widgets/imagelib/effects/kpEffectHSVWidget.h"
0041 #include "widgets/imagelib/effects/kpEffectInvertWidget.h"
0042 #include "widgets/imagelib/effects/kpEffectReduceColorsWidget.h"
0043 #include "widgets/imagelib/effects/kpEffectToneEnhanceWidget.h"
0044 #include "pixmapfx/kpPixmapFX.h"
0045 #include "environments/dialogs/imagelib/transforms/kpTransformDialogEnvironment.h"
0046 
0047 #include <KConfig>
0048 #include "kpLogCategories.h"
0049 #include <KLocalizedString>
0050 
0051 #include <QComboBox>
0052 #include <QGroupBox>
0053 #include <QLabel>
0054 #include <QLayout>
0055 #include <QTimer>
0056 #include <QImage>
0057 
0058 
0059 // protected static
0060 int kpEffectsDialog::s_lastWidth = 640;
0061 int kpEffectsDialog::s_lastHeight = 620;
0062 
0063 
0064 kpEffectsDialog::kpEffectsDialog (bool actOnSelection,
0065                                   kpTransformDialogEnvironment *_env,
0066                                   QWidget *parent,
0067                                   int defaultSelectedEffect)
0068     : kpTransformPreviewDialog (kpTransformPreviewDialog::Preview,
0069                            true/*reserve top row*/,
0070                            QString()/*caption*/,
0071                            QString()/*afterActionText (no Dimensions Group Box)*/,
0072                            actOnSelection,
0073                            _env,
0074                            parent),
0075       m_delayedUpdateTimer (new QTimer (this)),
0076       m_effectsComboBox (nullptr),
0077       m_settingsGroupBox (nullptr),
0078       m_settingsLayout (nullptr),
0079       m_effectWidget (nullptr)
0080 {
0081 #if DEBUG_KP_EFFECTS_DIALOG
0082     qCDebug(kpLogDialogs) << "kpEffectsDialog::kpEffectsDialog()";
0083 #endif
0084     const bool e = updatesEnabled ();
0085     setUpdatesEnabled (false);
0086 
0087 
0088     if (actOnSelection) {
0089         setWindowTitle (i18nc ("@title:window", "More Image Effects (Selection)"));
0090     }
0091     else {
0092         setWindowTitle (i18nc ("@title:window", "More Image Effects"));
0093     }
0094 
0095 
0096     m_delayedUpdateTimer->setSingleShot (true);
0097     connect (m_delayedUpdateTimer, &QTimer::timeout,
0098              this, &kpEffectsDialog::slotUpdateWithWaitCursor);
0099 
0100 
0101     QWidget *effectContainer = new QWidget (mainWidget ());
0102 
0103     auto *containerLayout = new QHBoxLayout (effectContainer);
0104     containerLayout->setContentsMargins(0, 0, 0, 0);
0105 
0106     QLabel *label = new QLabel (i18n ("&Effect:"), effectContainer);
0107 
0108     m_effectsComboBox = new QComboBox (effectContainer);
0109     // Keep in alphabetical order.
0110     // TODO: What about translations?
0111     // sync: order in selectEffect().
0112     m_effectsComboBox->addItem (i18n ("Balance"));
0113     m_effectsComboBox->addItem (i18n ("Emboss"));
0114     m_effectsComboBox->addItem (i18n ("Flatten"));
0115     m_effectsComboBox->addItem (i18n ("Histogram Equalizer"));
0116     m_effectsComboBox->addItem (i18n ("Hue, Saturation, Value"));
0117     m_effectsComboBox->addItem (i18n ("Invert"));
0118     m_effectsComboBox->addItem (i18n ("Reduce Colors"));
0119     m_effectsComboBox->addItem (i18n ("Soften & Sharpen"));
0120 
0121     containerLayout->addWidget (label);
0122     containerLayout->addWidget (m_effectsComboBox, 1);
0123 
0124     label->setBuddy (m_effectsComboBox);
0125 
0126     addCustomWidgetToFront (effectContainer);
0127 
0128 
0129     m_settingsGroupBox = new QGroupBox (mainWidget ());
0130     m_settingsLayout = new QVBoxLayout ( m_settingsGroupBox );
0131     addCustomWidgetToBack (m_settingsGroupBox);
0132 
0133 
0134     connect (m_effectsComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
0135              this, &kpEffectsDialog::selectEffect);
0136 
0137 
0138     selectEffect (defaultSelectedEffect);
0139 
0140 
0141     resize (s_lastWidth, s_lastHeight);
0142 
0143 
0144 #if DEBUG_KP_EFFECTS_DIALOG
0145     qCDebug(kpLogDialogs) << "about to setUpdatesEnabled()";
0146 #endif
0147     // OPT: The preview pixmap gets recalculated here and then possibly
0148     //      again when QResizeEvent fires, when the dialog is shown.
0149     setUpdatesEnabled (e);
0150 #if DEBUG_KP_EFFECTS_DIALOG
0151     qCDebug(kpLogDialogs) << endl
0152               << endl
0153               << endl;
0154 #endif
0155 }
0156 
0157 kpEffectsDialog::~kpEffectsDialog ()
0158 {
0159     s_lastWidth = width ();
0160     s_lastHeight = height ();
0161 }
0162 
0163 
0164 // public virtual [base kpTransformPreviewDialog]
0165 bool kpEffectsDialog::isNoOp () const
0166 {
0167     if (!m_effectWidget) {
0168         return true;
0169     }
0170 
0171     return m_effectWidget->isNoOp ();
0172 }
0173 
0174 // public
0175 kpEffectCommandBase *kpEffectsDialog::createCommand () const
0176 {
0177     if (!m_effectWidget) {
0178         return nullptr;
0179     }
0180 
0181     return m_effectWidget->createCommand (m_environ->commandEnvironment ());
0182 }
0183 
0184 
0185 // protected virtual [base kpTransformPreviewDialog]
0186 QSize kpEffectsDialog::newDimensions () const
0187 {
0188     kpDocument *doc = document ();
0189     if (!doc) {
0190         return  {};
0191     }
0192 
0193     return  {doc->width (m_actOnSelection), doc->height (m_actOnSelection)};
0194 }
0195 
0196 // protected virtual [base kpTransformPreviewDialog]
0197 QImage kpEffectsDialog::transformPixmap (const QImage &pixmap,
0198                                          int targetWidth, int targetHeight) const
0199 {
0200     QImage pixmapWithEffect;
0201 
0202     if (m_effectWidget && !m_effectWidget->isNoOp ()) {
0203         pixmapWithEffect = m_effectWidget->applyEffect (pixmap);
0204     }
0205     else {
0206         pixmapWithEffect = pixmap;
0207     }
0208 
0209     return kpPixmapFX::scale (pixmapWithEffect, targetWidth, targetHeight);
0210 }
0211 
0212 
0213 // public
0214 int kpEffectsDialog::selectedEffect () const
0215 {
0216     return m_effectsComboBox->currentIndex ();
0217 }
0218 
0219 // public slot
0220 void kpEffectsDialog::selectEffect (int which)
0221 {
0222 #if DEBUG_KP_EFFECTS_DIALOG
0223     qCDebug(kpLogDialogs) << "kpEffectsDialog::selectEffect(" << which << ")";
0224 #endif
0225 
0226     if (which < 0 ||
0227         which >= m_effectsComboBox->count ())
0228     {
0229         return;
0230     }
0231 
0232     if (which != m_effectsComboBox->currentIndex ()) {
0233         m_effectsComboBox->setCurrentIndex (which);
0234     }
0235 
0236 
0237     delete m_effectWidget;
0238     m_effectWidget = nullptr;
0239 
0240 
0241     m_settingsGroupBox->setWindowTitle(QString());
0242 
0243 #define CREATE_EFFECT_WIDGET(name)  \
0244     m_effectWidget = new name (m_actOnSelection, m_settingsGroupBox)
0245     // sync: order in constructor.
0246     switch (which)
0247     {
0248     case 0:
0249         CREATE_EFFECT_WIDGET (kpEffectBalanceWidget);
0250         break;
0251 
0252     case 1:
0253         CREATE_EFFECT_WIDGET (kpEffectEmbossWidget);
0254         break;
0255 
0256     case 2:
0257         CREATE_EFFECT_WIDGET (kpEffectFlattenWidget);
0258         break;
0259     
0260     case 3:
0261         CREATE_EFFECT_WIDGET (kpEffectToneEnhanceWidget);
0262         break;
0263 
0264     case 4:
0265         CREATE_EFFECT_WIDGET (kpEffectHSVWidget);
0266         break;
0267 
0268     case 5:
0269         CREATE_EFFECT_WIDGET (kpEffectInvertWidget);
0270         break;
0271 
0272     case 6:
0273         CREATE_EFFECT_WIDGET (kpEffectReduceColorsWidget);
0274         break;
0275 
0276     case 7:
0277         CREATE_EFFECT_WIDGET (kpEffectBlurSharpenWidget);
0278         break;
0279     }
0280 #undef CREATE_EFFECT_WIDGET
0281 
0282 
0283     if (m_effectWidget)
0284     {
0285         const bool e = updatesEnabled ();
0286         setUpdatesEnabled (false);
0287 
0288     #if DEBUG_KP_EFFECTS_DIALOG
0289         qCDebug(kpLogDialogs) << "widget exists for effect #";
0290     #endif
0291         m_settingsGroupBox->setTitle (m_effectWidget->caption ());
0292 
0293         // Show widget.
0294         //
0295         // Don't resize the whole dialog when doing this.
0296         // This seems to work magically without any extra code with Qt4.
0297     #if DEBUG_KP_EFFECTS_DIALOG
0298         qCDebug(kpLogDialogs) << "addWidget";
0299     #endif
0300         m_settingsLayout->addWidget (m_effectWidget);
0301     #if DEBUG_KP_EFFECTS_DIALOG
0302         qCDebug(kpLogDialogs) << "show widget";
0303     #endif
0304         m_effectWidget->show ();
0305 
0306         connect (m_effectWidget, &kpEffectWidgetBase::settingsChangedNoWaitCursor,
0307                  this, &kpEffectsDialog::slotUpdate);
0308         connect (m_effectWidget, &kpEffectWidgetBase::settingsChanged,
0309                  this, &kpEffectsDialog::slotUpdateWithWaitCursor);
0310         connect (m_effectWidget, &kpEffectWidgetBase::settingsChangedDelayed,
0311                  this, &kpEffectsDialog::slotDelayedUpdate);
0312 
0313     #if DEBUG_KP_EFFECTS_DIALOG
0314         qCDebug(kpLogDialogs) << "about to setUpdatesEnabled()";
0315     #endif
0316         setUpdatesEnabled (e);
0317     }
0318 
0319 
0320 #if DEBUG_KP_EFFECTS_DIALOG
0321     qCDebug(kpLogDialogs) << "done"
0322               << endl
0323               << endl
0324               << endl;
0325 #endif
0326 }
0327 
0328 
0329 // protected slot virtual [base kpTransformPreviewDialog]
0330 void kpEffectsDialog::slotUpdate ()
0331 {
0332 #if DEBUG_KP_EFFECTS_DIALOG
0333     qCDebug(kpLogDialogs) << "kpEffectsDialog::slotUpdate()"
0334                << " timerActive=" << m_delayedUpdateTimer->isActive ()
0335                << endl;
0336 #endif
0337 
0338     m_delayedUpdateTimer->stop ();
0339 
0340     kpTransformPreviewDialog::slotUpdate ();
0341 }
0342 
0343 // protected slot virtual [base kpTransformPreviewDialog]
0344 void kpEffectsDialog::slotUpdateWithWaitCursor ()
0345 {
0346 #if DEBUG_KP_EFFECTS_DIALOG
0347     qCDebug(kpLogDialogs) << "kpEffectsDialog::slotUpdateWithWaitCursor()"
0348                << " timerActive=" << m_delayedUpdateTimer->isActive ()
0349                << endl;
0350 #endif
0351 
0352     m_delayedUpdateTimer->stop ();
0353 
0354     kpTransformPreviewDialog::slotUpdateWithWaitCursor ();
0355 }
0356 
0357 
0358 // protected slot
0359 void kpEffectsDialog::slotDelayedUpdate ()
0360 {
0361 #if DEBUG_KP_EFFECTS_DIALOG
0362     qCDebug(kpLogDialogs) << "kpEffectsDialog::slotDelayedUpdate()"
0363                << " timerActive=" << m_delayedUpdateTimer->isActive ()
0364                << endl;
0365 #endif
0366     m_delayedUpdateTimer->stop ();
0367 
0368     // (single shot)
0369     m_delayedUpdateTimer->start (400/*ms*/);
0370 }
0371 
0372 #include "moc_kpEffectsDialog.cpp"