]> Shamusworld >> Repos - architektonas/blob - src/widgets/qg_graphicview.cpp
9e68c5df957d12cf19b0cf2b31b4960bbbd5204b
[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 "qg_dialogfactory.h"
18 #include "actiondefault.h"
19 #include "actionzoomin.h"
20 #include "actionzoompan.h"
21 #include "actionzoomscroll.h"
22 #include "actionmodifydelete.h"
23 #include "actionselectsingle.h"
24 #include "cadtoolbar.h"
25 #include "rs_dialogfactory.h"
26 #include "drawing.h"
27 #include "graphicview.h"
28 #include "rs_patternlist.h"
29 #include "paintinterface.h"
30 #include "rs_preview.h"
31 #include "settings.h"
32 #include "rs_system.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 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 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         GraphicView::mouseMoveEvent(e);
432         QWidget::mouseMoveEvent(e);
433 }
434
435 /**
436  * support for the wacom graphic tablet.
437  */
438 void QG_GraphicView::tabletEvent(QTabletEvent * e)
439 {
440 //      if (hasMouse())
441         if (testAttribute(Qt::WA_UnderMouse))
442         {
443                 switch (e->device())
444                 {
445                 case QTabletEvent::Eraser:
446                         if (e->type() == QEvent::TabletRelease)
447                         {
448                                 if (container != NULL)
449                                 {
450                                         ActionSelectSingle * a = new ActionSelectSingle(*container, *this);
451                                         setCurrentAction(a);
452 #warning "!!! !!!"
453 //                                      QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(), Qt::LeftButton, Qt::LeftButton);
454 //                                      mouseReleaseEvent(&ev);
455                                         a->finish();
456
457                                         if (container->countSelected() > 0)
458                                                 setCurrentAction(new ActionModifyDelete(*container, *this));
459                                 }
460                         }
461                         break;
462
463                 case QTabletEvent::Stylus:
464                 case QTabletEvent::Puck:
465                         if (e->type() == QEvent::TabletPress)
466                         {
467 #warning "!!! !!!"
468 //                              QMouseEvent ev(QEvent::MouseButtonPress, e->pos(), Qt::LeftButton, Qt::LeftButton);
469 //                              mousePressEvent(&ev);
470                         }
471                         else if (e->type() == QEvent::TabletRelease)
472                         {
473 #warning "!!! !!!"
474 //                              QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(), Qt::LeftButton, Qt::LeftButton);
475 //                              mouseReleaseEvent(&ev);
476                         }
477                         else if (e->type() == QEvent::TabletMove)
478                         {
479 #warning "!!! !!!"
480 //                              QMouseEvent ev(QEvent::MouseMove, e->pos(), Qt::NoButton, 0);
481 //                              mouseMoveEvent(&ev);
482                         }
483                         break;
484
485                 default:
486                         break;
487                 }
488         }
489
490         // a 'mouse' click:
491         /*if (e->pressure()>10 && lastPressure<10) {
492                 QMouseEvent e(QEvent::MouseButtonPress, e->pos(),
493                 Qt::LeftButton, Qt::LeftButton);
494                 mousePressEvent(&e);
495 }
496         else if (e->pressure()<10 && lastPressure>10) {
497                 QMouseEvent e(QEvent::MouseButtonRelease, e->pos(),
498                 Qt::LeftButton, Qt::LeftButton);
499                 mouseReleaseEvent(&e);
500 }       else if (lastPos!=e->pos()) {
501                 QMouseEvent e(QEvent::MouseMove, e->pos(),
502                 Qt::NoButton, 0);
503                 mouseMoveEvent(&e);
504 }
505
506         lastPressure = e->pressure();
507         lastPos = e->pos();
508         */
509 }
510
511 void QG_GraphicView::leaveEvent(QEvent * e)
512 {
513         GraphicView::mouseLeaveEvent();
514         QWidget::leaveEvent(e);
515 }
516
517 void QG_GraphicView::enterEvent(QEvent * e)
518 {
519         GraphicView::mouseEnterEvent();
520         QWidget::enterEvent(e);
521 }
522
523 void QG_GraphicView::focusOutEvent(QFocusEvent * e)
524 {
525         QWidget::focusOutEvent(e);
526 }
527
528 void QG_GraphicView::focusInEvent(QFocusEvent * e)
529 {
530 //printf("-->QG_GraphicView::focusInEvent(): Start. this %s focus...\n", (hasFocus() ? "has" : "DOES NOT HAVE"));
531         GraphicView::mouseEnterEvent();
532         QWidget::focusInEvent(e);
533 //printf("-->QG_GraphicView::focusInEvent(): End.   this %s focus...\n", (hasFocus() ? "has" : "DOES NOT HAVE"));
534 }
535
536 /**
537  * mouse wheel event. zooms in/out or scrolls when
538  * shift or ctrl is pressed.
539  */
540 void QG_GraphicView::wheelEvent(QWheelEvent * e)
541 {
542         //RS_DEBUG->print("wheel: %d", e->delta());
543
544         //printf("state: %d\n", e->state());
545         //printf("ctrl: %d\n", Qt::ControlButton);
546         if (!container)
547                 return;
548
549         Qt::KeyboardModifiers keyState = QApplication::keyboardModifiers();
550         Vector mouse = toGraph(Vector(e->x(), e->y()));
551
552         bool scroll = false;
553         RS2::Direction direction = RS2::Up;
554
555         // scroll up / down:
556 //      if (e->state() == Qt::ControlModifier)
557         if (keyState == Qt::ControlModifier)
558         {
559                 scroll = true;
560
561                 if (e->delta() > 0)
562                         direction = RS2::Up;
563                 else
564                         direction = RS2::Down;
565         }
566         // scroll left / right:
567 //      else if (e->state() == Qt::ShiftModifier)
568         else if (keyState == Qt::ShiftModifier)
569         {
570                 scroll = true;
571
572                 if (e->delta() > 0)
573                         direction = RS2::Right;
574                 else
575                         direction = RS2::Left;
576         }
577
578         if (scroll)
579                 setCurrentAction(new ActionZoomScroll(direction, *container, *this));
580         // zoom in / out:
581 //      else if (e->state() == 0)
582         else if (keyState == 0)
583         {
584                 if (e->delta() > 0)
585                         setCurrentAction(new ActionZoomIn(*container, *this, RS2::In, RS2::Both, mouse));
586                 else
587                         setCurrentAction(new ActionZoomIn(*container, *this, RS2::Out, RS2::Both, mouse));
588         }
589
590         e->accept();
591 }
592
593 void QG_GraphicView::keyPressEvent(QKeyEvent * e)
594 {
595         if (!container)
596                 return;
597
598         bool scroll = false;
599         RS2::Direction direction = RS2::Up;
600
601         switch (e->key())
602         {
603         case Qt::Key_Left:
604                 scroll = true;
605                 direction = RS2::Right;
606                 break;
607         case Qt::Key_Right:
608                 scroll = true;
609                 direction = RS2::Left;
610                 break;
611         case Qt::Key_Up:
612                 scroll = true;
613                 direction = RS2::Up;
614                 break;
615         case Qt::Key_Down:
616                 scroll = true;
617                 direction = RS2::Down;
618                 break;
619         default:
620                 scroll = false;
621                 break;
622         }
623
624         if (scroll)
625                 setCurrentAction(new ActionZoomScroll(direction, *container, *this));
626
627         GraphicView::keyPressEvent(e);
628 }
629
630 void QG_GraphicView::keyReleaseEvent(QKeyEvent * e)
631 {
632         GraphicView::keyReleaseEvent(e);
633 }
634
635 /**
636  * Called whenever the graphic view has changed.
637  * Adjusts the scrollbar ranges / steps.
638  */
639 void QG_GraphicView::adjustOffsetControls()
640 {
641         static bool running = false;
642
643         if (running)
644                 return;
645
646         running = true;
647
648         RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() begin");
649
650         if (!container || !hScrollBar || !vScrollBar)
651                 return;
652
653         disableUpdate();
654         int ox = getOffsetX();
655         int oy = getOffsetY();
656
657         Vector min = container->getMin();
658         Vector max = container->getMax();
659
660         // no drawing yet - still allow to scroll
661         if (max.x < min.x + 1.0e-6 || max.y < min.y + 1.0e-6
662                 || max.x > RS_MAXDOUBLE || max.x < RS_MINDOUBLE
663                 || min.x > RS_MAXDOUBLE || min.x < RS_MINDOUBLE
664                 || max.y > RS_MAXDOUBLE || max.y < RS_MINDOUBLE
665                 || min.y > RS_MAXDOUBLE || min.y < RS_MINDOUBLE)
666         {
667                 min = Vector(-10, -10);
668                 max = Vector(100, 100);
669         }
670
671         int minVal = (int)(min.x * getFactor().x - QG_SCROLLMARGIN - getBorderLeft());
672         int maxVal = (int)(max.x * getFactor().x - getWidth() + QG_SCROLLMARGIN + getBorderRight());
673
674         hScrollBar->setValue(0);
675
676         if (minVal <= maxVal)
677                 hScrollBar->setRange(minVal, maxVal);
678
679         minVal = (int)(getHeight() - max.y * getFactor().y
680                 - QG_SCROLLMARGIN - getBorderTop());
681         maxVal = (int)(QG_SCROLLMARGIN + getBorderBottom()
682                 - (min.y * getFactor().y));
683
684         if (minVal <= maxVal)
685                 vScrollBar->setRange(minVal, maxVal);
686
687         hScrollBar->setPageStep((int)(getWidth()));
688         vScrollBar->setPageStep((int)(getHeight()));
689
690         hScrollBar->setValue(-ox);
691         vScrollBar->setValue(oy);
692
693         slotHScrolled(-ox);
694         slotVScrolled(oy);
695
696         RS_DEBUG->print("H min: %d / max: %d / step: %d / value: %d\n",
697                 hScrollBar->minimum(), hScrollBar->maximum(), hScrollBar->pageStep(), ox);
698         RS_DEBUG->print("V min: %d / max: %d / step: %d / value: %d\n",
699                 vScrollBar->minimum(), vScrollBar->maximum(), vScrollBar->pageStep(), oy);
700
701         enableUpdate();
702
703         RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() end");
704
705         running = false;
706 }
707
708 /**
709  * override this to adjust controls and widgets that
710  * control the zoom factor of the graphic.
711  */
712 void QG_GraphicView::adjustZoomControls()
713 {
714 }
715
716 /**
717  * Slot for horizontal scroll events.
718  */
719 void QG_GraphicView::slotHScrolled(int value)
720 {
721         // Scrollbar behaviour tends to change with every Qt version..
722         // so let's keep old code in here for now
723
724         //static int running = false;
725         //if (!running) {
726         //running = true;
727         ////RS_DEBUG->print("value x: %d\n", value);
728         if (hScrollBar->maximum() == hScrollBar->minimum())
729                 centerOffsetX();
730         else
731                 setOffsetX(-value);
732
733         //if (isUpdateEnabled()) {
734         updateGrid();
735         redraw();
736         //}
737         ////updateView();
738         //running = false;
739         //}
740 }
741
742 /**
743  * Slot for vertical scroll events.
744  */
745 void QG_GraphicView::slotVScrolled(int value)
746 {
747         // Scrollbar behaviour tends to change with every Qt version..
748         // so let's keep old code in here for now
749
750         //static int running = false;
751         //if (!running) {
752         //running = true;
753         ////RS_DEBUG->print("value y: %d\n", value);
754         if (vScrollBar->maximum() == vScrollBar->minimum())
755                 centerOffsetY();
756         else
757                 setOffsetY(value);
758
759         //if (isUpdateEnabled()) {
760         updateGrid();
761         redraw();
762         //}
763         ////updateView();
764         //running = false;
765         //}
766 }
767
768 /**
769  * Handles paint events by redrawing the graphic in this view.
770  * usually that's very fast since we only paint the buffer we
771  * have from the last call..
772  *
773  * This is not true anymore--even if it was true in the first place, which
774  * seems doubtful to me. Everything is redrawn every time; we need to see if
775  * relying on Qt do to the clipping is wise or not... Also, we need to clarify
776  * all rendering paths since they are not all logical or consistent.
777  */
778 void QG_GraphicView::paintEvent(QPaintEvent *)
779 {
780         RS_DEBUG->print("QG_GraphicView::paintEvent begin");
781
782         if (simulationRunning)
783                 return;
784
785 /*
786 To fix the broken rendering here, we need to do one of the following:
787
788 1) Put preview object here and fix draw code to do an update() instead
789    of trying to draw directly to a widget context
790 2) Use a QPixmap as a randomly drawable surface and fix createDirectPainter()
791    to do an update() after drawing to the pixmap which will eventually end
792    up here.
793
794 I think 1) is cleaner in the long run, and will make the codebase much more
795 maintainable. However, 2) would make it possible to fix things fairly easily
796 without having to rearrange classes too much.
797
798 The way the UI is written is crap. It tries to be clever by doing direct
799 painting, bypassing the toolkit's built in rendering pipeline. Also, there
800 are tons of references to Qt stuff in what is supposed to be a toolkit
801 independent manner, resulting in unnecessary divisions of code and rendundant
802 class definitions. Still, the core is still useful and worth fixing just to
803 have something back in portage. We can make it better, faster, stronger. ;-)
804
805 If we can make the UI more like Inkscape we'll be in good shape. Plus elements
806 of VectorWorks & etc. as well...
807 */
808
809 // Qt4 handles double buffering of screen writes now, so this needs
810 // a rewrite.
811 #warning "!!! Need to pass a valid QPainter to drawIt() !!!"
812
813         QPainter pntr(this);
814         pntr.setBackgroundMode(Qt::OpaqueMode);
815         pntr.setBackground(QBrush(background));
816
817         painter = new PaintInterface(&pntr);
818
819 //Note that we do drawIt() regardless here because paintEvent() clears the background
820 //*unless* we create the window with a specific style. Depending on our draw code, we
821 //just may go that way...
822         drawIt();
823
824         // Draw the snapper first, we want to be able to see the preview on top of
825         // this...
826         if (snapper.Visible())
827                 snapper.Draw(this, painter);
828
829         if (preview.Visible())
830 #if 0
831         {
832                 painter->setPen(RS_Pen(RS_Color(60, 255, 80), RS2::Width00, RS2::SolidLine));
833                 painter->setOffset(preview.Offset());
834
835                 // We have to traverse the container ourselves, because RS_Container::draw()
836                 // uses drawEntity() instead of drawEntityPlain()...
837                 for(RS_Entity * e=preview.firstEntity(RS2::ResolveNone); e!=NULL;
838                         e = preview.nextEntity(RS2::ResolveNone))
839                 {
840                         drawEntityPlain(e);
841                 }
842
843                 painter->setOffset(Vector(0, 0));
844         }
845 #else
846                 preview.Draw(this, painter);
847 #endif
848
849         delete painter;
850         painter = NULL;
851
852         RS_DEBUG->print("QG_GraphicView::paintEvent end");
853 }