Remove this line
[kdeaccessibility.git] / kmag / kmagzoomview.cpp
blobe1afaa2dc4d6ef9731699edec89bef6c8538943d
1 /***************************************************************************
2 kmagview.cpp - description
3 -------------------
4 begin : Mon Feb 12 23:45:41 EST 2001
5 copyright : (C) 2001-2003 by Sarang Lakare
6 email : sarang#users.sourceforge.net
7 copyright : (C) 2003-2004 by Olaf Schmidt
8 email : ojschmidt@kde.org
9 copyright : (C) 2008 by Matthew Woehlke
10 email : mw_triad@users.sourceforge.net
11 ***************************************************************************/
13 /***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 ***************************************************************************/
23 // application specific includes
24 #include "kmagzoomview.h"
25 #include "kmagzoomview.moc"
26 #include "colorsim.h"
28 // include files for Qt
29 #include <QtGui/QBitmap>
30 #include <QtGui/QCursor>
31 #include <QtCore/qglobal.h>
32 #include <QtGui/QPainter>
33 #include <QtGui/QWidget>
34 #include <QtGui/QPixmap>
35 #include <QtGui/QFocusEvent>
36 #include <QtGui/QHideEvent>
37 #include <QtGui/QKeyEvent>
38 #include <QtGui/QShowEvent>
39 #include <QtGui/QResizeEvent>
40 #include <QtGui/QMouseEvent>
41 #include <QtGui/QDesktopWidget>
43 // include files for KDE
44 #include <kapplication.h>
45 #include <kcursor.h>
46 #include <kdebug.h>
47 #include <klocale.h>
49 // include bitmaps for cursors
50 static uchar left_ptr_bits[] = {
51 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
52 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01,
53 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00};
55 static uchar left_ptrmsk_bits[] = {
56 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
57 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03,
58 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03};
60 static uchar phand_bits[] = {
61 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
62 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00,
63 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00,
64 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00,
65 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
72 static uchar phandm_bits[] = {
73 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
74 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
75 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
76 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00,
77 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
78 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
86 KMagZoomView::KMagZoomView(QWidget *parent, const char *name)
87 : Q3ScrollView(parent, name),
88 m_selRect(0, 0, 128, 128, this),
89 m_grabTimer(parent),
90 m_mouseViewTimer(parent),
91 m_latestCursorPos(0,0),
92 m_followMouse(false),
93 m_showMouse(1),
94 m_zoom(1.0),
95 m_rotation(0),
96 m_fitToWindow(true)
98 KApplication::setGlobalMouseTracking(true);
99 viewport()->setMouseTracking(true);
100 viewport()->setBackgroundMode (Qt::NoBackground);
101 viewport()->setFocusPolicy(Qt::StrongFocus);
103 // init the zoom matrix
104 m_zoomMatrix.reset();
105 m_zoomMatrix.scale(m_zoom, m_zoom);
106 m_zoomMatrix.rotate(m_rotation);
108 m_ctrlKeyPressed = false;
109 m_shiftKeyPressed = false;
110 m_refreshSwitch = true;
111 m_refreshSwitchStateOnHide = m_refreshSwitch;
113 // set the refresh rate
114 setRefreshRate(10);
116 // connect it to grabFrame()
117 connect(&m_grabTimer, SIGNAL(timeout()), SLOT(grabFrame()));
118 // start the grabTimer
119 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
121 // connect it to updateMouseView()
122 connect(&m_mouseViewTimer, SIGNAL(timeout()), SLOT(updateMouseView()));
123 // start the grabTimer @ 25 frames per second!
124 m_mouseViewTimer.start(25);
126 this->setWhatsThis( i18n("This is the main window which shows the contents of the\
127 selected region. The contents will be magnified according to the zoom level that is set."));
129 // different ways to show the cursor.
130 m_showMouseTypes << "Hidden" << "Box" << "Arrow" << "Actual";
132 if(m_fitToWindow)
133 fitToWindow();
136 KMagZoomView::~KMagZoomView()
138 KApplication::setGlobalMouseTracking(true);
142 * This function will set/reset mouse following of grab window.
144 void KMagZoomView::followMouse(bool follow)
146 if(follow) {
147 m_followMouse = true;
148 m_mouseMode = Normal;
149 setVScrollBarMode (Q3ScrollView::AlwaysOff);
150 setHScrollBarMode (Q3ScrollView::AlwaysOff);
151 } else {
152 m_followMouse = false;
153 m_mouseMode = Normal;
154 setVScrollBarMode (Q3ScrollView::AlwaysOn);
155 setHScrollBarMode (Q3ScrollView::AlwaysOn);
160 * Called when the widget is hidden. Stop refresh when this happens.
162 void KMagZoomView::hideEvent( QHideEvent* )
164 // Save the state of the refresh switch.. the state will be restored
165 // when showEvent is called
166 m_refreshSwitchStateOnHide = m_refreshSwitch;
168 // Check if refresh is ON
169 if(m_refreshSwitch) {
170 toggleRefresh();
176 * Called when the widget is shown. Start refresh when this happens.
178 void KMagZoomView::showEvent( QShowEvent* )
180 // Check if refresh switch was ON when hide was called and if currently it is OFF
181 if(m_refreshSwitchStateOnHide && !m_refreshSwitch) {
182 // start the refresh in that case
183 toggleRefresh();
188 * Called when the widget is resized. Check if fitToWindow is active when this happens.
190 void KMagZoomView::resizeEvent( QResizeEvent * e )
192 Q3ScrollView::resizeEvent (e);
193 if(m_fitToWindow)
194 fitToWindow();
198 * Called when the widget is to be repainted.
200 * @param p
202 void KMagZoomView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
204 if(m_zoomedPixmap.isNull())
205 return;
207 // Paint empty areas Qt::black
208 if (contentsX()+contentsWidth() < visibleWidth())
209 p->fillRect (
210 QRect (contentsX()+contentsWidth(), clipy, visibleWidth()-contentsX()-contentsWidth(), cliph)
211 & QRect (clipx, clipy, clipw, cliph),
212 Qt::black);
213 if (contentsY()+contentsHeight() < visibleHeight())
214 p->fillRect (
215 QRect (clipx, contentsY()+contentsHeight(), clipw, visibleHeight()-contentsY()-contentsHeight())
216 & QRect (clipx, clipy, clipw, cliph),
217 Qt::black);
219 // A pixmap which will be eventually displayed
220 QPixmap *zoomView;
222 // Get mouse position relative to the image
223 QPoint mousePos = calcMousePos (m_refreshSwitch);
225 // show the pixel under mouse cursor
226 if(m_showMouse) {
228 // Pixmap which will have the zoomed pixmap + mouse
229 zoomView = new QPixmap(m_zoomedPixmap);
231 // paint the mouse cursor
232 paintMouseCursor(zoomView, mousePos);
233 } else { // do not show mouse
234 zoomView = &m_zoomedPixmap;
237 // bitBlt this part on to the widget.
238 bitBlt(viewport(), QPoint (clipx-contentsX(), clipy-contentsY()), zoomView, QRect(clipx, clipy, clipw, cliph));
240 if(zoomView != &m_zoomedPixmap)
241 delete zoomView;
245 * Draws the mouse cursor according to the current selection of the type of
246 * mouse cursor to draw.
248 void KMagZoomView::paintMouseCursor(QPaintDevice *dev, const QPoint &mousePos)
250 if(!dev)
251 return;
253 // painter for the zoom view
254 QPainter pz(dev);
256 if(m_latestCursorPos.x() >= 0 && m_latestCursorPos.x() < m_selRect.width() &&
257 m_latestCursorPos.y() >= 0 && m_latestCursorPos.y() < m_selRect.height() ) { // || updateMousePos) {
258 // mouse position is indeed inside the selRect
260 // How to show the mouse :
262 switch(m_showMouse) {
263 case 1:
264 // 1. Square around the pixel
265 pz.setPen(Qt::white);
266 #ifdef __GNUC__
267 #warning "Port Qt4 pz.setRasterOp(Qt::XorROP);";
268 #endif
269 //pz.setRasterOp(Qt::XorROP);
270 pz.drawRect(mousePos.x()-1, mousePos.y()-1, (int)m_zoom+2, (int)m_zoom+2);
271 break;
273 case 2:
275 // 2. Arrow cursor
276 pz.setPen(Qt::black);
277 pz.setBackgroundColor(Qt::white);
279 QBitmap sCursor = QBitmap::fromData( QSize(16, 16), left_ptr_bits);
280 QBitmap mask = QBitmap::fromData( QSize(16, 16), left_ptrmsk_bits);
281 sCursor.setMask(mask);
282 sCursor = sCursor.transformed(m_zoomMatrix);
284 // since hot spot is at 3,1
285 if (m_rotation == 0)
286 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
287 else if (m_rotation == 90)
288 pz.drawPixmap(mousePos.x()-(int)(16.0*m_zoom), mousePos.y()-(int)(3.0*m_zoom), sCursor);
289 else if (m_rotation == 180)
290 pz.drawPixmap(mousePos.x()-(int)(13.0*m_zoom), mousePos.y()-(int)(16.0*m_zoom), sCursor);
291 else if (m_rotation == 270)
292 pz.drawPixmap(mousePos.x()-(int)m_zoom, mousePos.y()-(int)(13.0*m_zoom), sCursor);
294 break;
296 case 3:
298 // 3. Actual cursor
299 // Get the current cursor type
300 QWidget *dummy = KApplication::topLevelAt(QCursor::pos());
301 if(!dummy)
302 break;
303 kDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-";
304 switch(this->cursor().shape()) {
305 case Qt::ArrowCursor :
307 // 2. Arrow cursor
308 pz.setPen(Qt::black);
309 pz.setBackgroundColor(Qt::white);
311 QBitmap sCursor = QBitmap::fromData( QSize(16, 16), left_ptr_bits);
312 QBitmap mask = QBitmap::fromData( QSize(16, 16), left_ptrmsk_bits);
313 sCursor.setMask(mask);
314 sCursor = sCursor.transformed(m_zoomMatrix);
316 // since hot spot is at 3,1
317 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
319 break;
320 default:
321 QBitmap sCursor = QBitmap::fromData( QSize(32, 32), phand_bits);
322 QBitmap mask = QBitmap::fromData( QSize(32, 32), phandm_bits);
323 sCursor.setMask(mask);
325 pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
326 break;
327 } // switch(cursor)
331 break;
333 default:
334 // do not show anything
335 break;
336 } // switch(m_showMouse)
341 QPoint KMagZoomView::calcMousePos(bool updateMousePos)
343 // get position of mouse wrt selRect
344 if(updateMousePos) { // get a new position only if asked
345 m_latestCursorPos = QCursor::pos();
346 m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
349 // get coordinates of the pixel w.r.t. the zoomed pixmap
350 if (m_rotation == 90)
351 return QPoint ((int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom),
352 (int)((float)m_latestCursorPos.x()*m_zoom));
353 else if (m_rotation == 180)
354 return QPoint ((int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom),
355 (int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom));
356 else if (m_rotation == 270)
357 return QPoint ((int)((float)m_latestCursorPos.y()*m_zoom),
358 (int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom));
359 else
360 return QPoint ((int)((float)m_latestCursorPos.x()*m_zoom),
361 (int)((float)m_latestCursorPos.y()*m_zoom));
365 // MOUSE ACTIONS
368 * Called when mouse is clicked inside the window.
370 * @param e
372 void KMagZoomView::mousePressEvent(QMouseEvent *e)
374 switch(e->button()) {
375 case Qt::LeftButton :
376 if(m_ctrlKeyPressed) {
377 // check if currently in resize mode
378 // don't do anything if fitToWindow is enabled
379 if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
380 // set the mode to ResizeSelection
381 m_mouseMode = ResizeSelection;
383 // set mouse cursor to "resize all direction"
384 setCursor(Qt::SizeAllCursor);
386 // backup the old position
387 m_oldMousePos.setX(e->globalX());
388 m_oldMousePos.setY(e->globalY());
390 // set the cursor position to the bottom-right of the selected region
391 QCursor::setPos(m_selRect.bottomRight());
393 // show the selection rectangle
394 m_selRect.show();
396 else {
397 // ignore this button press.. so it goes to the parent
398 e->ignore();
400 } else if(m_shiftKeyPressed) {
401 // check if currently in move mode
402 // don't do anything if follow mouse is enabled
403 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
404 m_mouseMode = MoveSelection;
406 // set mouse cursor to cross hair
407 setCursor(Qt::CrossCursor);
409 // backup the old position
410 m_oldMousePos.setX(e->globalX());
411 m_oldMousePos.setY(e->globalY());
413 // set the cursor position to the center of the selected region
414 QCursor::setPos(m_selRect.center());
416 // show the selected rectangle
417 m_selRect.show();
419 else {
420 // ignore this button press.. so it goes to the parent
421 e->ignore();
423 } else {
424 // check if currently in move mode
425 // don't do anything if follow mouse is enabled
426 if ((m_mouseMode != GrabSelection) && !m_followMouse) {
427 m_mouseMode = GrabSelection;
429 // set mouse cursor to hand
430 setCursor(Qt::PointingHandCursor);
432 // store the old position
433 m_oldMousePos.setX(e->globalX());
434 m_oldMousePos.setY(e->globalY());
436 m_oldCenter = m_selRect.center();
438 // show the selected rectangle
439 m_selRect.show();
441 else {
442 // ignore this button press.. so it goes to the parent
443 e->ignore();
446 break;
448 case Qt::MidButton :
449 // check if currently in move mode
450 // don't do anything if follow mouse is enabled
451 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
452 m_mouseMode = MoveSelection;
454 // set mouse cursor to cross hair
455 setCursor(Qt::CrossCursor);
457 // backup the old position
458 m_oldMousePos.setX(e->globalX());
459 m_oldMousePos.setY(e->globalY());
461 // set the cursor position to the center of the selected region
462 QCursor::setPos(m_selRect.center());
464 // show the selected rectangle
465 m_selRect.show();
467 else {
468 // ignore this button press.. so it goes to the parent
469 e->ignore();
471 break;
472 // do nothing
473 default:
474 // ignore this button press.. so it goes to the parent
475 e->ignore();
476 break;
482 * Called when a mouse button is released
484 * @param e
486 void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
488 switch(e->button()) {
489 case Qt::LeftButton :
490 case Qt::MidButton :
491 // check if currently in move mode
492 if(m_mouseMode == MoveSelection) {
493 // hide the selection window
494 m_selRect.hide();
495 // set the mouse mode to normal
496 m_mouseMode = Normal;
498 // restore the cursor shape
499 setCursor(Qt::ArrowCursor);
501 // restore the cursor position
502 QCursor::setPos(m_oldMousePos);
503 } else if(m_mouseMode == ResizeSelection) {
504 // hide the selection window
505 m_selRect.hide();
506 // set the mouse mode to normal
507 m_mouseMode = Normal;
509 // restore the cursor shape
510 setCursor(Qt::ArrowCursor);
512 // restore the cursor position
513 QCursor::setPos(m_oldMousePos);
514 } else if(m_mouseMode == GrabSelection) {
515 // hide the selection window
516 m_selRect.hide();
518 // set the mouse mode to normal
519 m_mouseMode = Normal;
521 // restore the cursor shape
522 setCursor(Qt::ArrowCursor);
524 break;
526 case Qt::RightButton :
527 break;
528 case Qt::NoButton :
529 break;
531 // do nothing
532 default:
539 * Called when mouse is moved inside the window
541 * @param e
543 void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
545 if(m_mouseMode == ResizeSelection) {
546 // In resize selection mode
547 // set the current mouse position as the bottom, right corner
548 m_selRect.setRight(e->globalX());
549 m_selRect.setBottom(e->globalY());
550 m_selRect.update();
551 grabFrame();
552 } else if(m_mouseMode == MoveSelection) {
553 QPoint newCenter;
555 // set new center to be the current mouse position
556 newCenter = e->globalPos();
558 // make sure the mouse position is not taking the grab window outside
559 // the display
560 if(newCenter.x() < m_selRect.width()/2) {
561 // set X to the minimum possible X
562 newCenter.setX(m_selRect.width()/2);
563 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
564 // set X to the maximum possible X
565 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
568 if(newCenter.y() < m_selRect.height()/2) {
569 // set Y to the minimum possible Y
570 newCenter.setY(m_selRect.height()/2);
571 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
572 // set Y to the maximum possible Y
573 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
575 // move to the new center
576 m_selRect.moveCenter(newCenter);
577 // update the grab rectangle display
578 m_selRect.update();
579 grabFrame();
580 } else if(m_mouseMode == GrabSelection) {
581 QPoint newPos;
583 // get new position
584 newPos = e->globalPos();
586 QPoint delta = (newPos - m_oldMousePos)/m_zoom;
587 QPoint newCenter = m_oldCenter-delta;
589 // make sure the mouse position is not taking the grab window outside
590 // the display
591 if(newCenter.x() < m_selRect.width()/2) {
592 // set X to the minimum possible X
593 newCenter.setX(m_selRect.width()/2);
594 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
595 // set X to the maximum possible X
596 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
599 if(newCenter.y() < m_selRect.height()/2) {
600 // set Y to the minimum possible Y
601 newCenter.setY(m_selRect.height()/2);
602 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
603 // set Y to the maximum possible Y
604 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
607 // move to the new center
608 m_selRect.moveCenter(newCenter);
609 // update the grab rectangle display
610 m_selRect.update();
611 grabFrame();
615 void KMagZoomView::keyPressEvent(QKeyEvent *e)
617 int offset = 16;
618 if (e->state() & Qt::ShiftModifier)
619 offset = 1;
621 if (e->key() == Qt::Key_Control)
622 m_ctrlKeyPressed = true;
623 else if (e->key() == Qt::Key_Shift)
624 m_shiftKeyPressed = true;
625 else if (e->key() == Qt::Key_Left)
627 if (e->state() & Qt::ControlModifier)
629 if (offset >= m_selRect.width())
630 m_selRect.setWidth (1);
631 else
632 m_selRect.setWidth (m_selRect.width()-offset);
634 else if (contentsX() > 0)
636 offset = (int)(offset*m_zoom);
637 if (contentsX() > offset)
638 setContentsPos (contentsX()-offset, contentsY());
639 else
640 setContentsPos (0, contentsY());
642 else if (m_followMouse == false)
644 if (offset > m_selRect.x())
645 m_selRect.setX (0);
646 else
647 m_selRect.translate (-offset,0);
649 m_selRect.update();
651 else if (e->key() == Qt::Key_Right)
653 if (e->state() & Qt::ControlModifier)
655 if (m_selRect.right()+offset >= QApplication::desktop()->width())
656 m_selRect.setRight (QApplication::desktop()->width()-1);
657 else
658 m_selRect.setRight (m_selRect.right()+offset);
660 else if (contentsX() < contentsWidth()-visibleWidth())
662 offset = (int)(offset*m_zoom);
663 if (contentsX()+offset < contentsWidth()-visibleWidth())
664 setContentsPos (contentsX()+offset, contentsY());
665 else
666 setContentsPos (contentsWidth()-visibleWidth(), contentsY());
668 else if (m_followMouse == false)
670 if (m_selRect.right()+offset >= QApplication::desktop()->width())
671 m_selRect.moveTopRight (QPoint (QApplication::desktop()->width()-1, m_selRect.top()));
672 else
673 m_selRect.translate (offset,0);
675 m_selRect.update();
677 else if (e->key() == Qt::Key_Up)
679 if (e->state() & Qt::ControlModifier)
681 if (offset >= m_selRect.height())
682 m_selRect.setHeight (1);
683 else
684 m_selRect.setHeight (m_selRect.height()-offset);
686 else if (contentsY() > 0)
688 offset = (int)(offset*m_zoom);
689 if (contentsY() > offset)
690 setContentsPos (contentsX(), contentsY()-offset);
691 else
692 setContentsPos (contentsX(), 0);
694 else if (m_followMouse == false)
696 if (offset > m_selRect.y())
697 m_selRect.setY (0);
698 else
699 m_selRect.translate (0, -offset);
701 m_selRect.update();
703 else if (e->key() == Qt::Key_Down)
705 if (e->state() & Qt::ControlModifier)
707 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
708 m_selRect.setBottom (QApplication::desktop()->height()-1);
709 else
710 m_selRect.setBottom (m_selRect.bottom()+offset);
712 else if (contentsY() < contentsHeight()-visibleHeight())
714 offset = (int)(offset*m_zoom);
715 if (contentsY()+offset < contentsHeight()-visibleHeight())
716 setContentsPos (contentsX(), contentsY()+offset);
717 else
718 setContentsPos (contentsX(), contentsHeight()-visibleHeight());
720 else if (m_followMouse == false)
722 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
723 m_selRect.moveBottomLeft (QPoint (m_selRect.left(), QApplication::desktop()->height()-1));
724 else
725 m_selRect.translate (0, offset);
727 m_selRect.update();
729 else
730 e->ignore();
733 void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
735 if (e->key() == Qt::Key_Control)
736 m_ctrlKeyPressed = false;
737 else if (e->key() == Qt::Key_Shift)
738 m_shiftKeyPressed = false;
739 else
740 e->ignore();
743 void KMagZoomView::focusOutEvent(QFocusEvent *e)
745 if(e->lostFocus() == true) {
746 m_ctrlKeyPressed = false;
747 m_shiftKeyPressed = false;
751 // SLOTS
754 * This will fit the zoom view to the view window, thus using the maximum
755 * possible space in the window.
757 void KMagZoomView::fitToWindow()
759 unsigned int newWidth, newHeight;
761 // this is a temporary solution, cast, maybe newWidth and newHeight should be float
762 if ((m_rotation == 90) || (m_rotation == 270))
764 newWidth = static_cast<unsigned int>(visibleHeight()/m_zoom);
765 newHeight = static_cast<unsigned int>(visibleWidth()/m_zoom);
766 } else {
767 newWidth = static_cast<unsigned int>(visibleWidth()/m_zoom);
768 newHeight = static_cast<unsigned int>(visibleHeight()/m_zoom);
771 QPoint currCenter = m_selRect.center();
773 m_selRect.setWidth(newWidth);
774 m_selRect.setHeight(newHeight);
776 // make sure the selection window does not go outside of the display
777 if(currCenter.x() < m_selRect.width()/2) {
778 // set X to the minimum possible X
779 currCenter.setX(m_selRect.width()/2);
780 } else if(currCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
781 // set X to the maximum possible X
782 currCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
785 if(currCenter.y() < m_selRect.height()/2) {
786 // set Y to the minimum possible Y
787 currCenter.setY(m_selRect.height()/2);
788 } else if(currCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
789 // set Y to the maximum possible Y
790 currCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
793 m_selRect.moveCenter(currCenter);
794 // update the grab rectangle display
795 m_selRect.update();
796 // m_fitToWindow = true;
797 viewport()->repaint(false);
800 void KMagZoomView::setFitToWindow(bool fit)
802 m_fitToWindow = fit;
803 if (fit)
804 fitToWindow();
809 * Grabs frame from X
811 void KMagZoomView::grabFrame()
813 // check refresh status
814 if (!m_refreshSwitch)
815 return;
817 // check if follow-mouse is enabled
818 if(m_followMouse && (m_mouseMode != ResizeSelection)) {
819 // in this case grab w.r.t the current mouse position
820 QPoint newCenter;
822 // set new center to be the current mouse position
823 newCenter = QCursor::pos();
825 // make sure the mouse position is not taking the grab window outside
826 // the display
827 if(newCenter.x() < m_selRect.width()/2) {
828 // set X to the minimum possible X
829 newCenter.setX(m_selRect.width()/2);
830 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
831 // set X to the maximum possible X
832 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
835 if(newCenter.y() < m_selRect.height()/2) {
836 // set Y to the minimum possible Y
837 newCenter.setY(m_selRect.height()/2);
838 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
839 // set Y to the maximum possible Y
840 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
842 // move to the new center
843 m_selRect.moveCenter(newCenter);
845 // update the grab rectangle display
846 m_selRect.update();
849 //QRect r = pixmapRect();
851 // define a normalized rectangle
852 QRect selRect = m_selRect.normalized();
854 // grab screenshot from the screen and put it in the pixmap
855 m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
856 selRect.width(), selRect.height());
858 // colorize the grabbed pixmap, if applicable - TODO
859 if (m_colormode == 0)
860 m_coloredPixmap = m_grabbedPixmap;
861 else
862 m_coloredPixmap = ColorSim::recolor(m_grabbedPixmap, m_colormode);
864 // zoom the image
865 m_zoomedPixmap = m_coloredPixmap.transformed(m_zoomMatrix);
867 // call repaint to display the newly grabbed image
868 resizeContents (m_zoomedPixmap.width(), m_zoomedPixmap.height());
869 viewport()->repaint(false);
874 * Updates the mouse cursor in the zoom view.
876 void KMagZoomView::updateMouseView()
878 QPoint pos(QCursor::pos());
879 if(m_selRect.left() <= pos.x() && pos.x() <= m_selRect.right() &&
880 m_selRect.top() <= pos.y() && pos.y() <= m_selRect.bottom() &&
881 m_refreshSwitch)
882 viewport()->repaint(false);
886 * Toggles the state of refreshing.
888 void KMagZoomView::toggleRefresh()
890 if(m_refreshSwitch) {
891 m_refreshSwitch = false;
892 m_grabTimer.stop();
893 m_mouseViewTimer.stop();
894 } else {
895 m_refreshSwitch = true;
896 m_grabTimer.start(1000/m_fps);
897 m_mouseViewTimer.start(40);
902 * This function sets the zoom value to be used.
904 void KMagZoomView::setZoom(float zoom)
906 // use this zoom
907 m_zoom = zoom;
909 // update selection window size when zooming in if necessary
910 if (m_fitToWindow)
911 fitToWindow();
913 // recompute the zoom matrix
914 m_zoomMatrix.reset();
915 m_zoomMatrix.scale(m_zoom, m_zoom);
916 m_zoomMatrix.rotate(m_rotation);
918 m_zoomedPixmap = m_coloredPixmap.transformed(m_zoomMatrix);
920 viewport()->repaint();
924 * This function sets the rotation value to be used.
926 void KMagZoomView::setRotation(int rotation)
928 // use this rotation
929 m_rotation = rotation;
931 // update selection window size if necessary
932 if (m_fitToWindow)
933 fitToWindow();
935 // recompute the zoom matrix
936 m_zoomMatrix.reset();
937 m_zoomMatrix.scale(m_zoom, m_zoom);
938 m_zoomMatrix.rotate(m_rotation);
940 m_zoomedPixmap = m_coloredPixmap.transformed(m_zoomMatrix);
942 viewport()->repaint();
946 * Set a new color simulation mode.
948 void KMagZoomView::setColorMode(int mode)
950 if (m_colormode != mode) {
951 m_colormode = mode;
952 viewport()->repaint();
957 * Set a new refresh rate.
959 void KMagZoomView::setRefreshRate(float fps)
961 if(fps < 0.1)
962 return;
963 m_fps = static_cast<unsigned int>(fps);
965 if(m_grabTimer.isActive())
966 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
969 void KMagZoomView::showSelRect(bool show)
971 m_selRect.alwaysVisible(show);
972 if(show) {
973 m_selRect.show();
974 } else if(m_mouseMode == Normal) {
975 m_selRect.hide();
980 * Sets the selection rectangle to the given position.
982 void KMagZoomView::setSelRectPos(const QRect & rect)
984 m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height());
985 m_selRect.update();
986 grabFrame();
989 bool KMagZoomView::showMouse(unsigned int type)
991 if(type > m_showMouseTypes.count()-1)
992 return (false);
993 else
994 m_showMouse = type;
996 return(true);
999 unsigned int KMagZoomView::getShowMouseType() const
1001 return (m_showMouse);
1004 QStringList KMagZoomView::getShowMouseStringList() const
1006 return (m_showMouseTypes);
1011 * Returns the image which is being displayed. It's again drawn by adding
1012 * the mouse cursor if needed.
1014 QPixmap KMagZoomView::getPixmap()
1016 // show the pixel under mouse cursor
1017 if(m_showMouse && !m_zoomedPixmap.isNull()) {
1018 // Pixmap which will have the zoomed pixmap + mouse
1019 QPixmap zoomView(m_zoomedPixmap);
1021 // paint the mouse cursor w/o updating to a newer position
1022 paintMouseCursor(&zoomView, calcMousePos(false));
1024 return(zoomView);
1025 } else { // no mouse cursor
1026 return(m_zoomedPixmap);