summaryrefslogtreecommitdiff
path: root/noncore/unsupported/showimg/showimg.cpp
Unidiff
Diffstat (limited to 'noncore/unsupported/showimg/showimg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/showimg/showimg.cpp1242
1 files changed, 1242 insertions, 0 deletions
diff --git a/noncore/unsupported/showimg/showimg.cpp b/noncore/unsupported/showimg/showimg.cpp
new file mode 100644
index 0000000..24377ed
--- a/dev/null
+++ b/noncore/unsupported/showimg/showimg.cpp
@@ -0,0 +1,1242 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21//
22// Full-screen and rotation options contributed by Robert Wittams <robert@wittams.com>
23//
24
25#include "showimg.h"
26#include "ImageFileSelector.h"
27#include "settingsdialog.h"
28
29/* OPIE */
30#include <opie2/odebug.h>
31#include <opie2/ofiledialog.h>
32#include <qpe/qpeapplication.h>
33#include <qpe/config.h>
34#include <qpe/resource.h>
35using namespace Opie::Core;
36using namespace Opie::Ui;
37
38/* QT */
39#include <qtoolbar.h>
40#include <qaction.h>
41#include <qfiledialog.h>
42#include <qmenubar.h>
43#include <qspinbox.h>
44
45/* STD */
46#include <math.h>
47
48ControlsDialog::ControlsDialog(const QString &caption,QImage image,int *brightness,QWidget *parent)
49 : QDialog(parent,0,true)
50{
51 setCaption(caption);
52
53 if ( parent ) {
54 setPalette(parent->palette());
55 }
56
57 b=brightness;
58 img=image;
59
60 setMinimumSize(140,80);
61
62 QGridLayout *gl= new QGridLayout(this,2,2,4,4);
63
64 pixmap =new ImageWidget(this);;
65 QPixmap pm;
66 pm.convertFromImage(img);
67 pixmap->setPixmap(pm);
68 pixmap->setMinimumSize(pm.width(),pm.height());
69 gl->addMultiCellWidget(pixmap,0,0,0,2,AlignCenter);
70 QLabel *l=new QLabel(tr("Brightness")+":",this);
71 gl->addWidget(l,1,0,AlignLeft);
72 spb=new QSpinBox(-100,100,2,this);
73 gl->addWidget(spb,1,1,AlignRight);
74
75 spb->setValue(0);
76
77 connect(spb,SIGNAL(valueChanged(int)),this, SLOT(bValueChanged(int)));
78
79}
80
81void ControlsDialog::bValueChanged(int value)
82{
83 QImage nImage=img;
84 nImage.detach();
85 ImageViewer::intensity(nImage, (float)value/100);
86 QPixmap pm;
87 pm.convertFromImage(nImage);
88 pixmap->setPixmap(pm);
89 pixmap->repaint(false);
90
91
92}
93
94void ControlsDialog::accept()
95{
96 *b=spb->value();
97 done(1);
98}
99
100//===========================================================================
101
102InfoDialog::InfoDialog(const QString &caption, const QStringList text,QWidget *parent)
103 : QDialog(parent,0,true)
104{
105 setCaption(caption);
106
107 if ( parent )
108 {
109 setPalette(parent->palette());
110 }
111
112
113
114 QString labels[]={ tr("File Name"),tr("Format"),tr("File Size"),tr("Size"),tr("Colors"),tr("Alpha") };
115
116 setMinimumSize(180,80);
117 int num=ImageViewer::LAST+1;
118 if ( text[ImageViewer::ALPHA].isEmpty() )
119 num--;
120 QGridLayout *gl= new QGridLayout(this,num,2,4,2);
121 QLabel *l;
122 int count=0;
123 for ( int i=0;i<num;i++ )
124 {
125 if ( i==1 )
126 {
127 QFrame *frm=new QFrame(this);
128 frm->setFrameStyle(QFrame::HLine|QFrame::Sunken);
129 gl->addMultiCellWidget(frm,i,i,0,1);
130 }
131 else
132 {
133 l=new QLabel( tr( labels[count] )+":",this);
134 gl->addWidget(l,i,0,AlignLeft);
135 l=new QLabel(text[count],this);
136 gl->addWidget(l,i,1,AlignRight);
137 count++;
138 }
139
140 }
141
142}
143
144void InfoDialog::displayInfo(const QString &caption, const QStringList text, QWidget *parent)
145{
146 InfoDialog *dlg=new InfoDialog(caption,text,parent);
147 dlg->exec();
148 delete dlg;
149}
150
151//===========================================================================
152
153
154ImagePane::ImagePane( QWidget *parent ) : QWidget( parent )
155{
156 vb = new QVBoxLayout( this );
157
158 image = new QScrollView(this,0,WResizeNoErase|WNorthWestGravity);
159 pic=new ImageWidget(image);
160 image->addChild(pic);
161
162 connect(pic, SIGNAL( clicked() ), this, SLOT( imageClicked() ));
163
164 vb->addWidget( image );
165
166}
167
168void ImagePane::setPixmap( const QPixmap &pm )
169{
170 pic->setPixmap( pm );
171 pic->resize(pm.width(),pm.height());
172 image->updateScrollBars ();
173 pic->repaint(false);
174}
175
176void ImagePane::imageClicked()
177{
178 emit clicked();
179}
180//===========================================================================
181/*
182 Draws the portion of the scaled pixmap that needs to be updated
183*/
184
185void ImageWidget::paintEvent( QPaintEvent *e )
186{
187 QPainter painter(this);
188
189 painter.setClipRect(e->rect());
190 painter.fillRect(0,0,width(),height(),QColor(0,0,0));
191
192 if ( pixmap.size() != QSize( 0, 0 ) )
193 { // is an image loaded?
194 painter.drawPixmap((width() - pixmap.width()) / 2, (height() - pixmap.height()) / 2, pixmap);
195 }
196}
197
198void ImageWidget::mouseReleaseEvent(QMouseEvent *)
199{
200 emit clicked();
201}
202
203//===========================================================================
204
205ImageViewer::ImageViewer( QWidget *parent, const char *name, int /*wFlags*/ )
206: QMainWindow( parent, name, WResizeNoErase ), filename( 0 ), bFromDocView( FALSE )
207{
208 setCaption( tr("Image Viewer") );
209 setIcon( Resource::loadPixmap( "ImageViewer" ) );
210
211
212 Config cfg("Image Viewer");
213 cfg.setGroup("Image Viewer");
214
215 showThumbView=cfg.readBoolEntry("ShowThumbnails",false);
216 isSized=cfg.readBoolEntry("SizeToScreen",true);
217
218 isFullScreen = FALSE;
219
220 setToolBarsMovable( FALSE );
221
222 toolBar = new QToolBar( this );
223 toolBar->setHorizontalStretchable( TRUE );
224
225 menuBar = new QMenuBar( toolBar );
226
227 current=menuBar;
228
229
230
231 fileMenuFile = new QPopupMenu(this);
232 //menuBarmenubarFile->insertItem( tr("File"), fileMenu );
233 fileMenuFile->insertItem(tr("Open"),
234 this, SLOT(openFile()), 0);
235
236 viewMenuFile = new QPopupMenu( this );
237 //menubarFile->insertItem( tr("View"), viewMenu );
238 viewMenuFile->insertItem( tr("Thumbnail View"),
239 this, SLOT(switchThumbView()), 0, SHOW_THUMBNAILS );
240
241 viewMenuFile->setItemChecked ( SHOW_THUMBNAILS, showThumbView );
242
243
244
245
246 optionsMenuFile = new QPopupMenu( this);
247 //menubarFile->insertItem( tr("Options"),optionsMenu );
248 slideAction = new QAction( tr( "Slide show" ), Resource::loadIconSet( "slideshow" ),
249 QString::null, 0, this, 0 );
250 slideAction->setToggleAction( TRUE );
251 connect( slideAction, SIGNAL( toggled(bool) ), this, SLOT( slideShow(bool) ) );
252 slideAction->addTo( optionsMenuFile);
253// slideAction->addTo( toolBar );
254
255
256// optionsMenuFile->insertItem( tr("Slideshow") );
257 optionsMenuFile->insertSeparator();
258 optionsMenuFile->insertItem( tr("Preferences.."), this, SLOT(settings()), 0);
259// optionsMenuFile->insertItem( tr("Help"), this, SLOT(help()), 0);
260
261 QStrList fmt = QImage::outputFormats();
262
263
264 fileMenuView = new QPopupMenu( this );
265 //menubarView->insertItem( tr("File"),fileMenu );
266 fileMenuView->insertItem( tr("Image Info ..."),this, SLOT(displayInfoDialog()),0 );
267 fileMenuView->insertSeparator();
268
269 viewMenuView = new QPopupMenu(this );
270 viewMenuView->setCheckable ( true );
271
272 //menubarView->insertItem( tr("View"),viewMenu );
273 viewMenuView->insertItem(tr("Horizontal flip"), this, SLOT(hFlip()), 0);
274 viewMenuView->insertItem(tr("Vertical flip"), this, SLOT(vFlip()), 0);
275
276 stack = new QWidgetStack( this );
277 stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
278 setCentralWidget( stack );
279
280
281 imagePanel = new ImagePane( stack );
282 connect(imagePanel, SIGNAL(clicked()), this, SLOT(normalView()));
283
284
285 ImageFileSelector::CURRENT_VIEW cv;
286 if(showThumbView)
287 cv=ImageFileSelector::THUMBNAIL;
288 else
289 cv=ImageFileSelector::DETAILED;
290
291 odebug << "cv = " << cv << "" << oendl;
292
293 fileSelector = new ImageFileSelector( cv,stack, "fs");
294
295 //switchThumbView();
296
297
298 //fileSelector = new ImageFileSelector("image/*", stack, "fs");
299 //fileSelector->setNewVisible(FALSE);
300 //fileSelector->setCloseVisible(FALSE);
301 connect( fileSelector, SIGNAL( closeMe() ), this, SLOT( closeFileSelector() ) );
302 connect( fileSelector, SIGNAL( fileSelected(const DocLnk&) ),
303 this, SLOT( openFile(const DocLnk&) ) );
304
305 imageList = fileSelector->fileList();
306 slideAction->setEnabled( imageList.count() != 0);
307
308 iconToolBar = new QToolBar(this);
309
310 QAction *a;
311
312 a = new QAction( tr( "Open ..." ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 );
313 connect( a, SIGNAL( activated() ), this, SLOT( open() ) );
314 a->addTo( fileMenuView);
315 a->addTo( iconToolBar );
316
317
318 a = new QAction( tr( "Rotate 90"), Resource::loadPixmap( "rotate90" ), QString::null, 0, this, 0);
319 connect( a, SIGNAL( activated() ), this, SLOT( rot90() ) );
320 a->addTo( iconToolBar );
321 a->addTo( viewMenuView );
322
323 a = new QAction( tr( "Rotate 180" ), Resource::loadPixmap( "repeat" ), QString::null, 0, this, 0 );
324 connect( a, SIGNAL( activated() ), this, SLOT( rot180() ) );
325 a->addTo( iconToolBar );
326 a->addTo( viewMenuView );
327
328
329 a = new QAction( tr( "Rotate 270"), Resource::loadPixmap( "rotate270" ), QString::null, 0, this, 0);
330 connect( a, SIGNAL( activated() ), this, SLOT( rot270() ) );
331 //a->addTo( iconToolBar );
332 a->addTo( viewMenuView );
333
334
335
336 viewMenuView->insertSeparator();
337 viewMenuView->insertItem(tr("Brightness ..."), this, SLOT(displayControlsDialog()), 0);
338 viewMenuView->insertItem(tr("Black And White"), this, SLOT(blackAndWhite()), 0,BLACKANDWHITE);
339 viewMenuView->insertSeparator();
340
341
342 sss = new QAction( tr( "Scale to Screen"), Resource::loadPixmap( "scale" ), QString::null, 0, this, 0,true);
343 connect( sss, SIGNAL( activated() ), this, SLOT( switchSizeToScreen() ) );
344 sss->addTo( iconToolBar );
345 sss->addTo( viewMenuView );
346
347 sss->setOn(isSized);
348 viewMenuView->insertSeparator();
349
350
351 a = new QAction( tr( "Fullscreen" ), Resource::loadPixmap( "fullscreen" ),
352 QString::null, 0, this, 0 );
353 connect( a, SIGNAL( activated() ), this, SLOT( fullScreen() ) );
354 a->addTo( iconToolBar );
355 a->addTo( viewMenuView);
356
357 a = new QAction( tr( "Stop Slideshow" ), Resource::loadPixmap( "quit_icon" ),
358 QString::null, 0, this, 0 );
359 connect( a, SIGNAL( activated() ), this, SLOT( stopSlideShow() ) );
360 a->addTo( iconToolBar );
361 a->addTo( viewMenuView);
362
363
364 Config config( "ImageViewer" );
365 config.setGroup( "SlideShow" );
366 slideDelay = config.readNumEntry( "Delay", 2);
367 slideRepeat = config.readBoolEntry( "Repeat", FALSE );
368 slideReverse = config.readBoolEntry("Reverse", FALSE);
369
370 config.setGroup("Default");
371 rotateOnLoad = config.readBoolEntry("Rotate", FALSE);
372 fastLoad = config.readBoolEntry("FastLoad", TRUE);
373 slideTimer = new QTimer( this );
374 connect( slideTimer, SIGNAL(timeout()), this, SLOT(slideUpdate()) );
375
376 switchToFileSelector();
377
378 setMouseTracking( TRUE );
379
380
381}
382
383ImageViewer::~ImageViewer()
384{
385 Config cfg("Image Viewer");
386 cfg.setGroup("Image Viewer");
387
388 cfg.writeEntry("ShowThumbnails",(int)showThumbView);
389 cfg.writeEntry("SizeToScreen",(int)isSized);
390
391 cfg.setGroup( "SlideShow" );
392 cfg.writeEntry( "Delay", slideDelay);
393 cfg.writeEntry( "Repeat", slideRepeat );
394 cfg.writeEntry("Reverse", slideReverse);
395
396 cfg.setGroup("Default");
397 cfg.writeEntry("Rotate", rotateOnLoad);
398 cfg.writeEntry("FastLoad", fastLoad);
399
400 delete imagePanel; // in case it is fullscreen
401}
402
403void ImageViewer::help() {
404
405}
406
407
408void ImageViewer::settings()
409{
410 SettingsDialog dlg( this, 0, TRUE );
411 dlg.setDelay( slideDelay );
412 dlg.setRepeat( slideRepeat );
413 dlg.setReverse( slideReverse );
414 dlg.setRotate(rotateOnLoad);
415 dlg.setFastLoad(fastLoad);
416
417 if ( QPEApplication::execDialog(&dlg) == QDialog::Accepted ) {
418 odebug << "<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>" << oendl;
419 slideDelay = dlg.delay();
420 slideRepeat = dlg.repeat();
421 slideReverse = dlg.reverse();
422 rotateOnLoad = dlg.rotate();
423 fastLoad = dlg.fastLoad();
424
425 Config config( "ImageViewer" );
426 config.setGroup( "SlideShow" );
427 config.writeEntry( "Delay", slideDelay );
428 config.writeEntry( "Repeat", slideRepeat );
429 config.writeEntry("Reverse", slideReverse);
430
431 config.setGroup("Default");
432 config.writeEntry("Rotate", rotateOnLoad);
433 config.writeEntry("FastLoad", fastLoad);
434 }
435}
436
437void ImageViewer::switchSizeToScreen()
438{
439 isSized=!isSized;
440 sss->setOn(isSized);
441 updateImage();
442}
443
444void ImageViewer::updateImage()
445{
446 if ( isSized ) {
447 imagePanel->setPixmap(pmScaled);
448 } else {
449 imagePanel->setPixmap(pm);
450 }
451}
452
453void ImageViewer::switchThumbView()
454{
455
456 showThumbView=!showThumbView;
457 viewMenuFile->setItemChecked ( SHOW_THUMBNAILS, showThumbView );
458 fileSelector->switchView();
459
460}
461
462void ImageViewer::switchToFileSelector()
463{
464 stack->raiseWidget(fileSelector);
465 menuBar->clear();
466 menuBar->insertItem( tr("File"), fileMenuFile );
467 menuBar->insertItem( tr("View"), viewMenuFile );
468 menuBar->insertItem( tr("Options"), optionsMenuFile );
469 iconToolBar->hide();
470 imagePanel->disable();
471 slideShow(false);
472
473}
474
475void ImageViewer::switchToImageView()
476{
477 stack->raiseWidget(imagePanel);
478
479 menuBar->clear();
480 menuBar->insertItem( tr("File"), fileMenuView );
481 menuBar->insertItem( tr("View"), viewMenuView );
482 viewMenuView->setItemEnabled(BLACKANDWHITE,true);
483 iconToolBar->show();
484
485 imagePanel->setPosition(0,0);
486
487}
488
489
490void ImageViewer::setDocument(const QString& fileref)
491{
492 delayLoad = fileref;
493 switchToImageView();
494 QTimer::singleShot( 0, this, SLOT(doDelayedLoad()) );
495}
496
497void ImageViewer::doDelayedLoad()
498{
499 show(delayLoad);
500}
501
502void ImageViewer::show()
503{
504 normalView();
505 QMainWindow::show();
506}
507
508void ImageViewer::show(const QString& fileref)
509{
510// odebug << "Show "+fileref << oendl;
511 bFromDocView = TRUE;
512 closeFileSelector();
513 DocLnk link(fileref);
514 if ( link.isValid() ) {
515 openFile(link);
516 } else {
517 filename = fileref;
518 updateCaption( fileref );
519 loadImage( fileref );
520 }
521}
522
523void ImageViewer::openFile() {
524 MimeTypes types;
525 QStringList image;
526 image << "image/*";
527 types.insert("Images", image);
528
529 QString str = OFileDialog::getOpenFileName( 1,QPEApplication::documentDir(),"", types, 0 );
530 DocLnk link(str);
531// if ( link.isValid() )
532 openFile(link);
533
534}
535
536void ImageViewer::openFile( const DocLnk &link )
537{
538 closeFileSelector();
539// DocLnk link(file);
540 odebug << "open "+link.name() << oendl;
541 updateCaption( link.name() );
542 loadImage( link.file() );
543 if (slideTimer->isActive()) {
544 slideTimer->start(slideDelay * 1000, FALSE);
545 }
546
547}
548
549void ImageViewer::open()
550{
551 switchToFileSelector();
552}
553
554void ImageViewer::closeFileSelector()
555{
556 switchToImageView();
557}
558
559void ImageViewer::updateCaption( QString name )
560{
561 int sep = name.findRev( '/' );
562 if ( sep >= 0 )
563 name = name.mid( sep+1 );
564 setCaption( name + tr(" - Image Viewer") );
565}
566
567/*
568 This function loads an image from a file.
569*/
570
571void ImageViewer::loadImage( const char *fileName )
572{
573 filename = fileName;
574 if ( filename ) {
575 QApplication::setOverrideCursor( waitCursor ); // this might take time
576 //imagePanel->statusLabel()->setText( tr("Loading image...") );
577 qApp->processEvents();
578 bool ok = image.load(filename, 0);
579 if ( ok ) {
580 ok = reconvertImage();
581 updateImageInfo(filename);
582 }
583 if ( !ok ) {
584 pm.resize(0,0); // couldn't load image
585 update();
586 }
587 QApplication::restoreOverrideCursor(); // restore original cursor
588 }
589
590// fastLoad ? ", Fast" : "",
591// fastLoad ? QMAX(imagewidth/maxsize, imageheight/maxsize) : 1);
592
593
594// matrix.reset();
595 rotated90 = FALSE;
596
597 if (rotateOnLoad) {
598 rotated90 = TRUE;
599 rot90();
600// matrix.rotate( -90.0 );
601 }
602
603 switchToImageView();
604 updateImage();
605
606}
607
608bool ImageViewer::loadSelected()
609{
610 bool ok = false;
611 if ( stack->visibleWidget() == fileSelector )
612 {
613 const DocLnk *link = fileSelector->selected();
614 if ( link )
615 {
616 if ( link->file() != filename )
617 {
618 updateCaption( link->name() );
619 filename = link->file();
620 qApp->processEvents();
621 ok = image.load(filename, 0);
622 if ( ok )
623 {
624 updateImageInfo(filename);
625 ok = reconvertImage();
626 }
627 if ( !ok )
628 pm.resize(0,0);
629 }
630 }
631 }
632 if ( !image.isNull() )
633 {
634 ok = true;
635 closeFileSelector();
636 }
637
638 return ok;
639}
640
641bool ImageViewer::reconvertImage()
642{
643 bool success = FALSE;
644
645 if ( image.isNull() ) return FALSE;
646
647 QApplication::setOverrideCursor( waitCursor ); // this might take time
648 if ( pm.convertFromImage(image /*, conversion_flags */ ) )
649 {
650 pmScaled = QPixmap();
651 scale();
652 success = TRUE; // load successful
653 }
654 else
655 {
656 pm.resize(0,0); // couldn't load image
657 }
658 QApplication::restoreOverrideCursor(); // restore original cursor
659
660 return success; // TRUE if loaded OK
661}
662
663
664int ImageViewer::calcHeight()
665{
666 if ( !isFullScreen )
667 return imagePanel->paneHeight();
668 else
669 return qApp->desktop()->height();
670}
671/*
672 This functions scales the pixmap in the member variable "pm" to fit the
673 widget size and puts the resulting pixmap in the member variable "pmScaled".
674*/
675void ImageViewer::scale()
676{
677 int h = calcHeight();
678 if ( image.isNull() ) return;
679
680 QApplication::setOverrideCursor( waitCursor ); // this might take time
681 if ( imagePanel->paneWidth() == pm.width() && h == pm.height() )
682 { // no need to scale if widget
683 pmScaled = pm; // size equals pixmap size
684 }
685 else
686 {
687 double hs = (double)h / (double)image.height();
688 double ws = (double)imagePanel->paneWidth() / (double)image.width();
689 double scaleFactor = (hs > ws) ? ws : hs;
690 int smoothW = (int)(scaleFactor * image.width());
691 int smoothH = (int)(scaleFactor * image.height());
692
693 pmScaled.convertFromImage( image.smoothScale( smoothW, smoothH ) /*, conversion_flags */ );
694 }
695 QApplication::restoreOverrideCursor(); // restore original cursor
696}
697
698/*
699 The resize event handler, if a valid pixmap was loaded it will call
700 scale() to fit the pixmap to the new widget size.
701*/
702
703void ImageViewer::resizeEvent( QResizeEvent * )
704{
705
706 if ( pm.size() == QSize( 0, 0 ) ) // we couldn't load the image
707 return;
708
709 int h = calcHeight();
710
711 if ( imagePanel->paneWidth() != pmScaled.width() || h != pmScaled.height() )
712 { // if new size,
713 scale(); // scale pmScaled to window
714 }
715 if ( image.hasAlphaBuffer() )
716 erase();
717}
718
719
720void ImageViewer::hFlip()
721{
722// matrix.scale( -1.0, 1.0 );
723
724 setImage(image.mirror(TRUE,FALSE));
725}
726
727void ImageViewer::vFlip()
728{
729// matrix.scale( 1.0, -1.0 );
730 setImage(image.mirror(FALSE,TRUE));
731}
732
733void ImageViewer::rot180()
734{
735// matrix.rotate( 180.0 );
736 setImage(image.mirror(TRUE,TRUE));
737}
738
739void ImageViewer::rot90()
740{
741 QImage oldimage;
742 oldimage = image.convertDepth(32);
743// matrix.rotate( -90.0 );
744 setImage(rotate(oldimage,Rotate90));
745
746}
747void ImageViewer::rot270()
748{
749
750 QImage oldimage;
751 oldimage = image.convertDepth(32);
752// matrix.rotate(90.0);
753 setImage(rotate(oldimage,Rotate270));
754
755}
756
757void ImageViewer::blackAndWhite()
758{
759
760 viewMenuView->setItemEnabled(BLACKANDWHITE,false);
761 setImage(toGray(image,false));
762}
763
764void ImageViewer::displayControlsDialog()
765{
766 int w=80;
767 int h=w;
768 QImage small;
769
770 if ( image.width()<w ||image.height()<h )
771 small=image.smoothScale(w,h);
772 else
773 small=image.copy(0,0,w,h);
774
775 int newB=0;
776 ControlsDialog *dlg=new ControlsDialog("Image Viewer",small,&newB,this);
777 dlg->exec();
778 if ( newB ) {
779 intensity(image,(float)newB/100);
780 setImage(image);
781 }
782
783}
784
785
786void ImageViewer::displayInfoDialog()
787{
788
789 QStringList ls;
790
791 for ( int i=0;i<LAST;i++ )
792 ls.append(imageInfo[i]);
793
794 InfoDialog::displayInfo("Image Viewer",ls,this);
795}
796void ImageViewer::normalView()
797{
798 if ( !imagePanel->parentWidget() )
799 {
800
801 isFullScreen = FALSE;
802 stack->addWidget( imagePanel, 1 );
803 switchToImageView();
804 if ( isSized )
805 scale();
806
807 updateImage();
808
809 }
810}
811
812void ImageViewer::stopSlideShow() {
813 if (slideTimer->isActive())
814 slideTimer->stop();
815}
816
817void ImageViewer::fullScreen()
818{
819 // Full-screen option
820 // contributed by Robert Wittams <robert@wittams.com>
821 if ( imagePanel->parentWidget() && loadSelected() )
822 {
823 isFullScreen = TRUE;
824 imagePanel->reparent(0,QPoint(0,0));
825 imagePanel->resize(qApp->desktop()->width(), qApp->desktop()->height());
826
827 if ( isSized )
828 scale();
829 updateImage();
830 imagePanel->showFullScreen();
831 }
832}
833
834void ImageViewer::setImage(const QImage& newimage)
835{
836 image = newimage;
837 reconvertImage();
838 updateImage();
839}
840
841void ImageViewer::updateImageInfo(QString &filePath)
842{
843
844 for ( int i=0;i<LAST;i++ )
845 {
846 imageInfo[i]="";
847 }
848
849 imageInfo[FORMAT]=QImage::imageFormat (filePath );
850 QFileInfo fi(filePath);
851 imageInfo[PATH]=fi.fileName();
852 imageInfo[FILE_SIZE]=QString::number(fi.size())+" (bytes)";
853 QString message("%1x%2");
854 imageInfo[SIZE]=QString("%1x%2");
855 imageInfo[SIZE]=imageInfo[SIZE].arg(image.width()).arg(image.height());
856 if ( image.numColors() > 0 )
857 {
858 imageInfo[COLORS]=tr("%1 colors").arg(image.numColors());
859 }
860 else if ( image.depth() >= 16 )
861 {
862 imageInfo[COLORS]=tr(" True color");
863 }
864 if ( image.hasAlphaBuffer() )
865 {
866 if ( image.depth() == 8 )
867 {
868 int i;
869 bool alpha[256];
870 int nalpha=0;
871
872 for ( i=0; i<256; i++ )
873 alpha[i] = FALSE;
874
875 for ( i=0; i<image.numColors(); i++ )
876 {
877 int alevel = image.color(i) >> 24;
878 if ( !alpha[alevel] )
879 {
880 alpha[alevel] = TRUE;
881 nalpha++;
882 }
883 }
884 imageInfo[ALPHA]=tr("%1 alpha levels").arg(nalpha);
885 }
886 else
887 {
888 imageInfo[ALPHA]=tr("8-bit alpha channel");
889 }
890 }
891
892}
893
894void ImageViewer::closeEvent( QCloseEvent *e )
895{
896 if ( stack->visibleWidget() == imagePanel && !bFromDocView )
897 {
898 e->ignore();
899 open();
900 }
901 else
902 {
903 bFromDocView = FALSE;
904 e->accept();
905 }
906}
907
908// Intensity,toGray and rotate code courtesy of KDE project.
909
910
911QImage& ImageViewer::intensity(QImage &image, float percent)
912{
913
914 int segColors = image.depth() > 8 ? 256 : image.numColors();
915 unsigned char *segTbl = new unsigned char[segColors];
916 int pixels = image.depth() > 8 ? image.width()*image.height() :
917 image.numColors();
918 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
919 (unsigned int *)image.colorTable();
920
921 bool brighten = (percent >= 0);
922 if ( percent < 0 )
923 percent = -percent;
924
925 if ( brighten )
926 { // keep overflow check out of loops
927 for ( int i=0; i < segColors; ++i )
928 {
929 int tmp = (int)(i*percent);
930 if ( tmp > 255 )
931 tmp = 255;
932 segTbl[i] = tmp;
933 }
934 }
935 else
936 {
937 for ( int i=0; i < segColors; ++i )
938 {
939 int tmp = (int)(i*percent);
940 if ( tmp < 0 )
941 tmp = 0;
942 segTbl[i] = tmp;
943 }
944 }
945
946 if ( brighten )
947 { // same here
948 for ( int i=0; i < pixels; ++i )
949 {
950 int r = qRed(data[i]);
951 int g = qGreen(data[i]);
952 int b = qBlue(data[i]);
953 int a = qAlpha(data[i]);
954 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
955 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
956 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
957 data[i] = qRgba(r, g, b,a);
958 }
959 }
960 else
961 {
962 for ( int i=0; i < pixels; ++i )
963 {
964 int r = qRed(data[i]);
965 int g = qGreen(data[i]);
966 int b = qBlue(data[i]);
967 int a = qAlpha(data[i]);
968 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
969 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
970 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
971 data[i] = qRgba(r, g, b, a);
972 }
973 }
974 delete [] segTbl;
975
976 return image;
977}
978
979QImage& ImageViewer::toGray(QImage &img, bool fast)
980{
981 if ( img.width() == 0 || img.height() == 0 )
982 return img;
983
984 if ( fast )
985 {
986 if ( img.depth() == 32 )
987 {
988 register uchar * r(img.bits());
989 register uchar * g(img.bits() + 1);
990 register uchar * b(img.bits() + 2);
991
992 uchar * end(img.bits() + img.numBytes());
993
994 while ( r != end )
995 {
996
997 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
998
999 r += 4;
1000 g += 4;
1001 b += 4;
1002 }
1003 }
1004 else
1005 {
1006 for ( int i = 0; i < img.numColors(); i++ )
1007 {
1008 register uint r = qRed(img.color(i));
1009 register uint g = qGreen(img.color(i));
1010 register uint b = qBlue(img.color(i));
1011
1012 register uint gray = (((r + g) >> 1) + b) >> 1;
1013 img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
1014 }
1015 }
1016 }
1017 else
1018 {
1019 int pixels = img.depth() > 8 ? img.width()*img.height() :
1020 img.numColors();
1021 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
1022 (unsigned int *)img.colorTable();
1023 int val, i;
1024 for ( i=0; i < pixels; ++i )
1025 {
1026 val = qGray(data[i]);
1027 data[i] = qRgba(val, val, val, qAlpha(data[i]));
1028 }
1029 }
1030 return img;
1031}
1032
1033
1034QImage ImageViewer::rotate(QImage &img, RotateDirection r)
1035{
1036 QImage dest;
1037 int x, y;
1038 if ( img.depth() > 8 )
1039 {
1040 unsigned int *srcData, *destData;
1041 switch ( r )
1042 {
1043 case Rotate90:
1044 dest.create(img.height(), img.width(), img.depth());
1045 for ( y=0; y < img.height(); ++y )
1046 {
1047 srcData = (unsigned int *)img.scanLine(y);
1048 for ( x=0; x < img.width(); ++x )
1049 {
1050 destData = (unsigned int *)dest.scanLine(x);
1051 destData[img.height()-y-1] = srcData[x];
1052 }
1053 }
1054 break;
1055 case Rotate180:
1056 dest.create(img.width(), img.height(), img.depth());
1057 for ( y=0; y < img.height(); ++y )
1058 {
1059 srcData = (unsigned int *)img.scanLine(y);
1060 destData = (unsigned int *)dest.scanLine(img.height()-y-1);
1061 for ( x=0; x < img.width(); ++x )
1062 destData[img.width()-x-1] = srcData[x];
1063 }
1064 break;
1065 case Rotate270:
1066 dest.create(img.height(), img.width(), img.depth());
1067 for ( y=0; y < img.height(); ++y )
1068 {
1069 srcData = (unsigned int *)img.scanLine(y);
1070 for ( x=0; x < img.width(); ++x )
1071 {
1072 destData = (unsigned int *)dest.scanLine(img.width()-x-1);
1073 destData[y] = srcData[x];
1074 }
1075 }
1076 break;
1077 default:
1078 dest = img;
1079 break;
1080 }
1081 }
1082 else
1083 {
1084 unsigned char *srcData, *destData;
1085 unsigned int *srcTable, *destTable;
1086 switch ( r )
1087 {
1088 case Rotate90:
1089 dest.create(img.height(), img.width(), img.depth());
1090 dest.setNumColors(img.numColors());
1091 srcTable = (unsigned int *)img.colorTable();
1092 destTable = (unsigned int *)dest.colorTable();
1093 for ( x=0; x < img.numColors(); ++x )
1094 destTable[x] = srcTable[x];
1095 for ( y=0; y < img.height(); ++y )
1096 {
1097 srcData = (unsigned char *)img.scanLine(y);
1098 for ( x=0; x < img.width(); ++x )
1099 {
1100 destData = (unsigned char *)dest.scanLine(x);
1101 destData[img.height()-y-1] = srcData[x];
1102 }
1103 }
1104 break;
1105 case Rotate180:
1106 dest.create(img.width(), img.height(), img.depth());
1107 dest.setNumColors(img.numColors());
1108 srcTable = (unsigned int *)img.colorTable();
1109 destTable = (unsigned int *)dest.colorTable();
1110 for ( x=0; x < img.numColors(); ++x )
1111 destTable[x] = srcTable[x];
1112 for ( y=0; y < img.height(); ++y )
1113 {
1114 srcData = (unsigned char *)img.scanLine(y);
1115 destData = (unsigned char *)dest.scanLine(img.height()-y-1);
1116 for ( x=0; x < img.width(); ++x )
1117 destData[img.width()-x-1] = srcData[x];
1118 }
1119 break;
1120 case Rotate270:
1121 dest.create(img.height(), img.width(), img.depth());
1122 dest.setNumColors(img.numColors());
1123 srcTable = (unsigned int *)img.colorTable();
1124 destTable = (unsigned int *)dest.colorTable();
1125 for ( x=0; x < img.numColors(); ++x )
1126 destTable[x] = srcTable[x];
1127 for ( y=0; y < img.height(); ++y )
1128 {
1129 srcData = (unsigned char *)img.scanLine(y);
1130 for ( x=0; x < img.width(); ++x )
1131 {
1132 destData = (unsigned char *)dest.scanLine(img.width()-x-1);
1133 destData[y] = srcData[x];
1134 }
1135 }
1136 break;
1137 default:
1138 dest = img;
1139 break;
1140 }
1141
1142 }
1143 return (dest);
1144}
1145
1146void ImageViewer::slideShow( bool on )
1147{
1148 if (on) {
1149 if (!imageList.isEmpty()) {
1150 slideTimer->start(slideDelay * 1000, FALSE);
1151 filename = ""; // force restart
1152 slideReverse ? prevImage() : nextImage();
1153 }
1154 } else {
1155 slideTimer->stop();
1156 slideAction->setOn( false);
1157 }
1158}
1159
1160void ImageViewer::slideUpdate()
1161{
1162 bool final_image = slideReverse ? prevImage() : nextImage();
1163
1164 if (final_image && !slideRepeat) {
1165 slideTimer->stop();
1166 slideAction->setOn(FALSE);
1167 }
1168}
1169
1170//
1171// Display the image after the current one in the image list.
1172// Return TRUE if the next call to nextImage() will wrap around to the
1173// first image in the list (ie. we're now viewing the last image in the list).
1174//
1175bool ImageViewer::nextImage(void)
1176{
1177 int idx = 0;
1178
1179 if (imageList.count() > 0) {
1180 idx = imageIndex();
1181 if (idx != -1) {
1182 if (idx == int(imageList.count() - 1)) {
1183 idx = 0;
1184 } else {
1185 idx++;
1186 }
1187 } else {
1188 idx = 0;
1189 }
1190 openFile(imageList[idx]);
1191 }
1192
1193 return idx == int(imageList.count() - 1) ? TRUE : FALSE;
1194}
1195
1196//
1197// Display the image preceeding the current one in the image list.
1198// Return TRUE if the next call to prevImage() will wrap around to the last
1199// image in the list (ie. we're now viewing the first image in the list).
1200//
1201bool ImageViewer::prevImage(void)
1202{
1203 int idx = -1;
1204
1205 if (imageList.count() > 0) {
1206 idx = imageIndex();
1207 if (idx != -1) {
1208 if (idx == 0) {
1209 idx = imageList.count() - 1;
1210 } else {
1211 idx--;
1212 }
1213 } else {
1214 idx = imageList.count() - 1;
1215 }
1216 openFile(imageList[idx]);
1217 }
1218
1219 return idx == 0 ? TRUE : FALSE;
1220}
1221
1222//
1223// Return the index into the imageList of the currently viewed
1224// image (ie. ImageViewer::filename in ImageViewer::imageList).
1225//
1226int ImageViewer::imageIndex(void)
1227{
1228 QValueListConstIterator<DocLnk> i;
1229 int index;
1230
1231 if (imageList.count() == 0) {
1232 return -1;
1233 }
1234
1235 for (index = 0, i = imageList.begin(); i != imageList.end(); ++i, index++) {
1236 if ((*i).file() == filename) {
1237 return index;
1238 }
1239 }
1240
1241 return -1;
1242}