-rw-r--r-- | noncore/graphics/opie-eye/gui/imagescrollview.cpp | 185 | ||||
-rw-r--r-- | noncore/graphics/opie-eye/gui/imagescrollview.h | 23 |
2 files changed, 199 insertions, 9 deletions
diff --git a/noncore/graphics/opie-eye/gui/imagescrollview.cpp b/noncore/graphics/opie-eye/gui/imagescrollview.cpp index 019f376..0d35354 100644 --- a/noncore/graphics/opie-eye/gui/imagescrollview.cpp +++ b/noncore/graphics/opie-eye/gui/imagescrollview.cpp | |||
@@ -1,105 +1,276 @@ | |||
1 | #include "imagescrollview.h" | 1 | #include "imagescrollview.h" |
2 | 2 | ||
3 | #include <opie2/odebug.h> | 3 | #include <opie2/odebug.h> |
4 | 4 | ||
5 | using namespace Opie::Core; | 5 | using namespace Opie::Core; |
6 | 6 | ||
7 | #include <qimage.h> | 7 | #include <qimage.h> |
8 | #include <qlayout.h> | 8 | #include <qlayout.h> |
9 | 9 | ||
10 | ImageScrollView::ImageScrollView (const QImage&img, QWidget * parent, const char * name, WFlags f) | 10 | ImageScrollView::ImageScrollView (const QImage&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit) |
11 | :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(img) | 11 | :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(img),scale_to_fit(always_scale), |
12 | rotate_to_fit(rfit),first_resize_done(false) | ||
12 | { | 13 | { |
13 | init(); | 14 | init(); |
14 | } | 15 | } |
15 | 16 | ||
16 | ImageScrollView::ImageScrollView (const QString&img, QWidget * parent, const char * name, WFlags f) | 17 | ImageScrollView::ImageScrollView (const QString&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit) |
17 | :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(img) | 18 | :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(img),scale_to_fit(always_scale), |
19 | rotate_to_fit(rfit),first_resize_done(false) | ||
18 | { | 20 | { |
19 | init(); | 21 | init(); |
20 | } | 22 | } |
21 | 23 | ||
22 | void ImageScrollView::setImage(const QImage&img) | 24 | void ImageScrollView::setImage(const QImage&img) |
23 | { | 25 | { |
24 | _image_data = img; | 26 | _image_data = QImage(); |
27 | _original_data=img; | ||
28 | first_resize_done = false; | ||
25 | init(); | 29 | init(); |
26 | } | 30 | } |
27 | 31 | ||
28 | /* should be called every time the QImage changed it content */ | 32 | /* should be called every time the QImage changed it content */ |
29 | void ImageScrollView::init() | 33 | void ImageScrollView::init() |
30 | { | 34 | { |
31 | viewport()->setBackgroundColor(white); | 35 | viewport()->setBackgroundColor(white); |
32 | resizeContents(_image_data.width(),_image_data.height()); | 36 | if (_original_data.size().isValid()) { |
37 | resizeContents(_original_data.width(),_original_data.height()); | ||
38 | } | ||
39 | last_rot = Rotate0; | ||
33 | } | 40 | } |
34 | 41 | ||
35 | ImageScrollView::~ImageScrollView() | 42 | ImageScrollView::~ImageScrollView() |
36 | { | 43 | { |
37 | } | 44 | } |
38 | 45 | ||
46 | void ImageScrollView::rescaleImage(int w, int h) | ||
47 | { | ||
48 | if (_image_data.width()==w && _image_data.height()==h) { | ||
49 | return; | ||
50 | } | ||
51 | double hs = (double)h / (double)_image_data.height() ; | ||
52 | double ws = (double)w / (double)_image_data.width() ; | ||
53 | double scaleFactor = (hs > ws) ? ws : hs; | ||
54 | int smoothW = (int)(scaleFactor * _image_data.width()); | ||
55 | int smoothH = (int)(scaleFactor * _image_data.height()); | ||
56 | _image_data = _image_data.smoothScale(smoothW,smoothH); | ||
57 | } | ||
58 | |||
59 | void ImageScrollView::rotate_into_data(Rotation r) | ||
60 | { | ||
61 | /* realy - we must do this that way, 'cause when acting direct on _image_data the app will | ||
62 | segfault :( */ | ||
63 | QImage dest; | ||
64 | int x, y; | ||
65 | if ( _original_data.depth() > 8 ) | ||
66 | { | ||
67 | unsigned int *srcData, *destData; | ||
68 | switch ( r ) | ||
69 | { | ||
70 | case Rotate90: | ||
71 | dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); | ||
72 | for ( y=0; y < _original_data.height(); ++y ) | ||
73 | { | ||
74 | srcData = (unsigned int *)_original_data.scanLine(y); | ||
75 | for ( x=0; x < _original_data.width(); ++x ) | ||
76 | { | ||
77 | destData = (unsigned int *)dest.scanLine(x); | ||
78 | destData[_original_data.height()-y-1] = srcData[x]; | ||
79 | } | ||
80 | } | ||
81 | break; | ||
82 | case Rotate180: | ||
83 | dest.create(_original_data.width(), _original_data.height(), _original_data.depth()); | ||
84 | for ( y=0; y < _original_data.height(); ++y ) | ||
85 | { | ||
86 | srcData = (unsigned int *)_original_data.scanLine(y); | ||
87 | destData = (unsigned int *)dest.scanLine(_original_data.height()-y-1); | ||
88 | for ( x=0; x < _original_data.width(); ++x ) | ||
89 | destData[_original_data.width()-x-1] = srcData[x]; | ||
90 | } | ||
91 | break; | ||
92 | case Rotate270: | ||
93 | dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); | ||
94 | for ( y=0; y < _original_data.height(); ++y ) | ||
95 | { | ||
96 | srcData = (unsigned int *)_original_data.scanLine(y); | ||
97 | for ( x=0; x < _original_data.width(); ++x ) | ||
98 | { | ||
99 | destData = (unsigned int *)dest.scanLine(_original_data.width()-x-1); | ||
100 | destData[y] = srcData[x]; | ||
101 | } | ||
102 | } | ||
103 | break; | ||
104 | default: | ||
105 | dest = _original_data; | ||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | unsigned char *srcData, *destData; | ||
112 | unsigned int *srcTable, *destTable; | ||
113 | switch ( r ) | ||
114 | { | ||
115 | case Rotate90: | ||
116 | dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); | ||
117 | dest.setNumColors(_original_data.numColors()); | ||
118 | srcTable = (unsigned int *)_original_data.colorTable(); | ||
119 | destTable = (unsigned int *)dest.colorTable(); | ||
120 | for ( x=0; x < _original_data.numColors(); ++x ) | ||
121 | destTable[x] = srcTable[x]; | ||
122 | for ( y=0; y < _original_data.height(); ++y ) | ||
123 | { | ||
124 | srcData = (unsigned char *)_original_data.scanLine(y); | ||
125 | for ( x=0; x < _original_data.width(); ++x ) | ||
126 | { | ||
127 | destData = (unsigned char *)dest.scanLine(x); | ||
128 | destData[_original_data.height()-y-1] = srcData[x]; | ||
129 | } | ||
130 | } | ||
131 | break; | ||
132 | case Rotate180: | ||
133 | dest.create(_original_data.width(), _original_data.height(), _original_data.depth()); | ||
134 | dest.setNumColors(_original_data.numColors()); | ||
135 | srcTable = (unsigned int *)_original_data.colorTable(); | ||
136 | destTable = (unsigned int *)dest.colorTable(); | ||
137 | for ( x=0; x < _original_data.numColors(); ++x ) | ||
138 | destTable[x] = srcTable[x]; | ||
139 | for ( y=0; y < _original_data.height(); ++y ) | ||
140 | { | ||
141 | srcData = (unsigned char *)_original_data.scanLine(y); | ||
142 | destData = (unsigned char *)dest.scanLine(_original_data.height()-y-1); | ||
143 | for ( x=0; x < _original_data.width(); ++x ) | ||
144 | destData[_original_data.width()-x-1] = srcData[x]; | ||
145 | } | ||
146 | break; | ||
147 | case Rotate270: | ||
148 | dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); | ||
149 | dest.setNumColors(_original_data.numColors()); | ||
150 | srcTable = (unsigned int *)_original_data.colorTable(); | ||
151 | destTable = (unsigned int *)dest.colorTable(); | ||
152 | for ( x=0; x < _original_data.numColors(); ++x ) | ||
153 | destTable[x] = srcTable[x]; | ||
154 | for ( y=0; y < _original_data.height(); ++y ) | ||
155 | { | ||
156 | srcData = (unsigned char *)_original_data.scanLine(y); | ||
157 | for ( x=0; x < _original_data.width(); ++x ) | ||
158 | { | ||
159 | destData = (unsigned char *)dest.scanLine(_original_data.width()-x-1); | ||
160 | destData[y] = srcData[x]; | ||
161 | } | ||
162 | } | ||
163 | break; | ||
164 | default: | ||
165 | dest = _original_data; | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | } | ||
170 | _image_data = dest; | ||
171 | } | ||
172 | |||
173 | void ImageScrollView::resizeEvent(QResizeEvent * e) | ||
174 | { | ||
175 | odebug << "ImageScrollView resizeEvent" << oendl; | ||
176 | QScrollView::resizeEvent(e); | ||
177 | Rotation r = Rotate0; | ||
178 | if (width()>height()&&_original_data.width()<_original_data.height() || | ||
179 | width()<height()&&_original_data.width()>_original_data.height()) { | ||
180 | if (rotate_to_fit) r = Rotate90; | ||
181 | } | ||
182 | odebug << " r = " << r << oendl; | ||
183 | if (scale_to_fit) { | ||
184 | if (!_image_data.size().isValid()||width()>_image_data.width()||height()>_image_data.height()) { | ||
185 | if (r==Rotate0) { | ||
186 | _image_data = _original_data; | ||
187 | } else { | ||
188 | rotate_into_data(r); | ||
189 | } | ||
190 | } | ||
191 | rescaleImage(width(),height()); | ||
192 | resizeContents(width()-10,height()-10); | ||
193 | } else if (!first_resize_done||r!=last_rot) { | ||
194 | if (r==Rotate0) { | ||
195 | _image_data = _original_data; | ||
196 | } else { | ||
197 | rotate_into_data(r); | ||
198 | } | ||
199 | last_rot = r; | ||
200 | resizeContents(_image_data.width(),_image_data.height()); | ||
201 | } | ||
202 | first_resize_done = true; | ||
203 | } | ||
204 | |||
39 | void ImageScrollView::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph) | 205 | void ImageScrollView::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph) |
40 | { | 206 | { |
41 | int w = clipw; | 207 | int w = clipw; |
42 | int h = cliph; | 208 | int h = cliph; |
43 | int x = clipx; | 209 | int x = clipx; |
44 | int y = clipy; | 210 | int y = clipy; |
45 | bool erase = false; | 211 | bool erase = false; |
46 | 212 | ||
213 | if (!_image_data.size().isValid()) { | ||
214 | p->fillRect(clipx,clipy,clipw,cliph,white); | ||
215 | return; | ||
216 | } | ||
47 | if (w>_image_data.width()) { | 217 | if (w>_image_data.width()) { |
48 | w=_image_data.width(); | 218 | w=_image_data.width(); |
49 | x = 0; | 219 | x = 0; |
50 | erase = true; | 220 | erase = true; |
51 | } else if (x+w>_image_data.width()){ | 221 | } else if (x+w>_image_data.width()){ |
52 | x = _image_data.width()-w; | 222 | x = _image_data.width()-w; |
53 | } | 223 | } |
54 | if (h>_image_data.height()) { | 224 | if (h>_image_data.height()) { |
55 | h=_image_data.height(); | 225 | h=_image_data.height(); |
56 | y = 0; | 226 | y = 0; |
57 | erase = true; | 227 | erase = true; |
58 | } else if (y+h>_image_data.height()){ | 228 | } else if (y+h>_image_data.height()){ |
59 | y = _image_data.height()-h; | 229 | y = _image_data.height()-h; |
60 | } | 230 | } |
61 | if (erase) { | 231 | if (erase||_image_data.hasAlphaBuffer()) { |
62 | p->fillRect(clipx,clipy,clipw,cliph,white); | 232 | p->fillRect(clipx,clipy,clipw,cliph,white); |
63 | } | 233 | } |
64 | p->drawImage(clipx,clipy,_image_data,x,y,w,h); | 234 | p->drawImage(clipx,clipy,_image_data,x,y,w,h); |
65 | } | 235 | } |
66 | 236 | ||
67 | /* using the real geometry points and not the translated points is wanted! */ | 237 | /* using the real geometry points and not the translated points is wanted! */ |
68 | void ImageScrollView::viewportMouseMoveEvent(QMouseEvent* e) | 238 | void ImageScrollView::viewportMouseMoveEvent(QMouseEvent* e) |
69 | { | 239 | { |
70 | int mx, my; | 240 | int mx, my; |
71 | mx = e->x(); | 241 | mx = e->x(); |
72 | my = e->y(); | 242 | my = e->y(); |
73 | int diffx = _mouseStartPosX-mx; | 243 | int diffx = _mouseStartPosX-mx; |
74 | int diffy = _mouseStartPosY-my; | 244 | int diffy = _mouseStartPosY-my; |
75 | scrollBy(diffx,diffy); | 245 | scrollBy(diffx,diffy); |
76 | _mouseStartPosX=mx; | 246 | _mouseStartPosX=mx; |
77 | _mouseStartPosY=my; | 247 | _mouseStartPosY=my; |
78 | } | 248 | } |
79 | 249 | ||
80 | void ImageScrollView::contentsMouseReleaseEvent ( QMouseEvent * e) | 250 | void ImageScrollView::contentsMouseReleaseEvent ( QMouseEvent * e) |
81 | { | 251 | { |
82 | _mouseStartPosX = e->x(); | 252 | _mouseStartPosX = e->x(); |
83 | _mouseStartPosY = e->y(); | 253 | _mouseStartPosY = e->y(); |
84 | } | 254 | } |
85 | 255 | ||
86 | void ImageScrollView::contentsMousePressEvent ( QMouseEvent * e) | 256 | void ImageScrollView::contentsMousePressEvent ( QMouseEvent * e) |
87 | { | 257 | { |
88 | _mouseStartPosX = e->x(); | 258 | _mouseStartPosX = e->x(); |
89 | _mouseStartPosY = e->y(); | 259 | _mouseStartPosY = e->y(); |
90 | } | 260 | } |
91 | 261 | ||
92 | /* for testing */ | 262 | /* for testing */ |
93 | ImageDlg::ImageDlg(const QString&fname,QWidget * parent, const char * name) | 263 | ImageDlg::ImageDlg(const QString&fname,QWidget * parent, const char * name) |
94 | :QDialog(parent,name,true,WStyle_ContextHelp) | 264 | :QDialog(parent,name,true,WStyle_ContextHelp) |
95 | { | 265 | { |
96 | QVBoxLayout*dlglayout = new QVBoxLayout(this); | 266 | QVBoxLayout*dlglayout = new QVBoxLayout(this); |
97 | dlglayout->setSpacing(2); | 267 | dlglayout->setSpacing(2); |
98 | dlglayout->setMargin(1); | 268 | dlglayout->setMargin(1); |
99 | ImageScrollView*inf = new ImageScrollView(fname,this); | 269 | ImageScrollView*inf = new ImageScrollView(fname,this); |
100 | dlglayout->addWidget(inf); | 270 | dlglayout->addWidget(inf); |
271 | odebug << "Imagedlg constructor end" << oendl; | ||
101 | } | 272 | } |
102 | 273 | ||
103 | ImageDlg::~ImageDlg() | 274 | ImageDlg::~ImageDlg() |
104 | { | 275 | { |
105 | } | 276 | } |
diff --git a/noncore/graphics/opie-eye/gui/imagescrollview.h b/noncore/graphics/opie-eye/gui/imagescrollview.h index edea235..e25f955 100644 --- a/noncore/graphics/opie-eye/gui/imagescrollview.h +++ b/noncore/graphics/opie-eye/gui/imagescrollview.h | |||
@@ -1,43 +1,62 @@ | |||
1 | #ifndef _IMAGE_SCROLL_VIEW_H | 1 | #ifndef _IMAGE_SCROLL_VIEW_H |
2 | #define _IMAGE_SCROLL_VIEW_H | 2 | #define _IMAGE_SCROLL_VIEW_H |
3 | 3 | ||
4 | #include <qscrollview.h> | 4 | #include <qscrollview.h> |
5 | #include <qimage.h> | 5 | #include <qimage.h> |
6 | #include <qstring.h> | 6 | #include <qstring.h> |
7 | #include <qdialog.h> | 7 | #include <qdialog.h> |
8 | 8 | ||
9 | class QPainter; | 9 | class QPainter; |
10 | 10 | ||
11 | class ImageScrollView:public QScrollView | 11 | class ImageScrollView:public QScrollView |
12 | { | 12 | { |
13 | Q_OBJECT | 13 | Q_OBJECT |
14 | public: | 14 | public: |
15 | ImageScrollView (const QImage&, QWidget * parent=0, const char * name=0, WFlags f=0 ); | 15 | ImageScrollView (const QImage&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false ); |
16 | ImageScrollView (const QString&, QWidget * parent=0, const char * name=0, WFlags f=0 ); | 16 | ImageScrollView (const QString&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false ); |
17 | virtual ~ImageScrollView(); | 17 | virtual ~ImageScrollView(); |
18 | 18 | ||
19 | void setImage(const QImage&); | 19 | void setImage(const QImage&); |
20 | |||
21 | enum Rotation { | ||
22 | Rotate0, | ||
23 | Rotate90, | ||
24 | Rotate180, | ||
25 | Rotate270 | ||
26 | }; | ||
27 | |||
20 | protected: | 28 | protected: |
21 | virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph ); | 29 | virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph ); |
22 | void init(); | 30 | void init(); |
23 | 31 | ||
24 | QImage _image_data; | 32 | QImage _image_data; |
33 | QImage _original_data; | ||
25 | 34 | ||
26 | int _mouseStartPosX,_mouseStartPosY; | 35 | int _mouseStartPosX,_mouseStartPosY; |
27 | 36 | ||
37 | bool scale_to_fit; | ||
38 | bool rotate_to_fit; | ||
39 | bool first_resize_done; | ||
40 | Rotation last_rot; | ||
41 | |||
42 | void rescaleImage(int w, int h); | ||
43 | |||
44 | void rotate_into_data(Rotation r); | ||
45 | |||
28 | protected slots: | 46 | protected slots: |
29 | virtual void viewportMouseMoveEvent(QMouseEvent* e); | 47 | virtual void viewportMouseMoveEvent(QMouseEvent* e); |
30 | virtual void contentsMousePressEvent ( QMouseEvent * e); | 48 | virtual void contentsMousePressEvent ( QMouseEvent * e); |
31 | virtual void contentsMouseReleaseEvent ( QMouseEvent * e); | 49 | virtual void contentsMouseReleaseEvent ( QMouseEvent * e); |
50 | virtual void resizeEvent(QResizeEvent * e); | ||
32 | }; | 51 | }; |
33 | 52 | ||
34 | /* for testing */ | 53 | /* for testing */ |
35 | class ImageDlg:public QDialog | 54 | class ImageDlg:public QDialog |
36 | { | 55 | { |
37 | Q_OBJECT | 56 | Q_OBJECT |
38 | public: | 57 | public: |
39 | ImageDlg(const QString&,QWidget * parent=0, const char * name=0); | 58 | ImageDlg(const QString&,QWidget * parent=0, const char * name=0); |
40 | virtual ~ImageDlg(); | 59 | virtual ~ImageDlg(); |
41 | }; | 60 | }; |
42 | 61 | ||
43 | #endif | 62 | #endif |