00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qcheckbox.h>
00025 #include <qradiobutton.h>
00026 #include <qpainter.h>
00027 #include <qpoint.h>
00028 #include <qpushbutton.h>
00029 #include <qlayout.h>
00030 #include <qlabel.h>
00031 #include <qapplication.h>
00032 #include <qcolor.h>
00033 #include <qgroupbox.h>
00034 #include <qcursor.h>
00035 #include <qtimer.h>
00036
00037 #include <kdebug.h>
00038 #include <kiconloader.h>
00039 #include <kpushbutton.h>
00040
00041 #include <kis_cursor.h>
00042 #include <kis_colorspace.h>
00043 #include <kis_colorspace_factory_registry.h>
00044 #include <kis_config.h>
00045 #include <kis_filter_strategy.h>
00046 #include <kis_global.h>
00047 #include <kis_image.h>
00048 #include <kis_layer.h>
00049 #include <kis_paint_layer.h>
00050 #include <kis_group_layer.h>
00051 #include <kis_meta_registry.h>
00052 #include <kis_painter.h>
00053 #include <kis_profile.h>
00054 #include <kis_types.h>
00055 #include <kis_undo_adapter.h>
00056 #include <kis_label_progress.h>
00057 #include <kis_selection.h>
00058 #include <kis_transform_worker.h>
00059
00060 #include "kis_previewwidgetbase.h"
00061 #include "kis_previewwidget.h"
00062 #include "imageviewer.h"
00063
00064 static const int ZOOM_PAUSE = 100;
00065 static const int FILTER_PAUSE = 500;
00066 static const double ZOOM_FACTOR = 1.1;
00067
00068 KisPreviewWidget::KisPreviewWidget( QWidget* parent, const char* name )
00069 : PreviewWidgetBase( parent, name )
00070 , m_autoupdate(true)
00071 , m_previewIsDisplayed(true)
00072 , m_scaledOriginal()
00073 , m_dirtyOriginal(true)
00074 , m_origDevice(new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temp"))
00075 , m_scaledPreview()
00076 , m_dirtyPreview(true)
00077 , m_previewDevice(new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temp"))
00078 , m_scaledImage(NULL)
00079 , m_filterZoom(1.0)
00080 , m_zoom(-1.0)
00081 , m_profile(NULL)
00082 , m_progress( 0 )
00083 , m_zoomTimer(new QTimer(this))
00084 , m_filterTimer(new QTimer(this))
00085 , m_firstFilter(true)
00086 , m_firstZoom(true)
00087 {
00088 btnZoomIn->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag+", KIcon::MainToolbar, 16 ));
00089 connect(btnZoomIn, SIGNAL(clicked()), this, SLOT(zoomIn()));
00090 btnZoomOut->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag-", KIcon::MainToolbar, 16 ));
00091 connect(btnZoomOut, SIGNAL(clicked()), this, SLOT(zoomOut()));
00092 btnUpdate->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "reload", KIcon::MainToolbar, 16 ));
00093 connect(btnUpdate, SIGNAL(clicked()), this, SLOT(forceUpdate()));
00094
00095 connect(radioBtnPreview, SIGNAL(toggled(bool)), this, SLOT(setPreviewDisplayed(bool)));
00096
00097 connect(checkBoxAutoUpdate, SIGNAL(toggled(bool)), this, SLOT(slotSetAutoUpdate(bool)));
00098 btnZoomOneToOne->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag1", KIcon::MainToolbar, 16 ));
00099 connect(btnZoomOneToOne, SIGNAL(clicked()), this, SLOT(zoomOneToOne()));
00100
00101 m_progress = new KisLabelProgress(frmProgress);
00102 m_progress->setMaximumHeight(fontMetrics().height() );
00103 QVBoxLayout *vbox = new QVBoxLayout( frmProgress );
00104 vbox->addWidget(m_progress);
00105 m_progress->hide();
00106
00107 connect(m_zoomTimer, SIGNAL(timeout()), this, SLOT(updateZoom()));
00108 connect(m_filterTimer, SIGNAL(timeout()), this, SLOT(runFilterHelper()));
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 }
00123
00124 KisPreviewWidget::~KisPreviewWidget() { }
00125
00126 void KisPreviewWidget::forceUpdate()
00127 {
00128 if(m_previewIsDisplayed)
00129 {
00130 m_groupBox->setTitle(m_origDevice->name());
00131 emit updated();
00132 }
00133 }
00134
00135 void KisPreviewWidget::slotSetDevice(KisPaintDeviceSP dev)
00136 {
00137 Q_ASSERT( dev );
00138
00139 if (!dev) return;
00140
00141 m_origDevice = dev;
00142 m_previewDevice = dev;
00143 m_filterZoom = 1.0;
00144
00145 KisConfig cfg;
00146 QString monitorProfileName = cfg.monitorProfile();
00147 m_profile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName);
00148
00149 QRect r = dev->exactBounds();
00150
00151 m_groupBox->setTitle(i18n("Preview: ") + dev->name());
00152 m_previewIsDisplayed = true;
00153
00154 m_zoom = -1.0;
00155 zoomChanged(double(m_preview->width()) / double(r.width()) );
00156 }
00157
00158 void KisPreviewWidget::updateZoom()
00159 {
00160 QApplication::setOverrideCursor(KisCursor::waitCursor());
00161
00162 if(m_previewIsDisplayed)
00163 {
00164 if(m_dirtyPreview)
00165 {
00166 QSize r = m_previewDevice->extent().size();
00167 int w = r.width(), h = r.height();
00168 int sw = int(ceil(m_zoom * w / m_filterZoom));
00169 int sh = int(ceil(m_zoom * h / m_filterZoom));
00170 m_dirtyPreview = false;
00171 m_scaledPreview = m_previewDevice->convertToQImage(m_profile, 0, 0, w, h);
00172 m_scaledPreview = m_scaledPreview.scale(sw,sh, QImage::ScaleMax);
00173 }
00174 m_preview->setImage(m_scaledPreview);
00175 } else
00176 {
00177 if(m_dirtyOriginal)
00178 {
00179 QSize r = m_origDevice->extent().size();
00180 int w = r.width(), h = r.height();
00181 int sw = int(ceil(m_zoom * w));
00182 int sh = int(ceil(m_zoom * h));
00183 m_dirtyOriginal = false;
00184 m_scaledOriginal = m_origDevice->convertToQImage(m_profile, 0, 0, w, h);
00185 m_scaledOriginal = m_scaledOriginal.scale(sw,sh, QImage::ScaleMax);
00186 }
00187 m_preview->setImage(m_scaledOriginal);
00188 }
00189
00190 QApplication::restoreOverrideCursor();
00191 }
00192
00193 void KisPreviewWidget::slotSetAutoUpdate(bool set) {
00194 m_autoupdate = set;
00195 }
00196
00197 void KisPreviewWidget::wheelEvent(QWheelEvent * e)
00198 {
00199 if (e->delta() > 0) {
00200 zoomIn();
00201 } else {
00202 zoomOut();
00203 }
00204 e->accept();
00205 }
00206
00207 void KisPreviewWidget::setPreviewDisplayed(bool v)
00208 {
00209 if(v != m_previewIsDisplayed)
00210 {
00211 m_previewIsDisplayed = v;
00212 if(m_previewIsDisplayed) {
00213 m_groupBox->setTitle(i18n("Preview: ") + m_origDevice->name());
00214 } else {
00215 m_groupBox->setTitle(i18n("Original: ") + m_origDevice->name());
00216 }
00217
00218 updateZoom();
00219 }
00220 }
00221
00222 void KisPreviewWidget::needUpdate()
00223 {
00224 if(m_previewIsDisplayed)
00225 m_groupBox->setTitle(i18n("Preview (needs update)"));
00226 }
00227
00228 bool KisPreviewWidget::getAutoUpdate() const {
00229 return m_autoupdate;
00230 }
00231
00232 void KisPreviewWidget::zoomChanged(const double zoom)
00233 {
00234
00235 double tZoom = zoom;
00236 if(zoom <= 1./8.) { tZoom = 1./8.; }
00237 if(zoom > 8.) { tZoom = 8.; }
00238
00239 if(tZoom != m_zoom)
00240 {
00241 m_zoom = tZoom;
00242 m_dirtyOriginal = true;
00243 m_dirtyPreview = true;
00244
00245 if(m_firstZoom) {
00246 m_firstZoom = false;
00247 updateZoom();
00248 } else {
00249 m_zoomTimer->start(ZOOM_PAUSE, true);
00250 }
00251 }
00252 }
00253
00254 void KisPreviewWidget::zoomIn() {
00255 zoomChanged(m_zoom * ZOOM_FACTOR);
00256 }
00257
00258 void KisPreviewWidget::zoomOut() {
00259 zoomChanged(m_zoom / ZOOM_FACTOR);
00260 }
00261
00262 void KisPreviewWidget::zoomOneToOne() {
00263 zoomChanged(1.0);
00264 }
00265
00266 static inline void cropDevice(KisPaintDevice * device, const double & zoom) {
00267 QRect r = device->exactBounds();
00268 r.setX(int(zoom * r.x()) );
00269 r.setY(int(zoom * r.y()) );
00270 r.setWidth(int(zoom * r.width()) );
00271 r.setHeight(int(zoom * r.height()) );
00272 device->crop(r);
00273 }
00274
00275 class MyCropVisitor : public KisLayerVisitor {
00276 const double m_zoom;
00277
00278 public:
00279 MyCropVisitor(const double & z) : m_zoom(z) { }
00280 virtual ~MyCropVisitor() { }
00281
00282 virtual bool visit(KisPaintLayer *layer) {
00283 KisPaintDeviceSP device = layer->paintDevice();
00284 ::cropDevice(device.data(), m_zoom);
00285
00286 if(device->hasSelection()) {
00287 ::cropDevice(device->selection().data(), m_zoom);
00288 }
00289
00290 return true;
00291 }
00292 virtual bool visit(KisGroupLayer *layer) {
00293 for(KisLayerSP l = layer->firstChild(); l; l = l->nextSibling()) {
00294 l->accept(*this);
00295 }
00296 return true;
00297 }
00298 virtual bool visit(KisPartLayer *) { return true; }
00299 virtual bool visit(KisAdjustmentLayer *) { return true; }
00300 };
00301
00302 void KisPreviewWidget::runFilter(KisFilter * filter, KisFilterConfiguration * config) {
00303 if(!filter) return;
00304 if(!config) return;
00305
00306 m_filter = filter;
00307 m_config = config;
00308
00309 if(m_firstFilter) {
00310 m_firstFilter = false;
00311 runFilterHelper();
00312 } else {
00313 m_filterTimer->start(FILTER_PAUSE, true);
00314 }
00315 }
00316
00321 void KisPreviewWidget::runFilterHelper() {
00322
00323 m_filterZoom = m_zoom;
00324
00325 if(m_filterZoom > 1.0) {
00326 m_filterZoom = 1.0;
00327 }
00328
00329 KisPaintDeviceSP scaledDevice;
00330 KisHermiteFilterStrategy strategy;
00331
00332
00333 if (m_origDevice->image())
00334 {
00335 m_scaledImage = new KisImage(*m_origDevice->image());
00336 if(!m_origDevice->parentLayer()) return;
00337 QString layerName = m_origDevice->parentLayer()->name();
00338 KisPaintLayerSP pl = ::qt_cast<KisPaintLayer*>(m_scaledImage->findLayer(layerName));
00339 if(!pl) return;
00340 scaledDevice = pl->paintDevice();
00341
00342 KisSelectionSP select;
00343 if(scaledDevice->hasSelection())
00344 {
00345 select = new KisSelection(*scaledDevice->selection());
00346 scaledDevice->deselect();
00347 }
00348
00349 m_scaledImage->setUndoAdapter(NULL);
00350 m_scaledImage->scale(m_filterZoom, m_filterZoom, NULL, &strategy);
00351
00352 if(select)
00353 {
00354 KisPaintDeviceSP t = select.data();
00355 KisTransformWorker tw(t, m_filterZoom, m_filterZoom,
00356 0.0, 0.0, 0.0, 0, 0, NULL, &strategy);
00357 tw.run();
00358 scaledDevice->setSelection(select);
00359 select->setParentLayer(scaledDevice->parentLayer());
00360 }
00361
00362
00363 MyCropVisitor v(m_filterZoom);
00364 m_scaledImage->rootLayer()->accept(v);
00365 } else
00366 {
00367 scaledDevice = new KisPaintDevice(*m_origDevice);
00368 KisSelectionSP select;
00369 if(scaledDevice->hasSelection())
00370 {
00371 select = new KisSelection(*scaledDevice->selection());
00372 scaledDevice->deselect();
00373 }
00374 KisTransformWorker tw(scaledDevice, m_filterZoom, m_filterZoom,
00375 0.0, 0.0, 0.0, 0, 0, NULL, &strategy);
00376 tw.run();
00377
00378 if(select)
00379 {
00380 KisPaintDeviceSP t = select.data();
00381 KisTransformWorker tw(t, m_filterZoom, m_filterZoom,
00382 0.0, 0.0, 0.0, 0, 0, NULL, &strategy);
00383 tw.run();
00384 scaledDevice->setSelection(select);
00385 ::cropDevice(select.data(), m_filterZoom);
00386 }
00387 ::cropDevice(scaledDevice.data(), m_filterZoom);
00388 }
00389
00390 m_previewDevice = new KisPaintDevice(*scaledDevice);
00391
00392
00393 m_filter->enableProgress();
00394 m_progress->setSubject(m_filter, true, true);
00395 m_filter->setProgressDisplay(m_progress);
00396 m_filter->process(scaledDevice, m_previewDevice, m_config, scaledDevice->exactBounds());
00397 m_filter->disableProgress();
00398
00399 m_dirtyPreview = true;
00400
00401 if(m_firstZoom) {
00402 m_firstZoom = false;
00403 updateZoom();
00404 } else {
00405 m_zoomTimer->start(ZOOM_PAUSE, true);
00406 }
00407 }
00408
00409 #include "kis_previewwidget.moc"