]> Shamusworld >> Repos - architektonas/blob - src/widgets/qg_graphicview.cpp
3c825c780fae70271f1b72ada736d0f31619bac1
[architektonas] / src / widgets / qg_graphicview.cpp
1 // qg_graphicview.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/10/2010  Added this text. :-)
13 //
14
15 #include "qg_graphicview.h"
16
17 #include "rs_actiondefault.h"
18 #include "rs_actionzoomin.h"
19 #include "rs_actionzoompan.h"
20 #include "rs_actionzoomscroll.h"
21 #include "rs_actionmodifydelete.h"
22 #include "rs_actionselectsingle.h"
23 #include "rs_dialogfactory.h"
24 #include "graphicview.h"
25 #include "rs_preview.h"
26 #include "drawing.h"
27 #include "settings.h"
28 #include "rs_system.h"
29 #include "rs_patternlist.h"
30 #include "cadtoolbar.h"
31 #include "paintintf.h"
32 #include "qg_dialogfactory.h"
33
34 #define QG_SCROLLMARGIN 400
35
36 /**
37  * Constructor.
38  */
39 QG_GraphicView::QG_GraphicView(QWidget * parent, const char */*name*/, Qt::WindowFlags f):
40         QWidget(parent, f), GraphicView()//, refCount(0)
41 {
42         RS_DEBUG->print("QG_GraphicView::QG_GraphicView(parent, name, flags)...");
43         CommonInitialization();
44 }
45
46 /**
47  * Constructor II.
48  */
49 QG_GraphicView::QG_GraphicView(RS_Document * doc, QWidget * parent)
50 {
51 //      QG_GraphicView(parent, "graphicview");
52         CommonInitialization();
53
54         RS_DEBUG->print("QG_GraphicView::QG_GraphicView(doc, parent)...");
55         //document = doc;
56         RS_DEBUG->print("  Setting Container...");
57
58         if (doc)
59                 setContainer(doc);
60
61         RS_DEBUG->print("  container set.");
62         setFactorX(4.0);
63         setFactorY(4.0);
64         setOffset(50, 50);
65         setBorders(10, 10, 10, 10);
66
67         if (doc)
68                 setDefaultAction(new RS_ActionDefault(*doc, *this));
69 }
70
71 void QG_GraphicView::CommonInitialization(void)
72 {
73         setBackground(background);
74 //meh   buffer = NULL;
75         lastWidth = 0;
76         lastHeight = 0;
77 //hrm.
78 painter = NULL;
79
80         RS_DEBUG->print("--> Setting up layout...");
81         QGridLayout * layout = new QGridLayout(this);
82         layout->setColumnStretch(0, 1);
83         layout->setColumnStretch(1, 0);
84         layout->setColumnStretch(2, 0);
85         layout->setRowStretch(0, 1);
86         layout->setRowStretch(1, 0);
87
88 /*
89 void QGridLayout::addMultiCellWidget ( QWidget * w, int fromRow, int toRow, int fromCol, int toCol, int alignment = 0 )
90 Adds the widget w to the cell grid, spanning multiple rows/columns. The cell will span from fromRow, fromCol to toRow, toCol.
91
92 Alignment is specified by alignment, which is a bitwise OR of Qt::AlignmentFlags values. The default alignment is 0, which means that the widget fills the entire cell.
93
94 A non-zero alignment indicates that the widget should not grow to fill the available space but should be sized according to sizeHint().
95 */
96         RS_DEBUG->print("--> Creating hScrollBar...");
97 //      hScrollBar = new QG_ScrollBar(Qt::Horizontal, this);
98         hScrollBar = new QScrollBar(Qt::Horizontal, this);
99 //    hScrollBar->setLineStep(50);
100         hScrollBar->setSingleStep(50);
101 //    layout->addMultiCellWidget(hScrollBar, 1, 1, 0, 0);
102         layout->addWidget(hScrollBar, 1, 0);
103 //    layout->addRowSpacing(1, hScrollBar->sizeHint().height());
104         layout->addItem(new QSpacerItem(0, hScrollBar->sizeHint().height()), 1, 0);
105
106         RS_DEBUG->print("--> Creating vScrollBar...");
107 //      vScrollBar = new QG_ScrollBar(Qt::Vertical, this);
108         vScrollBar = new QScrollBar(Qt::Vertical, this);
109 //    vScrollBar->setLineStep(50);
110         vScrollBar->setSingleStep(50);
111 //    layout->addMultiCellWidget(vScrollBar, 0, 0, 2, 2);
112         layout->addWidget(vScrollBar, 0, 2);
113 //    layout->addColSpacing(2, vScrollBar->sizeHint().width());
114         layout->addItem(new QSpacerItem(vScrollBar->sizeHint().width(), 0), 0, 2);
115
116         connect(hScrollBar, SIGNAL(valueChanged(int)), this, SLOT(slotHScrolled(int)));
117         connect(vScrollBar, SIGNAL(valueChanged(int)), this, SLOT(slotVScrolled(int)));
118
119 #ifndef __APPLE__
120         // Mouse Cursors:
121         QBitmap bmp;
122         QPixmap cur1(":/res/cur_cad_bmp.xpm");
123         bmp = QPixmap(":/res/cur_cad_mask.xpm");
124         cur1.setMask(bmp);
125         curCad = new QCursor(cur1, 15, 15);
126
127         QPixmap cur2(":/res/cur_glass_bmp.xpm");
128         bmp = QPixmap(":/res/cur_glass_mask.xpm");
129         cur2.setMask(bmp);
130         curMagnifier = new QCursor(cur2, 12, 12);
131
132         QPixmap cur3(":/res/cur_del_bmp.xpm");
133         bmp = QPixmap(":/res/cur_del_mask.xpm");
134         cur3.setMask(bmp);
135         curDel = new QCursor(cur3, 15, 15);
136
137         QPixmap cur4(":/res/cur_select_bmp.xpm");
138         bmp = QPixmap(":/res/cur_select_mask.xpm");
139         cur4.setMask(bmp);
140         curSelect = new QCursor(cur4, 15, 15);
141
142         QPixmap cur5(":/res/cur_hand_bmp.xpm");
143         bmp = QPixmap(":/res/cur_hand_mask.xpm");
144         cur5.setMask(bmp);
145         curHand = new QCursor(cur5, 15, 15);
146 #else
147         // No individual cursors for the Mac
148         curCad = NULL;
149         curMagnifier = NULL;
150         curDel = NULL;
151         curSelect = NULL;
152         curHand = NULL;
153 #endif
154
155         // Dummy widgets for scrollbar corners:
156         //layout->addWidget(new QWidget(this), 1, 1);
157         //QWidget* w = new QWidget(this);
158         //w->setEraseColor(QColor(255,0,0));
159         gridStatus = new QLabel("-", this);
160         gridStatus->setAlignment(Qt::AlignRight);
161 //      gridStatus->setAutoFillBackground(true);
162 //    layout->addMultiCellWidget(gridStatus, 1, 1, 1, 2);
163         layout->addWidget(gridStatus, 1, 1, 1, 2);
164 //    layout->addColSpacing(1, 50);
165         layout->addItem(new QSpacerItem(50, 0), 0, 1);
166
167         setMouseTracking(true);
168         // flickering under win:
169         //setFocusPolicy(WheelFocus);
170
171 #warning "QG_GraphicView constructor is setting Qt::NoFocus!!!"
172 // A-HAH! THIS IS THE PROBLEM!!!
173 //    setFocusPolicy(Qt::NoFocus);
174 //hm.
175 //      setFocusPolicy(Qt::StrongFocus);
176 }
177
178 /**
179  * Destructor
180  */
181 QG_GraphicView::~QG_GraphicView()
182 {
183         if (painter)
184                 delete painter;
185
186 //meh   if (buffer)
187 //      {
188 //              delete buffer;
189 //              buffer = NULL;
190 //      }
191
192         cleanUp();
193 }
194
195 /**
196  * @return width of widget.
197  */
198 int QG_GraphicView::getWidth()
199 {
200         return width() - vScrollBar->sizeHint().width();
201 }
202
203 /**
204  * @return height of widget.
205  */
206 int QG_GraphicView::getHeight()
207 {
208         return height() - hScrollBar->sizeHint().height();
209 }
210
211 /**
212  * Changes the current background color of this view.
213  */
214 void QG_GraphicView::setBackground(const RS_Color & bg)
215 {
216         GraphicView::setBackground(bg);
217
218 //      setBackgroundColor(bg);
219         QPalette palette;
220         palette.setColor(backgroundRole(), bg);
221         setPalette(palette);
222 }
223
224 /**
225  * Sets the mouse cursor to the given type.
226  */
227 void QG_GraphicView::setMouseCursor(RS2::CursorType c)
228 {
229         switch (c)
230         {
231         default:
232         case RS2::ArrowCursor:
233                 setCursor(Qt::ArrowCursor);
234                 break;
235         case RS2::UpArrowCursor:
236                 setCursor(Qt::UpArrowCursor);
237                 break;
238         case RS2::CrossCursor:
239                 setCursor(Qt::CrossCursor);
240                 break;
241         case RS2::WaitCursor:
242                 setCursor(Qt::WaitCursor);
243                 break;
244         case RS2::IbeamCursor:
245                 setCursor(Qt::IBeamCursor);
246                 break;
247         case RS2::SizeVerCursor:
248                 setCursor(Qt::SizeVerCursor);
249                 break;
250         case RS2::SizeHorCursor:
251                 setCursor(Qt::SizeHorCursor);
252                 break;
253         case RS2::SizeBDiagCursor:
254                 setCursor(Qt::SizeBDiagCursor);
255                 break;
256         case RS2::SizeFDiagCursor:
257                 setCursor(Qt::SizeFDiagCursor);
258                 break;
259         case RS2::SizeAllCursor:
260                 setCursor(Qt::SizeAllCursor);
261                 break;
262         case RS2::BlankCursor:
263                 setCursor(Qt::BlankCursor);
264                 break;
265         case RS2::SplitVCursor:
266                 setCursor(Qt::SplitVCursor);
267                 break;
268         case RS2::SplitHCursor:
269                 setCursor(Qt::SplitHCursor);
270                 break;
271         case RS2::PointingHandCursor:
272                 setCursor(Qt::PointingHandCursor);
273                 break;
274         case RS2::ForbiddenCursor:
275                 setCursor(Qt::ForbiddenCursor);
276                 break;
277         case RS2::WhatsThisCursor:
278                 setCursor(Qt::WhatsThisCursor);
279                 break;
280
281 #ifndef __APPLE__
282         case RS2::CadCursor:
283                 setCursor(*curCad);
284                 break;
285         case RS2::DelCursor:
286                 setCursor(*curDel);
287                 break;
288         case RS2::SelectCursor:
289                 setCursor(*curSelect);
290                 break;
291         case RS2::MagnifierCursor:
292                 setCursor(*curMagnifier);
293                 break;
294         case RS2::MovingHandCursor:
295                 setCursor(*curHand);
296                 break;
297 #else
298                 // Reduced cursor selection for the Mac:
299         case RS2::CadCursor:
300                 setCursor(Qt::CrossCursor);
301                 break;
302         case RS2::DelCursor:
303                 setCursor(Qt::CrossCursor);
304                 break;
305         case RS2::SelectCursor:
306                 setCursor(Qt::CrossCursor);
307                 break;
308         case RS2::MagnifierCursor:
309                 setCursor(Qt::CrossCursor);
310                 break;
311         case RS2::MovingHandCursor:
312                 setCursor(Qt::PointingHandCursor);
313                 break;
314 #endif
315         }
316 }
317
318 /**
319  * Sets the text for the grid status widget in the left bottom corner.
320  */
321 void QG_GraphicView::updateGridStatusWidget(const QString & text)
322 {
323         gridStatus->setText(text);
324 }
325
326 /**
327  * Redraws the widget.
328  */
329 void QG_GraphicView::redraw()
330 {
331         RS_DEBUG->print("QG_GraphicView::redraw begin 1");
332
333         if (simulationRunning)
334                 return;
335
336 //Also, this stuff is properly taken care of by the Qt toolkit--
337 //so we don't have to be concerned with shit like this as long
338 //as we use update() instead of repaint()
339         // never run twice
340         static bool running = false;
341
342         if (!running)
343         {
344                 running = true;
345                 RS_DEBUG->print("QG_GraphicView::redraw begin 2");
346
347 /*
348 This is the only place in the entire codebase that a proper update is
349 triggered.
350 */
351                 if (isUpdateEnabled())
352 //                      repaint(false);
353                         update();
354
355                 RS_DEBUG->print("QG_GraphicView::redraw end 2");
356                 running = false;
357         }
358
359         RS_DEBUG->print("QG_GraphicView::redraw end 1");
360 }
361
362 void QG_GraphicView::resizeEvent(QResizeEvent * /*e*/)
363 {
364         RS_DEBUG->print("QG_GraphicView::resizeEvent begin");
365         adjustOffsetControls();
366         adjustZoomControls();
367         updateGrid();
368         RS_DEBUG->print("QG_GraphicView::resizeEvent end");
369 }
370
371 /*
372 This is retarded. There is absolutely no reason to have this shit in here.
373 This could be easily called from whoever calls this crap.
374
375 And so... We remove it.
376 */
377 #if 0
378 // Next three methods from RS_LayerListListener Interface:
379 void QG_GraphicView::layerEdited(RS_Layer *)
380 {
381         redraw();
382 }
383
384 void QG_GraphicView::layerRemoved(RS_Layer *)
385 {
386         redraw();
387 }
388
389 void QG_GraphicView::layerToggled(RS_Layer *)
390 {
391         redraw();
392 }
393 #endif
394
395 void QG_GraphicView::emulateMouseMoveEvent()
396 {
397 //      QMouseEvent e(QEvent::MouseMove, QPoint(mx, my), Qt::NoButton, Qt::NoButton);
398         //mouseMoveEvent(&e);
399 }
400
401 void QG_GraphicView::mousePressEvent(QMouseEvent * e)
402 {
403         // pan zoom with middle mouse button
404         if (e->button() == Qt::MidButton /*|| (e->state()==Qt::LeftButton|Qt::AltButton)*/)
405                 setCurrentAction(new RS_ActionZoomPan(*container, *this));
406
407         GraphicView::mousePressEvent(e);
408         QWidget::mousePressEvent(e);
409 }
410
411 void QG_GraphicView::mouseReleaseEvent(QMouseEvent * e)
412 {
413         RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent");
414         GraphicView::mouseReleaseEvent(e);
415         //QWidget::mouseReleaseEvent(e);
416
417         if (!e->isAccepted())
418         {
419                 if (QG_DIALOGFACTORY && QG_DIALOGFACTORY->getCadToolBar())
420                 {
421                         RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: fwd to cadtoolbar");
422                         QG_DIALOGFACTORY->getCadToolBar()->mouseReleaseEvent(e);
423                 }
424         }
425
426         RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: OK");
427 }
428
429 void QG_GraphicView::mouseMoveEvent(QMouseEvent * e)
430 {
431         //RS_DEBUG->print("QG_GraphicView::mouseMoveEvent begin");
432         //QMouseEvent rsm = QG_Qt2Rs::mouseEvent(e);
433
434         GraphicView::mouseMoveEvent(e);
435         QWidget::mouseMoveEvent(e);
436
437 //What kind of cacamamie crap is this???
438 //#ifdef Q_OS_WIN32
439 //      // make sure that we can still use hotkeys and the mouse wheel
440 //      if (parent() != NULL)
441 //              ((QWidget *)parent())->setFocus();
442 //#endif
443
444         //RS_DEBUG->print("QG_GraphicView::mouseMoveEvent end");
445 }
446
447 /**
448  * support for the wacom graphic tablet.
449  */
450 void QG_GraphicView::tabletEvent(QTabletEvent * e)
451 {
452 //      if (hasMouse())
453         if (testAttribute(Qt::WA_UnderMouse))
454         {
455                 switch (e->device())
456                 {
457                 case QTabletEvent::Eraser:
458                         if (e->type() == QEvent::TabletRelease)
459                         {
460                                 if (container != NULL)
461                                 {
462                                         RS_ActionSelectSingle * a = new RS_ActionSelectSingle(*container, *this);
463                                         setCurrentAction(a);
464 #warning "!!! !!!"
465 //                                      QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(), Qt::LeftButton, Qt::LeftButton);
466 //                                      mouseReleaseEvent(&ev);
467                                         a->finish();
468
469                                         if (container->countSelected() > 0)
470                                                 setCurrentAction(new RS_ActionModifyDelete(*container, *this));
471                                 }
472                         }
473                         break;
474
475                 case QTabletEvent::Stylus:
476                 case QTabletEvent::Puck:
477                         if (e->type() == QEvent::TabletPress)
478                         {
479 #warning "!!! !!!"
480 //                              QMouseEvent ev(QEvent::MouseButtonPress, e->pos(), Qt::LeftButton, Qt::LeftButton);
481 //                              mousePressEvent(&ev);
482                         }
483                         else if (e->type() == QEvent::TabletRelease)
484                         {
485 #warning "!!! !!!"
486 //                              QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(), Qt::LeftButton, Qt::LeftButton);
487 //                              mouseReleaseEvent(&ev);
488                         }
489                         else if (e->type() == QEvent::TabletMove)
490                         {
491 #warning "!!! !!!"
492 //                              QMouseEvent ev(QEvent::MouseMove, e->pos(), Qt::NoButton, 0);
493 //                              mouseMoveEvent(&ev);
494                         }
495                         break;
496
497                 default:
498                         break;
499                 }
500         }
501
502         // a 'mouse' click:
503         /*if (e->pressure()>10 && lastPressure<10) {
504                 QMouseEvent e(QEvent::MouseButtonPress, e->pos(),
505                 Qt::LeftButton, Qt::LeftButton);
506                 mousePressEvent(&e);
507 }
508         else if (e->pressure()<10 && lastPressure>10) {
509                 QMouseEvent e(QEvent::MouseButtonRelease, e->pos(),
510                 Qt::LeftButton, Qt::LeftButton);
511                 mouseReleaseEvent(&e);
512 }       else if (lastPos!=e->pos()) {
513                 QMouseEvent e(QEvent::MouseMove, e->pos(),
514                 Qt::NoButton, 0);
515                 mouseMoveEvent(&e);
516 }
517
518         lastPressure = e->pressure();
519         lastPos = e->pos();
520         */
521 }
522
523 void QG_GraphicView::leaveEvent(QEvent * e)
524 {
525         GraphicView::mouseLeaveEvent();
526         QWidget::leaveEvent(e);
527 }
528
529 void QG_GraphicView::enterEvent(QEvent * e)
530 {
531         GraphicView::mouseEnterEvent();
532         QWidget::enterEvent(e);
533 }
534
535 void QG_GraphicView::focusOutEvent(QFocusEvent * e)
536 {
537         QWidget::focusOutEvent(e);
538 }
539
540 void QG_GraphicView::focusInEvent(QFocusEvent * e)
541 {
542 //printf("-->QG_GraphicView::focusInEvent(): Start. this %s focus...\n", (hasFocus() ? "has" : "DOES NOT HAVE"));
543         GraphicView::mouseEnterEvent();
544         QWidget::focusInEvent(e);
545 //printf("-->QG_GraphicView::focusInEvent(): End.   this %s focus...\n", (hasFocus() ? "has" : "DOES NOT HAVE"));
546 }
547
548 /**
549  * mouse wheel event. zooms in/out or scrolls when
550  * shift or ctrl is pressed.
551  */
552 void QG_GraphicView::wheelEvent(QWheelEvent * e)
553 {
554         //RS_DEBUG->print("wheel: %d", e->delta());
555
556         //printf("state: %d\n", e->state());
557         //printf("ctrl: %d\n", Qt::ControlButton);
558         if (!container)
559                 return;
560
561         Qt::KeyboardModifiers keyState = QApplication::keyboardModifiers();
562         Vector mouse = toGraph(Vector(e->x(), e->y()));
563
564         bool scroll = false;
565         RS2::Direction direction = RS2::Up;
566
567         // scroll up / down:
568 //      if (e->state() == Qt::ControlModifier)
569         if (keyState == Qt::ControlModifier)
570         {
571                 scroll = true;
572
573                 if (e->delta() > 0)
574                         direction = RS2::Up;
575                 else
576                         direction = RS2::Down;
577         }
578         // scroll left / right:
579 //      else if (e->state() == Qt::ShiftModifier)
580         else if (keyState == Qt::ShiftModifier)
581         {
582                 scroll = true;
583
584                 if (e->delta() > 0)
585                         direction = RS2::Right;
586                 else
587                         direction = RS2::Left;
588         }
589
590         if (scroll)
591                 setCurrentAction(new RS_ActionZoomScroll(direction, *container, *this));
592         // zoom in / out:
593 //      else if (e->state() == 0)
594         else if (keyState == 0)
595         {
596                 if (e->delta() > 0)
597                         setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::In, RS2::Both, mouse));
598                 else
599                         setCurrentAction(new RS_ActionZoomIn(*container, *this, RS2::Out, RS2::Both, mouse));
600         }
601
602         e->accept();
603 }
604
605 void QG_GraphicView::keyPressEvent(QKeyEvent * e)
606 {
607         if (!container)
608                 return;
609
610         bool scroll = false;
611         RS2::Direction direction = RS2::Up;
612
613         switch (e->key())
614         {
615         case Qt::Key_Left:
616                 scroll = true;
617                 direction = RS2::Right;
618                 break;
619         case Qt::Key_Right:
620                 scroll = true;
621                 direction = RS2::Left;
622                 break;
623         case Qt::Key_Up:
624                 scroll = true;
625                 direction = RS2::Up;
626                 break;
627         case Qt::Key_Down:
628                 scroll = true;
629                 direction = RS2::Down;
630                 break;
631         default:
632                 scroll = false;
633                 break;
634         }
635
636         if (scroll)
637                 setCurrentAction(new RS_ActionZoomScroll(direction, *container, *this));
638
639         GraphicView::keyPressEvent(e);
640 }
641
642 void QG_GraphicView::keyReleaseEvent(QKeyEvent * e)
643 {
644         GraphicView::keyReleaseEvent(e);
645 }
646
647 /**
648  * Called whenever the graphic view has changed.
649  * Adjusts the scrollbar ranges / steps.
650  */
651 void QG_GraphicView::adjustOffsetControls()
652 {
653         static bool running = false;
654
655         if (running)
656                 return;
657
658         running = true;
659
660         RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() begin");
661
662         if (!container || !hScrollBar || !vScrollBar)
663                 return;
664
665         disableUpdate();
666         int ox = getOffsetX();
667         int oy = getOffsetY();
668
669         Vector min = container->getMin();
670         Vector max = container->getMax();
671
672         // no drawing yet - still allow to scroll
673         if (max.x < min.x + 1.0e-6 || max.y < min.y + 1.0e-6
674                 || max.x > RS_MAXDOUBLE || max.x < RS_MINDOUBLE
675                 || min.x > RS_MAXDOUBLE || min.x < RS_MINDOUBLE
676                 || max.y > RS_MAXDOUBLE || max.y < RS_MINDOUBLE
677                 || min.y > RS_MAXDOUBLE || min.y < RS_MINDOUBLE)
678         {
679                 min = Vector(-10, -10);
680                 max = Vector(100, 100);
681         }
682
683         int minVal = (int)(min.x * getFactor().x - QG_SCROLLMARGIN - getBorderLeft());
684         int maxVal = (int)(max.x * getFactor().x - getWidth() + QG_SCROLLMARGIN + getBorderRight());
685
686         hScrollBar->setValue(0);
687
688         if (minVal <= maxVal)
689                 hScrollBar->setRange(minVal, maxVal);
690
691         minVal = (int)(getHeight() - max.y * getFactor().y
692                 - QG_SCROLLMARGIN - getBorderTop());
693         maxVal = (int)(QG_SCROLLMARGIN + getBorderBottom()
694                 - (min.y * getFactor().y));
695
696         if (minVal <= maxVal)
697                 vScrollBar->setRange(minVal, maxVal);
698
699         hScrollBar->setPageStep((int)(getWidth()));
700         vScrollBar->setPageStep((int)(getHeight()));
701
702         hScrollBar->setValue(-ox);
703         vScrollBar->setValue(oy);
704
705         slotHScrolled(-ox);
706         slotVScrolled(oy);
707
708         RS_DEBUG->print("H min: %d / max: %d / step: %d / value: %d\n",
709                 hScrollBar->minimum(), hScrollBar->maximum(), hScrollBar->pageStep(), ox);
710         RS_DEBUG->print("V min: %d / max: %d / step: %d / value: %d\n",
711                 vScrollBar->minimum(), vScrollBar->maximum(), vScrollBar->pageStep(), oy);
712
713         enableUpdate();
714
715         RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() end");
716
717         running = false;
718 }
719
720 /**
721  * override this to adjust controls and widgets that
722  * control the zoom factor of the graphic.
723  */
724 void QG_GraphicView::adjustZoomControls()
725 {
726 }
727
728 /**
729  * Slot for horizontal scroll events.
730  */
731 void QG_GraphicView::slotHScrolled(int value)
732 {
733         // Scrollbar behaviour tends to change with every Qt version..
734         // so let's keep old code in here for now
735
736         //static int running = false;
737         //if (!running) {
738         //running = true;
739         ////RS_DEBUG->print("value x: %d\n", value);
740         if (hScrollBar->maximum() == hScrollBar->minimum())
741                 centerOffsetX();
742         else
743                 setOffsetX(-value);
744
745         //if (isUpdateEnabled()) {
746         updateGrid();
747         redraw();
748         //}
749         ////updateView();
750         //running = false;
751         //}
752 }
753
754 /**
755  * Slot for vertical scroll events.
756  */
757 void QG_GraphicView::slotVScrolled(int value)
758 {
759         // Scrollbar behaviour tends to change with every Qt version..
760         // so let's keep old code in here for now
761
762         //static int running = false;
763         //if (!running) {
764         //running = true;
765         ////RS_DEBUG->print("value y: %d\n", value);
766         if (vScrollBar->maximum() == vScrollBar->minimum())
767                 centerOffsetY();
768         else
769                 setOffsetY(value);
770
771         //if (isUpdateEnabled()) {
772         updateGrid();
773         redraw();
774         //}
775         ////updateView();
776         //running = false;
777         //}
778 }
779
780 /**
781  * Handles paint events by redrawing the graphic in this view.
782  * usually that's very fast since we only paint the buffer we
783  * have from the last call..
784  *
785  * This is not true anymore--even if it was true in the first place, which
786  * seems doubtful to me. Everything is redrawn every time; we need to see if
787  * relying on Qt do to the clipping is wise or not... Also, we need to clarify
788  * all rendering paths since they are not all logical or consistent.
789  */
790 void QG_GraphicView::paintEvent(QPaintEvent *)
791 {
792         RS_DEBUG->print("QG_GraphicView::paintEvent begin");
793
794         if (simulationRunning)
795                 return;
796
797 /*
798 To fix the broken rendering here, we need to do one of the following:
799
800 1) Put preview object here and fix draw code to do an update() instead
801    of trying to draw directly to a widget context
802 2) Use a QPixmap as a randomly drawable surface and fix createDirectPainter()
803    to do an update() after drawing to the pixmap which will eventually end
804    up here.
805
806 I think 1) is cleaner in the long run, and will make the codebase much more
807 maintainable. However, 2) would make it possible to fix things fairly easily
808 without having to rearrange classes too much.
809
810 The way the UI is written is crap. It tries to be clever by doing direct
811 painting, bypassing the toolkit's built in rendering pipeline. Also, there
812 are tons of references to Qt stuff in what is supposed to be a toolkit
813 independent manner, resulting in unnecessary divisions of code and rendundant
814 class definitions. Still, the core is still useful and worth fixing just to
815 have something back in portage. We can make it better, faster, stronger. ;-)
816
817 If we can make the UI more like Inkscape we'll be in good shape. Plus elements
818 of VectorWorks & etc. as well...
819 */
820
821 // Qt4 handles double buffering of screen writes now, so this needs
822 // a rewrite.
823 #warning "!!! Need to pass a valid QPainter to drawIt() !!!"
824
825         QPainter pntr(this);
826         pntr.setBackgroundMode(Qt::OpaqueMode);
827         pntr.setBackground(QBrush(background));
828
829         painter = new PaintInterface(&pntr);
830
831 //Note that we do drawIt() regardless here because paintEvent() clears the background
832 //*unless* we create the window with a specific style. Depending on our draw code, we
833 //just may go that way...
834         drawIt();
835
836         // Draw the snapper first, we want to be able to see the preview on top of
837         // this...
838         if (snapper.Visible())
839                 snapper.Draw(this, painter);
840
841         if (preview.Visible())
842         {
843                 painter->setPen(RS_Pen(RS_Color(60, 255, 80), RS2::Width00, RS2::SolidLine));
844                 painter->setOffset(preview.Offset());
845
846                 // We have to traverse the container ourselves, because RS_Container::draw()
847                 // uses drawEntity() instead of drawEntityPlain()...
848                 for(RS_Entity * e=preview.firstEntity(RS2::ResolveNone); e!=NULL;
849                         e = preview.nextEntity(RS2::ResolveNone))
850                 {
851                         drawEntityPlain(e);
852                 }
853
854                 painter->setOffset(Vector(0, 0));
855         }
856
857         delete painter;
858         painter = NULL;
859
860         RS_DEBUG->print("QG_GraphicView::paintEvent end");
861 }