summaryrefslogtreecommitdiff
authorwarmi <warmi>2002-08-15 03:19:32 (UTC)
committer warmi <warmi>2002-08-15 03:19:32 (UTC)
commitacdedf093413a37a3e2c1ab5b12c1ab0a95b670b (patch) (unidiff)
treee5ffc814ae6b7e0787b24347e3e98c16fa3ca68c
parent92640e4094075342138796065040441210348c76 (diff)
downloadopie-acdedf093413a37a3e2c1ab5b12c1ab0a95b670b.zip
opie-acdedf093413a37a3e2c1ab5b12c1ab0a95b670b.tar.gz
opie-acdedf093413a37a3e2c1ab5b12c1ab0a95b670b.tar.bz2
Bunch of new GUI features ( brightness control, ability to view unscaled images ..)
Qte image handling issues are still not fixed though.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/showimg/showimg.cpp1019
1 files changed, 753 insertions, 266 deletions
diff --git a/noncore/multimedia/showimg/showimg.cpp b/noncore/multimedia/showimg/showimg.cpp
index 24218e6..d7d53ec 100644
--- a/noncore/multimedia/showimg/showimg.cpp
+++ b/noncore/multimedia/showimg/showimg.cpp
@@ -14,544 +14,1031 @@
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21// 21//
22// Full-screen and rotation options contributed by Robert Wittams <robert@wittams.com> 22// Full-screen and rotation options contributed by Robert Wittams <robert@wittams.com>
23// 23//
24 24
25#include "showimg.h" 25#include "showimg.h"
26 26#include "ImageFileSelector.h"
27
28#include <qpe/config.h>
27#include <qpe/resource.h> 29#include <qpe/resource.h>
28#include <qpe/fileselector.h> 30#include <qpe/fileselector.h>
29#include <qpe/applnk.h> 31#include <qpe/applnk.h>
30 32#include <qfileinfo.h>
33#include <math.h>
31#include <qpe/qpemenubar.h> 34#include <qpe/qpemenubar.h>
32#include <qwidgetstack.h> 35#include <qwidgetstack.h>
33#include <qpe/qpetoolbar.h> 36#include <qpe/qpetoolbar.h>
34#include <qaction.h> 37#include <qaction.h>
35#include <qfiledialog.h> 38#include <qfiledialog.h>
36#include <qmessagebox.h> 39#include <qmessagebox.h>
37#include <qpopupmenu.h> 40#include <qpopupmenu.h>
41#include <qscrollview.h>
38#include <qlabel.h> 42#include <qlabel.h>
39#include <qpainter.h> 43#include <qpainter.h>
40#include <qkeycode.h> 44#include <qkeycode.h>
41#include <qapplication.h> 45#include <qapplication.h>
42#include <qclipboard.h> 46#include <qclipboard.h>
43#include <qtimer.h> 47#include <qtimer.h>
48#include <qspinbox.h>
44 49
45 50
46ImagePane::ImagePane( QWidget *parent ) : QWidget( parent ) 51
52ControlsDialog::ControlsDialog(const QString &caption,QImage image,int *brightness,QWidget *parent):QDialog(parent,0,true)
47{ 53{
48 vb = new QVBoxLayout( this ); 54 setCaption(caption);
49 55
50 image = new ImageWidget( this ); 56 if ( parent )
51 connect(image, SIGNAL( clicked() ), this, SLOT( imageClicked() )); 57 {
58 setPalette(parent->palette());
59 }
52 60
53 vb->addWidget( image ); 61 b=brightness;
62 img=image;
63
64 setMinimumSize(140,80);
65
66 QGridLayout *gl= new QGridLayout(this,2,2,4,4);
67
68 pixmap =new ImageWidget(this);;
69 QPixmap pm;
70 pm.convertFromImage(img);
71 pixmap->setPixmap(pm);
72 pixmap->setMinimumSize(pm.width(),pm.height());
73 gl->addMultiCellWidget(pixmap,0,0,0,2,AlignCenter);
74 QLabel *l=new QLabel(tr("Brightness")+":",this);
75 gl->addWidget(l,1,0,AlignLeft);
76 spb=new QSpinBox(-100,100,2,this);
77 gl->addWidget(spb,1,1,AlignRight);
78
79 spb->setValue(0);
80
81 connect(spb,SIGNAL(valueChanged(int)),this, SLOT(bValueChanged(int)));
54 82
55 status = new QLabel( this );
56 status->setFixedHeight( fontMetrics().height() + 4 );
57 vb->addWidget( status );
58} 83}
59 84
60void ImagePane::setPixmap( const QPixmap &pm ) 85void ControlsDialog::bValueChanged(int value)
61{ 86{
62 image->setPixmap( pm ); 87 QImage nImage=img;
63 image->repaint( false ); 88 nImage.detach();
89 ImageViewer::intensity(nImage, (float)value/100);
90 QPixmap pm;
91 pm.convertFromImage(nImage);
92 pixmap->setPixmap(pm);
93 pixmap->repaint(false);
94
95
64} 96}
65 97
66void ImagePane::imageClicked() 98void ControlsDialog::accept()
67{ 99{
68 emit clicked(); 100 *b=spb->value();
101 done(1);
69} 102}
70 103
71void ImagePane::showStatus() 104
105
106InfoDialog::InfoDialog(const QString &caption, const QStringList text,QWidget *parent):QDialog(parent,0,true)
72{ 107{
73 delete vb; 108 setCaption(caption);
74 vb = new QVBoxLayout( this ); 109
75 vb->addWidget( image ); 110 if ( parent )
76 status->show(); 111 {
77 vb->addWidget( status ); 112 setPalette(parent->palette());
113 }
114
115 const char *labels[]={"File Name","Format","File Size","Size","Colors","Alpha"};
116
117 setMinimumSize(180,80);
118 int num=ImageViewer::LAST+1;
119 if ( text[ImageViewer::ALPHA].isEmpty() )
120 num--;
121 QGridLayout *gl= new QGridLayout(this,num,2,4,2);
122 QLabel *l;
123 int count=0;
124 for ( int i=0;i<num;i++ )
125 {
126 if ( i==1 )
127 {
128 QFrame *frm=new QFrame(this);
129 frm->setFrameStyle(QFrame::HLine|QFrame::Sunken);
130 gl->addMultiCellWidget(frm,i,i,0,1);
131 }
132 else
133 {
134 l=new QLabel(tr(labels[count])+":",this);
135 gl->addWidget(l,i,0,AlignLeft);
136 l=new QLabel(text[count],this);
137 gl->addWidget(l,i,1,AlignRight);
138 count++;
139 }
140
141 }
142
78} 143}
79 144
145void InfoDialog::displayInfo(const QString &caption, const QStringList text, QWidget *parent)
146{
147 InfoDialog *dlg=new InfoDialog(caption,text,parent);
148 dlg->exec();
149 delete dlg;
150}
151
80 152
81void ImagePane::hideStatus() 153ImagePane::ImagePane( QWidget *parent ) : QWidget( parent )
82{ 154{
83 delete vb;
84 vb = new QVBoxLayout( this ); 155 vb = new QVBoxLayout( this );
156
157 image = new QScrollView(this,0,WResizeNoErase|WNorthWestGravity);
158 pic=new ImageWidget(image);
159 image->addChild(pic);
160
161 connect(pic, SIGNAL( clicked() ), this, SLOT( imageClicked() ));
162
85 vb->addWidget( image ); 163 vb->addWidget( image );
86 status->hide(); 164
87} 165}
88 166
167void ImagePane::setPixmap( const QPixmap &pm )
168{
169 pic->setPixmap( pm );
170 pic->resize(pm.width(),pm.height());
171 image->updateScrollBars ();
172 pic->repaint(false);
173}
174
175void ImagePane::imageClicked()
176{
177 emit clicked();
178}
89//=========================================================================== 179//===========================================================================
90/* 180/*
91 Draws the portion of the scaled pixmap that needs to be updated 181 Draws the portion of the scaled pixmap that needs to be updated
92*/ 182*/
93 183
94void ImageWidget::paintEvent( QPaintEvent *e ) 184void ImageWidget::paintEvent( QPaintEvent *e )
95{ 185{
96 QPainter painter(this); 186 QPainter painter(this);
97 187
98 painter.setClipRect(e->rect()); 188 painter.setClipRect(e->rect());
99 painter.setBrush( black ); 189 painter.fillRect(0,0,width(),height(),QColor(0,0,0));
100 painter.drawRect( 0, 0, width(), height() );
101 190
102 if ( pixmap.size() != QSize( 0, 0 ) ) { // is an image loaded? 191 if ( pixmap.size() != QSize( 0, 0 ) )
103 painter.drawPixmap((width() - pixmap.width()) / 2, (height() - pixmap.height()) / 2, pixmap); 192 { // is an image loaded?
193 painter.drawPixmap((width() - pixmap.width()) / 2, (height() - pixmap.height()) / 2, pixmap);
104 } 194 }
105} 195}
106 196
107void ImageWidget::mouseReleaseEvent(QMouseEvent *) 197void ImageWidget::mouseReleaseEvent(QMouseEvent *)
108{ 198{
109 emit clicked(); 199 emit clicked();
110} 200}
111 201
112
113//=========================================================================== 202//===========================================================================
114 203
115ImageViewer::ImageViewer( QWidget *parent, const char *name, int wFlags ) 204ImageViewer::ImageViewer( QWidget *parent, const char *name, int wFlags )
116 : QMainWindow( parent, name, wFlags ), filename( 0 ), 205: QMainWindow( parent, name, wFlags ), filename( 0 ), bFromDocView( FALSE )
117 pickx( -1 ), picky( -1 ), clickx( -1 ), clicky( -1 ), bFromDocView( FALSE )
118{ 206{
119 setCaption( tr("Image Viewer") ); 207 setCaption( tr("Image Viewer") );
120 setIcon( Resource::loadPixmap( "ImageViewer" ) ); 208 setIcon( Resource::loadPixmap( "ImageViewer" ) );
121 209
210
211 Config cfg("Image Viewer");
212 cfg.setGroup("Image Viewer");
213
214 showThumbView=cfg.readBoolEntry("ShowThumbnails",false);
215 isSized=cfg.readBoolEntry("SizeToScreen",true);
216
122 isFullScreen = FALSE; 217 isFullScreen = FALSE;
123 218
124 setToolBarsMovable( FALSE ); 219 setToolBarsMovable( FALSE );
125 220
126 toolBar = new QPEToolBar( this ); 221 toolBar = new QPEToolBar( this );
127 toolBar->setHorizontalStretchable( TRUE ); 222 toolBar->setHorizontalStretchable( TRUE );
128 223
129 menubar = new QPEMenuBar( toolBar ); 224 menuBar = new QPEMenuBar( toolBar );
225
226 current=menuBar;
227
228
229
230 fileMenuFile = new QPopupMenu(this);
231 //menuBarmenubarFile->insertItem( tr("File"), fileMenu );
232 fileMenuFile->insertItem(tr("Open"), this, SLOT(openFile()), 0);
233
234 viewMenuFile = new QPopupMenu( this );
235 //menubarFile->insertItem( tr("View"), viewMenu );
236 viewMenuFile->insertItem( tr("Thumbnail View"), this, SLOT(switchThumbView()), 0, SHOW_THUMBNAILS );
237
238 viewMenuFile->setItemChecked ( SHOW_THUMBNAILS, showThumbView );
239
240
241
242
243 optionsMenuFile = new QPopupMenu( this);
244 //menubarFile->insertItem( tr("Options"),optionsMenu );
245 optionsMenuFile->insertItem( tr("Slideshow") );
246 optionsMenuFile->insertSeparator();
247 optionsMenuFile->insertItem( tr("Preferences.."));
248 optionsMenuFile->insertItem( tr("Help"));
249
250
251
130 252
131 QStrList fmt = QImage::outputFormats(); 253 QStrList fmt = QImage::outputFormats();
132 254
133 QPopupMenu *edit = new QPopupMenu( menubar );
134 QPopupMenu *view = new QPopupMenu( menubar );
135 255
136 menubar->insertItem(tr("Edit"), edit ); 256 fileMenuView = new QPopupMenu( this );
137 menubar->insertItem(tr("View"), view ); 257 //menubarView->insertItem( tr("File"),fileMenu );
258 fileMenuView->insertItem( tr("Image Info ..."),this, SLOT(displayInfoDialog()),0 );
259 fileMenuView->insertSeparator();
260
261 viewMenuView = new QPopupMenu(this );
262 viewMenuView->setCheckable ( true );
138 263
139 edit->insertItem(tr("Horizontal flip"), this, SLOT(hFlip()), 0); 264 //menubarView->insertItem( tr("View"),viewMenu );
140 edit->insertItem(tr("Vertical flip"), this, SLOT(vFlip()), 0); 265 viewMenuView->insertItem(tr("Horizontal flip"), this, SLOT(hFlip()), 0);
266 viewMenuView->insertItem(tr("Vertical flip"), this, SLOT(vFlip()), 0);
141 267
142 stack = new QWidgetStack( this ); 268 stack = new QWidgetStack( this );
143 stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); 269 stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
144 setCentralWidget( stack ); 270 setCentralWidget( stack );
145 271
146 imagePanel = new ImagePane( stack ); 272
273 imagePanel = new ImagePane( stack );
147 connect(imagePanel, SIGNAL(clicked()), this, SLOT(normalView())); 274 connect(imagePanel, SIGNAL(clicked()), this, SLOT(normalView()));
148 275
149 fileSelector = new FileSelector("image/*", stack, "fs"); 276
150 fileSelector->setNewVisible(FALSE); 277 ImageFileSelector::CURRENT_VIEW cv;
151 fileSelector->setCloseVisible(FALSE); 278 if(showThumbView)
279 cv=ImageFileSelector::THUMBNAIL;
280 else
281 cv=ImageFileSelector::DETAILED;
282
283 qDebug("cv = %d",cv);
284
285 fileSelector = new ImageFileSelector( cv,stack, "fs");
286
287 //switchThumbView();
288
289
290 //fileSelector = new ImageFileSelector("image/*", stack, "fs");
291 //fileSelector->setNewVisible(FALSE);
292 //fileSelector->setCloseVisible(FALSE);
152 connect( fileSelector, SIGNAL( closeMe() ), this, SLOT( closeFileSelector() ) ); 293 connect( fileSelector, SIGNAL( closeMe() ), this, SLOT( closeFileSelector() ) );
153 connect( fileSelector, SIGNAL( fileSelected( const DocLnk &) ), this, SLOT( openFile( const DocLnk & ) ) ); 294 connect( fileSelector, SIGNAL( fileSelected( const DocLnk &) ), this, SLOT( openFile( const DocLnk & ) ) );
154 295
155 toolBar = new QPEToolBar( this ); 296 iconToolBar = new QPEToolBar(this);
156 297
157 QAction *a; 298 QAction *a;
158 299
159 a = new QAction( tr( "Open" ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 ); 300 a = new QAction( tr( "Open ..." ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 );
160 connect( a, SIGNAL( activated() ), this, SLOT( open() ) ); 301 connect( a, SIGNAL( activated() ), this, SLOT( open() ) );
161 a->addTo( toolBar ); 302 a->addTo( fileMenuView);
303 a->addTo( iconToolBar );
162 304
163 a = new QAction( tr( "Rotate 180" ), Resource::loadPixmap( "repeat" ), QString::null, 0, this, 0 );
164 connect( a, SIGNAL( activated() ), this, SLOT( rot180() ) );
165 a->addTo( toolBar );
166 a->addTo( edit );
167 305
168 a = new QAction( tr( "Rotate 90"), Resource::loadPixmap( "rotate90" ), QString::null, 0, this, 0); 306 a = new QAction( tr( "Rotate 90"), Resource::loadPixmap( "rotate90" ), QString::null, 0, this, 0);
169 connect( a, SIGNAL( activated() ), this, SLOT( rot90() ) ); 307 connect( a, SIGNAL( activated() ), this, SLOT( rot90() ) );
170 a->addTo( toolBar ); 308 a->addTo( iconToolBar );
171 a->addTo( edit ); 309 a->addTo( viewMenuView );
310
311 a = new QAction( tr( "Rotate 180" ), Resource::loadPixmap( "repeat" ), QString::null, 0, this, 0 );
312 connect( a, SIGNAL( activated() ), this, SLOT( rot180() ) );
313 a->addTo( iconToolBar );
314 a->addTo( viewMenuView );
315
316
317 a = new QAction( tr( "Rotate 270"), Resource::loadPixmap( "rotate270" ), QString::null, 0, this, 0);
318 connect( a, SIGNAL( activated() ), this, SLOT( rot270() ) );
319 //a->addTo( iconToolBar );
320 a->addTo( viewMenuView );
321
322
323
324 viewMenuView->insertSeparator();
325 viewMenuView->insertItem(tr("Brightness ..."), this, SLOT(displayControlsDialog()), 0);
326 viewMenuView->insertItem(tr("Black And White"), this, SLOT(blackAndWhite()), 0,BLACKANDWHITE);
327 viewMenuView->insertSeparator();
328
329
330 sss = new QAction( tr( "Scale to Screen"), Resource::loadPixmap( "scale" ), QString::null, 0, this, 0,true);
331 connect( sss, SIGNAL( activated() ), this, SLOT( switchSizeToScreen() ) );
332 sss->addTo( iconToolBar );
333 sss->addTo( viewMenuView );
334
335 sss->setOn(isSized);
336 viewMenuView->insertSeparator();
337
172 338
173 a = new QAction( tr( "Fullscreen" ), Resource::loadPixmap( "fullscreen" ), QString::null, 0, this, 0 ); 339 a = new QAction( tr( "Fullscreen" ), Resource::loadPixmap( "fullscreen" ), QString::null, 0, this, 0 );
174 connect( a, SIGNAL( activated() ), this, SLOT( fullScreen() ) ); 340 connect( a, SIGNAL( activated() ), this, SLOT( fullScreen() ) );
175 a->addTo( toolBar ); 341 a->addTo( iconToolBar );
176 a->addTo( view); 342 a->addTo( viewMenuView);
343
344 switchToFileSelector();
177 345
178 stack->raiseWidget( fileSelector ); 346 setMouseTracking( TRUE );
179 347
180 setMouseTracking( TRUE ); 348
181} 349}
182 350
183ImageViewer::~ImageViewer() 351ImageViewer::~ImageViewer()
184{ 352{
353 Config cfg("Image Viewer");
354 cfg.setGroup("Image Viewer");
355
356 cfg.writeEntry("ShowThumbnails",(int)showThumbView);
357 cfg.writeEntry("SizeToScreen",(int)isSized);
358
185 delete imagePanel; // in case it is fullscreen 359 delete imagePanel; // in case it is fullscreen
186} 360}
187 361
362void ImageViewer::switchSizeToScreen()
363{
364 isSized=!isSized;
365 sss->setOn(isSized);
366 updateImage();
367}
368
369void ImageViewer::updateImage()
370{
371 if ( isSized )
372 {
373 imagePanel->setPixmap(pmScaled);
374 }
375 else
376 {
377 imagePanel->setPixmap(pm);
378 }
379}
380
381void ImageViewer::switchThumbView()
382{
383
384 showThumbView=!showThumbView;
385 viewMenuFile->setItemChecked ( SHOW_THUMBNAILS, showThumbView );
386 fileSelector->switchView();
387
388}
389
390void ImageViewer::switchToFileSelector()
391{
392 stack->raiseWidget(fileSelector);
393 menuBar->clear();
394 menuBar->insertItem( tr("File"), fileMenuFile );
395 menuBar->insertItem( tr("View"), viewMenuFile );
396 menuBar->insertItem( tr("Options"), optionsMenuFile );
397 iconToolBar->hide();
398 imagePanel->disable();
399
400}
401
402void ImageViewer::switchToImageView()
403{
404 stack->raiseWidget(imagePanel);
405
406 menuBar->clear();
407 menuBar->insertItem( tr("File"), fileMenuView );
408 menuBar->insertItem( tr("View"), viewMenuView );
409 viewMenuView->setItemEnabled(BLACKANDWHITE,true);
410 iconToolBar->show();
411
412 imagePanel->setPosition(0,0);
413
414}
415
416
188void ImageViewer::setDocument(const QString& fileref) 417void ImageViewer::setDocument(const QString& fileref)
189{ 418{
190 delayLoad = fileref; 419 delayLoad = fileref;
191 stack->raiseWidget(imagePanel); 420 switchToImageView();
192 QTimer::singleShot( 0, this, SLOT(doDelayedLoad()) ); 421 QTimer::singleShot( 0, this, SLOT(doDelayedLoad()) );
193} 422}
194 423
195void ImageViewer::doDelayedLoad() 424void ImageViewer::doDelayedLoad()
196{ 425{
197 show(delayLoad); 426 show(delayLoad);
198} 427}
199 428
200void ImageViewer::show() 429void ImageViewer::show()
201{ 430{
202 normalView(); 431 normalView();
203 QMainWindow::show(); 432 QMainWindow::show();
204} 433}
205 434
206void ImageViewer::show(const QString& fileref) 435void ImageViewer::show(const QString& fileref)
207{ 436{
208 bFromDocView = TRUE; 437 bFromDocView = TRUE;
209 closeFileSelector(); 438 closeFileSelector();
210 DocLnk link(fileref); 439 DocLnk link(fileref);
211 if ( link.isValid() ) { 440 if ( link.isValid() )
212 openFile(link); 441 {
213 } else { 442 openFile(link);
214 filename = fileref; 443 }
215 updateCaption( fileref ); 444 else
216 loadImage( fileref ); 445 {
446 filename = fileref;
447 updateCaption( fileref );
448 loadImage( fileref );
217 } 449 }
218} 450}
219 451
220void ImageViewer::openFile( const DocLnk &file ) 452void ImageViewer::openFile( const DocLnk &file )
221{ 453{
222 closeFileSelector(); 454 closeFileSelector();
223 DocLnk link(file); 455 DocLnk link(file);
224 updateCaption( link.name() ); 456 updateCaption( link.name() );
225 loadImage( link.file() ); 457 loadImage( link.file() );
226} 458}
227 459
228void ImageViewer::open() 460void ImageViewer::open()
229{ 461{
230 stack->raiseWidget(fileSelector); 462 switchToFileSelector();
231} 463}
232 464
233void ImageViewer::closeFileSelector() 465void ImageViewer::closeFileSelector()
234{ 466{
235 stack->raiseWidget(imagePanel); 467 switchToImageView();
236} 468}
237 469
238void ImageViewer::updateCaption( QString name ) 470void ImageViewer::updateCaption( QString name )
239{ 471{
240 int sep = name.findRev( '/' ); 472 int sep = name.findRev( '/' );
241 if ( sep >= 0 ) 473 if ( sep >= 0 )
242 name = name.mid( sep+1 ); 474 name = name.mid( sep+1 );
243 setCaption( name + tr(" - Image Viewer") ); 475 setCaption( name + tr(" - Image Viewer") );
244} 476}
245 477
246/* 478/*
247 This function loads an image from a file. 479 This function loads an image from a file.
248*/ 480*/
249 481
250void ImageViewer::loadImage( const char *fileName ) 482void ImageViewer::loadImage( const char *fileName )
251{ 483{
252 filename = fileName; 484 filename = fileName;
253 if ( filename ) { 485 if ( filename )
254 QApplication::setOverrideCursor( waitCursor ); // this might take time 486 {
255 imagePanel->statusLabel()->setText( tr("Loading image...") ); 487 QApplication::setOverrideCursor( waitCursor ); // this might take time
256 qApp->processEvents(); 488 //imagePanel->statusLabel()->setText( tr("Loading image...") );
257 bool ok = image.load(filename, 0); 489 qApp->processEvents();
258 pickx = -1; 490 bool ok = image.load(filename, 0);
259 clickx = -1; 491 if ( ok )
260 if ( ok ) 492 {
261 ok = reconvertImage(); 493 ok = reconvertImage();
262 if ( !ok ) { 494 updateImageInfo(filename);
263 pm.resize(0,0); // couldn't load image 495 }
264 update(); 496 if ( !ok )
265 } 497 {
266 QApplication::restoreOverrideCursor();// restore original cursor 498 pm.resize(0,0); // couldn't load image
267 } 499 update();
268 updateStatus(); 500 }
269 imagePanel->setPixmap( pmScaled ); 501 QApplication::restoreOverrideCursor(); // restore original cursor
270 stack->raiseWidget(imagePanel); 502 }
503 switchToImageView();
504 updateImage();
505
271} 506}
272 507
273bool ImageViewer::loadSelected() 508bool ImageViewer::loadSelected()
274{ 509{
275 bool ok = false; 510 bool ok = false;
276 if ( stack->visibleWidget() == fileSelector ) { 511 if ( stack->visibleWidget() == fileSelector )
277 const DocLnk *link = fileSelector->selected(); 512 {
278 if ( link ) { 513 const DocLnk *link = fileSelector->selected();
279 if ( link->file() != filename ) { 514 if ( link )
280 updateCaption( link->name() ); 515 {
281 filename = link->file(); 516 if ( link->file() != filename )
282 imagePanel->statusLabel()->setText( tr("Loading image...") ); 517 {
283 qApp->processEvents(); 518 updateCaption( link->name() );
284 ok = image.load(filename, 0); 519 filename = link->file();
285 if ( ok ) 520 qApp->processEvents();
286 ok = reconvertImage(); 521 ok = image.load(filename, 0);
287 if ( !ok ) 522 if ( ok )
288 pm.resize(0,0); 523 {
289 } 524 updateImageInfo(filename);
290 } 525 ok = reconvertImage();
291 } 526 }
292 if ( !image.isNull() ) { 527 if ( !ok )
293 ok = true; 528 pm.resize(0,0);
294 closeFileSelector(); 529 }
530 }
531 }
532 if ( !image.isNull() )
533 {
534 ok = true;
535 closeFileSelector();
295 } 536 }
296 537
297 return ok; 538 return ok;
298} 539}
299 540
300bool ImageViewer::reconvertImage() 541bool ImageViewer::reconvertImage()
301{ 542{
302 bool success = FALSE; 543 bool success = FALSE;
303 544
304 if ( image.isNull() ) return FALSE; 545 if ( image.isNull() ) return FALSE;
305 546
306 QApplication::setOverrideCursor( waitCursor ); // this might take time 547 QApplication::setOverrideCursor( waitCursor ); // this might take time
307 if ( pm.convertFromImage(image /*, conversion_flags */ ) ) 548 if ( pm.convertFromImage(image /*, conversion_flags */ ) )
308 { 549 {
309 pmScaled = QPixmap(); 550 pmScaled = QPixmap();
310 scale(); 551 scale();
311 success = TRUE; // load successful 552 success = TRUE; // load successful
312 } else { 553 }
313 pm.resize(0,0); // couldn't load image 554 else
555 {
556 pm.resize(0,0); // couldn't load image
314 } 557 }
315 QApplication::restoreOverrideCursor();// restore original cursor 558 QApplication::restoreOverrideCursor(); // restore original cursor
316 559
317 return success; // TRUE if loaded OK 560 return success; // TRUE if loaded OK
318} 561}
319 562
320 563
321int ImageViewer::calcHeight() 564int ImageViewer::calcHeight()
322{ 565{
323 if ( !isFullScreen) 566 if ( !isFullScreen )
324 return height() - menubar->heightForWidth( width() ) 567 return imagePanel->paneHeight();
325 - imagePanel->statusLabel()->height();
326 else 568 else
327 return qApp->desktop()->height(); 569 return qApp->desktop()->height();
328} 570}
329/* 571/*
330 This functions scales the pixmap in the member variable "pm" to fit the 572 This functions scales the pixmap in the member variable "pm" to fit the
331 widget size and puts the resulting pixmap in the member variable "pmScaled". 573 widget size and puts the resulting pixmap in the member variable "pmScaled".
332*/ 574*/
333
334void ImageViewer::scale() 575void ImageViewer::scale()
335{ 576{
336 int h = calcHeight(); 577 int h = calcHeight();
337 if ( image.isNull() ) return; 578 if ( image.isNull() ) return;
338 579
339 QApplication::setOverrideCursor( waitCursor ); // this might take time 580 QApplication::setOverrideCursor( waitCursor ); // this might take time
340 if ( width() == pm.width() && h == pm.height() ) { // no need to scale if widget 581 if ( imagePanel->paneWidth() == pm.width() && h == pm.height() )
341 pmScaled = pm; // size equals pixmap size 582 { // no need to scale if widget
342 } else { 583 pmScaled = pm; // size equals pixmap size
343 double hs = (double)h / (double)image.height(); 584 }
344 double ws = (double)width() / (double)image.width(); 585 else
345 double scaleFactor = (hs > ws) ? ws : hs; 586 {
346 int smoothW = (int)(scaleFactor * image.width()); 587 double hs = (double)h / (double)image.height();
347 int smoothH = (int)(scaleFactor * image.height()); 588 double ws = (double)imagePanel->paneWidth() / (double)image.width();
589 double scaleFactor = (hs > ws) ? ws : hs;
590 int smoothW = (int)(scaleFactor * image.width());
591 int smoothH = (int)(scaleFactor * image.height());
348 592
349 pmScaled.convertFromImage( image.smoothScale( smoothW, smoothH ) /*, conversion_flags */ ); 593 pmScaled.convertFromImage( image.smoothScale( smoothW, smoothH ) /*, conversion_flags */ );
350 } 594 }
351 QApplication::restoreOverrideCursor();// restore original cursor 595 QApplication::restoreOverrideCursor(); // restore original cursor
352} 596}
353 597
354/* 598/*
355 The resize event handler, if a valid pixmap was loaded it will call 599 The resize event handler, if a valid pixmap was loaded it will call
356 scale() to fit the pixmap to the new widget size. 600 scale() to fit the pixmap to the new widget size.
357*/ 601*/
358 602
359void ImageViewer::resizeEvent( QResizeEvent * ) 603void ImageViewer::resizeEvent( QResizeEvent * )
360{ 604{
361 imagePanel->statusLabel()->setGeometry(0, height() - imagePanel->statusLabel()->height(),
362 width(), imagePanel->statusLabel()->height());
363 605
364 if ( pm.size() == QSize( 0, 0 ) ) // we couldn't load the image 606 if ( pm.size() == QSize( 0, 0 ) ) // we couldn't load the image
365 return; 607 return;
366 608
367 int h = calcHeight(); 609 int h = calcHeight();
368 610
369 if ( width() != pmScaled.width() || h != pmScaled.height()) 611 if ( imagePanel->paneWidth() != pmScaled.width() || h != pmScaled.height() )
370 { // if new size, 612 { // if new size,
371 scale(); // scale pmScaled to window 613 scale(); // scale pmScaled to window
372 updateStatus();
373 } 614 }
374 if ( image.hasAlphaBuffer() ) 615 if ( image.hasAlphaBuffer() )
375 erase(); 616 erase();
376} 617}
377 618
378void ImageViewer::convertEvent( QMouseEvent* e, int& x, int& y)
379{
380 if ( pm.size() != QSize( 0, 0 ) ) {
381 int h = height() - menubar->heightForWidth( width() ) - imagePanel->statusLabel()->height();
382 int nx = e->x() * image.width() / width();
383 int ny = (e->y()-menubar->heightForWidth( width() )) * image.height() / h;
384 if (nx != x || ny != y ) {
385 x = nx;
386 y = ny;
387 updateStatus();
388 }
389 }
390}
391 619
392void ImageViewer::mousePressEvent( QMouseEvent *e ) 620void ImageViewer::hFlip()
393{ 621{
394 convertEvent(e, clickx, clicky); 622 setImage(image.mirror(TRUE,FALSE));
395} 623}
396 624
397void ImageViewer::mouseMoveEvent( QMouseEvent *e ) 625void ImageViewer::vFlip()
398{ 626{
399 convertEvent( e, pickx, picky ); 627 setImage(image.mirror(FALSE,TRUE));
400} 628}
401 629
402void ImageViewer::hFlip() 630void ImageViewer::rot180()
403{ 631{
404 if ( loadSelected() ) 632
405 setImage(image.mirror(TRUE,FALSE)); 633 setImage(image.mirror(TRUE,TRUE));
406} 634}
407 635
408void ImageViewer::vFlip() 636void ImageViewer::rot90()
409{ 637{
410 if ( loadSelected() ) 638 QImage oldimage;
411 setImage(image.mirror(FALSE,TRUE)); 639 oldimage = image.convertDepth(32);
412} 640 setImage(rotate(oldimage,Rotate90));
413 641
414void ImageViewer::rot180() 642}
643void ImageViewer::rot270()
415{ 644{
416 if ( loadSelected() ) 645
417 setImage(image.mirror(TRUE,TRUE)); 646 QImage oldimage;
647 oldimage = image.convertDepth(32);
648 setImage(rotate(oldimage,Rotate270));
649
418} 650}
419 651
420void ImageViewer::rot90() 652void ImageViewer::blackAndWhite()
421{ 653{
422 if ( loadSelected() ) {
423 QImage oldimage, newimage;
424 uchar *oldbits, *newbits;
425 int i, j, p;
426 int w, h;
427 654
428 oldimage = image.convertDepth(32); 655 viewMenuView->setItemEnabled(BLACKANDWHITE,false);
429 w = oldimage.height(); 656 setImage(toGray(image,false));
430 h = oldimage.width(); 657
431 newimage = QImage( w, h, 32);
432 658
433 oldbits = oldimage.bits(); 659}
434 newbits = newimage.bits(); 660
661void ImageViewer::displayControlsDialog()
662{
663 int w=80;
664 int h=w;
665 QImage small;
435 666
436 for (i=0; i < w ; i++) 667 if ( image.width()<w ||image.height()<h )
437 for (j=0; j < h; j++) 668 small=image.smoothScale(w,h);
438 for (p = 0 ; p < 4 ; p++) 669 else
439 newbits[(j * w + i) * 4 + p] = oldbits[ ((i + 1) * h - j ) * 4 + p]; 670 small=image.copy(0,0,w,h);
440 671
441 setImage(newimage); 672 int newB=0;
673 ControlsDialog *dlg=new ControlsDialog("Image Viewer",small,&newB,this);
674 dlg->exec();
675 if ( newB )
676 {
677 intensity(image,(float)newB/100);
678 setImage(image);
442 } 679 }
680
443} 681}
444 682
445 683
684void ImageViewer::displayInfoDialog()
685{
686
687 QStringList ls;
688
689 for ( int i=0;i<LAST;i++ )
690 ls.append(imageInfo[i]);
446 691
692 InfoDialog::displayInfo("Image Viewer",ls,this);
693}
447void ImageViewer::normalView() 694void ImageViewer::normalView()
448{ 695{
449 if ( !imagePanel->parentWidget() ) { 696 if ( !imagePanel->parentWidget() )
450 isFullScreen = FALSE; 697 {
451 stack->addWidget( imagePanel, 1 ); 698
452 //imagePanel->reparent(stack,0,QPoint(0,0),FALSE); 699 isFullScreen = FALSE;
453 //imagePanel->resize(width(), calcHeight()); 700 stack->addWidget( imagePanel, 1 );
454 scale(); 701 switchToImageView();
455 updateStatus(); 702 if ( isSized )
456 imagePanel->setPixmap( pmScaled ); 703 scale();
457 imagePanel->showStatus(); 704
458 //imagePanel->show(); 705 updateImage();
459 stack->raiseWidget( imagePanel ); 706
460 } 707 }
461} 708}
462 709
463void ImageViewer::fullScreen() 710void ImageViewer::fullScreen()
464{ 711{
465 // Full-screen and rotation options 712 // Full-screen option
466 // contributed by Robert Wittams <robert@wittams.com> 713 // contributed by Robert Wittams <robert@wittams.com>
467 714 if ( imagePanel->parentWidget() && loadSelected() )
468 if ( imagePanel->parentWidget() && loadSelected() ) { 715 {
469 isFullScreen = TRUE; 716 isFullScreen = TRUE;
470 imagePanel->reparent(0,QPoint(0,0)); 717 imagePanel->reparent(0,QPoint(0,0));
471 imagePanel->resize(qApp->desktop()->width(), qApp->desktop()->height()); 718 imagePanel->resize(qApp->desktop()->width(), qApp->desktop()->height());
472 719
473 scale(); 720 if ( isSized )
474 updateStatus(); 721 scale();
475 imagePanel->hideStatus(); 722 updateImage();
476 imagePanel->setPixmap( pmScaled ); 723 imagePanel->showFullScreen();
477 imagePanel->showFullScreen();
478 } 724 }
479} 725}
480 726
481void ImageViewer::setImage(const QImage& newimage) 727void ImageViewer::setImage(const QImage& newimage)
482{ 728{
483 image = newimage; 729 image = newimage;
484 pickx = -1;
485 clickx = -1;
486 reconvertImage(); 730 reconvertImage();
487 imagePanel->setPixmap( pmScaled ); 731 updateImage();
488 updateStatus(); 732}
489} 733
490 734void ImageViewer::updateImageInfo(QString &filePath)
491void ImageViewer::updateStatus() 735{
492{ 736
493 if ( pm.size() == QSize( 0, 0 ) ) { 737 for ( int i=0;i<LAST;i++ )
494 if ( filename ) 738 {
495 imagePanel->statusLabel()->setText( tr("Could not load image") ); 739 imageInfo[i]="";
496 else 740 }
497 imagePanel->statusLabel()->setText( tr("No image - select Open from File menu.") ); 741
498 } else { 742 imageInfo[FORMAT]=QImage::imageFormat (filePath );
499 QString message("%1x%2"); 743 QFileInfo fi(filePath);
500 message = message.arg(image.width()).arg(image.height()); 744 imageInfo[PATH]=fi.fileName();
501 if ( pm.size() != pmScaled.size() ) 745 imageInfo[FILE_SIZE]=QString::number(fi.size())+" (bytes)";
502 message += QString(" [%1x%2]").arg(pmScaled.width()).arg(pmScaled.height()); 746 QString message("%1x%2");
503 if (image.valid(pickx,picky)) { 747 imageInfo[SIZE]=QString("%1x%2");
504 QString moremsg; 748 imageInfo[SIZE]=imageInfo[SIZE].arg(image.width()).arg(image.height());
505 moremsg.sprintf("(%d,%d)=#%0*x ", 749 if ( image.numColors() > 0 )
506 pickx, picky, 750 {
507 image.hasAlphaBuffer() ? 8 : 6, 751 imageInfo[COLORS]=tr("%1 colors").arg(image.numColors());
508 image.pixel(pickx,picky)); 752 }
509 message += moremsg; 753 else if ( image.depth() >= 16 )
510 } 754 {
511 if ( image.numColors() > 0 ) { 755 imageInfo[COLORS]=tr(" True color");
512 if (image.valid(pickx,picky)) { 756 }
513 message += tr(", %1/%2 colors") 757 if ( image.hasAlphaBuffer() )
514 .arg(image.pixelIndex(pickx,picky)) 758 {
515 .arg(image.numColors()); 759 if ( image.depth() == 8 )
516 } else { 760 {
517 message += tr(", %1 colors").arg(image.numColors()); 761 int i;
518 } 762 bool alpha[256];
519 } else if ( image.depth() >= 16 ) { 763 int nalpha=0;
520 message += tr(" True color"); 764
521 } 765 for ( i=0; i<256; i++ )
522 if ( image.hasAlphaBuffer() ) { 766 alpha[i] = FALSE;
523 if ( image.depth() == 8 ) { 767
524 int i; 768 for ( i=0; i<image.numColors(); i++ )
525 bool alpha[256]; 769 {
526 int nalpha=0; 770 int alevel = image.color(i) >> 24;
527 771 if ( !alpha[alevel] )
528 for (i=0; i<256; i++) 772 {
529 alpha[i] = FALSE; 773 alpha[alevel] = TRUE;
530 774 nalpha++;
531 for (i=0; i<image.numColors(); i++) { 775 }
532 int alevel = image.color(i) >> 24; 776 }
533 if (!alpha[alevel]) { 777 imageInfo[ALPHA]=tr("%1 alpha levels").arg(nalpha);
534 alpha[alevel] = TRUE; 778 }
535 nalpha++; 779 else
536 } 780 {
537 } 781 imageInfo[ALPHA]=tr("8-bit alpha channel");
538 message += tr(", %1 alpha levels").arg(nalpha); 782 }
539 } else {
540 // Too many pixels to bother counting.
541 message += tr(", 8-bit alpha channel");
542 }
543 }
544 imagePanel->statusLabel()->setText(message);
545 } 783 }
784
546} 785}
547 786
548void ImageViewer::closeEvent( QCloseEvent *e ) 787void ImageViewer::closeEvent( QCloseEvent *e )
549{ 788{
550 if ( stack->visibleWidget() == imagePanel && !bFromDocView ) { 789 if ( stack->visibleWidget() == imagePanel && !bFromDocView )
551 e->ignore(); 790 {
552 open(); 791 e->ignore();
553 } else { 792 open();
554 bFromDocView = FALSE; 793 }
555 e->accept(); 794 else
795 {
796 bFromDocView = FALSE;
797 e->accept();
798 }
799}
800
801// Intensity,toGray and rotate code courtesy of KDE project.
802
803
804QImage& ImageViewer::intensity(QImage &image, float percent)
805{
806
807 int segColors = image.depth() > 8 ? 256 : image.numColors();
808 unsigned char *segTbl = new unsigned char[segColors];
809 int pixels = image.depth() > 8 ? image.width()*image.height() :
810 image.numColors();
811 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
812 (unsigned int *)image.colorTable();
813
814 bool brighten = (percent >= 0);
815 if ( percent < 0 )
816 percent = -percent;
817
818 if ( brighten )
819 { // keep overflow check out of loops
820 for ( int i=0; i < segColors; ++i )
821 {
822 int tmp = (int)(i*percent);
823 if ( tmp > 255 )
824 tmp = 255;
825 segTbl[i] = tmp;
826 }
827 }
828 else
829 {
830 for ( int i=0; i < segColors; ++i )
831 {
832 int tmp = (int)(i*percent);
833 if ( tmp < 0 )
834 tmp = 0;
835 segTbl[i] = tmp;
836 }
837 }
838
839 if ( brighten )
840 { // same here
841 for ( int i=0; i < pixels; ++i )
842 {
843 int r = qRed(data[i]);
844 int g = qGreen(data[i]);
845 int b = qBlue(data[i]);
846 int a = qAlpha(data[i]);
847 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
848 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
849 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
850 data[i] = qRgba(r, g, b,a);
851 }
852 }
853 else
854 {
855 for ( int i=0; i < pixels; ++i )
856 {
857 int r = qRed(data[i]);
858 int g = qGreen(data[i]);
859 int b = qBlue(data[i]);
860 int a = qAlpha(data[i]);
861 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
862 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
863 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
864 data[i] = qRgba(r, g, b, a);
865 }
866 }
867 delete [] segTbl;
868
869 return image;
870}
871
872QImage& ImageViewer::toGray(QImage &img, bool fast)
873{
874 if ( img.width() == 0 || img.height() == 0 )
875 return img;
876
877 if ( fast )
878 {
879 if ( img.depth() == 32 )
880 {
881 register uchar * r(img.bits());
882 register uchar * g(img.bits() + 1);
883 register uchar * b(img.bits() + 2);
884
885 uchar * end(img.bits() + img.numBytes());
886
887 while ( r != end )
888 {
889
890 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
891
892 r += 4;
893 g += 4;
894 b += 4;
895 }
896 }
897 else
898 {
899 for ( int i = 0; i < img.numColors(); i++ )
900 {
901 register uint r = qRed(img.color(i));
902 register uint g = qGreen(img.color(i));
903 register uint b = qBlue(img.color(i));
904
905 register uint gray = (((r + g) >> 1) + b) >> 1;
906 img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
907 }
908 }
909 }
910 else
911 {
912 int pixels = img.depth() > 8 ? img.width()*img.height() :
913 img.numColors();
914 unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
915 (unsigned int *)img.colorTable();
916 int val, i;
917 for ( i=0; i < pixels; ++i )
918 {
919 val = qGray(data[i]);
920 data[i] = qRgba(val, val, val, qAlpha(data[i]));
921 }
922 }
923 return img;
924}
925
926
927QImage ImageViewer::rotate(QImage &img, RotateDirection r)
928{
929 QImage dest;
930 int x, y;
931 if ( img.depth() > 8 )
932 {
933 unsigned int *srcData, *destData;
934 switch ( r )
935 {
936 case Rotate90:
937 dest.create(img.height(), img.width(), img.depth());
938 for ( y=0; y < img.height(); ++y )
939 {
940 srcData = (unsigned int *)img.scanLine(y);
941 for ( x=0; x < img.width(); ++x )
942 {
943 destData = (unsigned int *)dest.scanLine(x);
944 destData[img.height()-y-1] = srcData[x];
945 }
946 }
947 break;
948 case Rotate180:
949 dest.create(img.width(), img.height(), img.depth());
950 for ( y=0; y < img.height(); ++y )
951 {
952 srcData = (unsigned int *)img.scanLine(y);
953 destData = (unsigned int *)dest.scanLine(img.height()-y-1);
954 for ( x=0; x < img.width(); ++x )
955 destData[img.width()-x-1] = srcData[x];
956 }
957 break;
958 case Rotate270:
959 dest.create(img.height(), img.width(), img.depth());
960 for ( y=0; y < img.height(); ++y )
961 {
962 srcData = (unsigned int *)img.scanLine(y);
963 for ( x=0; x < img.width(); ++x )
964 {
965 destData = (unsigned int *)dest.scanLine(img.width()-x-1);
966 destData[y] = srcData[x];
967 }
968 }
969 break;
970 default:
971 dest = img;
972 break;
973 }
974 }
975 else
976 {
977 unsigned char *srcData, *destData;
978 unsigned int *srcTable, *destTable;
979 switch ( r )
980 {
981 case Rotate90:
982 dest.create(img.height(), img.width(), img.depth());
983 dest.setNumColors(img.numColors());
984 srcTable = (unsigned int *)img.colorTable();
985 destTable = (unsigned int *)dest.colorTable();
986 for ( x=0; x < img.numColors(); ++x )
987 destTable[x] = srcTable[x];
988 for ( y=0; y < img.height(); ++y )
989 {
990 srcData = (unsigned char *)img.scanLine(y);
991 for ( x=0; x < img.width(); ++x )
992 {
993 destData = (unsigned char *)dest.scanLine(x);
994 destData[img.height()-y-1] = srcData[x];
995 }
996 }
997 break;
998 case Rotate180:
999 dest.create(img.width(), img.height(), img.depth());
1000 dest.setNumColors(img.numColors());
1001 srcTable = (unsigned int *)img.colorTable();
1002 destTable = (unsigned int *)dest.colorTable();
1003 for ( x=0; x < img.numColors(); ++x )
1004 destTable[x] = srcTable[x];
1005 for ( y=0; y < img.height(); ++y )
1006 {
1007 srcData = (unsigned char *)img.scanLine(y);
1008 destData = (unsigned char *)dest.scanLine(img.height()-y-1);
1009 for ( x=0; x < img.width(); ++x )
1010 destData[img.width()-x-1] = srcData[x];
1011 }
1012 break;
1013 case Rotate270:
1014 dest.create(img.height(), img.width(), img.depth());
1015 dest.setNumColors(img.numColors());
1016 srcTable = (unsigned int *)img.colorTable();
1017 destTable = (unsigned int *)dest.colorTable();
1018 for ( x=0; x < img.numColors(); ++x )
1019 destTable[x] = srcTable[x];
1020 for ( y=0; y < img.height(); ++y )
1021 {
1022 srcData = (unsigned char *)img.scanLine(y);
1023 for ( x=0; x < img.width(); ++x )
1024 {
1025 destData = (unsigned char *)dest.scanLine(img.width()-x-1);
1026 destData[y] = srcData[x];
1027 }
1028 }
1029 break;
1030 default:
1031 dest = img;
1032 break;
1033 }
1034
556 } 1035 }
1036 return (dest);
1037
1038
557} 1039}
1040
1041
1042
1043
1044