Adapt to new kde4 api
[kdeaccessibility.git] / kmag / kmagzoomview.cpp
blobd730f2c1fc343c7f1a198e90ff04402319fc531b
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 ***************************************************************************/
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
21 // application specific includes
22 #include "kmagzoomview.h"
23 #include "kmagzoomview.moc"
25 // include files for Qt
26 #include <qbitmap.h>
27 #include <qcursor.h>
28 #include <qglobal.h>
29 #include <qpainter.h>
31 #include <qwidget.h>
32 //Added by qt3to4:
33 #include <QPixmap>
34 #include <QFocusEvent>
35 #include <QHideEvent>
36 #include <QKeyEvent>
37 #include <QShowEvent>
38 #include <QResizeEvent>
39 #include <QMouseEvent>
40 #include <QDesktopWidget>
41 // include files for KDE
42 #include <kapplication.h>
43 #include <kcursor.h>
44 #include <kdebug.h>
45 #include <klocale.h>
47 // include bitmaps for cursors
48 static uchar left_ptr_bits[] = {
49 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
50 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01,
51 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00};
53 static uchar left_ptrmsk_bits[] = {
54 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
55 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03,
56 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03};
58 static uchar phand_bits[] = {
59 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
60 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00,
61 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00,
62 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00,
63 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 };
70 static uchar phandm_bits[] = {
71 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
72 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
73 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
74 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00,
75 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
76 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 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 };
84 KMagZoomView::KMagZoomView(QWidget *parent, const char *name)
85 : Q3ScrollView(parent, name),
86 m_selRect(0, 0, 128, 128, this),
87 m_grabTimer(parent),
88 m_mouseViewTimer(parent),
89 m_latestCursorPos(0,0),
90 m_followMouse(false),
91 m_showMouse(1),
92 m_zoom(1.0),
93 m_rotation(0),
94 m_fitToWindow(true)
96 KApplication::setGlobalMouseTracking(TRUE);
97 viewport()->setMouseTracking(TRUE);
98 viewport()->setBackgroundMode (Qt::NoBackground);
99 viewport()->setFocusPolicy(Qt::StrongFocus);
101 // init the zoom matrix
102 m_zoomMatrix.reset();
103 m_zoomMatrix.scale(m_zoom, m_zoom);
104 m_zoomMatrix.rotate(m_rotation);
106 m_ctrlKeyPressed = false;
107 m_shiftKeyPressed = false;
108 m_refreshSwitch = true;
109 m_refreshSwitchStateOnHide = m_refreshSwitch;
111 // set the refresh rate
112 setRefreshRate(10);
114 // connect it to grabFrame()
115 connect(&m_grabTimer, SIGNAL(timeout()), SLOT(grabFrame()));
116 // start the grabTimer
117 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
119 // connect it to updateMouseView()
120 connect(&m_mouseViewTimer, SIGNAL(timeout()), SLOT(updateMouseView()));
121 // start the grabTimer @ 25 frames per second!
122 m_mouseViewTimer.start(25);
124 this->setWhatsThis( i18n("This is the main window which shows the contents of the\
125 selected region. The contents will be magnified according to the zoom level that is set."));
127 // different ways to show the cursor.
128 m_showMouseTypes << "Hidden" << "Box" << "Arrow" << "Actual";
130 if(m_fitToWindow)
131 fitToWindow();
134 KMagZoomView::~KMagZoomView()
136 KApplication::setGlobalMouseTracking(FALSE);
140 * This function will set/reset mouse following of grab window.
142 void KMagZoomView::followMouse(bool follow)
144 if(follow) {
145 m_followMouse = true;
146 m_mouseMode = Normal;
147 setVScrollBarMode (Q3ScrollView::AlwaysOff);
148 setHScrollBarMode (Q3ScrollView::AlwaysOff);
149 } else {
150 m_followMouse = false;
151 m_mouseMode = Normal;
152 setVScrollBarMode (Q3ScrollView::AlwaysOn);
153 setHScrollBarMode (Q3ScrollView::AlwaysOn);
158 * Called when the widget is hidden. Stop refresh when this happens.
160 void KMagZoomView::hideEvent( QHideEvent* )
162 // Save the state of the refresh switch.. the state will be restored
163 // when showEvent is called
164 m_refreshSwitchStateOnHide = m_refreshSwitch;
166 // Check if refresh is ON
167 if(m_refreshSwitch) {
168 toggleRefresh();
174 * Called when the widget is shown. Start refresh when this happens.
176 void KMagZoomView::showEvent( QShowEvent* )
178 // Check if refresh switch was ON when hide was called and if currently it is OFF
179 if(m_refreshSwitchStateOnHide && !m_refreshSwitch) {
180 // start the refresh in that case
181 toggleRefresh();
186 * Called when the widget is resized. Check if fitToWindow is active when this happens.
188 void KMagZoomView::resizeEvent( QResizeEvent * e )
190 Q3ScrollView::resizeEvent (e);
191 if(m_fitToWindow)
192 fitToWindow();
196 * Called when the widget is to be repainted
198 * @param p
200 void KMagZoomView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
202 if(m_grabbedZoomedPixmap.isNull())
203 return;
205 // Paint empty areas Qt::black
206 if (contentsX()+contentsWidth() < visibleWidth())
207 p->fillRect (
208 QRect (contentsX()+contentsWidth(), clipy, visibleWidth()-contentsX()-contentsWidth(), cliph)
209 & QRect (clipx, clipy, clipw, cliph),
210 Qt::black);
211 if (contentsY()+contentsHeight() < visibleHeight())
212 p->fillRect (
213 QRect (clipx, contentsY()+contentsHeight(), clipw, visibleHeight()-contentsY()-contentsHeight())
214 & QRect (clipx, clipy, clipw, cliph),
215 Qt::black);
217 // A pixmap which will be eventually displayed
218 QPixmap *zoomView;
220 // Get mouse position relative to the image
221 QPoint mousePos = calcMousePos (m_refreshSwitch);
223 // show the pixel under mouse cursor
224 if(m_showMouse) {
226 // Pixmap which will have the zoomed pixmap + mouse
227 zoomView = new QPixmap(m_grabbedZoomedPixmap);
229 // paint the mouse cursor
230 paintMouseCursor(zoomView, mousePos);
231 } else { // do not show mouse
232 zoomView = &m_grabbedZoomedPixmap;
235 // bitBlt this part on to the widget.
236 bitBlt(viewport(), QPoint (clipx-contentsX(), clipy-contentsY()), zoomView, QRect(clipx, clipy, clipw, cliph));
238 if(zoomView != &m_grabbedZoomedPixmap)
239 delete zoomView;
243 * Draws the mouse cursor according to the current selection of the type of
244 * mouse cursor to draw.
246 void KMagZoomView::paintMouseCursor(QPaintDevice *dev, QPoint mousePos)
248 if(!dev)
249 return;
251 // painter for the zoom view
252 QPainter pz(dev);
254 if(m_latestCursorPos.x() >= 0 && m_latestCursorPos.x() < m_selRect.width() &&
255 m_latestCursorPos.y() >= 0 && m_latestCursorPos.y() < m_selRect.height() ) { // || updateMousePos) {
256 // mouse position is indeed inside the selRect
258 // How to show the mouse :
260 switch(m_showMouse) {
261 case 1:
262 // 1. Square around the pixel
263 pz.setPen(Qt::white);
264 #warning "Port Qt4 pz.setRasterOp(Qt::XorROP);";
265 //pz.setRasterOp(Qt::XorROP);
266 pz.drawRect(mousePos.x()-1, mousePos.y()-1, (int)m_zoom+2, (int)m_zoom+2);
267 break;
269 case 2:
271 // 2. Arrow cursor
272 pz.setPen(Qt::black);
273 pz.setBackgroundColor(Qt::white);
275 QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
276 QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
277 sCursor.setMask(mask);
278 sCursor = sCursor.xForm(m_zoomMatrix);
280 // since hot spot is at 3,1
281 if (m_rotation == 0)
282 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
283 else if (m_rotation == 90)
284 pz.drawPixmap(mousePos.x()-(int)(16.0*m_zoom), mousePos.y()-(int)(3.0*m_zoom), sCursor);
285 else if (m_rotation == 180)
286 pz.drawPixmap(mousePos.x()-(int)(13.0*m_zoom), mousePos.y()-(int)(16.0*m_zoom), sCursor);
287 else if (m_rotation == 270)
288 pz.drawPixmap(mousePos.x()-(int)m_zoom, mousePos.y()-(int)(13.0*m_zoom), sCursor);
290 break;
292 case 3:
294 // 3. Actual cursor
295 // Get the current cursor type
296 QWidget *dummy = KApplication::widgetAt(QCursor::pos(), FALSE);
297 if(!dummy)
298 break;
299 kdDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-" << endl;
300 switch(this->cursor().shape()) {
301 case Qt::ArrowCursor :
303 // 2. Arrow cursor
304 pz.setPen(Qt::black);
305 pz.setBackgroundColor(Qt::white);
307 QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
308 QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
309 sCursor.setMask(mask);
310 sCursor = sCursor.xForm(m_zoomMatrix);
312 // since hot spot is at 3,1
313 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
315 break;
316 default:
317 QBitmap sCursor( 32, 32, phand_bits, TRUE );
318 QBitmap mask( 32, 32, phandm_bits, TRUE );
319 sCursor.setMask(mask);
321 pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
322 break;
323 } // switch(cursor)
327 break;
329 default:
330 // do not show anything
331 break;
332 } // switch(m_showMouse)
337 QPoint KMagZoomView::calcMousePos(bool updateMousePos)
339 // get position of mouse wrt selRect
340 if(updateMousePos) { // get a new position only if asked
341 m_latestCursorPos = QCursor::pos();
342 m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
345 // get coordinates of the pixel w.r.t. the zoomed pixmap
346 if (m_rotation == 90)
347 return QPoint ((int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom),
348 (int)((float)m_latestCursorPos.x()*m_zoom));
349 else if (m_rotation == 180)
350 return QPoint ((int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom),
351 (int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom));
352 else if (m_rotation == 270)
353 return QPoint ((int)((float)m_latestCursorPos.y()*m_zoom),
354 (int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom));
355 else
356 return QPoint ((int)((float)m_latestCursorPos.x()*m_zoom),
357 (int)((float)m_latestCursorPos.y()*m_zoom));
361 // MOUSE ACTIONS
364 * Called when mouse is clicked inside the window
366 * @param e
368 void KMagZoomView::mousePressEvent(QMouseEvent *e)
370 switch(e->button()) {
371 case Qt::LeftButton :
372 if(m_ctrlKeyPressed) {
373 // check if currently in resize mode
374 // don't do anything if fitToWindow is enabled
375 if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
376 // set the mode to ResizeSelection
377 m_mouseMode = ResizeSelection;
379 // set mouse cursor to "resize all direction"
380 setCursor(Qt::SizeAllCursor);
382 // backup the old position
383 m_oldMousePos.setX(e->globalX());
384 m_oldMousePos.setY(e->globalY());
386 // set the cursor position to the bottom-right of the selected region
387 QCursor::setPos(m_selRect.bottomRight());
389 // show the selection rectangle
390 m_selRect.show();
392 else {
393 // ignore this button press.. so it goes to the parent
394 e->ignore();
396 } else if(m_shiftKeyPressed) {
397 // check if currently in move mode
398 // don't do anything if follow mouse is enabled
399 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
400 m_mouseMode = MoveSelection;
402 // set mouse cursor to cross hair
403 setCursor(Qt::CrossCursor);
405 // backup the old position
406 m_oldMousePos.setX(e->globalX());
407 m_oldMousePos.setY(e->globalY());
409 // set the cursor position to the center of the selected region
410 QCursor::setPos(m_selRect.center());
412 // show the selected rectangle
413 m_selRect.show();
415 else {
416 // ignore this button press.. so it goes to the parent
417 e->ignore();
419 } else {
420 // check if currently in move mode
421 // don't do anything if follow mouse is enabled
422 if ((m_mouseMode != GrabSelection) && !m_followMouse) {
423 m_mouseMode = GrabSelection;
425 // set mouse cursor to hand
426 setCursor(KCursor::handCursor());
428 // store the old position
429 m_oldMousePos.setX(e->globalX());
430 m_oldMousePos.setY(e->globalY());
432 m_oldCenter = m_selRect.center();
434 // show the selected rectangle
435 m_selRect.show();
437 else {
438 // ignore this button press.. so it goes to the parent
439 e->ignore();
442 break;
444 case Qt::MidButton :
445 // check if currently in move mode
446 // don't do anything if follow mouse is enabled
447 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
448 m_mouseMode = MoveSelection;
450 // set mouse cursor to cross hair
451 setCursor(Qt::CrossCursor);
453 // backup the old position
454 m_oldMousePos.setX(e->globalX());
455 m_oldMousePos.setY(e->globalY());
457 // set the cursor position to the center of the selected region
458 QCursor::setPos(m_selRect.center());
460 // show the selected rectangle
461 m_selRect.show();
463 else {
464 // ignore this button press.. so it goes to the parent
465 e->ignore();
467 break;
468 // do nothing
469 default:
470 // ignore this button press.. so it goes to the parent
471 e->ignore();
472 break;
478 * Called when a mouse button is released
480 * @param e
482 void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
484 switch(e->button()) {
485 case Qt::LeftButton :
486 case Qt::MidButton :
487 // check if currently in move mode
488 if(m_mouseMode == MoveSelection) {
489 // hide the selection window
490 m_selRect.hide();
491 // set the mouse mode to normal
492 m_mouseMode = Normal;
494 // restore the cursor shape
495 setCursor(Qt::ArrowCursor);
497 // restore the cursor position
498 QCursor::setPos(m_oldMousePos);
499 } else if(m_mouseMode == ResizeSelection) {
500 // hide the selection window
501 m_selRect.hide();
502 // set the mouse mode to normal
503 m_mouseMode = Normal;
505 // restore the cursor shape
506 setCursor(Qt::ArrowCursor);
508 // restore the cursor position
509 QCursor::setPos(m_oldMousePos);
510 } else if(m_mouseMode == GrabSelection) {
511 // hide the selection window
512 m_selRect.hide();
514 // set the mouse mode to normal
515 m_mouseMode = Normal;
517 // restore the cursor shape
518 setCursor(Qt::ArrowCursor);
520 break;
522 case Qt::RightButton :
523 break;
524 case Qt::NoButton :
525 break;
527 // do nothing
528 default:
535 * Called when mouse is moved inside the window
537 * @param e
539 void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
541 if(m_mouseMode == ResizeSelection) {
542 // In resize selection mode
543 // set the current mouse position as the bottom, right corner
544 m_selRect.setRight(e->globalX());
545 m_selRect.setBottom(e->globalY());
546 m_selRect.update();
547 grabFrame();
548 } else if(m_mouseMode == MoveSelection) {
549 QPoint newCenter;
551 // set new center to be the current mouse position
552 newCenter = e->globalPos();
554 // make sure the mouse position is not taking the grab window outside
555 // the display
556 if(newCenter.x() < m_selRect.width()/2) {
557 // set X to the minimum possible X
558 newCenter.setX(m_selRect.width()/2);
559 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
560 // set X to the maximum possible X
561 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
564 if(newCenter.y() < m_selRect.height()/2) {
565 // set Y to the minimum possible Y
566 newCenter.setY(m_selRect.height()/2);
567 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
568 // set Y to the maximum possible Y
569 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
571 // move to the new center
572 m_selRect.moveCenter(newCenter);
573 // update the grab rectangle display
574 m_selRect.update();
575 grabFrame();
576 } else if(m_mouseMode == GrabSelection) {
577 QPoint newPos;
579 // get new position
580 newPos = e->globalPos();
582 QPoint delta = (newPos - m_oldMousePos)/m_zoom;
583 QPoint newCenter = m_oldCenter-delta;
585 // make sure the mouse position is not taking the grab window outside
586 // the display
587 if(newCenter.x() < m_selRect.width()/2) {
588 // set X to the minimum possible X
589 newCenter.setX(m_selRect.width()/2);
590 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
591 // set X to the maximum possible X
592 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
595 if(newCenter.y() < m_selRect.height()/2) {
596 // set Y to the minimum possible Y
597 newCenter.setY(m_selRect.height()/2);
598 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
599 // set Y to the maximum possible Y
600 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
603 // move to the new center
604 m_selRect.moveCenter(newCenter);
605 // update the grab rectangle display
606 m_selRect.update();
607 grabFrame();
611 void KMagZoomView::keyPressEvent(QKeyEvent *e)
613 int offset = 16;
614 if (e->state() & Qt::ShiftModifier)
615 offset = 1;
617 if (e->key() == Qt::Key_Control)
618 m_ctrlKeyPressed = true;
619 else if (e->key() == Qt::Key_Shift)
620 m_shiftKeyPressed = true;
621 else if (e->key() == Qt::Key_Left)
623 if (e->state() & Qt::ControlModifier)
625 if (offset >= m_selRect.width())
626 m_selRect.setWidth (1);
627 else
628 m_selRect.setWidth (m_selRect.width()-offset);
630 else if (contentsX() > 0)
632 offset = (int)(offset*m_zoom);
633 if (contentsX() > offset)
634 setContentsPos (contentsX()-offset, contentsY());
635 else
636 setContentsPos (0, contentsY());
638 else if (m_followMouse == false)
640 if (offset > m_selRect.x())
641 m_selRect.setX (0);
642 else
643 m_selRect.moveBy (-offset,0);
645 m_selRect.update();
647 else if (e->key() == Qt::Key_Right)
649 if (e->state() & Qt::ControlModifier)
651 if (m_selRect.right()+offset >= QApplication::desktop()->width())
652 m_selRect.setRight (QApplication::desktop()->width()-1);
653 else
654 m_selRect.setRight (m_selRect.right()+offset);
656 else if (contentsX() < contentsWidth()-visibleWidth())
658 offset = (int)(offset*m_zoom);
659 if (contentsX()+offset < contentsWidth()-visibleWidth())
660 setContentsPos (contentsX()+offset, contentsY());
661 else
662 setContentsPos (contentsWidth()-visibleWidth(), contentsY());
664 else if (m_followMouse == false)
666 if (m_selRect.right()+offset >= QApplication::desktop()->width())
667 m_selRect.moveTopRight (QPoint (QApplication::desktop()->width()-1, m_selRect.top()));
668 else
669 m_selRect.moveBy (offset,0);
671 m_selRect.update();
673 else if (e->key() == Qt::Key_Up)
675 if (e->state() & Qt::ControlModifier)
677 if (offset >= m_selRect.height())
678 m_selRect.setHeight (1);
679 else
680 m_selRect.setHeight (m_selRect.height()-offset);
682 else if (contentsY() > 0)
684 offset = (int)(offset*m_zoom);
685 if (contentsY() > offset)
686 setContentsPos (contentsX(), contentsY()-offset);
687 else
688 setContentsPos (contentsX(), 0);
690 else if (m_followMouse == false)
692 if (offset > m_selRect.y())
693 m_selRect.setY (0);
694 else
695 m_selRect.moveBy (0, -offset);
697 m_selRect.update();
699 else if (e->key() == Qt::Key_Down)
701 if (e->state() & Qt::ControlModifier)
703 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
704 m_selRect.setBottom (QApplication::desktop()->height()-1);
705 else
706 m_selRect.setBottom (m_selRect.bottom()+offset);
708 else if (contentsY() < contentsHeight()-visibleHeight())
710 offset = (int)(offset*m_zoom);
711 if (contentsY()+offset < contentsHeight()-visibleHeight())
712 setContentsPos (contentsX(), contentsY()+offset);
713 else
714 setContentsPos (contentsX(), contentsHeight()-visibleHeight());
716 else if (m_followMouse == false)
718 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
719 m_selRect.moveBottomLeft (QPoint (m_selRect.left(), QApplication::desktop()->height()-1));
720 else
721 m_selRect.moveBy (0, offset);
723 m_selRect.update();
725 else
726 e->ignore();
729 void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
731 if (e->key() == Qt::Key_Control)
732 m_ctrlKeyPressed = false;
733 else if (e->key() == Qt::Key_Shift)
734 m_shiftKeyPressed = false;
735 else
736 e->ignore();
739 void KMagZoomView::focusOutEvent(QFocusEvent *e)
741 if(e->lostFocus() == TRUE) {
742 m_ctrlKeyPressed = false;
743 m_shiftKeyPressed = false;
747 // SLOTS
750 * This will fit the zoom view to the view window, thus using the maximum
751 * possible space in the window.
753 void KMagZoomView::fitToWindow()
755 unsigned int newWidth, newHeight;
757 // this is a temporary solution, cast, maybe newWidth and newHeight should be float
758 if ((m_rotation == 90) || (m_rotation == 270))
760 newWidth = static_cast<unsigned int>(visibleHeight()/m_zoom);
761 newHeight = static_cast<unsigned int>(visibleWidth()/m_zoom);
762 } else {
763 newWidth = static_cast<unsigned int>(visibleWidth()/m_zoom);
764 newHeight = static_cast<unsigned int>(visibleHeight()/m_zoom);
767 QPoint currCenter = m_selRect.center();
769 m_selRect.setWidth(newWidth);
770 m_selRect.setHeight(newHeight);
772 // make sure the selection window does not go outside of the display
773 if(currCenter.x() < m_selRect.width()/2) {
774 // set X to the minimum possible X
775 currCenter.setX(m_selRect.width()/2);
776 } else if(currCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
777 // set X to the maximum possible X
778 currCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
781 if(currCenter.y() < m_selRect.height()/2) {
782 // set Y to the minimum possible Y
783 currCenter.setY(m_selRect.height()/2);
784 } else if(currCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
785 // set Y to the maximum possible Y
786 currCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
789 m_selRect.moveCenter(currCenter);
790 // update the grab rectangle display
791 m_selRect.update();
792 // m_fitToWindow = true;
793 viewport()->repaint(false);
796 void KMagZoomView::setFitToWindow(bool fit)
798 m_fitToWindow = fit;
799 if (fit)
800 fitToWindow();
805 * Grabs frame from X
807 void KMagZoomView::grabFrame()
809 // check refresh status
810 if (!m_refreshSwitch)
811 return;
813 // check if follow-mouse is enabled
814 if(m_followMouse && (m_mouseMode != ResizeSelection)) {
815 // in this case grab w.r.t the current mouse position
816 QPoint newCenter;
818 // set new center to be the current mouse position
819 newCenter = QCursor::pos();
821 // make sure the mouse position is not taking the grab window outside
822 // the display
823 if(newCenter.x() < m_selRect.width()/2) {
824 // set X to the minimum possible X
825 newCenter.setX(m_selRect.width()/2);
826 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
827 // set X to the maximum possible X
828 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
831 if(newCenter.y() < m_selRect.height()/2) {
832 // set Y to the minimum possible Y
833 newCenter.setY(m_selRect.height()/2);
834 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
835 // set Y to the maximum possible Y
836 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
838 // move to the new center
839 m_selRect.moveCenter(newCenter);
841 // update the grab rectangle display
842 m_selRect.update();
845 //QRect r = pixmapRect();
847 // define a normalized rectangle
848 QRect selRect = m_selRect.normalize();
850 // grab screenshot from the screen and put it in the pixmap
851 m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
852 selRect.width(), selRect.height());
854 // zoom the image
855 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
857 // call repaint to display the newly grabbed image
858 resizeContents (m_grabbedZoomedPixmap.width(), m_grabbedZoomedPixmap.height());
859 viewport()->repaint(false);
864 * Updates the mouse cursor in the zoom view
866 void KMagZoomView::updateMouseView()
868 QPoint pos(QCursor::pos());
869 if(m_selRect.left() <= pos.x() <= m_selRect.right() &&
870 m_selRect.top() <= pos.y() <= m_selRect.bottom() &&
871 m_refreshSwitch)
872 viewport()->repaint(false);
876 * Toggles the state of refreshing.
878 void KMagZoomView::toggleRefresh()
880 if(m_refreshSwitch) {
881 m_refreshSwitch = false;
882 m_grabTimer.stop();
883 m_mouseViewTimer.stop();
884 } else {
885 m_refreshSwitch = true;
886 m_grabTimer.start(1000/m_fps);
887 m_mouseViewTimer.start(40);
892 * This function sets the zoom value to be used.
894 void KMagZoomView::setZoom(float zoom)
896 // use this zoom
897 m_zoom = zoom;
899 // update selection window size when zooming in if necessary
900 if (m_fitToWindow)
901 fitToWindow();
903 // recompute the zoom matrix
904 m_zoomMatrix.reset();
905 m_zoomMatrix.scale(m_zoom, m_zoom);
906 m_zoomMatrix.rotate(m_rotation);
908 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
910 viewport()->repaint();
914 * This function sets the rotation value to be used.
916 void KMagZoomView::setRotation(int rotation)
918 // use this rotation
919 m_rotation = rotation;
921 // update selection window size if necessary
922 if (m_fitToWindow)
923 fitToWindow();
925 // recompute the zoom matrix
926 m_zoomMatrix.reset();
927 m_zoomMatrix.scale(m_zoom, m_zoom);
928 m_zoomMatrix.rotate(m_rotation);
930 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
932 viewport()->repaint();
936 * Set a new refresh rate.
938 void KMagZoomView::setRefreshRate(float fps)
940 if(fps < 0.1)
941 return;
942 m_fps = static_cast<unsigned int>(fps);
944 if(m_grabTimer.isActive())
945 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
948 void KMagZoomView::showSelRect(bool show)
950 m_selRect.alwaysVisible(show);
951 if(show) {
952 m_selRect.show();
953 } else if(m_mouseMode == Normal) {
954 m_selRect.hide();
959 * Sets the selection rectangle to the given position.
961 void KMagZoomView::setSelRectPos(const QRect & rect)
963 m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height());
964 m_selRect.update();
965 grabFrame();
968 bool KMagZoomView::showMouse(unsigned int type)
970 if(type > m_showMouseTypes.count()-1)
971 return (false);
972 else
973 m_showMouse = type;
975 return(true);
978 unsigned int KMagZoomView::getShowMouseType() const
980 return (m_showMouse);
983 QStringList KMagZoomView::getShowMouseStringList() const
985 return (m_showMouseTypes);
990 * Returns the image which is being displayed. Its again drawn by adding
991 * the mouse cursor if needed.
993 QPixmap KMagZoomView::getPixmap()
995 // show the pixel under mouse cursor
996 if(m_showMouse && !m_grabbedZoomedPixmap.isNull()) {
997 // Pixmap which will have the zoomed pixmap + mouse
998 QPixmap zoomView(m_grabbedZoomedPixmap);
1000 // paint the mouse cursor w/o updating to a newer position
1001 paintMouseCursor(&zoomView, calcMousePos(false));
1003 return(zoomView);
1004 } else { // no mouse cursor
1005 return(m_grabbedZoomedPixmap);