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