Now kde doesn't use .la file
[kdeaccessibility.git] / kmag / kmagzoomview.cpp
blob5912be733e949dc1d47645373c5907161e55c803
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>
27 #include <QCursor>
28 #include <qglobal.h>
29 #include <QPainter>
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(true);
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 #ifdef __GNUC__
265 #warning "Port Qt4 pz.setRasterOp(Qt::XorROP);";
266 #endif
267 //pz.setRasterOp(Qt::XorROP);
268 pz.drawRect(mousePos.x()-1, mousePos.y()-1, (int)m_zoom+2, (int)m_zoom+2);
269 break;
271 case 2:
273 // 2. Arrow cursor
274 pz.setPen(Qt::black);
275 pz.setBackgroundColor(Qt::white);
277 QBitmap sCursor = QBitmap::fromData( QSize(16, 16), left_ptr_bits);
278 QBitmap mask = QBitmap::fromData( QSize(16, 16), left_ptrmsk_bits);
279 sCursor.setMask(mask);
280 sCursor = sCursor.transformed(m_zoomMatrix);
282 // since hot spot is at 3,1
283 if (m_rotation == 0)
284 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
285 else if (m_rotation == 90)
286 pz.drawPixmap(mousePos.x()-(int)(16.0*m_zoom), mousePos.y()-(int)(3.0*m_zoom), sCursor);
287 else if (m_rotation == 180)
288 pz.drawPixmap(mousePos.x()-(int)(13.0*m_zoom), mousePos.y()-(int)(16.0*m_zoom), sCursor);
289 else if (m_rotation == 270)
290 pz.drawPixmap(mousePos.x()-(int)m_zoom, mousePos.y()-(int)(13.0*m_zoom), sCursor);
292 break;
294 case 3:
296 // 3. Actual cursor
297 // Get the current cursor type
298 QWidget *dummy = KApplication::topLevelAt(QCursor::pos());
299 if(!dummy)
300 break;
301 kDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-" << endl;
302 switch(this->cursor().shape()) {
303 case Qt::ArrowCursor :
305 // 2. Arrow cursor
306 pz.setPen(Qt::black);
307 pz.setBackgroundColor(Qt::white);
309 QBitmap sCursor = QBitmap::fromData( QSize(16, 16), left_ptr_bits);
310 QBitmap mask = QBitmap::fromData( QSize(16, 16), left_ptrmsk_bits);
311 sCursor.setMask(mask);
312 sCursor = sCursor.transformed(m_zoomMatrix);
314 // since hot spot is at 3,1
315 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
317 break;
318 default:
319 QBitmap sCursor = QBitmap::fromData( QSize(32, 32), phand_bits);
320 QBitmap mask = QBitmap::fromData( QSize(32, 32), phandm_bits);
321 sCursor.setMask(mask);
323 pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
324 break;
325 } // switch(cursor)
329 break;
331 default:
332 // do not show anything
333 break;
334 } // switch(m_showMouse)
339 QPoint KMagZoomView::calcMousePos(bool updateMousePos)
341 // get position of mouse wrt selRect
342 if(updateMousePos) { // get a new position only if asked
343 m_latestCursorPos = QCursor::pos();
344 m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
347 // get coordinates of the pixel w.r.t. the zoomed pixmap
348 if (m_rotation == 90)
349 return QPoint ((int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom),
350 (int)((float)m_latestCursorPos.x()*m_zoom));
351 else if (m_rotation == 180)
352 return QPoint ((int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom),
353 (int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom));
354 else if (m_rotation == 270)
355 return QPoint ((int)((float)m_latestCursorPos.y()*m_zoom),
356 (int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom));
357 else
358 return QPoint ((int)((float)m_latestCursorPos.x()*m_zoom),
359 (int)((float)m_latestCursorPos.y()*m_zoom));
363 // MOUSE ACTIONS
366 * Called when mouse is clicked inside the window.
368 * @param e
370 void KMagZoomView::mousePressEvent(QMouseEvent *e)
372 switch(e->button()) {
373 case Qt::LeftButton :
374 if(m_ctrlKeyPressed) {
375 // check if currently in resize mode
376 // don't do anything if fitToWindow is enabled
377 if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
378 // set the mode to ResizeSelection
379 m_mouseMode = ResizeSelection;
381 // set mouse cursor to "resize all direction"
382 setCursor(Qt::SizeAllCursor);
384 // backup the old position
385 m_oldMousePos.setX(e->globalX());
386 m_oldMousePos.setY(e->globalY());
388 // set the cursor position to the bottom-right of the selected region
389 QCursor::setPos(m_selRect.bottomRight());
391 // show the selection rectangle
392 m_selRect.show();
394 else {
395 // ignore this button press.. so it goes to the parent
396 e->ignore();
398 } else if(m_shiftKeyPressed) {
399 // check if currently in move mode
400 // don't do anything if follow mouse is enabled
401 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
402 m_mouseMode = MoveSelection;
404 // set mouse cursor to cross hair
405 setCursor(Qt::CrossCursor);
407 // backup the old position
408 m_oldMousePos.setX(e->globalX());
409 m_oldMousePos.setY(e->globalY());
411 // set the cursor position to the center of the selected region
412 QCursor::setPos(m_selRect.center());
414 // show the selected rectangle
415 m_selRect.show();
417 else {
418 // ignore this button press.. so it goes to the parent
419 e->ignore();
421 } else {
422 // check if currently in move mode
423 // don't do anything if follow mouse is enabled
424 if ((m_mouseMode != GrabSelection) && !m_followMouse) {
425 m_mouseMode = GrabSelection;
427 // set mouse cursor to hand
428 setCursor(KCursor::handCursor());
430 // store the old position
431 m_oldMousePos.setX(e->globalX());
432 m_oldMousePos.setY(e->globalY());
434 m_oldCenter = m_selRect.center();
436 // show the selected rectangle
437 m_selRect.show();
439 else {
440 // ignore this button press.. so it goes to the parent
441 e->ignore();
444 break;
446 case Qt::MidButton :
447 // check if currently in move mode
448 // don't do anything if follow mouse is enabled
449 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
450 m_mouseMode = MoveSelection;
452 // set mouse cursor to cross hair
453 setCursor(Qt::CrossCursor);
455 // backup the old position
456 m_oldMousePos.setX(e->globalX());
457 m_oldMousePos.setY(e->globalY());
459 // set the cursor position to the center of the selected region
460 QCursor::setPos(m_selRect.center());
462 // show the selected rectangle
463 m_selRect.show();
465 else {
466 // ignore this button press.. so it goes to the parent
467 e->ignore();
469 break;
470 // do nothing
471 default:
472 // ignore this button press.. so it goes to the parent
473 e->ignore();
474 break;
480 * Called when a mouse button is released
482 * @param e
484 void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
486 switch(e->button()) {
487 case Qt::LeftButton :
488 case Qt::MidButton :
489 // check if currently in move mode
490 if(m_mouseMode == MoveSelection) {
491 // hide the selection window
492 m_selRect.hide();
493 // set the mouse mode to normal
494 m_mouseMode = Normal;
496 // restore the cursor shape
497 setCursor(Qt::ArrowCursor);
499 // restore the cursor position
500 QCursor::setPos(m_oldMousePos);
501 } else if(m_mouseMode == ResizeSelection) {
502 // hide the selection window
503 m_selRect.hide();
504 // set the mouse mode to normal
505 m_mouseMode = Normal;
507 // restore the cursor shape
508 setCursor(Qt::ArrowCursor);
510 // restore the cursor position
511 QCursor::setPos(m_oldMousePos);
512 } else if(m_mouseMode == GrabSelection) {
513 // hide the selection window
514 m_selRect.hide();
516 // set the mouse mode to normal
517 m_mouseMode = Normal;
519 // restore the cursor shape
520 setCursor(Qt::ArrowCursor);
522 break;
524 case Qt::RightButton :
525 break;
526 case Qt::NoButton :
527 break;
529 // do nothing
530 default:
537 * Called when mouse is moved inside the window
539 * @param e
541 void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
543 if(m_mouseMode == ResizeSelection) {
544 // In resize selection mode
545 // set the current mouse position as the bottom, right corner
546 m_selRect.setRight(e->globalX());
547 m_selRect.setBottom(e->globalY());
548 m_selRect.update();
549 grabFrame();
550 } else if(m_mouseMode == MoveSelection) {
551 QPoint newCenter;
553 // set new center to be the current mouse position
554 newCenter = e->globalPos();
556 // make sure the mouse position is not taking the grab window outside
557 // the display
558 if(newCenter.x() < m_selRect.width()/2) {
559 // set X to the minimum possible X
560 newCenter.setX(m_selRect.width()/2);
561 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
562 // set X to the maximum possible X
563 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
566 if(newCenter.y() < m_selRect.height()/2) {
567 // set Y to the minimum possible Y
568 newCenter.setY(m_selRect.height()/2);
569 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
570 // set Y to the maximum possible Y
571 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
573 // move to the new center
574 m_selRect.moveCenter(newCenter);
575 // update the grab rectangle display
576 m_selRect.update();
577 grabFrame();
578 } else if(m_mouseMode == GrabSelection) {
579 QPoint newPos;
581 // get new position
582 newPos = e->globalPos();
584 QPoint delta = (newPos - m_oldMousePos)/m_zoom;
585 QPoint newCenter = m_oldCenter-delta;
587 // make sure the mouse position is not taking the grab window outside
588 // the display
589 if(newCenter.x() < m_selRect.width()/2) {
590 // set X to the minimum possible X
591 newCenter.setX(m_selRect.width()/2);
592 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
593 // set X to the maximum possible X
594 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
597 if(newCenter.y() < m_selRect.height()/2) {
598 // set Y to the minimum possible Y
599 newCenter.setY(m_selRect.height()/2);
600 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
601 // set Y to the maximum possible Y
602 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
605 // move to the new center
606 m_selRect.moveCenter(newCenter);
607 // update the grab rectangle display
608 m_selRect.update();
609 grabFrame();
613 void KMagZoomView::keyPressEvent(QKeyEvent *e)
615 int offset = 16;
616 if (e->state() & Qt::ShiftModifier)
617 offset = 1;
619 if (e->key() == Qt::Key_Control)
620 m_ctrlKeyPressed = true;
621 else if (e->key() == Qt::Key_Shift)
622 m_shiftKeyPressed = true;
623 else if (e->key() == Qt::Key_Left)
625 if (e->state() & Qt::ControlModifier)
627 if (offset >= m_selRect.width())
628 m_selRect.setWidth (1);
629 else
630 m_selRect.setWidth (m_selRect.width()-offset);
632 else if (contentsX() > 0)
634 offset = (int)(offset*m_zoom);
635 if (contentsX() > offset)
636 setContentsPos (contentsX()-offset, contentsY());
637 else
638 setContentsPos (0, contentsY());
640 else if (m_followMouse == false)
642 if (offset > m_selRect.x())
643 m_selRect.setX (0);
644 else
645 m_selRect.translate (-offset,0);
647 m_selRect.update();
649 else if (e->key() == Qt::Key_Right)
651 if (e->state() & Qt::ControlModifier)
653 if (m_selRect.right()+offset >= QApplication::desktop()->width())
654 m_selRect.setRight (QApplication::desktop()->width()-1);
655 else
656 m_selRect.setRight (m_selRect.right()+offset);
658 else if (contentsX() < contentsWidth()-visibleWidth())
660 offset = (int)(offset*m_zoom);
661 if (contentsX()+offset < contentsWidth()-visibleWidth())
662 setContentsPos (contentsX()+offset, contentsY());
663 else
664 setContentsPos (contentsWidth()-visibleWidth(), contentsY());
666 else if (m_followMouse == false)
668 if (m_selRect.right()+offset >= QApplication::desktop()->width())
669 m_selRect.moveTopRight (QPoint (QApplication::desktop()->width()-1, m_selRect.top()));
670 else
671 m_selRect.translate (offset,0);
673 m_selRect.update();
675 else if (e->key() == Qt::Key_Up)
677 if (e->state() & Qt::ControlModifier)
679 if (offset >= m_selRect.height())
680 m_selRect.setHeight (1);
681 else
682 m_selRect.setHeight (m_selRect.height()-offset);
684 else if (contentsY() > 0)
686 offset = (int)(offset*m_zoom);
687 if (contentsY() > offset)
688 setContentsPos (contentsX(), contentsY()-offset);
689 else
690 setContentsPos (contentsX(), 0);
692 else if (m_followMouse == false)
694 if (offset > m_selRect.y())
695 m_selRect.setY (0);
696 else
697 m_selRect.translate (0, -offset);
699 m_selRect.update();
701 else if (e->key() == Qt::Key_Down)
703 if (e->state() & Qt::ControlModifier)
705 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
706 m_selRect.setBottom (QApplication::desktop()->height()-1);
707 else
708 m_selRect.setBottom (m_selRect.bottom()+offset);
710 else if (contentsY() < contentsHeight()-visibleHeight())
712 offset = (int)(offset*m_zoom);
713 if (contentsY()+offset < contentsHeight()-visibleHeight())
714 setContentsPos (contentsX(), contentsY()+offset);
715 else
716 setContentsPos (contentsX(), contentsHeight()-visibleHeight());
718 else if (m_followMouse == false)
720 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
721 m_selRect.moveBottomLeft (QPoint (m_selRect.left(), QApplication::desktop()->height()-1));
722 else
723 m_selRect.translate (0, offset);
725 m_selRect.update();
727 else
728 e->ignore();
731 void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
733 if (e->key() == Qt::Key_Control)
734 m_ctrlKeyPressed = false;
735 else if (e->key() == Qt::Key_Shift)
736 m_shiftKeyPressed = false;
737 else
738 e->ignore();
741 void KMagZoomView::focusOutEvent(QFocusEvent *e)
743 if(e->lostFocus() == true) {
744 m_ctrlKeyPressed = false;
745 m_shiftKeyPressed = false;
749 // SLOTS
752 * This will fit the zoom view to the view window, thus using the maximum
753 * possible space in the window.
755 void KMagZoomView::fitToWindow()
757 unsigned int newWidth, newHeight;
759 // this is a temporary solution, cast, maybe newWidth and newHeight should be float
760 if ((m_rotation == 90) || (m_rotation == 270))
762 newWidth = static_cast<unsigned int>(visibleHeight()/m_zoom);
763 newHeight = static_cast<unsigned int>(visibleWidth()/m_zoom);
764 } else {
765 newWidth = static_cast<unsigned int>(visibleWidth()/m_zoom);
766 newHeight = static_cast<unsigned int>(visibleHeight()/m_zoom);
769 QPoint currCenter = m_selRect.center();
771 m_selRect.setWidth(newWidth);
772 m_selRect.setHeight(newHeight);
774 // make sure the selection window does not go outside of the display
775 if(currCenter.x() < m_selRect.width()/2) {
776 // set X to the minimum possible X
777 currCenter.setX(m_selRect.width()/2);
778 } else if(currCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
779 // set X to the maximum possible X
780 currCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
783 if(currCenter.y() < m_selRect.height()/2) {
784 // set Y to the minimum possible Y
785 currCenter.setY(m_selRect.height()/2);
786 } else if(currCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
787 // set Y to the maximum possible Y
788 currCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
791 m_selRect.moveCenter(currCenter);
792 // update the grab rectangle display
793 m_selRect.update();
794 // m_fitToWindow = true;
795 viewport()->repaint(false);
798 void KMagZoomView::setFitToWindow(bool fit)
800 m_fitToWindow = fit;
801 if (fit)
802 fitToWindow();
807 * Grabs frame from X
809 void KMagZoomView::grabFrame()
811 // check refresh status
812 if (!m_refreshSwitch)
813 return;
815 // check if follow-mouse is enabled
816 if(m_followMouse && (m_mouseMode != ResizeSelection)) {
817 // in this case grab w.r.t the current mouse position
818 QPoint newCenter;
820 // set new center to be the current mouse position
821 newCenter = QCursor::pos();
823 // make sure the mouse position is not taking the grab window outside
824 // the display
825 if(newCenter.x() < m_selRect.width()/2) {
826 // set X to the minimum possible X
827 newCenter.setX(m_selRect.width()/2);
828 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
829 // set X to the maximum possible X
830 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
833 if(newCenter.y() < m_selRect.height()/2) {
834 // set Y to the minimum possible Y
835 newCenter.setY(m_selRect.height()/2);
836 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
837 // set Y to the maximum possible Y
838 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
840 // move to the new center
841 m_selRect.moveCenter(newCenter);
843 // update the grab rectangle display
844 m_selRect.update();
847 //QRect r = pixmapRect();
849 // define a normalized rectangle
850 QRect selRect = m_selRect.normalized();
852 // grab screenshot from the screen and put it in the pixmap
853 m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
854 selRect.width(), selRect.height());
856 // zoom the image
857 m_grabbedZoomedPixmap = m_grabbedPixmap.transformed(m_zoomMatrix);
859 // call repaint to display the newly grabbed image
860 resizeContents (m_grabbedZoomedPixmap.width(), m_grabbedZoomedPixmap.height());
861 viewport()->repaint(false);
866 * Updates the mouse cursor in the zoom view.
868 void KMagZoomView::updateMouseView()
870 QPoint pos(QCursor::pos());
871 if(m_selRect.left() <= pos.x() <= m_selRect.right() &&
872 m_selRect.top() <= pos.y() <= m_selRect.bottom() &&
873 m_refreshSwitch)
874 viewport()->repaint(false);
878 * Toggles the state of refreshing.
880 void KMagZoomView::toggleRefresh()
882 if(m_refreshSwitch) {
883 m_refreshSwitch = false;
884 m_grabTimer.stop();
885 m_mouseViewTimer.stop();
886 } else {
887 m_refreshSwitch = true;
888 m_grabTimer.start(1000/m_fps);
889 m_mouseViewTimer.start(40);
894 * This function sets the zoom value to be used.
896 void KMagZoomView::setZoom(float zoom)
898 // use this zoom
899 m_zoom = zoom;
901 // update selection window size when zooming in if necessary
902 if (m_fitToWindow)
903 fitToWindow();
905 // recompute the zoom matrix
906 m_zoomMatrix.reset();
907 m_zoomMatrix.scale(m_zoom, m_zoom);
908 m_zoomMatrix.rotate(m_rotation);
910 m_grabbedZoomedPixmap = m_grabbedPixmap.transformed(m_zoomMatrix);
912 viewport()->repaint();
916 * This function sets the rotation value to be used.
918 void KMagZoomView::setRotation(int rotation)
920 // use this rotation
921 m_rotation = rotation;
923 // update selection window size if necessary
924 if (m_fitToWindow)
925 fitToWindow();
927 // recompute the zoom matrix
928 m_zoomMatrix.reset();
929 m_zoomMatrix.scale(m_zoom, m_zoom);
930 m_zoomMatrix.rotate(m_rotation);
932 m_grabbedZoomedPixmap = m_grabbedPixmap.transformed(m_zoomMatrix);
934 viewport()->repaint();
938 * Set a new refresh rate.
940 void KMagZoomView::setRefreshRate(float fps)
942 if(fps < 0.1)
943 return;
944 m_fps = static_cast<unsigned int>(fps);
946 if(m_grabTimer.isActive())
947 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
950 void KMagZoomView::showSelRect(bool show)
952 m_selRect.alwaysVisible(show);
953 if(show) {
954 m_selRect.show();
955 } else if(m_mouseMode == Normal) {
956 m_selRect.hide();
961 * Sets the selection rectangle to the given position.
963 void KMagZoomView::setSelRectPos(const QRect & rect)
965 m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height());
966 m_selRect.update();
967 grabFrame();
970 bool KMagZoomView::showMouse(unsigned int type)
972 if(type > m_showMouseTypes.count()-1)
973 return (false);
974 else
975 m_showMouse = type;
977 return(true);
980 unsigned int KMagZoomView::getShowMouseType() const
982 return (m_showMouse);
985 QStringList KMagZoomView::getShowMouseStringList() const
987 return (m_showMouseTypes);
992 * Returns the image which is being displayed. It's again drawn by adding
993 * the mouse cursor if needed.
995 QPixmap KMagZoomView::getPixmap()
997 // show the pixel under mouse cursor
998 if(m_showMouse && !m_grabbedZoomedPixmap.isNull()) {
999 // Pixmap which will have the zoomed pixmap + mouse
1000 QPixmap zoomView(m_grabbedZoomedPixmap);
1002 // paint the mouse cursor w/o updating to a newer position
1003 paintMouseCursor(&zoomView, calcMousePos(false));
1005 return(zoomView);
1006 } else { // no mouse cursor
1007 return(m_grabbedZoomedPixmap);