Writing: finished (hopefully) part about quick convergency.
[fic.git] / gui.cpp
blob27769307e2560ce90e63fdadb0f6734e24ec8871
1 #include "gui.h"
2 #include "modules/colorModel.h" // using color coefficients for RGB->gray conversion
4 using namespace std;
6 //// Non-member functions
7 static vector<double> getColorPSNR(const QImage &a,const QImage &b) {
8 int width= a.width(), height= a.height();
9 int x, y;
10 QRgb *line1, *line2;
11 int sum, sumR, sumG, sumB;
12 sum= sumR= sumG= sumB= 0;
13 for (y=0; y<height; ++y) {
14 line1= (QRgb*)a.scanLine(y);
15 line2= (QRgb*)b.scanLine(y);
16 for (x=0; x<width; ++x) {
17 sum+= sqr( getGray(line1[x]) - getGray(line2[x]) );
18 sumR+= sqr( qRed(line1[x]) - qRed(line2[x]) );
19 sumG+= sqr( qGreen(line1[x]) - qGreen(line2[x]) );
20 sumB+= sqr( qBlue(line1[x]) - qBlue(line2[x]) );
23 vector<double> result(4);
24 result[0]= sumR;
25 result[1]= sumG;
26 result[2]= sumB;
27 result[3]= sum;
28 double mul= double(width*height) * double(sqr(255));
29 for (vector<double>::iterator it=result.begin(); it!=result.end(); ++it)
30 *it= 10.0 * log10(mul / *it);
31 return result;
33 static QString getPSNRmessage(const QImage &img1,const QImage &img2) {
34 vector<double> psnr= getColorPSNR(img1,img2);
35 return QObject::tr("gray PSNR: %3 dB\nR,G,B: %4,%5,%6 dB") .arg(psnr[3],0,'f',2)
36 .arg(psnr[0],0,'f',2) .arg(psnr[1],0,'f',2) .arg(psnr[2],0,'f',2);
40 //// Public members
41 ImageViewer::ImageViewer(QApplication &app)
42 : modules_settings( IRoot::newCompatibleModule() ), modules_encoding(0)
43 , zoom(0), lastPath(QDir::current().filePath("x"))
44 , readAct(this), writeAct(this), compareAct(this), exitAct(this)
45 , settingsAct(this), encodeAct(this), saveAct(this)
46 , loadAct(this), clearAct(this), iterateAct(this), zoomIncAct(this), zoomDecAct(this) {
47 // try to load guessed language translation
48 if ( translator.load( "lang-"+QLocale::system().name(), app.applicationDirPath() ) )
49 app.installTranslator(&translator);
50 // create a scrolling area with a label for viewing images
51 imageLabel= new QLabel(this);
52 imageLabel->setBackgroundRole(QPalette::Dark);
53 imageLabel->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored);
55 QScrollArea *scrollArea= new QScrollArea(this);
56 scrollArea->setBackgroundRole(QPalette::Dark);
57 scrollArea->setWidget(imageLabel);
58 setCentralWidget(scrollArea);
60 setStatusBar(new QStatusBar(this));
62 createActions();
63 createMenus();
64 translateUi();
65 updateActions();
67 resize(800,600);
70 //// Private methods
71 void ImageViewer::createActions() {
72 // create all actions and connect them to the appropriate slots
73 #define A(name) \
74 aConnect( &name##Act, SIGNAL(triggered()), this, SLOT(name()) );
75 #define AS(name,signal) \
76 aConnect( &name##Act, SIGNAL(triggered()), this, SLOT(signal()) );
77 A(read)
78 A(write)
79 A(compare)
80 AS(exit,close)
82 A(settings)
83 A(encode)
84 A(save)
86 A(load)
87 A(clear)
88 A(iterate)
89 A(zoomInc)
90 A(zoomDec)
92 #undef A
93 #undef AS
95 void ImageViewer::createMenus() {
96 imageMenu.addAction(&readAct);
97 imageMenu.addAction(&writeAct);
98 imageMenu.addSeparator();
99 imageMenu.addAction(&compareAct);
100 imageMenu.addSeparator();
101 imageMenu.addAction(&exitAct);
103 compMenu.addAction(&settingsAct);
104 compMenu.addAction(&encodeAct);
105 compMenu.addAction(&saveAct);
107 decompMenu.addAction(&loadAct);
108 decompMenu.addAction(&clearAct);
109 decompMenu.addAction(&iterateAct);
110 decompMenu.addSeparator();
111 decompMenu.addAction(&zoomIncAct);
112 decompMenu.addAction(&zoomDecAct);
114 menuBar()->addMenu(&imageMenu);
115 menuBar()->addMenu(&compMenu);
116 menuBar()->addMenu(&decompMenu);
117 //menuBar()->addMenu(langMenu);
118 //menuBar()->addMenu(helpMenu);
120 void ImageViewer::translateUi() {
121 setWindowTitle(tr("Fractal Image Compressor"));
122 // set action names and shortcuts
123 #define A(name,shortcut,text) \
124 name##Act.setText(tr(text)); \
125 name##Act.setShortcut(tr(shortcut));
126 A(read, "Ctrl+R", "Read...")
127 A(write, "Ctrl+W", "Write...")
128 A(compare, "", "Compare to...")
129 A(exit, "Ctrl+Q", "Quit")
131 A(settings, "", "Settings")
132 A(encode, " ", "Start encoding")
133 A(save, "Ctrl+S", "Save FIC...")
135 A(load, "Ctrl+L", "Load FIC...")
136 A(clear, "Ctrl+C", "Clear image")
137 A(iterate, "Ctrl+I", "Iterate image")
138 A(zoomInc, "Ctrl++", "Increase zoom")
139 A(zoomDec, "Ctrl+-", "Decrease zoom")
140 #undef A
142 // set the tiles of menu items
143 #define M(name,title) \
144 name##Menu.setTitle(tr(title));
145 M(image, "&Image");
146 M(comp, "&Compression");
147 M(decomp, "&Decompression");
148 #undef M
150 void ImageViewer::updateActions() {
151 bool pixmapOk= imageLabel->pixmap();
152 IRoot::Mode mode= modules_encoding ? modules_encoding->getMode() : IRoot::Clear;
154 //readAct.setEnabled(true);
155 writeAct.setEnabled(pixmapOk);
156 compareAct.setEnabled(pixmapOk);
157 //exitAct.setEnabled(true);
159 //settingsAct.setEnabled(true);
160 encodeAct.setEnabled(pixmapOk);
161 saveAct.setEnabled( mode != IRoot::Clear );
163 //loadAct.setEnabled(true);
164 clearAct.setEnabled ( mode != IRoot::Clear );
165 iterateAct.setEnabled( mode != IRoot::Clear );
166 zoomIncAct.setEnabled( mode != IRoot::Clear && zoom<3 );
167 zoomDecAct.setEnabled( mode != IRoot::Clear && zoom>0 );
170 //// Private slots
171 void ImageViewer::read() {
172 // get the file name
173 QString fname= QFileDialog::getOpenFileName( this, tr("Read image file")
174 , lastDir(), tr("PNG images (*.png)\nAll files (*.*)") );
175 if (fname.isEmpty())
176 // no file selected
177 return;
178 lastPath.setPath(fname);
179 // try to load, check for errors
180 QImage image(fname);
181 if (image.isNull()) {
182 QMessageBox::information( this, tr("Error"), tr("Cannot open %1.").arg(fname) );
183 return;
185 // convert to 32-bits
186 if (image.depth()<32)
187 image= image.convertToFormat(QImage::Format_RGB32);
188 // display it
189 changePixmap(QPixmap::fromImage(image));
190 updateActions();
192 void ImageViewer::write() {
193 // get the file name
194 QString fname= QFileDialog::getSaveFileName( this, tr("Write image file")
195 , lastDir(), tr("PNG images (*.png)\nAll files (*.*)") );
196 if (fname.isEmpty())
197 return;
198 lastPath.setPath(fname);
199 // try to save the image
200 if ( !imageLabel->pixmap()->save(fname) ) {
201 QMessageBox::information( this, tr("Error"), tr("Cannot write file %1.").arg(fname) );
202 return;
204 updateActions();
206 void ImageViewer::compare() {
207 // let the user choose a file
208 QString fname= QFileDialog::getOpenFileName
209 ( this, tr("Compare to image"), lastDir()
210 , tr("PNG images (*.png)\nJFIF images (*.jpg *.jpeg)\nAll files (*.*)") );
211 if (fname.isEmpty())
212 return;
213 lastPath.setPath(fname);
214 // open the file as an image, check it's got the same dimensions as the diplayed one
215 QImage image(fname);
216 image= image.convertToFormat(QImage::Format_RGB32);
217 if (image.isNull()) {
218 QMessageBox::information( this, tr("Error"), tr("Cannot open %1.").arg(fname) );
219 return;
221 if ( image.width()!=imageLabel->pixmap()->width()
222 || image.height()!=imageLabel->pixmap()->height() ) {
223 QMessageBox::information
224 ( this, tr("Error"), tr("Images don't have the same dimensions.").arg(fname) );
225 return;
227 // compute the PSNRs and display them
228 QString message= getPSNRmessage( image, imageLabel->pixmap()->toImage() );
229 QMessageBox::information( this, tr("Comparison"), message );
231 void ImageViewer::settings() {
232 IRoot *newSettings= clone(modules_settings);
233 SettingsDialog dialog(this,newSettings);
234 newSettings= dialog.getSettings();
235 if ( dialog.exec() )
236 // the dialog wasn't cancelled -> swap with the current and new settings
237 swap(newSettings,modules_settings);
238 delete newSettings;
240 void ImageViewer::encode() {
241 EncodingProgress::create(this);
243 void ImageViewer::encDone() {
244 int encMsecs;
245 IRoot *modules_encoded= EncodingProgress::destroy(encMsecs);
247 if (modules_encoded) { // encoding successful - iterate the image and display some info
248 // replace the old state
249 delete modules_encoding;
250 modules_encoding= modules_encoded;
251 // decode the image
252 QImage beforeImg= modules_encoding->toImage();
254 QTime decTime;
255 decTime.start();
256 modules_encoding->decodeAct(MTypes::Clear);
257 modules_encoding->decodeAct(MTypes::Iterate,AutoIterationCount);
258 int decMsecs= decTime.elapsed();
260 QImage afterImg= modules_encoding->toImage();
261 changePixmap( QPixmap::fromImage(afterImg) );
262 // show some info
263 QString message= tr("Time to encode: %1 seconds\nTime to decode: %2 seconds\n")
264 .arg(encMsecs/1000.0) .arg(decMsecs/1000.0) + getPSNRmessage(beforeImg,afterImg);
265 QMessageBox::information( this, tr("encoded"), message );
266 encData.clear();
269 updateActions();
271 void ImageViewer::save() {
272 // get a filename to suggest
273 QFileInfo finfo(lastPath.path());
274 QString fname= finfo.dir().filePath( finfo.completeBaseName() + tr(".fic") );
275 fname= QFileDialog::getSaveFileName
276 ( this, tr("Save encoded image"), fname, tr("FIC images (*.fic)") );
277 if (fname.isEmpty())
278 return;
279 lastPath.setPath(fname);
280 if ( !modules_encoding->toFile( fname.toStdString().c_str() ) )
281 QMessageBox::information( this, tr("Error"), tr("Cannot write file %1.").arg(fname) );
283 void ImageViewer::load() {
284 QString fname= QFileDialog::getOpenFileName
285 ( this, tr("Load encoded image"), lastDir(), tr("FIC images (*.fic)") );
286 if (fname.isEmpty())
287 return;
288 lastPath.setPath(fname);
289 // IRoot needs to be loaded from cleared state
290 IRoot *modules_old= modules_encoding;
291 modules_encoding= clone(modules_settings,Module::ShallowCopy);
293 string decData;
294 bool error= !file2string( fname.toStdString().c_str(), decData );
295 if (!error) {
296 stringstream stream(decData);
298 error= !modules_encoding->fromStream( stream, zoom );
301 if (error) {
302 QMessageBox::information( this, tr("Error"), tr("Cannot load file %1.").arg(fname) );
303 swap(modules_encoding,modules_old);
304 } else { // loading was successful
305 swap(encData,decData);
306 modules_encoding->decodeAct(Clear);
307 modules_encoding->decodeAct(MTypes::Iterate,AutoIterationCount);
308 changePixmap( QPixmap::fromImage(modules_encoding->toImage()) );
309 updateActions();
312 delete modules_old;
314 void ImageViewer::clear() {
315 modules_encoding->decodeAct(Clear);
316 changePixmap( QPixmap::fromImage(modules_encoding->toImage()) );
317 updateActions();
319 void ImageViewer::iterate() {
320 modules_encoding->decodeAct(Iterate);
321 changePixmap( QPixmap::fromImage(modules_encoding->toImage()) );
322 updateActions();
324 void ImageViewer::zoomInc() {
325 ++zoom;
326 if (!rezoom())
327 --zoom, QMessageBox::information( this, tr("Error"), tr("Zooming failed.") );
329 void ImageViewer::zoomDec() {
330 --zoom;
331 assert(zoom>=0);
332 if (!rezoom())
333 ++zoom, QMessageBox::information( this, tr("Error"), tr("Zooming failed.") );
336 bool ImageViewer::rezoom() {
337 stringstream stream;
338 if ( encData.empty() ) {
339 if ( !modules_encoding->toStream(stream) )
340 return false;
341 encData= stream.str();
342 } else
343 stream.str(encData);
345 IRoot *newRoot= clone(modules_settings,Module::ShallowCopy);
346 if ( newRoot->fromStream(stream,zoom) ) {
347 delete modules_encoding;
348 modules_encoding= newRoot;
349 } else {
350 delete newRoot;
351 return false;
354 modules_encoding->decodeAct(MTypes::Clear);
355 modules_encoding->decodeAct(MTypes::Iterate,AutoIterationCount);
356 changePixmap( QPixmap::fromImage(modules_encoding->toImage()) );
357 updateActions();
358 return true;
362 //// SettingsDialog class
364 SettingsDialog::SettingsDialog( ImageViewer *parent, IRoot *settingsHolder )
365 : QDialog(parent,Qt::Dialog), settings(settingsHolder) {
366 setWindowTitle(tr("Compression settings"));
367 setModal(true);
368 // create a grid layout for the dialog
369 QGridLayout *layout= new QGridLayout;
370 setLayout(layout);
371 // add a tree widget
372 this->treeWidget= new QTreeWidget(this);
373 treeWidget->setHeaderLabel(tr("Modules"));
374 layout->addWidget(treeWidget,0,0);
375 // add a group-box to display settings of a module
376 this->setBox= new QGroupBox(this);
377 layout->addWidget(setBox,0,1);
378 // add a load/save button-box and connect it to a slot of this dialog
379 this->loadSaveButtons= new QDialogButtonBox
380 ( QDialogButtonBox::Open|QDialogButtonBox::Save, Qt::Horizontal, this );
381 aConnect( loadSaveButtons, SIGNAL(clicked(QAbstractButton*))
382 , this, SLOT(loadSaveClick(QAbstractButton*)) );
383 layout->addWidget(loadSaveButtons,1,0,Qt::AlignLeft);
384 // add a button-box and connect the clicking actions
385 QDialogButtonBox *buttons= new QDialogButtonBox
386 ( QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, this );
387 layout->addWidget(buttons,1,1); // the right-bottom cell
388 aConnect( buttons, SIGNAL(accepted()), this, SLOT(accept()) );
389 aConnect( buttons, SIGNAL(rejected()), this, SLOT(reject()) );
390 // create the tree
391 QTreeWidgetItem *treeRoot= new QTreeWidgetItem;
392 treeWidget->addTopLevelItem(treeRoot);
393 treeRoot->setText( 0, tr("Root") );
395 aConnect( treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))
396 , this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)) );
398 initialize();
400 void SettingsDialog::initialize() {
401 QTreeWidgetItem *treeRoot= treeWidget->topLevelItem(0);
402 assert( treeRoot && settings && setBox );
403 clearContainer( treeRoot->takeChildren() );
404 settings->adjustSettings(-1,treeRoot,setBox);
405 treeWidget->setCurrentItem(treeRoot);
406 treeWidget->expandAll();
408 void SettingsDialog::currentItemChanged(QTreeWidgetItem *curItem,QTreeWidgetItem*) {
409 // get the module that should show its settings
410 assert(curItem);
411 Module *curMod= static_cast<Module*>( curItem->data(0,Qt::UserRole).value<void*>() );
412 assert(curMod);
413 // clear the settings box and make the module fill it
414 clearContainer( setBox->children() );
415 setBox->setTitle( tr("%1 module settings") .arg(curMod->info().name) );
416 curMod->adjustSettings(-1,0,setBox);
418 void SettingsDialog::settingChanges(int which) {
419 QTreeWidgetItem *tree= treeWidget->currentItem();
420 Module *module= static_cast<Module*>( tree->data(0,Qt::UserRole).value<void*>() );
421 module->adjustSettings(which,tree,setBox);
423 void SettingsDialog::loadSaveClick(QAbstractButton *button) {
424 QDialogButtonBox::StandardButton test= loadSaveButtons->standardButton(button);
425 switch ( test ) {
426 case QDialogButtonBox::Open: { // open-button has been clicked
427 // ask for the name to load from
428 QString fname= QFileDialog::getOpenFileName( this, tr("Load settings file")
429 , parentViewer().lastDir(), tr("FIC settings (*.fms)") );
430 if (fname.isEmpty())
431 return;
432 // try to load the settings
433 IRoot *newSettings= clone(settings,Module::ShallowCopy);
434 if ( newSettings->allSettingsFromFile(fname.toStdString().c_str()) ) {
435 delete settings;
436 settings= newSettings;
437 initialize();
438 } else {
439 QMessageBox::information( this, tr("Error")
440 , tr("Cannot load settings from %1.").arg(fname) );
441 delete newSettings;
443 } break;
444 case QDialogButtonBox::Save: { // save-button has been clicked
445 // ask for the name to save in
446 QString fname= QFileDialog::getSaveFileName( this, tr("Save settings file")
447 , parentViewer().lastDir(), tr("FIC settings (*.fms)") );
448 if (fname.isEmpty())
449 return;
450 // try to save the settings
451 if ( !settings->allSettingsToFile(fname.toStdString().c_str()) )
452 QMessageBox::information( this, tr("Error")
453 , tr("Cannot save settings into %1.").arg(fname) );
454 } break;
455 default:
456 assert(false);
460 //// GUI-related Module members
461 namespace NOSPACE {
462 QWidget* newSettingsWidget(Module::ChoiceType type,QWidget *parent) {
463 QWidget *result=0;
464 switch (type) {
465 case Module::Int:
466 case Module::IntLog2:
467 result= new QSpinBox(parent);
468 break;
469 case Module::Float:
470 result= new QDoubleSpinBox(parent);
471 break;
472 case Module::ModuleCombo:
473 case Module::Combo:
474 result= new QComboBox(parent);
475 break;
476 default:
477 assert(false);
478 }// switch
479 return result;
482 void Module::adjustSettings(int which,QTreeWidgetItem *myTree,QGroupBox *setBox) {
483 if (which<0) {
484 // no change has really happened
485 assert(which==-1);
486 if (myTree) {
487 // I should create the subtree -> store this-pointer as data
488 assert( myTree->childCount() == 0 );
489 myTree->setData( 0, Qt::UserRole, QVariant::fromValue((void*)this) );
490 if (!settings) {
491 myTree->setFlags(0);
492 return;
494 // find child modules and make them create their subtrees
495 const SettingsTypeItem *setType= info().setType;
496 const SettingsItem *setItem= settings;
497 for (; setType->type.type!=Stop; ++setItem,++setType)
498 if ( setType->type.type == ModuleCombo ) {
499 // it is a module -> label its subtree-root and recurse (polymorphically)
500 assert(setItem->m);
501 if ( !setItem->m->info().setLength )
502 continue; // skipping modules with no settings
503 QTreeWidgetItem *childTree= new QTreeWidgetItem(myTree);
504 childTree->setText( 0, QObject::tr(setType->label) );
505 setItem->m->adjustSettings( -1, childTree, 0 );
508 int setLength= info().setLength;
509 if ( setBox && setLength ) {
510 // fill the group-box
511 QGridLayout *layout= new QGridLayout(setBox);
512 setBox->setLayout(layout);
513 const SettingsTypeItem *typeItem= info().setType;
514 for (int i=0; i<setLength; ++i,++typeItem) {
515 // add a line - one option
516 QString desc(typeItem->desc);
517 QLabel *label= new QLabel( typeItem->label, setBox );
518 label->setToolTip(desc);
520 QWidget *widget= newSettingsWidget( typeItem->type.type, setBox );
521 settingsType2widget( widget, *typeItem );
522 settings2widget( widget, i );
523 widget->setToolTip(desc);
524 label->setBuddy(widget);
525 layout->addWidget( label, i, 0 );
526 layout->addWidget( widget, i, 1 );
528 SignalChanger *changer= new SignalChanger(i,widget,typeItem->type.type);
529 aConnect( changer, SIGNAL(notify(int)) // assuming the setBox's
530 , setBox->parent(), SLOT(settingChanges(int)) ); // parent is SettingsDialog
531 }// for loop
532 }// filling the box
533 } else {
534 // which>=0... a setting has changed -> get the change from the widget
535 assert( which < info().setLength );
536 QLayoutItem *item= setBox->layout()->itemAt(2*which+1);
537 assert(item);
538 widget2settings( item->widget() , which );
539 // handle module-type settings
540 const SettingsTypeItem *setType= info().setType;
541 if ( setType[which].type.type == ModuleCombo ) {
542 assert(myTree);
543 // get the new module id and check whether it has really changed
544 SettingsItem &setItem= settings[which];
545 int newId= (*setType->type.data.compatIDs)[setItem.val.i];
546 if ( newId == setItem.m->info().id )
547 return;
548 // replace the child module
549 clearContainer( myTree->takeChildren() );
550 delete setItem.m;
551 setItem.m= ModuleFactory::newModule(newId);
552 adjustSettings( -1, myTree, 0 );
554 // update module defaults
555 ModuleFactory::changeDefaultSettings(*this);
558 void Module::widget2settings(const QWidget *widget,int which) {
559 assert( 0<=which && which<info().setLength );
560 switch( info().setType[which].type.type ) {
561 case Int:
562 case IntLog2:
563 settings[which].val.i= debugCast<const QSpinBox*>(widget)->value();
564 break;
565 case Float:
566 settings[which].val.f= debugCast<const QDoubleSpinBox*>(widget)->value();
567 break;
568 case ModuleCombo:
569 case Combo:
570 settings[which].val.i= debugCast<const QComboBox*>(widget)->currentIndex();
571 break;
572 default:
573 assert(false);
574 }// switch
576 void Module::settings2widget(QWidget *widget,int which) {
577 assert( 0<=which && which<info().setLength );
578 switch( info().setType[which].type.type ) {
579 case Int:
580 case IntLog2:
581 debugCast<QSpinBox*>(widget)->setValue( settings[which].val.i );
582 break;
583 case Float:
584 debugCast<QDoubleSpinBox*>(widget)->setValue( settings[which].val.f );
585 break;
586 case ModuleCombo:
587 case Combo:
588 debugCast<QComboBox*>(widget)->setCurrentIndex( settings[which].val.i );
589 break;
590 default:
591 assert(false);
592 }// switch
594 namespace NOSPACE {
595 class ItemAdder {
596 QComboBox *box;
597 public:
598 ItemAdder(QWidget *widget): box( debugCast<QComboBox*>(widget) ) {}
599 void operator()(int i) {
600 box->addItem( ModuleFactory::moduleName(i) );
601 box->setItemData( box->count()-1
602 , QObject::tr(ModuleFactory::moduleDescription(i)), Qt::ToolTipRole );
606 void Module::settingsType2widget(QWidget *widget,const SettingsTypeItem &typeItem) {
607 assert( widget );
608 switch( typeItem.type.type ) {
609 case IntLog2:
610 debugCast<QSpinBox*>(widget)->setPrefix(QObject::tr("2^"));
611 // fall through
612 case Int:
613 debugCast<QSpinBox*>(widget)->
614 setRange( typeItem.type.data.i[0], typeItem.type.data.i[1] );
615 break;
616 case Float:
617 debugCast<QDoubleSpinBox*>(widget)->
618 setRange( typeItem.type.data.f[0], typeItem.type.data.f[1] );
619 break;
620 case ModuleCombo: {
621 const vector<int> &modules= *typeItem.type.data.compatIDs;
622 for_each( modules.begin(), modules.end(), ItemAdder(widget) );
623 break;
625 case Combo:
626 debugCast<QComboBox*>(widget)->
627 addItems( QString(typeItem.type.data.text).split('\n') );
628 break;
629 default:
630 assert(false);
631 }// switch
635 #ifndef NDEBUG
636 void ImageViewer::mousePressEvent(QMouseEvent *event) {
637 // check the event, get the clicking point coordinates relative to the image
638 if ( !event || !modules_encoding
639 || modules_encoding->getMode() == IRoot::Clear)
640 return;
641 const QPoint click= imageLabel->mapFrom( this, event->pos() );
642 // get the image
643 QPixmap pixmap= *imageLabel->pixmap();
644 if ( click.isNull() )
645 return;
647 static QWidget *debugWidget= 0;
648 delete debugWidget;
649 debugWidget= modules_encoding->debugModule(pixmap,click);
650 debugWidget->setParent(this);
651 debugWidget->setWindowFlags(Qt::Dialog);
652 debugWidget->show();
654 changePixmap(pixmap);
658 EncodingProgress *EncodingProgress::instance= 0;
660 #endif