diff options
Diffstat (limited to 'src/libs/dialogs/imageguidedlg.cpp')
-rw-r--r-- | src/libs/dialogs/imageguidedlg.cpp | 597 |
1 files changed, 597 insertions, 0 deletions
diff --git a/src/libs/dialogs/imageguidedlg.cpp b/src/libs/dialogs/imageguidedlg.cpp new file mode 100644 index 00000000..9713a872 --- /dev/null +++ b/src/libs/dialogs/imageguidedlg.cpp @@ -0,0 +1,597 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-05-07 + * Description : A threaded filter plugin dialog with a preview + * image guide widget and a settings user area + * + * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// TQt includes. + +#include <tqvgroupbox.h> +#include <tqlabel.h> +#include <tqpushbutton.h> +#include <tqwhatsthis.h> +#include <tqtooltip.h> +#include <tqlayout.h> +#include <tqframe.h> +#include <tqtimer.h> +#include <tqspinbox.h> +#include <tqsplitter.h> +#include <tqhbox.h> + +// KDE includes. + +#include <kcursor.h> +#include <tdelocale.h> +#include <tdeaboutdata.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <tdeapplication.h> +#include <tdepopupmenu.h> +#include <kstandarddirs.h> +#include <tdeglobalsettings.h> +#include <kprogress.h> +#include <kcolorbutton.h> +#include <tdeconfig.h> +#include <kseparator.h> + +// Local includes. + +#include "ddebug.h" +#include "sidebar.h" +#include "dimgthreadedfilter.h" +#include "dimginterface.h" +#include "imageguidedlg.h" +#include "imageguidedlg.moc" + +namespace Digikam +{ + +class ImageGuideDlgPriv +{ +public: + + enum RunningMode + { + NoneRendering=0, + PreviewRendering, + FinalRendering + }; + + ImageGuideDlgPriv() + { + tryAction = false; + progress = true; + currentRenderingMode = NoneRendering; + parent = 0; + settings = 0; + timer = 0; + aboutData = 0; + guideColorBt = 0; + progressBar = 0; + guideSize = 0; + mainLayout = 0; + settingsLayout = 0; + hbox = 0; + settingsSideBar = 0; + splitter = 0; + } + + bool tryAction; + bool progress; + + int currentRenderingMode; + + TQWidget *parent; + TQWidget *settings; + + TQTimer *timer; + + TQString name; + + TQGridLayout *mainLayout; + TQGridLayout *settingsLayout; + + TQSpinBox *guideSize; + + TQHBox *hbox; + + TQSplitter *splitter; + + KProgress *progressBar; + + KColorButton *guideColorBt; + + TDEAboutData *aboutData; + + Sidebar *settingsSideBar; +}; + +ImageGuideDlg::ImageGuideDlg(TQWidget* parent, TQString title, TQString name, + bool loadFileSettings, bool progress, + bool guideVisible, int guideMode, TQFrame* bannerFrame, + bool prevModeOptions, bool useImageSelection, + bool tryAction) + : KDialogBase(Plain, 0, + Help|Default|User1|User2|User3|Try|Ok|Cancel, Ok, + parent, 0, true, true, + i18n("&Abort"), + i18n("&Save As..."), + i18n("&Load...")) +{ + kapp->setOverrideCursor( KCursor::waitCursor() ); + setCaption(DImgInterface::defaultInterface()->getImageFileName() + TQString(" - ") + title); + + d = new ImageGuideDlgPriv; + d->parent = parent; + d->name = name; + d->progress = progress; + d->tryAction = tryAction; + m_threadedFilter = 0; + TQString whatsThis; + + setButtonWhatsThis ( Default, i18n("<p>Reset all filter parameters to their default values.") ); + setButtonWhatsThis ( User1, i18n("<p>Abort the current image rendering.") ); + setButtonWhatsThis ( User3, i18n("<p>Load all filter parameters from settings text file.") ); + setButtonWhatsThis ( User2, i18n("<p>Save all filter parameters to settings text file.") ); + showButton(User2, loadFileSettings); + showButton(User3, loadFileSettings); + showButton(Try, tryAction); + + resize(configDialogSize(name + TQString(" Tool Dialog"))); + + // ------------------------------------------------------------- + + d->mainLayout = new TQGridLayout( plainPage(), 2, 1); + + if (bannerFrame) + { + bannerFrame->reparent( plainPage(), TQPoint(0, 0) ); + d->mainLayout->addMultiCellWidget(bannerFrame, 0, 0, 0, 1); + } + + // ------------------------------------------------------------- + + TQString desc; + + if (guideVisible) + desc = i18n("<p>This is the the image filter effect preview. " + "If you move the mouse cursor on this area, " + "a vertical and horizontal dashed line will be draw " + "to guide you in adjusting the filter settings. " + "Press the left mouse button to freeze the dashed " + "line's position."); + else + desc = i18n("<p>This is the image filter effect preview."); + + d->hbox = new TQHBox(plainPage()); + d->splitter = new TQSplitter(d->hbox); + m_imagePreviewWidget = new ImageWidget(d->name, d->splitter, desc, prevModeOptions, + guideMode, guideVisible, useImageSelection); + + d->splitter->setFrameStyle( TQFrame::NoFrame ); + d->splitter->setFrameShadow( TQFrame::Plain ); + d->splitter->setFrameShape( TQFrame::NoFrame ); + d->splitter->setOpaqueResize(false); + + TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1); + m_imagePreviewWidget->setSizePolicy(rightSzPolicy); + + TQString sbName(d->name + TQString(" Image Plugin Sidebar")); + d->settingsSideBar = new Sidebar(d->hbox, sbName.ascii(), Sidebar::Right); + d->settingsSideBar->setSplitter(d->splitter); + + d->mainLayout->addMultiCellWidget(d->hbox, 1, 2, 0, 1); + d->mainLayout->setColStretch(0, 10); + d->mainLayout->setRowStretch(2, 10); + + // ------------------------------------------------------------- + + d->settings = new TQWidget(plainPage()); + d->settingsLayout = new TQGridLayout( d->settings, 1, 0); + TQVBoxLayout *vLayout = new TQVBoxLayout( spacingHint() ); + + // ------------------------------------------------------------- + + TQWidget *gboxGuideSettings = new TQWidget(d->settings); + TQGridLayout* grid = new TQGridLayout( gboxGuideSettings, 2, 2, marginHint(), spacingHint()); + KSeparator *line = new KSeparator(TQt::Horizontal, gboxGuideSettings); + grid->addMultiCellWidget(line, 0, 0, 0, 2); + + TQLabel *label5 = new TQLabel(i18n("Guide color:"), gboxGuideSettings); + d->guideColorBt = new KColorButton( TQColor( TQt::red ), gboxGuideSettings ); + TQWhatsThis::add( d->guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines.")); + grid->addMultiCellWidget(label5, 1, 1, 0, 0); + grid->addMultiCellWidget(d->guideColorBt, 1, 1, 2, 2); + + TQLabel *label6 = new TQLabel(i18n("Guide width:"), gboxGuideSettings); + d->guideSize = new TQSpinBox( 1, 5, 1, gboxGuideSettings); + TQWhatsThis::add( d->guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines.")); + grid->addMultiCellWidget(label6, 2, 2, 0, 0); + grid->addMultiCellWidget(d->guideSize, 2, 2, 2, 2); + grid->setColStretch(1, 10); + + if (guideVisible) gboxGuideSettings->show(); + else gboxGuideSettings->hide(); + + vLayout->addWidget(gboxGuideSettings); + + TQHBox *hbox = new TQHBox(d->settings); + TQLabel *space1 = new TQLabel(hbox); + space1->setFixedWidth(spacingHint()); + d->progressBar = new KProgress(100, hbox); + d->progressBar->setMaximumHeight( fontMetrics().height() ); + TQWhatsThis::add(d->progressBar ,i18n("<p>This is the percentage of the task which has been completed up to this point.")); + d->progressBar->setValue(0); + setProgressVisible(false); + TQLabel *space2 = new TQLabel(hbox); + space2->setFixedWidth(spacingHint()); + + vLayout->addWidget(hbox); + vLayout->addStretch(10); + + d->settingsLayout->addMultiCellLayout(vLayout, 1, 1, 0, 0); + + d->settingsSideBar->appendTab(d->settings, SmallIcon("configure"), i18n("Settings")); + d->settingsSideBar->loadViewState(); + + // Reading splitter sizes here prevent flicker effect in dialog. + TDEConfig *config = kapp->config(); + config->setGroup(d->name + TQString(" Tool Dialog")); + if(config->hasKey("SplitterSizes")) + d->splitter->setSizes(config->readIntListEntry("SplitterSizes")); + + // ------------------------------------------------------------- + + TQTimer::singleShot(0, this, TQ_SLOT(slotInit())); + kapp->restoreOverrideCursor(); +} + +ImageGuideDlg::~ImageGuideDlg() +{ + if (d->timer) + delete d->timer; + + if (m_threadedFilter) + delete m_threadedFilter; + + if (d->aboutData) + delete d->aboutData; + + delete d->settingsSideBar; + delete d; +} + +void ImageGuideDlg::readSettings(void) +{ + TQColor defaultGuideColor(TQt::red); + TDEConfig *config = kapp->config(); + config->setGroup(d->name + TQString(" Tool Dialog")); + d->guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor)); + d->guideSize->setValue(config->readNumEntry("Guide Width", 1)); + m_imagePreviewWidget->slotChangeGuideSize(d->guideSize->value()); + m_imagePreviewWidget->slotChangeGuideColor(d->guideColorBt->color()); +} + +void ImageGuideDlg::writeSettings(void) +{ + TDEConfig *config = kapp->config(); + config->setGroup(d->name + TQString(" Tool Dialog")); + config->writeEntry( "Guide Color", d->guideColorBt->color() ); + config->writeEntry( "Guide Width", d->guideSize->value() ); + config->writeEntry( "SplitterSizes", d->splitter->sizes() ); + config->sync(); + saveDialogSize(d->name + TQString(" Tool Dialog")); +} + +void ImageGuideDlg::slotInit() +{ + readSettings(); + // Reset values to defaults. + TQTimer::singleShot(0, this, TQ_SLOT(readUserSettings())); + + if (!d->tryAction) + { + connect(m_imagePreviewWidget, TQ_SIGNAL(signalResized()), + this, TQ_SLOT(slotResized())); + } + + connect(d->guideColorBt, TQ_SIGNAL(changed(const TQColor &)), + m_imagePreviewWidget, TQ_SLOT(slotChangeGuideColor(const TQColor &))); + + connect(d->guideSize, TQ_SIGNAL(valueChanged(int)), + m_imagePreviewWidget, TQ_SLOT(slotChangeGuideSize(int))); +} + +void ImageGuideDlg::setUserAreaWidget(TQWidget *w) +{ + w->reparent( d->settings, TQPoint(0, 0) ); + TQVBoxLayout *vLayout = new TQVBoxLayout( spacingHint() ); + vLayout->addWidget(w); + d->settingsLayout->addMultiCellLayout(vLayout, 0, 0, 0, 0); +} + +void ImageGuideDlg::setAboutData(TDEAboutData *about) +{ + d->aboutData = about; + TQPushButton *helpButton = actionButton( Help ); + KHelpMenu* helpMenu = new KHelpMenu(this, d->aboutData, false); + helpMenu->menu()->removeItemAt(0); + helpMenu->menu()->insertItem(i18n("digiKam Handbook"), this, TQ_SLOT(slotHelp()), 0, -1, 0); + helpButton->setPopup( helpMenu->menu() ); +} + +void ImageGuideDlg::setProgressVisible(bool v) +{ + if (v) + d->progressBar->show(); + else + d->progressBar->hide(); +} + +void ImageGuideDlg::abortPreview() +{ + d->currentRenderingMode = ImageGuideDlgPriv::NoneRendering; + d->progressBar->setValue(0); + setProgressVisible(false); + enableButton(Ok, true); + enableButton(User1, false); + enableButton(User2, true); + enableButton(User3, true); + enableButton(Try, true); + enableButton(Default, true); + renderingFinished(); +} + +void ImageGuideDlg::slotTry() +{ + slotEffect(); +} + +void ImageGuideDlg::slotResized(void) +{ + if (d->currentRenderingMode == ImageGuideDlgPriv::FinalRendering) + { + m_imagePreviewWidget->update(); + return; + } + else if (d->currentRenderingMode == ImageGuideDlgPriv::PreviewRendering) + { + if (m_threadedFilter) + m_threadedFilter->stopComputation(); + } + + TQTimer::singleShot(0, this, TQ_SLOT(slotEffect())); +} + +void ImageGuideDlg::slotUser1() +{ + if (d->currentRenderingMode != ImageGuideDlgPriv::NoneRendering) + if (m_threadedFilter) + m_threadedFilter->stopComputation(); +} + +void ImageGuideDlg::slotDefault() +{ + resetValues(); + slotEffect(); +} + +void ImageGuideDlg::slotCancel() +{ + if (d->currentRenderingMode != ImageGuideDlgPriv::NoneRendering) + { + if (m_threadedFilter) + m_threadedFilter->stopComputation(); + + kapp->restoreOverrideCursor(); + } + + writeSettings(); + done(Cancel); +} + +void ImageGuideDlg::closeEvent(TQCloseEvent *e) +{ + if (d->currentRenderingMode != ImageGuideDlgPriv::NoneRendering) + { + if (m_threadedFilter) + m_threadedFilter->stopComputation(); + + kapp->restoreOverrideCursor(); + } + + writeSettings(); + e->accept(); +} + +void ImageGuideDlg::slotHelp() +{ + // If setAboutData() is called by plugin, well DigikamImagePlugins help is lauched, + // else digiKam help. In this case, setHelp() method must be used to set anchor and handbook name. + + if (d->aboutData) + TDEApplication::kApplication()->invokeHelp(d->name, "digikam"); + else + KDialogBase::slotHelp(); +} + +void ImageGuideDlg::slotTimer() +{ + if (d->timer) + { + d->timer->stop(); + delete d->timer; + } + + d->timer = new TQTimer( this ); + connect( d->timer, TQ_SIGNAL(timeout()), + this, TQ_SLOT(slotEffect()) ); + d->timer->start(500, true); +} + +void ImageGuideDlg::slotEffect() +{ + // Computation already in process. + if (d->currentRenderingMode != ImageGuideDlgPriv::NoneRendering) + return; + + d->currentRenderingMode = ImageGuideDlgPriv::PreviewRendering; + DDebug() << "Preview " << d->name << " started..." << endl; + + enableButton(Ok, false); + enableButton(User1, true); + enableButton(User2, false); + enableButton(User3, false); + enableButton(Default, false); + enableButton(Try, false); + d->progressBar->setValue(0); + if (d->progress) setProgressVisible(true); + + if (m_threadedFilter) + { + delete m_threadedFilter; + m_threadedFilter = 0; + } + + prepareEffect(); +} + +void ImageGuideDlg::slotOk() +{ + d->currentRenderingMode = ImageGuideDlgPriv::FinalRendering; + DDebug() << "Final " << d->name << " started..." << endl; + writeSettings(); + writeUserSettings(); + + enableButton(Ok, false); + enableButton(User1, false); + enableButton(User2, false); + enableButton(User3, false); + enableButton(Default, false); + enableButton(Try, false); + kapp->setOverrideCursor( KCursor::waitCursor() ); + d->progressBar->setValue(0); + + if (m_threadedFilter) + { + delete m_threadedFilter; + m_threadedFilter = 0; + } + + prepareFinal(); +} + +void ImageGuideDlg::customEvent(TQCustomEvent *event) +{ + if (!event) return; + + DImgThreadedFilter::EventData *ed = (DImgThreadedFilter::EventData*) event->data(); + + if (!ed) return; + + if (ed->starting) // Computation in progress ! + { + d->progressBar->setValue(ed->progress); + } + else + { + if (ed->success) // Computation Completed ! + { + switch (d->currentRenderingMode) + { + case ImageGuideDlgPriv::PreviewRendering: + { + DDebug() << "Preview " << d->name << " completed..." << endl; + putPreviewData(); + abortPreview(); + break; + } + + case ImageGuideDlgPriv::FinalRendering: + { + DDebug() << "Final" << d->name << " completed..." << endl; + putFinalData(); + kapp->restoreOverrideCursor(); + accept(); + break; + } + } + } + else // Computation Failed ! + { + switch (d->currentRenderingMode) + { + case ImageGuideDlgPriv::PreviewRendering: + { + DDebug() << "Preview " << d->name << " failed..." << endl; + // abortPreview() must be call here for set progress bar to 0 properly. + abortPreview(); + break; + } + + case ImageGuideDlgPriv::FinalRendering: + break; + } + } + } + + delete ed; +} + +// Backport KDialog::keyPressEvent() implementation from KDELibs to ignore Enter/Return Key events +// to prevent any conflicts between dialog keys events and SpinBox keys events. + +void ImageGuideDlg::keyPressEvent(TQKeyEvent *e) +{ + if ( e->state() == 0 ) + { + switch ( e->key() ) + { + case Key_Escape: + e->accept(); + reject(); + break; + case Key_Enter: + case Key_Return: + e->ignore(); + break; + default: + e->ignore(); + return; + } + } + else + { + // accept the dialog when Ctrl-Return is pressed + if ( e->state() == ControlButton && + (e->key() == Key_Return || e->key() == Key_Enter) ) + { + e->accept(); + accept(); + } + else + { + e->ignore(); + } + } +} + +} // NameSpace Digikam |