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