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