summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiemm/oimagescrollview.cpp585
-rw-r--r--libopie2/opiemm/oimagescrollview.h95
-rw-r--r--libopie2/opiemm/oimagezoomer.cpp233
-rw-r--r--libopie2/opiemm/oimagezoomer.h141
-rw-r--r--libopie2/opiemm/opiemm.pro4
5 files changed, 1056 insertions, 2 deletions
diff --git a/libopie2/opiemm/oimagescrollview.cpp b/libopie2/opiemm/oimagescrollview.cpp
new file mode 100644
index 0000000..0e86bd0
--- a/dev/null
+++ b/libopie2/opiemm/oimagescrollview.cpp
@@ -0,0 +1,585 @@
1#include "oimagescrollview.h"
2
3#include <opie2/oimagezoomer.h>
4#include <opie2/odebug.h>
5#include <opie2/oapplication.h>
6#include <opie2/owait.h>
7
8#include <qimage.h>
9#include <qlayout.h>
10#include <qpe/qcopenvelope_qws.h>
11
12/* for usage with the bitset */
13#define AUTO_SCALE 0
14#define AUTO_ROTATE 1
15#define SHOW_ZOOMER 2
16#define FIRST_RESIZE_DONE 3
17#define IMAGE_IS_JPEG 4
18#define IMAGE_SCALED_LOADED 5
19
20#define SCROLLVIEW_BITSET_SIZE 6
21
22namespace Opie {
23namespace MM {
24OImageScrollView::OImageScrollView( QWidget* parent, const char* name, WFlags f )
25 :QScrollView(parent,name,f|Qt::WRepaintNoErase ),_image_data(),_original_data(),
26 m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("")
27{
28 _zoomer = 0;
29 m_states[AUTO_SCALE]=true;
30 m_states[AUTO_ROTATE]=true;
31 m_states[FIRST_RESIZE_DONE]=false;
32 m_states[IMAGE_IS_JPEG]=false;
33 m_states[IMAGE_SCALED_LOADED]=false;
34 m_states[SHOW_ZOOMER]=true;
35 init();
36}
37
38OImageScrollView::OImageScrollView (const QImage&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit)
39 :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(img),
40 m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("")
41{
42 _zoomer = 0;
43 m_states[AUTO_SCALE]=always_scale;
44 m_states[AUTO_ROTATE]=rfit;
45 m_states[FIRST_RESIZE_DONE]=false;
46 m_states[IMAGE_IS_JPEG]=false;
47 m_states[IMAGE_SCALED_LOADED]=false;
48 m_states[SHOW_ZOOMER]=true;
49 _original_data.convertDepth(QPixmap::defaultDepth());
50 _original_data.setAlphaBuffer(false);
51 init();
52}
53
54OImageScrollView::OImageScrollView (const QString&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit)
55 :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(),m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("")
56{
57 _zoomer = 0;
58 m_states.resize(SCROLLVIEW_BITSET_SIZE);
59 m_states[AUTO_SCALE]=always_scale;
60 m_states[AUTO_ROTATE]=rfit;
61 m_states[FIRST_RESIZE_DONE]=false;
62 m_states[IMAGE_IS_JPEG]=false;
63 m_states[IMAGE_SCALED_LOADED]=false;
64 m_states[SHOW_ZOOMER]=true;
65 init();
66 setImage(img);
67}
68
69void OImageScrollView::setImage(const QImage&img)
70{
71 _image_data = QImage();
72 _original_data=img;
73 _original_data.convertDepth(QPixmap::defaultDepth());
74 _original_data.setAlphaBuffer(false);
75 m_lastName = "";
76 setImageIsJpeg(false);
77 setImageScaledLoaded(false);
78 if (FirstResizeDone()) {
79 generateImage();
80 }
81}
82
83void OImageScrollView::loadJpeg(bool interncall)
84{
85 if (m_lastName.isEmpty()) return;
86 QImageIO iio( m_lastName, 0l );
87 QString param;
88 bool real_load = false;
89 if (AutoScale()) {
90 if (!interncall) {
91 int wid, hei;
92 wid = QApplication::desktop()->width();
93 hei = QApplication::desktop()->height();
94 if (hei>wid) {
95 wid = hei;
96 } else {
97 hei = wid;
98 }
99 param = QString( "Fast Shrink( 7 ) Scale( %1, %2, ScaleFree)" ).arg( wid ).arg( hei );
100 odebug << "Load jpeg scaled \"" << param << "\"" << oendl;
101 iio.setParameters(param.latin1());
102 setImageScaledLoaded(true);
103 real_load = true;
104 }
105 } else {
106 if (ImageScaledLoaded()||!interncall) {
107 odebug << "Load jpeg unscaled" << oendl;
108 real_load = true;
109 }
110 setImageScaledLoaded(false);
111 }
112 if (real_load) {
113 {
114 QCopEnvelope( "QPE/System", "busy()" );
115 }
116 _original_data = iio.read() ? iio.image() : QImage();
117 {
118 QCopEnvelope env( "QPE/System", "notBusy(QString)" );
119 env << "Image loaded";
120 }
121 }
122}
123
124void OImageScrollView::setImage( const QString& path ) {
125 odebug << "load new image " << oendl;
126 if (m_lastName == path) return;
127 m_lastName = path;
128 QString itype = QImage::imageFormat(m_lastName);
129 odebug << "Image type = " << itype << oendl;
130 if (itype == "JPEG") {
131 setImageIsJpeg(true);
132 loadJpeg();
133 } else {
134 {
135 QCopEnvelope( "QPE/System", "busy()" );
136 }
137 setImageIsJpeg(false);
138 _original_data.load(path);
139 _original_data.convertDepth(QPixmap::defaultDepth());
140 _original_data.setAlphaBuffer(false);
141 {
142 QCopEnvelope env( "QPE/System", "notBusy(QString)" );
143 env << "Image loaded";
144 }
145 }
146 _image_data = QImage();
147 if (FirstResizeDone()) {
148 generateImage();
149 }
150}
151
152/* should be called every time the QImage changed it content */
153void OImageScrollView::init()
154{
155 odebug << "init " << oendl;
156
157 /*
158 * create the zoomer
159 * and connect ther various signals
160 */
161 _zoomer = new Opie::MM::OImageZoomer( this, "The Zoomer" );
162 connect(_zoomer, SIGNAL( zoomAreaRel(int,int)),
163 this, SLOT(scrollBy(int,int)) );
164 connect(_zoomer, SIGNAL( zoomArea(int,int)),
165 this, SLOT(center(int,int)) );
166 connect(this,SIGNAL(contentsMoving(int,int)),
167 _zoomer, (SLOT(setVisiblePoint(int,int))) );
168 connect(this,SIGNAL(imageSizeChanged(const QSize&)),
169 _zoomer, SLOT(setImageSize(const QSize&)) );
170 connect(this,SIGNAL(viewportSizeChanged(const QSize&)),
171 _zoomer, SLOT(setViewPortSize(const QSize&)) );
172
173 viewport()->setBackgroundColor(white);
174 setFocusPolicy(QWidget::StrongFocus);
175 setImageScaledLoaded(false);
176 setImageIsJpeg(false);
177 if (FirstResizeDone()) {
178 m_last_rot = Rotate0;
179 generateImage();
180 } else if (_original_data.size().isValid()) {
181 if (image_fit_into(_original_data.size()) || !ShowZoomer()) _zoomer->hide();
182 resizeContents(_original_data.width(),_original_data.height());
183 }
184}
185
186void OImageScrollView::setAutoRotate(bool how)
187{
188 /* to avoid double repaints */
189 if (AutoRotate() != how) {
190 m_states.setBit(AUTO_ROTATE,how);
191 _image_data = QImage();
192 generateImage();
193 }
194}
195
196bool OImageScrollView::AutoRotate()const
197{
198 return m_states.testBit(AUTO_ROTATE);
199}
200
201void OImageScrollView::setAutoScale(bool how)
202{
203 m_states.setBit(AUTO_SCALE,how);
204 if (!how) {
205 setAutoRotate(false);
206 }
207 _image_data = QImage();
208 if (ImageIsJpeg() && how == false && ImageScaledLoaded()==true) {
209 loadJpeg(true);
210 }
211 generateImage();
212}
213
214bool OImageScrollView::AutoScale()const
215{
216 return m_states.testBit(AUTO_SCALE);
217}
218
219OImageScrollView::~OImageScrollView()
220{
221}
222
223void OImageScrollView::rescaleImage(int w, int h)
224{
225 if (_image_data.width()==w && _image_data.height()==h) {
226 return;
227 }
228 double hs = (double)h / (double)_image_data.height() ;
229 double ws = (double)w / (double)_image_data.width() ;
230 double scaleFactor = (hs > ws) ? ws : hs;
231 int smoothW = (int)(scaleFactor * _image_data.width());
232 int smoothH = (int)(scaleFactor * _image_data.height());
233 _image_data = _image_data.smoothScale(smoothW,smoothH);
234}
235
236void OImageScrollView::rotate_into_data(Rotation r)
237{
238 /* realy - we must do this that way, 'cause when acting direct on _image_data the app will
239 segfault :( */
240 QImage dest;
241 int x, y;
242 if ( _original_data.depth() > 8 )
243 {
244 unsigned int *srcData, *destData;
245 switch ( r )
246 {
247 case Rotate90:
248 dest.create(_original_data.height(), _original_data.width(), _original_data.depth());
249 for ( y=0; y < _original_data.height(); ++y )
250 {
251 srcData = (unsigned int *)_original_data.scanLine(y);
252 for ( x=0; x < _original_data.width(); ++x )
253 {
254 destData = (unsigned int *)dest.scanLine(x);
255 destData[_original_data.height()-y-1] = srcData[x];
256 }
257 }
258 break;
259 case Rotate180:
260 dest.create(_original_data.width(), _original_data.height(), _original_data.depth());
261 for ( y=0; y < _original_data.height(); ++y )
262 {
263 srcData = (unsigned int *)_original_data.scanLine(y);
264 destData = (unsigned int *)dest.scanLine(_original_data.height()-y-1);
265 for ( x=0; x < _original_data.width(); ++x )
266 destData[_original_data.width()-x-1] = srcData[x];
267 }
268 break;
269 case Rotate270:
270 dest.create(_original_data.height(), _original_data.width(), _original_data.depth());
271 for ( y=0; y < _original_data.height(); ++y )
272 {
273 srcData = (unsigned int *)_original_data.scanLine(y);
274 for ( x=0; x < _original_data.width(); ++x )
275 {
276 destData = (unsigned int *)dest.scanLine(_original_data.width()-x-1);
277 destData[y] = srcData[x];
278 }
279 }
280 break;
281 default:
282 dest = _original_data;
283 break;
284 }
285 }
286 else
287 {
288 unsigned char *srcData, *destData;
289 unsigned int *srcTable, *destTable;
290 switch ( r )
291 {
292 case Rotate90:
293 dest.create(_original_data.height(), _original_data.width(), _original_data.depth());
294 dest.setNumColors(_original_data.numColors());
295 srcTable = (unsigned int *)_original_data.colorTable();
296 destTable = (unsigned int *)dest.colorTable();
297 for ( x=0; x < _original_data.numColors(); ++x )
298 destTable[x] = srcTable[x];
299 for ( y=0; y < _original_data.height(); ++y )
300 {
301 srcData = (unsigned char *)_original_data.scanLine(y);
302 for ( x=0; x < _original_data.width(); ++x )
303 {
304 destData = (unsigned char *)dest.scanLine(x);
305 destData[_original_data.height()-y-1] = srcData[x];
306 }
307 }
308 break;
309 case Rotate180:
310 dest.create(_original_data.width(), _original_data.height(), _original_data.depth());
311 dest.setNumColors(_original_data.numColors());
312 srcTable = (unsigned int *)_original_data.colorTable();
313 destTable = (unsigned int *)dest.colorTable();
314 for ( x=0; x < _original_data.numColors(); ++x )
315 destTable[x] = srcTable[x];
316 for ( y=0; y < _original_data.height(); ++y )
317 {
318 srcData = (unsigned char *)_original_data.scanLine(y);
319 destData = (unsigned char *)dest.scanLine(_original_data.height()-y-1);
320 for ( x=0; x < _original_data.width(); ++x )
321 destData[_original_data.width()-x-1] = srcData[x];
322 }
323 break;
324 case Rotate270:
325 dest.create(_original_data.height(), _original_data.width(), _original_data.depth());
326 dest.setNumColors(_original_data.numColors());
327 srcTable = (unsigned int *)_original_data.colorTable();
328 destTable = (unsigned int *)dest.colorTable();
329 for ( x=0; x < _original_data.numColors(); ++x )
330 destTable[x] = srcTable[x];
331 for ( y=0; y < _original_data.height(); ++y )
332 {
333 srcData = (unsigned char *)_original_data.scanLine(y);
334 for ( x=0; x < _original_data.width(); ++x )
335 {
336 destData = (unsigned char *)dest.scanLine(_original_data.width()-x-1);
337 destData[y] = srcData[x];
338 }
339 }
340 break;
341 default:
342 dest = _original_data;
343 break;
344 }
345
346 }
347 _image_data = dest;
348}
349
350void OImageScrollView::generateImage()
351{
352 Rotation r = Rotate0;
353 if (_original_data.isNull()) return;
354 {
355 QCopEnvelope( "QPE/System", "busy()" );
356 }
357 if (width()>height()&&_original_data.width()<_original_data.height() ||
358 width()<height()&&_original_data.width()>_original_data.height()) {
359 if (AutoRotate()) r = Rotate90;
360 }
361
362 odebug << " r = " << r << oendl;
363 if (AutoScale()) {
364 if (!_image_data.size().isValid()||width()>_image_data.width()||height()>_image_data.height()) {
365 odebug << "Rescaling data" << oendl;
366 if (r==Rotate0) {
367 _image_data = _original_data;
368 } else {
369 rotate_into_data(r);
370 }
371 }
372 rescaleImage(width(),height());
373 resizeContents(_image_data.width(),_image_data.height());
374 } else if (!FirstResizeDone()||r!=m_last_rot||_image_data.width()==0) {
375 if (r==Rotate0) {
376 _image_data = _original_data;
377 } else {
378 rotate_into_data(r);
379 }
380 m_last_rot = r;
381 resizeContents(_image_data.width(),_image_data.height());
382 }
383 _pdata.convertFromImage(_image_data);
384
385
386 /*
387 * update the zoomer
388 */
389 check_zoomer();
390 emit imageSizeChanged( _image_data.size() );
391 rescaleImage( 128, 128 );
392 /*
393 * move scrollbar
394 */
395 if (_zoomer) {
396 _zoomer->setGeometry( viewport()->width()-_image_data.width()/2, viewport()->height()-_image_data.height()/2,
397 _image_data.width()/2, _image_data.height()/2 );
398 _zoomer->setImage( _image_data );
399 }
400 /*
401 * invalidate
402 */
403 _image_data=QImage();
404 {
405 QCopEnvelope env( "QPE/System", "notBusy(QString)" );
406 env << "Image generated";
407 }
408}
409
410void OImageScrollView::resizeEvent(QResizeEvent * e)
411{
412 odebug << "OImageScrollView resizeEvent" << oendl;
413 QScrollView::resizeEvent(e);
414 generateImage();
415 setFirstResizeDone(true);
416 emit viewportSizeChanged( viewport()->size() );
417
418}
419
420void OImageScrollView::keyPressEvent(QKeyEvent * e)
421{
422 if (!e) return;
423 int dx = horizontalScrollBar()->lineStep();
424 int dy = verticalScrollBar()->lineStep();
425 if (e->key()==Qt::Key_Right) {
426 scrollBy(dx,0);
427 e->accept();
428 } else if (e->key()==Qt::Key_Left) {
429 scrollBy(0-dx,0);
430 e->accept();
431 } else if (e->key()==Qt::Key_Up) {
432 scrollBy(0,0-dy);
433 e->accept();
434 } else if (e->key()==Qt::Key_Down) {
435 scrollBy(0,dy);
436 e->accept();
437 } else {
438 e->ignore();
439 }
440 QScrollView::keyPressEvent(e);
441}
442
443void OImageScrollView::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph)
444{
445 int w = clipw;
446 int h = cliph;
447 int x = clipx;
448 int y = clipy;
449 bool erase = false;
450
451 if (!_pdata.size().isValid()) {
452 p->fillRect(clipx,clipy,clipw,cliph,white);
453 return;
454 }
455 if (w>_pdata.width()) {
456 w=_pdata.width();
457 x = 0;
458 erase = true;
459 } else if (x+w>_pdata.width()){
460 x = _pdata.width()-w;
461 }
462 if (h>_pdata.height()) {
463 h=_pdata.height();
464 y = 0;
465 erase = true;
466 } else if (y+h>_pdata.height()){
467 y = _pdata.height()-h;
468 }
469 if (erase||_original_data.hasAlphaBuffer()) {
470 p->fillRect(clipx,clipy,clipw,cliph,white);
471 }
472 p->drawPixmap(clipx,clipy,_pdata,x,y,w,h);
473}
474
475/* using the real geometry points and not the translated points is wanted! */
476void OImageScrollView::viewportMouseMoveEvent(QMouseEvent* e)
477{
478 odebug << "Move X and Y " << e->x() << " " << e->y() << oendl;
479 int mx, my;
480 mx = e->x();
481 my = e->y();
482 if (_mouseStartPosX!=-1 && _mouseStartPosY!=-1) {
483 int diffx = _mouseStartPosX-mx;
484 int diffy = _mouseStartPosY-my;
485#if 0
486 QScrollBar*xbar = horizontalScrollBar();
487 QScrollBar*ybar = verticalScrollBar();
488 if (xbar->value()+diffx>xbar->maxValue()) {
489 diffx = xbar->maxValue()-xbar->value();
490 } else if (xbar->value()+diffx<0) {
491 diffx=0-xbar->value();
492 }
493 if (ybar->value()+diffy>ybar->maxValue()) {
494 diffy = ybar->maxValue()-ybar->value();
495 } else if (ybar->value()+diffy<0) {
496 diffy=0-ybar->value();
497 }
498#endif
499 scrollBy(diffx,diffy);
500 }
501 _mouseStartPosX=mx;
502 _mouseStartPosY=my;
503}
504
505void OImageScrollView::contentsMousePressEvent ( QMouseEvent * e)
506{
507 odebug << " X and Y " << e->x() << " " << e->y() << oendl;
508 /* this marks the beginning of a possible mouse move. Due internal reasons of QT
509 the geometry values here may real differ from that set in MoveEvent (I don't know
510 why). For getting them in real context, we use the first move-event to set the start
511 position ;)
512 */
513 _mouseStartPosX = -1;
514 _mouseStartPosY = -1;
515}
516
517void OImageScrollView::setDestructiveClose() {
518 WFlags fl = getWFlags();
519 /* clear it just in case */
520 fl &= ~WDestructiveClose;
521 fl |= WDestructiveClose;
522 setWFlags( fl );
523}
524
525bool OImageScrollView::image_fit_into(const QSize&s )
526{
527 if (s.width()>width()||s.height()>height()) {
528 return false;
529 }
530 return true;
531}
532
533void OImageScrollView::setShowZoomer(bool how)
534{
535 m_states.setBit(SHOW_ZOOMER,how);
536 check_zoomer();
537}
538
539bool OImageScrollView::ShowZoomer()const
540{
541 return m_states.testBit(SHOW_ZOOMER);
542}
543
544void OImageScrollView::check_zoomer()
545{
546 if (!_zoomer) return;
547 if ( (!ShowZoomer()||image_fit_into(_pdata.size()) ) && _zoomer->isVisible()) {
548 _zoomer->hide();
549 } else if ( ShowZoomer() && !image_fit_into(_pdata.size()) && _zoomer->isHidden()){
550 _zoomer->show();
551 }
552}
553
554bool OImageScrollView::FirstResizeDone()const
555{
556 return m_states.testBit(FIRST_RESIZE_DONE);
557}
558
559void OImageScrollView::setFirstResizeDone(bool how)
560{
561 m_states.setBit(FIRST_RESIZE_DONE,how);
562}
563
564bool OImageScrollView::ImageIsJpeg()const
565{
566 return m_states.testBit(IMAGE_IS_JPEG);
567}
568
569void OImageScrollView::setImageIsJpeg(bool how)
570{
571 m_states.setBit(IMAGE_IS_JPEG,how);
572}
573
574bool OImageScrollView::ImageScaledLoaded()const
575{
576 return m_states.testBit(IMAGE_SCALED_LOADED);
577}
578
579void OImageScrollView::setImageScaledLoaded(bool how)
580{
581 m_states.setBit(IMAGE_SCALED_LOADED,how);
582}
583
584} // namespace MM
585} // namespace Opie
diff --git a/libopie2/opiemm/oimagescrollview.h b/libopie2/opiemm/oimagescrollview.h
new file mode 100644
index 0000000..3d2ea38
--- a/dev/null
+++ b/libopie2/opiemm/oimagescrollview.h
@@ -0,0 +1,95 @@
1#ifndef _IMAGE_SCROLL_VIEW_H
2#define _IMAGE_SCROLL_VIEW_H
3
4#include <qscrollview.h>
5#include <qimage.h>
6#include <qpixmap.h>
7#include <qstring.h>
8#include <qdialog.h>
9#include <qbitarray.h>
10
11
12class QPainter;
13
14namespace Opie { namespace MM {
15
16 class OImageZoomer;
17
18class OImageScrollView:public QScrollView
19{
20 Q_OBJECT
21public:
22 enum Rotation {
23 Rotate0,
24 Rotate90,
25 Rotate180,
26 Rotate270
27 };
28
29 OImageScrollView( QWidget* parent, const char* name = 0, WFlags fl = 0 );
30 OImageScrollView (const QImage&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false );
31 OImageScrollView (const QString&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false );
32 virtual ~OImageScrollView();
33
34
35 virtual void setDestructiveClose();
36
37 virtual void setAutoRotate(bool);
38 virtual void setAutoScale(bool);
39 virtual void setShowZoomer(bool);
40
41 virtual bool AutoRotate()const;
42 virtual bool AutoScale()const;
43 virtual bool ShowZoomer()const;
44
45public slots:
46 virtual void setImage(const QImage&);
47 virtual void setImage( const QString& path );
48
49
50signals:
51 void imageSizeChanged( const QSize& );
52 void viewportSizeChanged( const QSize& );
53
54protected:
55 virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );
56 void init();
57
58 Opie::MM::OImageZoomer *_zoomer;
59 QImage _image_data;
60 QImage _original_data;
61 QPixmap _pdata;
62
63 int _mouseStartPosX,_mouseStartPosY;
64
65 QBitArray m_states;
66
67 Rotation m_last_rot;
68 QString m_lastName;
69 virtual void rescaleImage(int w, int h);
70
71 virtual void rotate_into_data(Rotation r);
72 virtual void generateImage();
73 virtual void loadJpeg(bool interncall = false);
74 bool image_fit_into(const QSize&s);
75 void check_zoomer();
76
77 /* internal bitset manipulation */
78 virtual bool ImageIsJpeg()const;
79 virtual void setImageIsJpeg(bool how);
80 virtual bool ImageScaledLoaded()const;
81 virtual void setImageScaledLoaded(bool how);
82 virtual bool FirstResizeDone()const;
83 virtual void setFirstResizeDone(bool how);
84
85protected slots:
86 virtual void viewportMouseMoveEvent(QMouseEvent* e);
87 virtual void contentsMousePressEvent ( QMouseEvent * e);
88 virtual void resizeEvent(QResizeEvent * e);
89 virtual void keyPressEvent(QKeyEvent * e);
90};
91
92}
93}
94
95#endif
diff --git a/libopie2/opiemm/oimagezoomer.cpp b/libopie2/opiemm/oimagezoomer.cpp
new file mode 100644
index 0000000..d1eec67
--- a/dev/null
+++ b/libopie2/opiemm/oimagezoomer.cpp
@@ -0,0 +1,233 @@
1#include "oimagezoomer.h"
2
3#include <opie2/odebug.h>
4
5#include <qimage.h>
6#include <qpixmap.h>
7#include <qpainter.h>
8#include <qrect.h>
9#include <qpoint.h>
10#include <qsize.h>
11
12namespace Opie {
13namespace MM {
14
15/**
16 * \brief The most simple c'tor
17 * The main c'tor. You still need to set a QPixmap/QIMage,
18 * setImageSize,setViewPortSize,setVisiblePoint
19 *
20 * @param parent The parent widget
21 * @param name A name for this widget
22 * @param fl The widget flags
23 *
24 */
25OImageZoomer::OImageZoomer( QWidget* parent, const char* name, WFlags fl )
26 : QFrame( parent, name, fl ) {
27 init();
28}
29
30
31/**
32 * \brief This c'tor takes a QPixmap additional
33 *
34 * You initially set the QPixmap but you still need to provide
35 * the additional data to make this widget useful
36 *
37 * @param pix A Pixmap it'll be converted to a QImage later!
38 * @param par The parent widget
39 * @param name The name of this widget
40 * @param fl The widget flags
41 */
42OImageZoomer::OImageZoomer( const QPixmap& pix, QWidget* par, const char* name, WFlags fl )
43 : QFrame( par, name, fl ) {
44 init();
45 setImage( pix );
46}
47
48
49/**
50 * \brief This c'tor takes a QImage instead
51 * You just provide a QImage which is saved. It behaves the same as the others.
52 *
53 * @param img A Image which will be used for the zoomer content
54 * @param par The parent of the widget
55 * @param name The name of the widget
56 * @param fl The widgets flags
57 */
58OImageZoomer::OImageZoomer( const QImage& img, QWidget* par, const char* name, WFlags fl)
59 : QFrame( par, name, fl ) {
60 init();
61 setImage( img );
62}
63
64
65/**
66 * \brief overloaded c'tor
67 *
68 * This differs only in the arguments it takes
69 *
70 *
71 * @param pSize The size of the Page you show
72 * @param vSize The size of the viewport. The size of the visible part of the widget
73 * @param par The parent of the widget
74 * @param name The name
75 * @param fl The window flags
76 */
77OImageZoomer::OImageZoomer( const QSize& pSize, const QSize& vSize, QWidget* par,
78 const char* name, WFlags fl )
79 : QFrame( par, name, fl ), m_imgSize( pSize ),m_visSize( vSize ) {
80 init();
81}
82
83/**
84 * d'tor
85 */
86OImageZoomer::~OImageZoomer() {
87
88}
89
90void OImageZoomer::init() {
91 m_mevent = false;
92 setFrameStyle( Panel | Sunken );
93}
94
95
96/**
97 * \brief set the page/image size
98 * Tell us the QSize of the Data you show to the user. We need this
99 * to do the calculations
100 *
101 * @param size The size of the stuff you want to zoom on
102 */
103void OImageZoomer::setImageSize( const QSize& size ) {
104 m_imgSize = size;
105 repaint();
106}
107
108/**
109 * \brief Set the size of the viewport
110 * Tell us the QSize of the viewport. The viewport is the part
111 * of the widget which is exposed on the screen
112 *
113 * @param size Te size of the viewport
114 *
115 * @see QScrollView::viewport()
116 */
117void OImageZoomer::setViewPortSize( const QSize& size ) {
118 m_visSize = size;
119 repaint();
120}
121
122/**
123 * \brief the point in the topleft corner which is currently visible
124 * Set the visible point. This most of the times relate to QScrollView::contentsX()
125 * and QScrollView::contentsY()
126 *
127 * @see setVisiblePoint(int,int)
128 */
129void OImageZoomer::setVisiblePoint( const QPoint& pt ) {
130 m_visPt = pt;
131 repaint();
132}
133
134
135/**
136 * Set the Image. The image will be resized on resizeEvent
137 * and it'll set the QPixmap background
138 *
139 * @param img The image will be stored internally and used as the background
140 */
141void OImageZoomer::setImage( const QImage& img) {
142 m_img = img;
143 resizeEvent( 0 );
144 repaint();
145}
146
147/**
148 * overloaded function it calls the QImage version
149 */
150void OImageZoomer::setImage( const QPixmap& pix) {
151 setImage( pix.convertToImage() );
152}
153
154void OImageZoomer::resizeEvent( QResizeEvent* ev ) {
155 QFrame::resizeEvent( ev );
156 setBackgroundOrigin( QWidget::WidgetOrigin );
157 // TODO Qt3 use PalettePixmap and use size
158 QPixmap pix; pix.convertFromImage( m_img.smoothScale( size().width(), size().height() ) );
159 setBackgroundPixmap( pix);
160}
161
162void OImageZoomer::drawContents( QPainter* p ) {
163 /*
164 * if the page size
165 */
166 if ( m_imgSize.isEmpty() )
167 return;
168
169 /*
170 * paint a red rect which represents the visible size
171 *
172 * We need to recalculate x,y and width and height of the
173 * rect. So image size relates to contentRect
174 *
175 */
176 QRect c( contentsRect() );
177 p->setPen( Qt::red );
178
179 /*
180 * the contentRect is set equal to the size of the image
181 * Rect/Original = NewRectORWidth/OriginalVisibleStuff and then simply we
182 * need to add the c.y/x due usage of QFrame
183 * For x and y we use the visiblePoint
184 * For height and width we use the size of the viewport
185 * if width/height would be bigger than our widget we use this width/height
186 *
187 */
188 int len = m_imgSize.width();
189 int x = (c.width()*m_visPt.x())/len + c.x();
190 int w = (c.width()*m_visSize.width() )/len + c.x();
191 if ( w > c.width() ) w = c.width();
192
193 len = m_imgSize.height();
194 int y = (c.height()*m_visPt.y() )/len + c.y();
195 int h = (c.height()*m_visSize.height() )/len + c.y();
196 if ( h > c.height() ) h = c.height();
197
198 p->drawRect( x, y, w, h );
199}
200
201void OImageZoomer::mousePressEvent( QMouseEvent*ev) {
202 m_mouseX = m_mouseY = -1;
203 m_mevent = true;
204}
205
206void OImageZoomer::mouseReleaseEvent( QMouseEvent*ev) {
207 if (!m_mevent) return;
208 int mx, my;
209 mx = ev->x();
210 my = ev->y();
211 int diffx = (mx) * m_imgSize.width() / width();
212 int diffy = (my) * m_imgSize.height() / height();
213 emit zoomArea(diffx,diffy);
214}
215
216void OImageZoomer::mouseMoveEvent( QMouseEvent* ev ) {
217 int mx, my;
218 mx = ev->x();
219 my = ev->y();
220
221 if ( m_mouseX != -1 && m_mouseY != -1 ) {
222 m_mevent = false;
223 int diffx = ( mx - m_mouseX ) * m_imgSize.width() / width();
224 int diffy = ( my - m_mouseY ) * m_imgSize.height() / height();
225 emit zoomAreaRel( diffx, diffy );
226 }
227 m_mouseX = mx;
228 m_mouseY = my;
229}
230
231
232}
233}
diff --git a/libopie2/opiemm/oimagezoomer.h b/libopie2/opiemm/oimagezoomer.h
new file mode 100644
index 0000000..0b356c9
--- a/dev/null
+++ b/libopie2/opiemm/oimagezoomer.h
@@ -0,0 +1,141 @@
1#ifndef OPIE_ODP_IMAGE_ZOOMER_H
2#define OPIE_ODP_IMAGE_ZOOMER_H
3
4#include <qframe.h>
5#include <qimage.h>
6
7class QPixmap;
8class QRect;
9class QPoint;
10
11
12namespace Opie {
13namespace MM {
14
15/**
16 * \brief small class to zoom over a Page
17 *
18 * This class represents your page but smaller.
19 * It can draw a Rect on top of an Image/Pixmap you supply
20 * and you can allow the user easily zooming/moving
21 * over your widget.
22 * All you need to do is to supply a image/pixmap, the visible size
23 * and the original image/pixmap size and the current visible top/left
24 * position.
25 *
26 * This Image works perfectly with QScrollView as you can connect
27 * QScrollView::contentsMoving to setVisiblePoint slot and the zoomAreRel
28 * to the QScrollView::scrollBy slot. Now you would only need to watch
29 * the resize event anf give us the new information about QScrollView::viewport
30 *
31 * You need to position and set the size of this widget! using setFixedSize() is quite
32 * a good idea for this widget
33 *
34 * @see QScrollView
35 * @see QScrollView::viewport()
36 *
37 * @since 1.2
38 *
39 */
40class OImageZoomer : public QFrame {
41 Q_OBJECT
42public:
43 OImageZoomer( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
44 OImageZoomer( const QPixmap&,QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
45 OImageZoomer( const QImage&, QWidget* parent = 0, const char* name= 0, WFlags fl = 0 );
46 OImageZoomer( const QSize&, const QSize&, QWidget* par, const char*, WFlags fl );
47 ~OImageZoomer();
48
49public slots:
50 void setImageSize( const QSize& );
51 void setViewPortSize( const QSize& );
52 void setVisiblePoint( const QPoint& );
53 void setVisiblePoint( int x, int y );
54 void setImage( const QImage& );
55 void setImage( const QPixmap& );
56
57signals:
58 /**
59 * Relative movement in the coordinates of the viewport
60 * This signal can easily be connected to QScrollView::scrollBy.
61 * This signal is emitted from within the mouseMoveEvent of this widget
62 *
63 *
64 * @param x The way to move relative on the X-Axis
65 * @param y The way to move relative on the Y-Axis
66 *
67 * @see setVisiblePoint
68 * @see QScrollView::scrollBy
69 */
70 void zoomAreaRel( int x,int y);
71
72 /**
73 * Here you get absolute coordinates.
74 * This slot will be emitted from within the mouseReleaseEvent of this widget.
75 * if no mouse move where done.
76 * So you may not delete this widget
77 *
78 * @param x The absolute X Coordinate to scroll to.
79 * @param y The absolute Y Coordinate to scroll to.
80 *
81 */
82 void zoomArea( int x,int y);
83
84public:
85 /**
86 * make sure to call these if you reimplement
87 * @internal
88 */
89 void resizeEvent( QResizeEvent* );
90
91protected:
92 /**
93 * make sure to call these if you reimplement
94 * @internal
95 */
96 void drawContents( QPainter* p );
97
98 /**
99 * make sure to call these if you reimplememt
100 * @internal
101 */
102 virtual void mousePressEvent( QMouseEvent* ev );
103 /**
104 * make sure to call these if you reimplement
105 * @internal
106 */
107 virtual void mouseMoveEvent( QMouseEvent* ev );
108 /**
109 * make sure to call these if you reimplement
110 * @internal
111 */
112 virtual void mouseReleaseEvent( QMouseEvent* ev );
113
114private:
115 /**
116 * @internal
117 */
118 void init();
119 QImage m_img;
120 QSize m_imgSize, m_visSize;
121 QPoint m_visPt;
122 int m_mouseX, m_mouseY;
123 bool m_mevent;
124};
125
126/**
127 * This slot is present for convience. You can connect the
128 * QScrollView::contentsMoved to this slot and it calls the QPoint
129 * version for you
130 * This realtes to QScrollView::contentsX() and QScrollView::contentsY()
131 *
132 * @param x The top left x coordinate
133 * @param y The top left y coorisnate
134 */
135inline void OImageZoomer::setVisiblePoint( int x, int y ) {
136 setVisiblePoint( QPoint( x, y ) );
137}
138
139}
140}
141#endif
diff --git a/libopie2/opiemm/opiemm.pro b/libopie2/opiemm/opiemm.pro
index f386618..09b5ed4 100644
--- a/libopie2/opiemm/opiemm.pro
+++ b/libopie2/opiemm/opiemm.pro
@@ -2,6 +2,6 @@ TEMPLATE = lib
2CONFIG += qt warn_on 2CONFIG += qt warn_on
3DESTDIR = $(OPIEDIR)/lib 3DESTDIR = $(OPIEDIR)/lib
4HEADERS = osoundsystem.h 4HEADERS = osoundsystem.h oimagezoomer.h oimagescrollview.h
5SOURCES = osoundsystem.cpp 5SOURCES = osoundsystem.cpp oimagezoomer.cpp oimagescrollview.cpp
6INTERFACES = 6INTERFACES =
7TARGET = opiemm2 7TARGET = opiemm2