SVN_SILENT made messages (.desktop file)
[kdeaccessibility.git] / kmag / kmagzoomview.cpp
blobc56be9f252b6becd1acac9dd80d135f5ea875f03
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>
30 #include <qwhatsthis.h>
31 #include <qwidget.h>
33 // include files for KDE
34 #include <kapplication.h>
35 #include <kcursor.h>
36 #include <kdebug.h>
37 #include <klocale.h>
39 // include bitmaps for cursors
40 static uchar left_ptr_bits[] = {
41 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
42 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01,
43 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00};
45 static uchar left_ptrmsk_bits[] = {
46 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
47 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03,
48 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03};
50 static uchar phand_bits[] = {
51 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
52 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00,
53 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00,
54 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00,
55 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
62 static uchar phandm_bits[] = {
63 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
64 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
65 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
66 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00,
67 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
68 0x00, 0x02, 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, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
76 KMagZoomView::KMagZoomView(QWidget *parent, const char *name)
77 : QScrollView(parent, name),
78 m_selRect(0, 0, 128, 128, this),
79 m_grabTimer(parent),
80 m_mouseViewTimer(parent),
81 m_latestCursorPos(0,0),
82 m_followMouse(false),
83 m_showMouse(1),
84 m_zoom(1.0),
85 m_rotation(0),
86 m_fitToWindow(true)
88 KApplication::setGlobalMouseTracking(TRUE);
89 viewport()->setMouseTracking(TRUE);
90 viewport()->setBackgroundMode (NoBackground);
91 viewport()->setFocusPolicy(QWidget::StrongFocus);
93 // init the zoom matrix
94 m_zoomMatrix.reset();
95 m_zoomMatrix.scale(m_zoom, m_zoom);
96 m_zoomMatrix.rotate(m_rotation);
98 m_ctrlKeyPressed = false;
99 m_shiftKeyPressed = false;
100 m_refreshSwitch = true;
101 m_refreshSwitchStateOnHide = m_refreshSwitch;
103 // set the refresh rate
104 setRefreshRate(10);
106 // connect it to grabFrame()
107 connect(&m_grabTimer, SIGNAL(timeout()), SLOT(grabFrame()));
108 // start the grabTimer
109 m_grabTimer.start(static_cast<int>(1000.0/m_fps));
111 // connect it to updateMouseView()
112 connect(&m_mouseViewTimer, SIGNAL(timeout()), SLOT(updateMouseView()));
113 // start the grabTimer @ 25 frames per second!
114 m_mouseViewTimer.start(25);
116 QWhatsThis::add(this, i18n("This is the main window which shows the contents of the\
117 selected region. The contents will be magnified according to the zoom level that is set."));
119 // different ways to show the cursor.
120 m_showMouseTypes << "Hidden" << "Box" << "Arrow" << "Actual";
122 if(m_fitToWindow)
123 fitToWindow();
126 KMagZoomView::~KMagZoomView()
128 KApplication::setGlobalMouseTracking(FALSE);
132 * This function will set/reset mouse following of grab window.
134 void KMagZoomView::followMouse(bool follow)
136 if(follow) {
137 m_followMouse = true;
138 m_mouseMode = Normal;
139 setVScrollBarMode (QScrollView::AlwaysOff);
140 setHScrollBarMode (QScrollView::AlwaysOff);
141 } else {
142 m_followMouse = false;
143 m_mouseMode = Normal;
144 setVScrollBarMode (QScrollView::AlwaysOn);
145 setHScrollBarMode (QScrollView::AlwaysOn);
150 * Called when the widget is hidden. Stop refresh when this happens.
152 void KMagZoomView::hideEvent( QHideEvent* )
154 // Save the state of the refresh switch.. the state will be restored
155 // when showEvent is called
156 m_refreshSwitchStateOnHide = m_refreshSwitch;
158 // Check if refresh is ON
159 if(m_refreshSwitch) {
160 toggleRefresh();
166 * Called when the widget is shown. Start refresh when this happens.
168 void KMagZoomView::showEvent( QShowEvent* )
170 // Check if refresh switch was ON when hide was called and if currently it is OFF
171 if(m_refreshSwitchStateOnHide && !m_refreshSwitch) {
172 // start the refresh in that case
173 toggleRefresh();
178 * Called when the widget is resized. Check if fitToWindow is active when this happens.
180 void KMagZoomView::resizeEvent( QResizeEvent * e )
182 QScrollView::resizeEvent (e);
183 if(m_fitToWindow)
184 fitToWindow();
188 * Called when the widget is to be repainted
190 * @param p
192 void KMagZoomView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
194 if(m_grabbedZoomedPixmap.isNull())
195 return;
197 // Paint empty areas black
198 if (contentsX()+contentsWidth() < visibleWidth())
199 p->fillRect (
200 QRect (contentsX()+contentsWidth(), clipy, visibleWidth()-contentsX()-contentsWidth(), cliph)
201 & QRect (clipx, clipy, clipw, cliph),
202 Qt::black);
203 if (contentsY()+contentsHeight() < visibleHeight())
204 p->fillRect (
205 QRect (clipx, contentsY()+contentsHeight(), clipw, visibleHeight()-contentsY()-contentsHeight())
206 & QRect (clipx, clipy, clipw, cliph),
207 Qt::black);
209 // A pixmap which will be eventually displayed
210 QPixmap *zoomView;
212 // Get mouse position relative to the image
213 QPoint mousePos = calcMousePos (m_refreshSwitch);
215 // show the pixel under mouse cursor
216 if(m_showMouse) {
218 // Pixmap which will have the zoomed pixmap + mouse
219 zoomView = new QPixmap(m_grabbedZoomedPixmap);
221 // paint the mouse cursor
222 paintMouseCursor(zoomView, mousePos);
223 } else { // do not show mouse
224 zoomView = &m_grabbedZoomedPixmap;
227 // bitBlt this part on to the widget.
228 bitBlt(viewport(), QPoint (clipx-contentsX(), clipy-contentsY()), zoomView, QRect(clipx, clipy, clipw, cliph));
230 if(zoomView != &m_grabbedZoomedPixmap)
231 delete zoomView;
235 * Draws the mouse cursor according to the current selection of the type of
236 * mouse cursor to draw.
238 void KMagZoomView::paintMouseCursor(QPaintDevice *dev, QPoint mousePos)
240 if(!dev)
241 return;
243 // painter for the zoom view
244 QPainter pz(dev);
246 if(m_latestCursorPos.x() >= 0 && m_latestCursorPos.x() < m_selRect.width() &&
247 m_latestCursorPos.y() >= 0 && m_latestCursorPos.y() < m_selRect.height() ) { // || updateMousePos) {
248 // mouse position is indeed inside the selRect
250 // How to show the mouse :
252 switch(m_showMouse) {
253 case 1:
254 // 1. Square around the pixel
255 pz.setPen(Qt::white);
256 pz.setRasterOp(Qt::XorROP);
257 pz.drawRect(mousePos.x()-1, mousePos.y()-1, (int)m_zoom+2, (int)m_zoom+2);
258 break;
260 case 2:
262 // 2. Arrow cursor
263 pz.setPen(Qt::black);
264 pz.setBackgroundColor(Qt::white);
266 QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
267 QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
268 sCursor.setMask(mask);
269 sCursor = sCursor.xForm(m_zoomMatrix);
271 // since hot spot is at 3,1
272 if (m_rotation == 0)
273 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
274 else if (m_rotation == 90)
275 pz.drawPixmap(mousePos.x()-(int)(16.0*m_zoom), mousePos.y()-(int)(3.0*m_zoom), sCursor);
276 else if (m_rotation == 180)
277 pz.drawPixmap(mousePos.x()-(int)(13.0*m_zoom), mousePos.y()-(int)(16.0*m_zoom), sCursor);
278 else if (m_rotation == 270)
279 pz.drawPixmap(mousePos.x()-(int)m_zoom, mousePos.y()-(int)(13.0*m_zoom), sCursor);
281 break;
283 case 3:
285 // 3. Actual cursor
286 // Get the current cursor type
287 QWidget *dummy = KApplication::widgetAt(QCursor::pos(), FALSE);
288 if(!dummy)
289 break;
290 kdDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-" << endl;
291 switch(this->cursor().shape()) {
292 case ArrowCursor :
294 // 2. Arrow cursor
295 pz.setPen(Qt::black);
296 pz.setBackgroundColor(Qt::white);
298 QBitmap sCursor( 16, 16, left_ptr_bits, TRUE );
299 QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE );
300 sCursor.setMask(mask);
301 sCursor = sCursor.xForm(m_zoomMatrix);
303 // since hot spot is at 3,1
304 pz.drawPixmap(mousePos.x()-(int)(3.0*m_zoom), mousePos.y()-(int)m_zoom, sCursor);
306 break;
307 default:
308 QBitmap sCursor( 32, 32, phand_bits, TRUE );
309 QBitmap mask( 32, 32, phandm_bits, TRUE );
310 sCursor.setMask(mask);
312 pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor);
313 break;
314 } // switch(cursor)
318 break;
320 default:
321 // do not show anything
322 break;
323 } // switch(m_showMouse)
328 QPoint KMagZoomView::calcMousePos(bool updateMousePos)
330 // get position of mouse wrt selRect
331 if(updateMousePos) { // get a new position only if asked
332 m_latestCursorPos = QCursor::pos();
333 m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y());
336 // get coordinates of the pixel w.r.t. the zoomed pixmap
337 if (m_rotation == 90)
338 return QPoint ((int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom),
339 (int)((float)m_latestCursorPos.x()*m_zoom));
340 else if (m_rotation == 180)
341 return QPoint ((int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom),
342 (int)((float)(m_selRect.height()-m_latestCursorPos.y())*m_zoom));
343 else if (m_rotation == 270)
344 return QPoint ((int)((float)m_latestCursorPos.y()*m_zoom),
345 (int)((float)(m_selRect.width()-m_latestCursorPos.x())*m_zoom));
346 else
347 return QPoint ((int)((float)m_latestCursorPos.x()*m_zoom),
348 (int)((float)m_latestCursorPos.y()*m_zoom));
352 // MOUSE ACTIONS
355 * Called when mouse is clicked inside the window
357 * @param e
359 void KMagZoomView::mousePressEvent(QMouseEvent *e)
361 switch(e->button()) {
362 case QMouseEvent::LeftButton :
363 if(m_ctrlKeyPressed) {
364 // check if currently in resize mode
365 // don't do anything if fitToWindow is enabled
366 if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) {
367 // set the mode to ResizeSelection
368 m_mouseMode = ResizeSelection;
370 // set mouse cursor to "resize all direction"
371 setCursor(sizeAllCursor);
373 // backup the old position
374 m_oldMousePos.setX(e->globalX());
375 m_oldMousePos.setY(e->globalY());
377 // set the cursor position to the bottom-right of the selected region
378 QCursor::setPos(m_selRect.bottomRight());
380 // show the selection rectangle
381 m_selRect.show();
383 else {
384 #if QT_VERSION >= 300
385 // ignore this button press.. so it goes to the parent
386 e->ignore();
387 #endif
389 } else if(m_shiftKeyPressed) {
390 // check if currently in move mode
391 // don't do anything if follow mouse is enabled
392 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
393 m_mouseMode = MoveSelection;
395 // set mouse cursor to cross hair
396 setCursor(crossCursor);
398 // backup the old position
399 m_oldMousePos.setX(e->globalX());
400 m_oldMousePos.setY(e->globalY());
402 // set the cursor position to the center of the selected region
403 QCursor::setPos(m_selRect.center());
405 // show the selected rectangle
406 m_selRect.show();
408 else {
409 #if QT_VERSION >= 300
410 // ignore this button press.. so it goes to the parent
411 e->ignore();
412 #endif
414 } else {
415 // check if currently in move mode
416 // don't do anything if follow mouse is enabled
417 if ((m_mouseMode != GrabSelection) && !m_followMouse) {
418 m_mouseMode = GrabSelection;
420 // set mouse cursor to hand
421 setCursor(KCursor::handCursor());
423 // store the old position
424 m_oldMousePos.setX(e->globalX());
425 m_oldMousePos.setY(e->globalY());
427 m_oldCenter = m_selRect.center();
429 // show the selected rectangle
430 m_selRect.show();
432 else {
433 #if QT_VERSION >= 300
434 // ignore this button press.. so it goes to the parent
435 e->ignore();
436 #endif
439 break;
441 case QMouseEvent::MidButton :
442 // check if currently in move mode
443 // don't do anything if follow mouse is enabled
444 if ((m_mouseMode != MoveSelection) && !m_followMouse) {
445 m_mouseMode = MoveSelection;
447 // set mouse cursor to cross hair
448 setCursor(crossCursor);
450 // backup the old position
451 m_oldMousePos.setX(e->globalX());
452 m_oldMousePos.setY(e->globalY());
454 // set the cursor position to the center of the selected region
455 QCursor::setPos(m_selRect.center());
457 // show the selected rectangle
458 m_selRect.show();
460 else {
461 #if QT_VERSION >= 300
462 // ignore this button press.. so it goes to the parent
463 e->ignore();
464 #endif
466 break;
467 // do nothing
468 default:
469 #if QT_VERSION >= 300
470 // ignore this button press.. so it goes to the parent
471 e->ignore();
472 #endif
473 break;
479 * Called when a mouse button is released
481 * @param e
483 void KMagZoomView::mouseReleaseEvent(QMouseEvent *e)
485 switch(e->button()) {
486 case QMouseEvent::LeftButton :
487 case QMouseEvent::MidButton :
488 // check if currently in move mode
489 if(m_mouseMode == MoveSelection) {
490 // hide the selection window
491 m_selRect.hide();
492 // set the mouse mode to normal
493 m_mouseMode = Normal;
495 // restore the cursor shape
496 setCursor(arrowCursor);
498 // restore the cursor position
499 QCursor::setPos(m_oldMousePos);
500 } else if(m_mouseMode == ResizeSelection) {
501 // hide the selection window
502 m_selRect.hide();
503 // set the mouse mode to normal
504 m_mouseMode = Normal;
506 // restore the cursor shape
507 setCursor(arrowCursor);
509 // restore the cursor position
510 QCursor::setPos(m_oldMousePos);
511 } else if(m_mouseMode == GrabSelection) {
512 // hide the selection window
513 m_selRect.hide();
515 // set the mouse mode to normal
516 m_mouseMode = Normal;
518 // restore the cursor shape
519 setCursor(arrowCursor);
521 break;
523 case QMouseEvent::RightButton :
524 break;
525 case QMouseEvent::NoButton :
526 break;
528 // do nothing
529 default:
536 * Called when mouse is moved inside the window
538 * @param e
540 void KMagZoomView::mouseMoveEvent(QMouseEvent *e)
542 if(m_mouseMode == ResizeSelection) {
543 // In resize selection mode
544 // set the current mouse position as the bottom, right corner
545 m_selRect.setRight(e->globalX());
546 m_selRect.setBottom(e->globalY());
547 m_selRect.update();
548 grabFrame();
549 } else if(m_mouseMode == MoveSelection) {
550 QPoint newCenter;
552 // set new center to be the current mouse position
553 newCenter = e->globalPos();
555 // make sure the mouse position is not taking the grab window outside
556 // the display
557 if(newCenter.x() < m_selRect.width()/2) {
558 // set X to the minimum possible X
559 newCenter.setX(m_selRect.width()/2);
560 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
561 // set X to the maximum possible X
562 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
565 if(newCenter.y() < m_selRect.height()/2) {
566 // set Y to the minimum possible Y
567 newCenter.setY(m_selRect.height()/2);
568 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
569 // set Y to the maximum possible Y
570 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
572 // move to the new center
573 m_selRect.moveCenter(newCenter);
574 // update the grab rectangle display
575 m_selRect.update();
576 grabFrame();
577 } else if(m_mouseMode == GrabSelection) {
578 QPoint newPos;
580 // get new position
581 newPos = e->globalPos();
583 QPoint delta = (newPos - m_oldMousePos)/m_zoom;
584 QPoint newCenter = m_oldCenter-delta;
586 // make sure the mouse position is not taking the grab window outside
587 // the display
588 if(newCenter.x() < m_selRect.width()/2) {
589 // set X to the minimum possible X
590 newCenter.setX(m_selRect.width()/2);
591 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
592 // set X to the maximum possible X
593 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
596 if(newCenter.y() < m_selRect.height()/2) {
597 // set Y to the minimum possible Y
598 newCenter.setY(m_selRect.height()/2);
599 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
600 // set Y to the maximum possible Y
601 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
604 // move to the new center
605 m_selRect.moveCenter(newCenter);
606 // update the grab rectangle display
607 m_selRect.update();
608 grabFrame();
612 void KMagZoomView::keyPressEvent(QKeyEvent *e)
614 int offset = 16;
615 if (e->state() & QKeyEvent::ShiftButton)
616 offset = 1;
618 if (e->key() == QKeyEvent::Key_Control)
619 m_ctrlKeyPressed = true;
620 else if (e->key() == QKeyEvent::Key_Shift)
621 m_shiftKeyPressed = true;
622 else if (e->key() == QKeyEvent::Key_Left)
624 if (e->state() & QKeyEvent::ControlButton)
626 if (offset >= m_selRect.width())
627 m_selRect.setWidth (1);
628 else
629 m_selRect.setWidth (m_selRect.width()-offset);
631 else if (contentsX() > 0)
633 offset = (int)(offset*m_zoom);
634 if (contentsX() > offset)
635 setContentsPos (contentsX()-offset, contentsY());
636 else
637 setContentsPos (0, contentsY());
639 else if (m_followMouse == false)
641 if (offset > m_selRect.x())
642 m_selRect.setX (0);
643 else
644 m_selRect.moveBy (-offset,0);
646 m_selRect.update();
648 else if (e->key() == QKeyEvent::Key_Right)
650 if (e->state() & QKeyEvent::ControlButton)
652 if (m_selRect.right()+offset >= QApplication::desktop()->width())
653 m_selRect.setRight (QApplication::desktop()->width()-1);
654 else
655 m_selRect.setRight (m_selRect.right()+offset);
657 else if (contentsX() < contentsWidth()-visibleWidth())
659 offset = (int)(offset*m_zoom);
660 if (contentsX()+offset < contentsWidth()-visibleWidth())
661 setContentsPos (contentsX()+offset, contentsY());
662 else
663 setContentsPos (contentsWidth()-visibleWidth(), contentsY());
665 else if (m_followMouse == false)
667 if (m_selRect.right()+offset >= QApplication::desktop()->width())
668 m_selRect.moveTopRight (QPoint (QApplication::desktop()->width()-1, m_selRect.top()));
669 else
670 m_selRect.moveBy (offset,0);
672 m_selRect.update();
674 else if (e->key() == QKeyEvent::Key_Up)
676 if (e->state() & QKeyEvent::ControlButton)
678 if (offset >= m_selRect.height())
679 m_selRect.setHeight (1);
680 else
681 m_selRect.setHeight (m_selRect.height()-offset);
683 else if (contentsY() > 0)
685 offset = (int)(offset*m_zoom);
686 if (contentsY() > offset)
687 setContentsPos (contentsX(), contentsY()-offset);
688 else
689 setContentsPos (contentsX(), 0);
691 else if (m_followMouse == false)
693 if (offset > m_selRect.y())
694 m_selRect.setY (0);
695 else
696 m_selRect.moveBy (0, -offset);
698 m_selRect.update();
700 else if (e->key() == QKeyEvent::Key_Down)
702 if (e->state() & QKeyEvent::ControlButton)
704 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
705 m_selRect.setBottom (QApplication::desktop()->height()-1);
706 else
707 m_selRect.setBottom (m_selRect.bottom()+offset);
709 else if (contentsY() < contentsHeight()-visibleHeight())
711 offset = (int)(offset*m_zoom);
712 if (contentsY()+offset < contentsHeight()-visibleHeight())
713 setContentsPos (contentsX(), contentsY()+offset);
714 else
715 setContentsPos (contentsX(), contentsHeight()-visibleHeight());
717 else if (m_followMouse == false)
719 if (m_selRect.bottom()+offset >= QApplication::desktop()->height())
720 m_selRect.moveBottomLeft (QPoint (m_selRect.left(), QApplication::desktop()->height()-1));
721 else
722 m_selRect.moveBy (0, offset);
724 m_selRect.update();
726 else
727 e->ignore();
730 void KMagZoomView::keyReleaseEvent(QKeyEvent *e)
732 if (e->key() == QKeyEvent::Key_Control)
733 m_ctrlKeyPressed = false;
734 else if (e->key() == QKeyEvent::Key_Shift)
735 m_shiftKeyPressed = false;
736 else
737 e->ignore();
740 void KMagZoomView::focusOutEvent(QFocusEvent *e)
742 if(e->lostFocus() == TRUE) {
743 m_ctrlKeyPressed = false;
744 m_shiftKeyPressed = false;
748 // SLOTS
751 * This will fit the zoom view to the view window, thus using the maximum
752 * possible space in the window.
754 void KMagZoomView::fitToWindow()
756 unsigned int newWidth, newHeight;
758 // this is a temporary solution, cast, maybe newWidth and newHeight should be float
759 if ((m_rotation == 90) || (m_rotation == 270))
761 newWidth = static_cast<unsigned int>(visibleHeight()/m_zoom);
762 newHeight = static_cast<unsigned int>(visibleWidth()/m_zoom);
763 } else {
764 newWidth = static_cast<unsigned int>(visibleWidth()/m_zoom);
765 newHeight = static_cast<unsigned int>(visibleHeight()/m_zoom);
768 QPoint currCenter = m_selRect.center();
770 m_selRect.setWidth(newWidth);
771 m_selRect.setHeight(newHeight);
773 // make sure the selection window does not go outside of the display
774 if(currCenter.x() < m_selRect.width()/2) {
775 // set X to the minimum possible X
776 currCenter.setX(m_selRect.width()/2);
777 } else if(currCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
778 // set X to the maximum possible X
779 currCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
782 if(currCenter.y() < m_selRect.height()/2) {
783 // set Y to the minimum possible Y
784 currCenter.setY(m_selRect.height()/2);
785 } else if(currCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
786 // set Y to the maximum possible Y
787 currCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
790 m_selRect.moveCenter(currCenter);
791 // update the grab rectangle display
792 m_selRect.update();
793 // m_fitToWindow = true;
794 viewport()->repaint(false);
797 void KMagZoomView::setFitToWindow(bool fit)
799 m_fitToWindow = fit;
800 if (fit)
801 fitToWindow();
806 * Grabs frame from X
808 void KMagZoomView::grabFrame()
810 // check refresh status
811 if (!m_refreshSwitch)
812 return;
814 // check if follow-mouse is enabled
815 if(m_followMouse && (m_mouseMode != ResizeSelection)) {
816 // in this case grab w.r.t the current mouse position
817 QPoint newCenter;
819 // set new center to be the current mouse position
820 newCenter = QCursor::pos();
822 // make sure the mouse position is not taking the grab window outside
823 // the display
824 if(newCenter.x() < m_selRect.width()/2) {
825 // set X to the minimum possible X
826 newCenter.setX(m_selRect.width()/2);
827 } else if(newCenter.x() >= QApplication::desktop()->width()-m_selRect.width()/2) {
828 // set X to the maximum possible X
829 newCenter.setX(QApplication::desktop()->width()-m_selRect.width()/2-1);
832 if(newCenter.y() < m_selRect.height()/2) {
833 // set Y to the minimum possible Y
834 newCenter.setY(m_selRect.height()/2);
835 } else if(newCenter.y() >= QApplication::desktop()->height()-m_selRect.height()/2) {
836 // set Y to the maximum possible Y
837 newCenter.setY(QApplication::desktop()->height()-m_selRect.height()/2-1);
839 // move to the new center
840 m_selRect.moveCenter(newCenter);
842 // update the grab rectangle display
843 m_selRect.update();
846 //QRect r = pixmapRect();
848 // define a normalized rectangle
849 QRect selRect = m_selRect.normalize();
851 // grab screenshot from the screen and put it in the pixmap
852 m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(),
853 selRect.width(), selRect.height());
855 // zoom the image
856 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
858 // call repaint to display the newly grabbed image
859 resizeContents (m_grabbedZoomedPixmap.width(), m_grabbedZoomedPixmap.height());
860 viewport()->repaint(false);
865 * Updates the mouse cursor in the zoom view
867 void KMagZoomView::updateMouseView()
869 QPoint pos(QCursor::pos());
870 if(m_selRect.left() <= pos.x() <= m_selRect.right() &&
871 m_selRect.top() <= pos.y() <= m_selRect.bottom() &&
872 m_refreshSwitch)
873 viewport()->repaint(false);
877 * Toggles the state of refreshing.
879 void KMagZoomView::toggleRefresh()
881 if(m_refreshSwitch) {
882 m_refreshSwitch = false;
883 m_grabTimer.stop();
884 m_mouseViewTimer.stop();
885 } else {
886 m_refreshSwitch = true;
887 m_grabTimer.start(1000/m_fps);
888 m_mouseViewTimer.start(40);
893 * This function sets the zoom value to be used.
895 void KMagZoomView::setZoom(float zoom)
897 // use this zoom
898 m_zoom = zoom;
900 // update selection window size when zooming in if necessary
901 if (m_fitToWindow)
902 fitToWindow();
904 // recompute the zoom matrix
905 m_zoomMatrix.reset();
906 m_zoomMatrix.scale(m_zoom, m_zoom);
907 m_zoomMatrix.rotate(m_rotation);
909 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
911 viewport()->repaint();
915 * This function sets the rotation value to be used.
917 void KMagZoomView::setRotation(int rotation)
919 // use this rotation
920 m_rotation = rotation;
922 // update selection window size if necessary
923 if (m_fitToWindow)
924 fitToWindow();
926 // recompute the zoom matrix
927 m_zoomMatrix.reset();
928 m_zoomMatrix.scale(m_zoom, m_zoom);
929 m_zoomMatrix.rotate(m_rotation);
931 m_grabbedZoomedPixmap = m_grabbedPixmap.xForm(m_zoomMatrix);
933 viewport()->repaint();
937 * Set a new refresh rate.
939 void KMagZoomView::setRefreshRate(float fps)
941 if(fps < 0.1)
942 return;
943 m_fps = static_cast<unsigned int>(fps);
945 if(m_grabTimer.isActive())
946 m_grabTimer.changeInterval(static_cast<int>(1000.0/m_fps));
949 void KMagZoomView::showSelRect(bool show)
951 m_selRect.alwaysVisible(show);
952 if(show) {
953 m_selRect.show();
954 } else if(m_mouseMode == Normal) {
955 m_selRect.hide();
960 * Sets the selection rectangle to the given position.
962 void KMagZoomView::setSelRectPos(const QRect & rect)
964 m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height());
965 m_selRect.update();
966 grabFrame();
969 bool KMagZoomView::showMouse(unsigned int type)
971 if(type > m_showMouseTypes.count()-1)
972 return (false);
973 else
974 m_showMouse = type;
976 return(true);
979 unsigned int KMagZoomView::getShowMouseType() const
981 return (m_showMouse);
984 QStringList KMagZoomView::getShowMouseStringList() const
986 return (m_showMouseTypes);
991 * Returns the image which is being displayed. Its again drawn by adding
992 * the mouse cursor if needed.
994 QPixmap KMagZoomView::getPixmap()
996 // show the pixel under mouse cursor
997 if(m_showMouse && !m_grabbedZoomedPixmap.isNull()) {
998 // Pixmap which will have the zoomed pixmap + mouse
999 QPixmap zoomView(m_grabbedZoomedPixmap);
1001 // paint the mouse cursor w/o updating to a newer position
1002 paintMouseCursor(&zoomView, calcMousePos(false));
1004 return(zoomView);
1005 } else { // no mouse cursor
1006 return(m_grabbedZoomedPixmap);