summaryrefslogtreecommitdiffstats
path: root/src/libs/dialogs/imageguidedlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dialogs/imageguidedlg.cpp')
-rw-r--r--src/libs/dialogs/imageguidedlg.cpp597
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