OSDN Git Service

15234cf7ece80e176b81a42b7e1d0227d82d4538
[kita/kita.git] / kita / src / part / kitaimgview.cpp
1 /***************************************************************************
2 *   Copyright (C) 2004 by Hideki Ikemoto , (c) 2004 by 421                *
3 *   ikemo@users.sourceforge.jp                                            *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 ***************************************************************************/
10
11 /* Image Viewer Widget */
12
13 #include "kitaimgview.h"
14 #include "libkita/imgmanager.h"
15
16 #include <kpopupmenu.h>
17 #include <kaction.h>
18 #include <khtml_part.h>
19 #include <khtmlview.h>
20 #include <kcursor.h>
21
22 #include <qpainter.h>
23 #include <qimage.h>
24 #include <qpixmap.h>
25 #include <qlayout.h>
26 #include <qapplication.h>
27
28
29 /*---------------------------------------------------------------*/
30
31
32 KitaImgView::KitaImgView( const KURL& url, const KURL& datURL, KActionCollection* action,
33                           QWidget* parent, const char* name, WFlags fl )
34         : QScrollView( parent, name, fl )
35 {
36     m_url = url;
37     m_datURL = datURL;
38     m_htmlPart = NULL;
39     m_layout = NULL;
40     m_action = action;
41     m_popup = NULL;
42     m_message = QString::null;
43     m_pixmap = NULL;
44
45     m_size = -100;
46     m_imgwd = m_imght = 0;
47     m_custom_wd = m_custom_ht = 0;
48
49     viewport() ->setEraseColor( Qt::black );
50     viewport() ->setPaletteBackgroundColor( Qt::black );
51 }
52
53
54 KitaImgView::~KitaImgView()
55 {
56     if ( m_pixmap ) delete m_pixmap;
57     if ( m_popup ) delete m_popup;
58     if ( m_layout ) delete m_layout;
59     if ( m_htmlPart ) delete m_htmlPart;
60 }
61
62
63 /* public */
64 const KURL KitaImgView::url() const
65 {
66     return m_url;
67 }
68
69
70 /* public */
71 const KURL KitaImgView::datURL() const
72 {
73     return m_datURL;
74 }
75
76
77 /* public */
78 void KitaImgView::showMessage( QString message )
79 {
80     m_message = message;
81     repaintContents();
82 }
83
84
85 /* show image */ /* public slot */
86 void KitaImgView::slotShowImage()
87 {
88     const int defaultsize = 0;
89
90     if ( m_size < -1 ) m_size = defaultsize; /* size is not initialized. */
91
92     bool usekhtmlpart = Kita::ImgManager::isAnimationGIF( m_url );
93     if ( m_htmlPart ) usekhtmlpart = TRUE;
94     if ( Kita::ImgManager::mosaic( m_url ) ) usekhtmlpart = FALSE;
95
96     if ( usekhtmlpart ) showImageWithKHTML();
97
98     if ( resizeImage() ) {
99         myResizeContents();
100         repaintContents();
101     }
102 }
103
104
105 /* public slot */
106 void KitaImgView::slotFitToWin()
107 {
108     if ( m_size == 0 ) return ;
109
110     m_size = 0;
111     slotShowImage();
112 }
113
114
115 /* public slot */
116 void KitaImgView::slotOriginalSize()
117 {
118     if ( m_size == 100 ) return ;
119
120     m_size = 100;
121     slotShowImage();
122 }
123
124
125 /* public slot */
126 void KitaImgView::slotSetSize( int size )
127 {
128     if ( m_size == size ) return ;
129
130     m_size = size;
131     slotShowImage();
132 }
133
134
135 /* public slot */
136 void KitaImgView::slotCustomSize( int wd, int ht )
137 {
138     const int minsize = 8;
139
140     if ( wd == m_custom_wd && ht == m_custom_ht ) return ;
141
142     m_custom_wd = QMAX( minsize, wd );
143     m_custom_ht = QMAX( minsize, ht );
144     m_size = -1;
145     slotShowImage();
146 }
147
148
149 /* public slot */
150 void KitaImgView::slotZoomIn()
151 {
152     const int maxsize = 400;
153
154     if ( m_size >= maxsize ) return ;
155
156     /* current mode is "fit to win" or "custom size" */
157     if ( m_size <= 0 && m_imgwd ) m_size = QMIN( 100, m_imgwd * 100 / Kita::ImgManager::width( m_url ) );
158
159     m_size += 10;
160     slotShowImage();
161 }
162
163
164 /* public slot */
165 void KitaImgView::slotZoomOut()
166 {
167     const int minsize = 10;
168
169     if ( m_size > 0 && m_size <= minsize ) return ;
170
171     /* current mode is "fit to win" or "custom size" */
172     if ( m_size <= 0 && m_imgwd ) m_size = QMIN( 100, m_imgwd * 100 / Kita::ImgManager::width( m_url ) );
173
174     m_size -= 10;
175     slotShowImage();
176 }
177
178
179
180 /* virtual protected */
181 void KitaImgView::resizeEvent( QResizeEvent * e )
182 {
183     QScrollView::resizeEvent( e );
184
185     if ( m_htmlPart ) showImageWithKHTML();
186
187     else if ( m_pixmap ) {
188         if ( m_size == 0 ) resizeImage();  /* fit to window */
189         myResizeContents();
190
191         /* drawContents is called later. */
192     }
193 }
194
195
196 /* virtual protected */
197 void KitaImgView::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph )
198 {
199     if ( m_htmlPart ) return ; /* use KHTMLPart */
200
201     if ( m_pixmap == NULL ) {
202         p->setPen( Qt::white );
203         if ( m_message != QString::null ) p->drawText( 16, 16, m_message );
204     } else {
205
206         p->fillRect( clipx, clipy, clipw, cliph, QColor( "black" ) );
207
208         int x = QMAX( 0, ( QMAX( width(), m_imgwd ) - m_imgwd ) / 2 );
209         int y = QMAX( 0, ( QMAX( height(), m_imght ) - m_imght ) / 2 );
210         int sx = QMAX( 0, clipx - x );
211         int sy = QMAX( 0, clipy - y );
212         int sw = QMIN( clipw, x + m_imgwd - clipx );
213         int sh = QMIN( cliph, y + m_imght - clipy );
214
215         if ( x + m_imgwd <= clipx || x >= clipx + clipw
216                 || y + m_imght <= clipy || y >= clipy + cliph ) return ;
217
218         x = QMAX( x, clipx );
219         y = QMAX( y, clipy );
220         p->drawPixmap( x, y, *m_pixmap, sx, sy, sw, sh );
221     }
222 }
223
224
225 /* virtual protected */
226 void KitaImgView::contentsMousePressEvent( QMouseEvent * e )
227 {
228     m_dragScroll = FALSE;
229     if ( e->button() & Qt::RightButton ) {
230         QString dummy;
231         slotPopupMenu( dummy, e->globalPos() );
232         return ;
233     }
234     else if ( e->button() & Qt::LeftButton ) { /* start dragscrolling */
235         m_dragScroll = TRUE;
236         QApplication::setOverrideCursor( KCursor::handCursor() );
237         m_dragx = e->globalX();
238         m_dragy = e->globalY();        
239     }
240
241     QScrollView::contentsMousePressEvent( e );
242 }
243
244 /* Note that e->button() is always NoButton. */ /* virtual protected */
245 void KitaImgView::contentsMouseMoveEvent( QMouseEvent * e )
246 {
247     if( !m_dragScroll ) return;
248     
249     /* drag & scroll */
250     int dx = m_dragx - e->globalX();
251     int dy = m_dragy - e->globalY();
252     scrollBy( dx, dy );
253     m_dragx = e->globalX();
254     m_dragy = e->globalY();        
255 }
256
257 /* virtual protected */
258 void KitaImgView::contentsMouseReleaseEvent( QMouseEvent *  )
259 {
260     if( m_dragScroll ){
261         m_dragScroll = FALSE;
262         QApplication::restoreOverrideCursor();
263     }
264 }
265
266
267 /* private */
268 bool KitaImgView::resizeImage()
269 {
270     const int mosaic_wd = 48;
271     const int mosaic_ht = 48;
272
273     /*-------------------------------------------*/
274
275     if ( Kita::ImgManager::code( m_url ) != 200 ) return FALSE;
276
277     QString path = Kita::ImgManager::getPath( m_url );
278     QImage orgimg = QImage( path );
279     if ( orgimg.isNull() ) return FALSE;
280
281     int imgwd = Kita::ImgManager::width( m_url );
282     int imght = Kita::ImgManager::height( m_url );
283
284     /* mosaic image */
285     if ( Kita::ImgManager::mosaic( m_url ) )
286         orgimg = orgimg.scale( mosaic_wd, mosaic_ht, QImage::ScaleMin ).scale( imgwd, imght, QImage::ScaleMin );
287
288     /* resize */
289     int wd;
290     int ht;
291     getImgSize( wd, ht );
292
293     if ( wd != imgwd || ht != imght ) orgimg = orgimg.scale( wd, ht, QImage::ScaleMin );
294
295     /* convert to pixmap */
296     if ( m_pixmap == NULL ) m_pixmap = new QPixmap();
297     m_pixmap->convertFromImage( orgimg );
298     m_imgwd = m_pixmap->width();
299     m_imght = m_pixmap->height();
300
301     return TRUE;
302 }
303
304
305
306
307 /* private */
308 void KitaImgView::getImgSize( int& wd, int& ht )
309 {
310     int imgwd = Kita::ImgManager::width( m_url );
311     int imght = Kita::ImgManager::height( m_url );
312
313     wd = imgwd;
314     ht = imght;
315
316     if ( m_size == -1 ) {    /* custom size */
317         wd = m_custom_wd;
318         ht = m_custom_ht;
319     } else if ( m_size == 0 ) { /* fit to window */
320
321         if ( width() < imgwd || height() < imght ) {
322
323             const int mrg = 16;
324
325             wd = width() - mrg;
326             ht = height() - mrg;
327         }
328     } else if ( m_size != 100 ) { /* % */
329         wd = imgwd * m_size / 100;
330         ht = imght * m_size / 100;
331     }
332 }
333
334
335
336 /* private */
337 void KitaImgView::myResizeContents()
338 {
339     int wd = QMAX( width(), m_imgwd );
340     int ht = QMAX( height(), m_imght );
341
342     resizeContents( wd, ht );
343
344     if ( wd == width() ) setHScrollBarMode( AlwaysOff );
345     else setHScrollBarMode( AlwaysOn );
346
347     if ( ht == height() ) setVScrollBarMode( AlwaysOff );
348     else setVScrollBarMode( AlwaysOn );
349
350     if ( m_htmlPart ) {
351
352         if ( wd == width() ) m_htmlPart->view() ->setHScrollBarMode( AlwaysOff );
353         else m_htmlPart->view() ->setHScrollBarMode( AlwaysOn );
354
355         if ( ht == height() ) m_htmlPart->view() ->setVScrollBarMode( AlwaysOff );
356         else m_htmlPart->view() ->setVScrollBarMode( AlwaysOn );
357     }
358 }
359
360
361 /* private slot */
362 void KitaImgView::slotPopupMenu( const QString& , const QPoint& global )
363 {
364     if ( !m_action ) return ;
365
366     if ( m_popup ) delete m_popup;
367     m_popup = new KPopupMenu( this );
368
369     if ( Kita::ImgManager::mosaic( m_url ) ) {
370         if ( m_action->action( "imgviewer_cancelmosaic" ) )
371             m_action->action( "imgviewer_cancelmosaic" ) ->plug( m_popup );
372         m_popup->insertSeparator();
373     }
374
375     if ( m_action->action( "imgviewer_fittowin" ) )
376         m_action->action( "imgviewer_fittowin" ) ->plug( m_popup );
377
378     if ( m_action->action( "imgviewer_original" ) )
379         m_action->action( "imgviewer_original" ) ->plug( m_popup );
380
381     if ( m_action->action( "imgviewer_selectsize" ) )
382         m_action->action( "imgviewer_selectsize" ) ->plug( m_popup );
383
384     if ( m_action->action( "imgviewer_zoomin" ) )
385         m_action->action( "imgviewer_zoomin" ) ->plug( m_popup );
386
387     if ( m_action->action( "imgviewer_zoomout" ) )
388         m_action->action( "imgviewer_zoomout" ) ->plug( m_popup );
389
390     m_popup->insertSeparator();
391     if ( m_action->action( "imgviewer_openbrowser" ) )
392         m_action->action( "imgviewer_openbrowser" ) ->plug( m_popup );
393     if ( m_action->action( "imgviewer_openthread" ) )
394         m_action->action( "imgviewer_openthread" ) ->plug( m_popup );
395     if ( m_action->action( "imgviewer_save" ) )
396         m_action->action( "imgviewer_save" ) ->plug( m_popup );
397
398     m_popup->exec( global );
399 }
400
401
402 /*----------------------------------------------*/
403
404 /* use KHTMLPart ( to show an Animation GIF ) */
405
406
407 bool KitaImgView::showImageWithKHTML()
408 {
409     if ( Kita::ImgManager::code( m_url ) != 200 ) return FALSE;
410     QString path = Kita::ImgManager::getPath( m_url );
411
412     /* create KHTMLPart */
413     if ( !m_htmlPart ) {
414         m_htmlPart = new KHTMLPart( this );
415         m_layout = new QVBoxLayout( this, 0, 0, "BoxLayout" );
416         m_layout->addWidget( m_htmlPart->view() );
417
418         connect( m_htmlPart, SIGNAL( popupMenu( const QString&, const QPoint& ) ),
419                  SLOT( slotPopupMenu( const QString&, const QPoint& ) ) );
420     }
421
422     /* show image */
423     if ( m_htmlPart ) {
424
425         QString sizetxt = QString::null;
426         int wd, ht;
427         int imgwd = Kita::ImgManager::width( m_url );
428         int imght = Kita::ImgManager::height( m_url );
429         m_imgwd = imgwd;
430         m_imght = imght;
431
432         getImgSize( wd, ht );
433
434         if ( m_size <= 0 ) { /* "fit to win" or "custom size" */
435
436             if ( ( double ) imght * wd / imgwd >= ht ) {
437                 sizetxt = "height=" + QString().setNum( ht );
438                 m_imgwd = ( int ) ( ( double ) imgwd * ht / imght );
439                 m_imght = ht;
440             } else {
441                 sizetxt = "width=" + QString().setNum( wd );
442                 m_imgwd = wd;
443                 m_imght = ( int ) ( ( double ) imght * wd / imgwd );
444             }
445         } else if ( m_size != 100 ) { /* % */
446             sizetxt = "width=" + QString().setNum( wd );
447             m_imgwd = wd;
448             m_imght = ( int ) ( ( double ) imght * wd / imgwd );
449         }
450
451         int x = QMAX( 0, ( QMAX( width(), m_imgwd ) - m_imgwd ) / 2 );
452         int y = QMAX( 0, ( QMAX( height(), m_imght ) - m_imght ) / 2 );
453
454         QString style = QString( "body { margin:%1px %2px; background-color:black; }" )
455                         .arg( y ).arg( x );
456
457         QString text = "<html><head><style>" + style + "</style></head><body>";
458         text += "<img src=\"file:" + path + "\" " + sizetxt + " >";
459         text += "</body></html>";
460
461         m_htmlPart->setJScriptEnabled( false );
462         m_htmlPart->setJavaEnabled( false );
463         m_htmlPart->begin( "file:/dummy.htm" );
464         m_htmlPart->write( text );
465         m_htmlPart->end();
466         m_htmlPart->view() ->show();
467     }
468
469     myResizeContents();
470
471     return TRUE;
472 }
473