1 #include <sstream> // needed for ::load and ::rezoom
4 #include "imageUtil.h" // Color::getPSNR function
5 #include "fileUtil.h" // file2string function
9 //// Non-member functions
10 static QString
getPSNRmessage(const QImage
&img1
,const QImage
&img2
) {
11 vector
<Real
> psnr
= Color::getPSNR(img1
,img2
);
12 return QObject::tr("gray PSNR: %3 dB\nR,G,B: %4,%5,%6 dB") .arg(psnr
[3],0,'f',2)
13 .arg(psnr
[0],0,'f',2) .arg(psnr
[1],0,'f',2) .arg(psnr
[2],0,'f',2);
18 ImageViewer::ImageViewer(QApplication
&app
,QTranslator
&trans
)
19 : modules_settings( IRoot::newCompatibleModule() ), modules_encoding(0)
20 , zoom(0), translator(trans
), lastPath(QDir::current().filePath("x"))
21 , readAct(this), writeAct(this), compareAct(this), exitAct(this)
22 , settingsAct(this), encodeAct(this), saveAct(this)
23 , loadAct(this), clearAct(this), iterateAct(this), zoomIncAct(this), zoomDecAct(this)
24 , loadLangAct(this), useLangAct(this) {
25 // try to load guessed language translation
26 if ( translator
.load( "lang-"+QLocale::system().name(), app
.applicationDirPath() ) )
27 app
.installTranslator(&translator
);
28 // create a scrolling area with a label for viewing images
29 imageLabel
= new QLabel(this);
30 imageLabel
->setBackgroundRole(QPalette::Dark
);
31 imageLabel
->setSizePolicy(QSizePolicy::Ignored
,QSizePolicy::Ignored
);
33 QScrollArea
*scrollArea
= new QScrollArea(this);
34 scrollArea
->setBackgroundRole(QPalette::Dark
);
35 scrollArea
->setWidget(imageLabel
);
36 setCentralWidget(scrollArea
);
38 setStatusBar(new QStatusBar(this));
49 void ImageViewer::createActions() {
50 // create all actions and connect them to the appropriate slots
52 aConnect( &name##Act, SIGNAL(triggered()), this, SLOT(name()) );
53 #define AS(name,signal) \
54 aConnect( &name##Act, SIGNAL(triggered()), this, SLOT(signal()) );
56 aConnect( &name##Act, SIGNAL(toggled(bool)), this, SLOT(name(bool)) );
80 useLangAct
.setCheckable(true);
81 useLangAct
.setChecked( !translator
.isEmpty() );
83 void ImageViewer::createMenus() {
84 imageMenu
.addAction(&readAct
);
85 imageMenu
.addAction(&writeAct
);
86 imageMenu
.addSeparator();
87 imageMenu
.addAction(&compareAct
);
88 imageMenu
.addSeparator();
89 imageMenu
.addAction(&exitAct
);
91 compMenu
.addAction(&settingsAct
);
92 compMenu
.addAction(&encodeAct
);
93 compMenu
.addAction(&saveAct
);
95 decompMenu
.addAction(&loadAct
);
96 decompMenu
.addAction(&clearAct
);
97 decompMenu
.addAction(&iterateAct
);
98 decompMenu
.addSeparator();
99 decompMenu
.addAction(&zoomIncAct
);
100 decompMenu
.addAction(&zoomDecAct
);
102 langMenu
.addAction(&loadLangAct
);
103 langMenu
.addAction(&useLangAct
);
105 menuBar()->addMenu(&imageMenu
);
106 menuBar()->addMenu(&compMenu
);
107 menuBar()->addMenu(&decompMenu
);
108 menuBar()->addMenu(&langMenu
);
109 //menuBar()->addMenu(&helpMenu);
111 void ImageViewer::translateUi() {
112 setWindowTitle(tr("Fractal Image Compressor"));
113 // set action names and shortcuts
114 #define A(name,shortcut,text) \
115 name##Act.setText(text); \
116 name##Act.setShortcut(tr(shortcut));
117 A(read
, "Ctrl+R", tr("Read..."))
118 A(write
, "Ctrl+W", tr("Write..."))
119 A(compare
, "", tr("Compare to..."))
120 A(exit
, "Ctrl+Q", tr("Quit"))
122 A(settings
, "", tr("Settings"))
123 A(encode
, " ", tr("Start encoding"))
124 A(save
, "Ctrl+S", tr("Save FCI..."))
126 A(load
, "Ctrl+L", tr("Load FCI..."))
127 A(clear
, "Ctrl+C", tr("Clear image"))
128 A(iterate
, "Ctrl+I", tr("Iterate image"))
129 A(zoomInc
, "Ctrl++", tr("Increase zoom"))
130 A(zoomDec
, "Ctrl+-", tr("Decrease zoom"))
132 A(loadLang
, "", tr("Load language..."))
133 A(useLang
, "", tr("Use language"))
136 // set the tiles of menu items
137 #define M(name,title) \
138 name##Menu.setTitle(title);
139 M(image
, tr("&Image"));
140 M(comp
, tr("&Compression"));
141 M(decomp
, tr("&Decompression"));
142 M(lang
, tr("&Language"))
145 void ImageViewer::updateActions() {
146 bool pixmapOk
= imageLabel
->pixmap();
147 IRoot::Mode mode
= modules_encoding
? modules_encoding
->getMode() : IRoot::Clear
;
149 //readAct.setEnabled(true);
150 writeAct
.setEnabled(pixmapOk
);
151 compareAct
.setEnabled(pixmapOk
);
152 //exitAct.setEnabled(true);
154 //settingsAct.setEnabled(true);
155 encodeAct
.setEnabled(pixmapOk
);
156 saveAct
.setEnabled( mode
!= IRoot::Clear
);
158 //loadAct.setEnabled(true);
159 clearAct
.setEnabled ( mode
!= IRoot::Clear
);
160 iterateAct
.setEnabled( mode
!= IRoot::Clear
);
161 zoomIncAct
.setEnabled( mode
!= IRoot::Clear
&& zoom
<3 );
162 zoomDecAct
.setEnabled( mode
!= IRoot::Clear
&& zoom
>0 );
164 useLangAct
.setEnabled( !translator
.isEmpty() );
168 void ImageViewer::read() {
170 QString fname
= QFileDialog::getOpenFileName( this, tr("Read image file")
171 , lastDir(), tr("PNG images (*.png)\nAll files (*.*)") );
175 lastPath
.setPath(fname
);
176 // try to load, check for errors
178 if (image
.isNull()) {
179 QMessageBox::information( this, tr("Error"), tr("Cannot open %1.").arg(fname
) );
182 // convert to 24-bits
183 if ( image
.format() != QImage::Format_RGB32
)
184 image
= image
.convertToFormat(QImage::Format_RGB32
);
186 changePixmap(QPixmap::fromImage(image
));
187 // clear the old modules
188 delete modules_encoding
;
192 void ImageViewer::write() {
194 QString fname
= QFileDialog::getSaveFileName( this, tr("Write image file")
195 , lastDir(), tr("PNG images (*.png)\nAll files (*.*)") );
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
) );
206 void ImageViewer::compare() {
207 // let the user choose a file
208 QString fname
= QFileDialog::getOpenFileName( this, tr("Compare to image"), lastDir()
209 , tr("PNG images (*.png)\nJFIF images (*.jpg *.jpeg)\nAll files (*.*)") );
212 lastPath
.setPath(fname
);
213 // open the file as an image, check it's got the same dimensions as the diplayed one
215 if ( image
.format() != QImage::Format_RGB32
)
216 image
= image
.convertToFormat(QImage::Format_RGB32
);
217 if (image
.isNull()) {
218 QMessageBox::information( this, tr("Error"), tr("Cannot open %1.").arg(fname
) );
221 if ( image
.rect() != imageLabel
->pixmap()->rect() ) {
222 QMessageBox::information
223 ( this, tr("Error"), tr("Images don't have the same dimensions.").arg(fname
) );
226 // compute the PSNRs and display them
227 QString message
= getPSNRmessage( image
, imageLabel
->pixmap()->toImage() );
228 QMessageBox::information( this, tr("Comparison"), message
);
230 void ImageViewer::settings() {
231 IRoot
*newSettings
= modules_settings
->clone();
232 SettingsDialog
dialog(this,newSettings
);
233 bool accepted
= dialog
.exec();
234 newSettings
= dialog
.getSettings();
235 if (accepted
) // the dialog wasn't cancelled -> swap with the current and new settings
236 swap(newSettings
,modules_settings
);
239 void ImageViewer::encode() {
240 EncodingProgress::create(this);
242 void ImageViewer::encDone() {
244 IRoot
*modules_encoded
= EncodingProgress::destroy(encMsecs
);
246 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
;
252 QImage beforeImg
= modules_encoding
->toImage();
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
) );
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
);
271 void ImageViewer::save() {
272 // get a filename to suggest
273 QFileInfo
finfo(lastPath
.path());
274 QString fname
= finfo
.dir().filePath( finfo
.completeBaseName() + tr(".fci") );
275 fname
= QFileDialog::getSaveFileName
276 ( this, tr("Save encoded image"), fname
, tr("Fractal-compressed images (*.fci)") );
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("Fractal-compressed images (*.fci)") );
288 lastPath
.setPath(fname
);
289 // IRoot needs to be loaded from cleared state
290 IRoot
*modules_old
= modules_encoding
;
291 modules_encoding
= modules_settings
->clone(Module::ShallowCopy
);
294 bool error
= !file2string( fname
.toStdString().c_str(), decData
);
296 stringstream
stream(decData
);
297 error
= !modules_encoding
->fromStream( stream
, zoom
);
301 QMessageBox::information( this, tr("Error"), tr("Cannot load file %1.").arg(fname
) );
302 swap(modules_encoding
,modules_old
);
303 } else { // loading was successful
304 swap(encData
,decData
);
305 modules_encoding
->decodeAct(Clear
);
306 modules_encoding
->decodeAct(MTypes::Iterate
,AutoIterationCount
);
307 changePixmap( QPixmap::fromImage(modules_encoding
->toImage()) );
313 void ImageViewer::clear() {
314 modules_encoding
->decodeAct(Clear
);
315 changePixmap( QPixmap::fromImage(modules_encoding
->toImage()) );
318 void ImageViewer::iterate() {
319 modules_encoding
->decodeAct(Iterate
);
320 changePixmap( QPixmap::fromImage(modules_encoding
->toImage()) );
323 void ImageViewer::zoomInc() {
326 --zoom
, QMessageBox::information( this, tr("Error"), tr("Zooming failed.") );
328 void ImageViewer::zoomDec() {
332 ++zoom
, QMessageBox::information( this, tr("Error"), tr("Zooming failed.") );
334 void ImageViewer::loadLang() {
335 QString fname
= QFileDialog::getOpenFileName( this, tr("Load Language")
336 , QApplication::applicationDirPath(), tr("Translation Definitions (*.qm)") );
339 if (translator
.load(fname
)) {
340 useLangAct
.setChecked(true);
343 QMessageBox::warning( this, tr("Error"), tr("Cannot load %1.").arg(fname
) );
346 void ImageViewer::useLang(bool use
) {
348 QApplication::installTranslator(&translator
);
350 QApplication::removeTranslator(&translator
);
354 bool ImageViewer::rezoom() {
355 // create a stream that contains the "saved image"
357 if ( encData
.empty() ) { // cache is empty - we have to create it (save the image)
358 if ( !modules_encoding
->toStream(stream
) )
360 encData
= stream
.str();
361 } else // reusing the cache
363 // reload the image from the stream
364 IRoot
*newRoot
= modules_settings
->clone(Module::ShallowCopy
);
365 if ( newRoot
->fromStream(stream
,zoom
) ) {
366 delete modules_encoding
;
367 modules_encoding
= newRoot
;
372 // successfully reloaded -> auto-iterate the image and show it
373 modules_encoding
->decodeAct(MTypes::Clear
);
374 modules_encoding
->decodeAct(MTypes::Iterate
,AutoIterationCount
);
375 changePixmap( QPixmap::fromImage(modules_encoding
->toImage()) );
381 //// SettingsDialog class
383 SettingsDialog::SettingsDialog( ImageViewer
*parent
, IRoot
*settingsHolder
)
384 : QDialog(parent
,Qt::Dialog
), settings(settingsHolder
) {
385 setWindowTitle(tr("Compression settings"));
387 // create a grid layout for the dialog
388 QGridLayout
*layout
= new QGridLayout
;
391 this->treeWidget
= new QTreeWidget(this);
392 treeWidget
->setHeaderLabel(tr("Modules"));
393 layout
->addWidget(treeWidget
,0,0);
394 // add a group-box to display settings of a module
395 this->setBox
= new QGroupBox(this);
396 layout
->addWidget(setBox
,0,1);
397 // add a load/save button-box and connect it to a slot of this dialog
398 this->loadSaveButtons
= new QDialogButtonBox
399 ( QDialogButtonBox::Open
|QDialogButtonBox::Save
, Qt::Horizontal
, this );
400 aConnect( loadSaveButtons
, SIGNAL(clicked(QAbstractButton
*))
401 , this, SLOT(loadSaveClick(QAbstractButton
*)) );
402 layout
->addWidget(loadSaveButtons
,1,0,Qt::AlignLeft
);
403 // add a button-box and connect the clicking actions
404 QDialogButtonBox
*buttons
= new QDialogButtonBox
405 ( QDialogButtonBox::Ok
|QDialogButtonBox::Cancel
, Qt::Horizontal
, this );
406 layout
->addWidget(buttons
,1,1); // the right-bottom cell
407 aConnect( buttons
, SIGNAL(accepted()), this, SLOT(accept()) );
408 aConnect( buttons
, SIGNAL(rejected()), this, SLOT(reject()) );
410 QTreeWidgetItem
*treeRoot
= new QTreeWidgetItem
;
411 treeWidget
->addTopLevelItem(treeRoot
);
412 treeRoot
->setText( 0, tr("Root") );
414 aConnect( treeWidget
, SIGNAL(currentItemChanged(QTreeWidgetItem
*,QTreeWidgetItem
*))
415 , this, SLOT(currentItemChanged(QTreeWidgetItem
*,QTreeWidgetItem
*)) );
419 void SettingsDialog::initialize() {
420 QTreeWidgetItem
*treeRoot
= treeWidget
->topLevelItem(0);
421 ASSERT( treeRoot
&& settings
&& setBox
);
423 clearQtContainer( treeRoot
->takeChildren() );
425 settings
->adjustSettings(-1,treeRoot
,setBox
);
426 treeWidget
->setCurrentItem(treeRoot
);
427 treeWidget
->expandAll();
429 void SettingsDialog::currentItemChanged(QTreeWidgetItem
*curItem
,QTreeWidgetItem
*) {
430 // get the module that should show its settings
432 Module
*curMod
= static_cast<Module
*>( curItem
->data(0,Qt::UserRole
).value
<void*>() );
434 // clear the settings box and make the module fill it
435 clearQtContainer( setBox
->children() );
436 setBox
->setTitle( tr("%1 module settings") .arg(QObject::tr(curMod
->info().name
)) );
437 curMod
->adjustSettings(-1,0,setBox
);
439 void SettingsDialog::settingChanges(int which
) {
440 QTreeWidgetItem
*tree
= treeWidget
->currentItem();
441 Module
*module
= static_cast<Module
*>( tree
->data(0,Qt::UserRole
).value
<void*>() );
442 module
->adjustSettings(which
,tree
,setBox
);
444 void SettingsDialog::loadSaveClick(QAbstractButton
*button
) {
445 QDialogButtonBox::StandardButton test
= loadSaveButtons
->standardButton(button
);
447 case QDialogButtonBox::Open
: { // open-button has been clicked
448 // ask for the name to load from
449 QString fname
= QFileDialog::getOpenFileName( this, tr("Load settings file")
450 , parentViewer().lastDir(), tr("Fractal compression settings (*.fcs)") );
453 // try to load the settings
454 IRoot
*newSettings
= settings
->clone(Module::ShallowCopy
);
455 if ( newSettings
->allSettingsFromFile(fname
.toStdString().c_str()) ) {
457 settings
= newSettings
;
460 QMessageBox::information( this, tr("Error")
461 , tr("Cannot load settings from %1.").arg(fname
) );
465 case QDialogButtonBox::Save
: { // save-button has been clicked
466 // ask for the name to save in
467 QString fname
= QFileDialog::getSaveFileName( this, tr("Save settings file")
468 , parentViewer().lastDir()+"/settings.fcs"
469 , tr("Fractal compression settings (*.fcs)") );
472 // try to save the settings
473 if ( !settings
->allSettingsToFile(fname
.toStdString().c_str()) )
474 QMessageBox::information( this, tr("Error")
475 , tr("Cannot save settings into %1.").arg(fname
) );
482 //// GUI-related Module members
484 QWidget
* newSettingsWidget(Module::ChoiceType type
,QWidget
*parent
) {
488 case Module::IntLog2
:
489 result
= new QSpinBox(parent
);
492 result
= new QDoubleSpinBox(parent
);
494 case Module::ModuleCombo
:
496 result
= new QComboBox(parent
);
504 void Module::adjustSettings(int which
,QTreeWidgetItem
*myTree
,QGroupBox
*setBox
) {
505 if (which
<0) { // no change has really happened
508 // I should create the subtree -> store this-pointer as data
509 ASSERT( myTree
->childCount() == 0 );
510 myTree
->setData( 0, Qt::UserRole
, QVariant::fromValue((void*)this) );
515 // find child modules and make them create their subtrees
516 const SettingTypeItem
*setType
= info().setType
;
517 const SettingItem
*setItem
= settings
;
518 for (; setType
->type
.type
!=Stop
; ++setItem
,++setType
)
519 if ( setType
->type
.type
== ModuleCombo
) {
520 // it is a module -> label its subtree-root and recurse (polymorphically)
522 if ( !setItem
->m
->info().setLength
)
523 continue; // skipping modules with no settings
524 QTreeWidgetItem
*childTree
= new QTreeWidgetItem(myTree
);
525 childTree
->setText( 0, QObject::tr(setType
->label
) );
526 setItem
->m
->adjustSettings( -1, childTree
, 0 );
529 int setLength
= info().setLength
;
530 if ( setBox
&& setLength
) {
531 // clear the group box
532 clearQtContainer( setBox
->children() );
533 ASSERT( setBox
->children().empty() );
534 // fill the group-box
535 QGridLayout
*layout
= new QGridLayout(setBox
);
536 setBox
->setLayout(layout
);
537 const SettingTypeItem
*typeItem
= info().setType
;
538 for (int i
=0; i
<setLength
; ++i
,++typeItem
) { // add a line - one option
539 QString desc
= QObject::tr(typeItem
->desc
);
540 QLabel
*label
= new QLabel( QObject::tr(typeItem
->label
), setBox
);
541 label
->setToolTip(desc
);
543 QWidget
*widget
= newSettingsWidget( typeItem
->type
.type
, setBox
);
544 settingsType2widget( widget
, *typeItem
);
545 settings2widget( widget
, i
);
546 widget
->setToolTip(desc
);
547 label
->setBuddy(widget
);
548 layout
->addWidget( label
, i
, 0 );
549 layout
->addWidget( widget
, i
, 1 );
551 SignalChanger
*changer
= new SignalChanger(i
,widget
,typeItem
->type
.type
);
552 aConnect( changer
, SIGNAL(notify(int)) // assuming the setBox's
553 , setBox
->parent(), SLOT(settingChanges(int)) ); // parent is SettingsDialog
557 // which>=0... a setting has changed -> get the change from the widget
558 ASSERT( which
< info().setLength
);
559 QLayoutItem
*item
= setBox
->layout()->itemAt(2*which
+1);
561 widget2settings( item
->widget() , which
);
562 // handle module-type settings
563 const SettingTypeItem
&setType
= info().setType
[which
];
564 if ( setType
.type
.type
== ModuleCombo
) {
566 // get the new module id and check whether it has really changed
567 SettingItem
&setItem
= settings
[which
];
568 int newId
= (*setType
.type
.data
.compatIDs
)[setItem
.val
.i
];
569 if ( newId
== setItem
.m
->info().id
)
571 // replace the child module
572 clearQtContainer( myTree
->takeChildren() );
574 setItem
.m
= ModuleFactory::newModule(newId
);
575 adjustSettings( -1, myTree
, 0 );
577 // update module defaults
578 ModuleFactory::changeDefaultSettings(*this);
581 void Module::widget2settings(const QWidget
*widget
,int which
) {
582 ASSERT( 0<=which
&& which
<info().setLength
);
583 switch( info().setType
[which
].type
.type
) {
586 settings
[which
].val
.i
= debugCast
<const QSpinBox
*>(widget
)->value();
589 settings
[which
].val
.f
= debugCast
<const QDoubleSpinBox
*>(widget
)->value();
593 settings
[which
].val
.i
= debugCast
<const QComboBox
*>(widget
)->currentIndex();
599 void Module::settings2widget(QWidget
*widget
,int which
) {
600 ASSERT( 0<=which
&& which
<info().setLength
);
601 switch( info().setType
[which
].type
.type
) {
604 debugCast
<QSpinBox
*>(widget
)->setValue( settings
[which
].val
.i
);
607 debugCast
<QDoubleSpinBox
*>(widget
)->setValue( settings
[which
].val
.f
);
611 debugCast
<QComboBox
*>(widget
)->setCurrentIndex( settings
[which
].val
.i
);
621 ItemAdder(QWidget
*widget
): box( debugCast
<QComboBox
*>(widget
) ) {}
622 void operator()(int i
) {
623 const Module::TypeInfo
&info
= ModuleFactory::prototype(i
).info();
624 box
->addItem(QObject::tr(info
.name
));
625 box
->setItemData( box
->count()-1, QObject::tr(info
.desc
), Qt::ToolTipRole
);
629 void Module::settingsType2widget(QWidget
*widget
,const SettingTypeItem
&typeItem
) {
631 const SettingType
&type
= typeItem
.type
;
635 debugCast
<QSpinBox
*>(widget
)->setPrefix(QObject::tr("2^"));
638 debugCast
<QSpinBox
*>(widget
)->setRange( type
.data
.i
[0], type
.data
.i
[1] );
639 // try to guess a reasonable step for the spin-box
640 int range
= type
.data
.i
[1]-type
.data
.i
[0];
641 int step
= (int)exp10(floor(log10(range
/5)));
644 debugCast
<QSpinBox
*>(widget
)->setSingleStep(step
);
648 debugCast
<QDoubleSpinBox
*>(widget
)->setRange( type
.data
.f
[0], type
.data
.f
[1] );
649 // try to guess a reasonable step for the spin-box
650 float range
= type
.data
.f
[1]-type
.data
.f
[0];
651 debugCast
<QDoubleSpinBox
*>(widget
)->setSingleStep( exp10(floor(log10(range
/5))) );
655 const vector
<int> &modules
= *typeItem
.type
.data
.compatIDs
;
656 for_each( modules
, ItemAdder(widget
) );
660 debugCast
<QComboBox
*>(widget
)->addItems( QObject::tr(type
.data
.text
).split('\n') );
669 void ImageViewer::mousePressEvent(QMouseEvent
*event
) {
670 // check the event, get the clicking point coordinates relative to the image
671 if ( !event
|| !modules_encoding
672 || modules_encoding
->getMode() == IRoot::Clear
)
674 const QPoint click
= imageLabel
->mapFrom( this, event
->pos() );
676 QPixmap pixmap
= *imageLabel
->pixmap();
677 if ( click
.isNull() )
680 static QWidget
*debugWidget
= 0;
682 debugWidget
= modules_encoding
->debugModule(pixmap
,click
);
683 debugWidget
->setParent(this);
684 debugWidget
->setWindowFlags(Qt::Dialog
);
687 changePixmap(pixmap
);
692 EncodingProgress
*EncodingProgress::instance
= 0;