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