4 #include <QtPrintSupport/qtprintsupportglobal.h> 6 #include <QPrintDialog> 7 #include <QPrinterInfo> 9 #include <QSvgGenerator> 28 <<
"Portable Document Files (*.pdf)" 29 <<
"Vector Graphics (*.svg)" 32 const QPen
BaseView::PEN_SELECT(QColor(0,144,0,180), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
36 : QGraphicsView(), view(v)
38 grabGesture(Qt::PanGesture);
39 grabGesture(Qt::PinchGesture);
49 case QEvent::HoverEnter:
50 case QEvent::HoverLeave:
51 case QEvent::MouseButtonPress:
52 case QEvent::GraphicsSceneMousePress:
53 std::cout <<
"break" << std::endl;
60 return QGraphicsView::event(
event);
65 QGraphicsView::mousePressEvent(
event);
71 QGraphicsView::mouseMoveEvent(
event);
76 if (
event->modifiers() & Qt::ControlModifier) {
78 QGraphicsView::wheelEvent(
event);
82 if (
event->delta() > 0)
100 case Qt::Key_4:
singleStep(horizontalScrollBar(),-1);
break;
102 case Qt::Key_6:
singleStep(horizontalScrollBar(),+1);
break;
104 case Qt::Key_8:
singleStep(verticalScrollBar(),-1);
break;
106 case Qt::Key_2:
singleStep(verticalScrollBar(),+1);
break;
109 case Qt::Key_9:
pageStep(verticalScrollBar(),-1);
break;
110 case Qt::Key_PageDown:
111 case Qt::Key_3:
pageStep(verticalScrollBar(),+1);
break;
118 if (gest =
event->gesture(Qt::PanGesture)) {
119 QPanGesture* pan = static_cast<QPanGesture*>(gest);
120 QPointF delta = pan->delta();
127 if (gest =
event->gesture(Qt::PinchGesture))
129 QPinchGesture* pinch = static_cast<QPinchGesture *>(gest);
130 QPointF center = pinch->centerPoint();
131 double scale = pinch->scaleFactor();
139 switch(pinch->state())
141 case Qt::GestureStarted:
144 case Qt::GestureUpdated:
145 case Qt::GestureFinished:
146 double angle = pinch->rotationAngle();
160 bar->setValue(bar->value() + round(factor*bar->singleStep()));
165 bar->setValue(bar->value() + round(factor*bar->pageStep()));
179 graphicsView->setRenderHint(QPainter::Antialiasing,
true);
180 graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
181 graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState);
190 graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
192 graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
194 graphicsView->setTransformationAnchor(QGraphicsView::AnchorViewCenter);
199 QSize iconSize(size, size);
205 QToolButton *zoomInIcon =
new QToolButton;
206 zoomInIcon->setAutoRepeat(
true);
207 zoomInIcon->setAutoRepeatInterval(33);
208 zoomInIcon->setAutoRepeatDelay(0);
209 zoomInIcon->setIcon(QPixmap(
":/awesome/search-plus.svg"));
210 zoomInIcon->setIconSize(iconSize);
211 QToolButton *zoomOutIcon =
new QToolButton;
212 zoomOutIcon->setAutoRepeat(
true);
213 zoomOutIcon->setAutoRepeatInterval(33);
214 zoomOutIcon->setAutoRepeatDelay(0);
215 zoomOutIcon->setIcon(QPixmap(
":/awesome/search-minus.svg"));
216 zoomOutIcon->setIconSize(iconSize);
218 zoomSlider->setTickPosition(QSlider::NoTicks);
228 QVBoxLayout *zoomSliderLayout =
new QVBoxLayout;
229 zoomSliderLayout->addWidget(zoomInIcon);
231 zoomSliderLayout->addWidget(zoomOutIcon);
233 QToolButton *rotateLeftIcon =
new QToolButton;
234 rotateLeftIcon->setIcon(QPixmap(
":/awesome/reply.svg"));
235 rotateLeftIcon->setIconSize(iconSize);
236 QToolButton *rotateRightIcon =
new QToolButton;
237 rotateRightIcon->setIcon(QPixmap(
":/awesome/reply-right.svg"));
238 rotateRightIcon->setIconSize(iconSize);
247 QHBoxLayout *rotateSliderLayout =
new QHBoxLayout;
248 rotateSliderLayout->addWidget(rotateLeftIcon);
250 rotateSliderLayout->addWidget(rotateRightIcon);
254 resetButton->setIcon(QPixmap(
":/awesome/circle.svg"));
259 rotateLeftIcon->setVisible(
false);
260 rotateRightIcon->setVisible(
false);
269 QGridLayout *topLayout =
new QGridLayout;
272 topLayout->addLayout(zoomSliderLayout, 1, 1);
273 topLayout->addLayout(rotateSliderLayout, 2, 0);
278 setLayout(topLayout);
284 graphicsView->setRenderHint(QPainter::Antialiasing,
true);
289 connect(
graphicsView->verticalScrollBar(), SIGNAL(valueChanged(
int)),
291 connect(
graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(
int)),
293 connect(rotateLeftIcon, SIGNAL(clicked()),
this, SLOT(
rotateLeft()));
294 connect(rotateRightIcon, SIGNAL(clicked()),
this, SLOT(
rotateRight()));
295 connect(zoomInIcon, SIGNAL(clicked()),
this, SLOT(
zoomIn()));
296 connect(zoomOutIcon, SIGNAL(clicked()),
this, SLOT(
zoomOut()));
337 QPoint pv =
event->pos();
341 static const int HOVER_DIST = 8;
342 QList<QGraphicsItem *> items =
graphicsView->items(pv.x()-HOVER_DIST, pv.y()-HOVER_DIST,
343 2*HOVER_DIST, 2*HOVER_DIST,
344 Qt::IntersectsItemShape);
346 for(QGraphicsItem* item : items)
370 QFrame::resizeEvent(event);
376 double zoomScale = qPow(2.0,
zoomSlider->value() / 50.0);
379 matrix.scale(zoomScale, zoomScale);
389 QRectF sceneRect =
scene->sceneRect();
392 double scale =
std::min( widgetRect.width() / sceneRect.width(),
393 widgetRect.height() / sceneRect.height());
394 QPointF offset = sceneRect.topLeft() - widgetRect.topLeft();
397 return QMatrix(scale,0, 0,
isFlipped ? -scale:+scale, offset.rx()/2, offset.ry()/2);
403 QPrinter printer(QPrinterInfo::defaultPrinter());
405 QPrintDialog dialog(&printer,
this);
406 if (dialog.exec() == QDialog::Accepted) {
407 QPainter painter(&printer);
418 fdlg.restoreState(settings.value(
"filedialog.saveas").toByteArray());
419 fdlg.setAcceptMode(QFileDialog::AcceptSave);
420 fdlg.setFileMode(QFileDialog::AnyFile);
422 fdlg.setDirectory(settings.value(
"filedialog.saveas.dir").toString());
424 QStringList fileNames;
425 if (fdlg.exec() == QDialog::Accepted) {
426 fileNames = fdlg.selectedFiles();
427 if (!fileNames.isEmpty()) {
428 QString file = fileNames.first();
429 QString suffix = QFileInfo(file).suffix().toLower();
430 QString filter = fdlg.selectedNameFilter();
434 else if ((suffix==
"svg") || (filter==
"svg"))
441 settings.setValue(
"filedialog.saveas",fdlg.saveState());
442 settings.setValue(
"filedialog.saveas.dir",fdlg.directory().absolutePath());
450 printer.setOutputFormat(QPrinter::PdfFormat);
452 printer.setOutputFileName(file);
454 QPainter painter(&printer);
463 QSvgGenerator generator;
465 generator.setFileName(file);
466 generator.setSize(QSize(size.width(),size.height()));
468 generator.setTitle(windowTitle());
469 generator.setDescription(
"Created by " 470 +QApplication::applicationDisplayName()+
" " 471 +QApplication::applicationVersion());
474 painter.begin(&generator);
476 QRectF(QPointF(0,0),size));
482 QRectF r =
scene->sceneRect();
483 QPoint topLeft =
graphicsView->mapFromScene(r.topLeft());
484 QPoint botRight =
graphicsView->mapFromScene(r.bottomRight());
487 source.setCoords(
std::min(topLeft.x(),botRight.x()),
490 std::max(topLeft.y(),botRight.y()));
514 settings.beginGroup(group);
518 int scroll_h =
graphicsView->horizontalScrollBar()->value();
519 int scroll_v =
graphicsView->verticalScrollBar()->value();
521 int max_h =
graphicsView->horizontalScrollBar()->maximum();
522 int max_v =
graphicsView->verticalScrollBar()->maximum();
524 settings.setValue(
"zoom", zoom);
525 settings.setValue(
"rotate", rot);
527 settings.setValue(
"scroll.horiz", scroll_h);
528 settings.setValue(
"scroll.vert", scroll_v);
535 settings.beginGroup(group);
537 int zoom = settings.value(
"zoom",0).toInt();
539 int scroll_h = settings.value(
"scroll.horiz",0).toInt();
540 int scroll_v = settings.value(
"scroll.vert",0).toInt();
545 int max_h =
graphicsView->horizontalScrollBar()->maximum();
546 int max_v =
graphicsView->verticalScrollBar()->maximum();
548 graphicsView->horizontalScrollBar()->setValue(scroll_h);
571 while (angle > 306) angle -= 360;
572 while (angle < -360) angle += 360;
581 QAbstractGraphicsShapeItem* shape = dynamic_cast<QAbstractGraphicsShapeItem*>(item);
583 QPen pen = shape->pen();
584 if (pen.widthF() != width) {
585 pen.setWidthF(width);
589 QGraphicsLineItem* line = dynamic_cast<QGraphicsLineItem*>(item);
591 QPen pen = line->pen();
592 if (pen.widthF() != width) {
593 pen.setWidthF(width);
598 for(
const auto& i : item->childItems())
605 return (a.x()==b.x()) && (a.y()==b.y());
610 if (
equals(line.p1(),line.p2())) {
617 ppath.moveTo(line.p1());
618 ppath.lineTo(line.p2());
631 addLine(ppath,QLineF(poly[0], poly[0]+QPointF(1e-9,1e-9))); }
633 case 2:
addLine(ppath,QLineF(poly[0],poly[1]));
break;
634 default: ppath.addPolygon(poly);
break;
640 ppath.addEllipse(point, diameter,diameter);
645 int min = slider->minimum();
646 int max = slider->maximum();
647 int val = slider->value();
654 int min = slider->minimum();
655 int max = slider->maximum();
658 slider->setValue(val);
663 QGraphicsItemGroup* group)
664 : QGraphicsLineItem(line,group), loc(aloc), a(aa), b(bb)
666 group->addToGroup(
this);
670 const_cast<int&>(
a) = aa;
671 const_cast<int&>(
b)=bb;
676 QPointF q = mapFromScene(scene_pos);
678 if (line().length()==0.0)
679 dist = numeric::euclidean_distance<double>(line().p1(),q);
681 dist = numeric::euclidean_segment_distance<double>(line(),q);
void singleStep(QAbstractSlider *, double factor)
perform a single step on a slider
base class for view widgets.
GraphicsView(BaseView *view)
default constructor
void saveAs()
save the contents of the graphics scene to disk (as PDF, or SVG)
void zoomIn(int level=-1)
zoom in; connected to the zomm controls
used for segments that are not mouse sensitive
void saveAsPdf(QString file)
save content of scene to a PDF file
void resetView()
reset zoom to default
void mouseMoveEvent(QMouseEvent *event)
bool event(QEvent *) override
static int distance(int a, int b, int n)
BaseView(QWidget *parent=0, QString title="", bool showRotate=true)
constructore with parent and title
int rot0
initial rotation angle
void keyPressEvent(QKeyEvent *) override
bool gestureEvent(QGestureEvent *)
QGraphicsView * view() const
int zoomStepMouse
zoom step for mouse wheel
global definitions for all algorithms.
void zoomOut(int level=-1)
connected to the zomm controls
bool is_close_to(QPointF scene_pos, int distance) const
check if the mouse is close to the line segment
double normalizedValue(QAbstractSlider *slider)
void wheelEvent(QWheelEvent *) override
void pageStep(QAbstractSlider *, double factor)
perform a page step on a slider
QSlider * rotateSlider
the slider control for rotate
void rotateLeft(double angle=10)
rotate the scene to the left
static void addPolygon(QPainterPath &ppath, const QPolygonF &poly)
add a polygon curve segment to a QPainterPath
bool isFlipped
true if the scene should be flipped vertically
void setupMatrix()
set up transformation matrix to account for zoom,rotate,scroll
const Location loc
location on screen
static const int ROTATE_DEFAULT_VALUE
what this?
QPoint mapSceneToGlobal(QPointF p) const
map scene coordinates to window coordinate
bool equals(QPointF a, QPointF b)
void setNormalizedValue(QAbstractSlider *slider, double nval)
update slider with a normalized value
QGraphicsScene * scene
scene that is displayed by graphicsView
static const QPen PEN_SELECT
pen for drawing selected polygon segment
GraphicsHoverLineItem * selected_item
the currently selected mouse sensitve polyon segment (or nullptr)
a QGraphicsLitem that can handle mouse hover events. It is used to highlight mouse sensitve polygon s...
void update(int a, int b)
update identifiers
void resizeEvent(QResizeEvent *) override
handles window resizes; adjusts controls to new window size
void flipVertical(bool flip)
flip graphics scene vertically
static void addPoint(QPainterPath &ppath, const QPointF &point, double diameter=1.0)
add a dot to a QPainterPath
void mouseMoveEvent(QMouseEvent *event)
handles a mouse move event and detects mouse sensitve polygon segments
void setRotation(double angle)
update rotation angle
const int a
parameters loc,a, and b identify a segment.
virtual void segmentSelected(GraphicsHoverLineItem *item)
called when the mouse hovers over a polygon segment; implemented by derived classes.
void rotateRight(double angle=10)
rotate the scene to the right
double min(double a, double b)
minimum function with checks for NAN
virtual void restoreSettings(QSettings &settings, QString group)
load view settings to application prefs
BaseView * view
parent widget
QGraphicsView * graphicsView
the embedded QGraphicsView
void print()
print the contents of the graphics scene
QToolButton * resetButton
the reset button
void mousePressEvent(QMouseEvent *event) override
void saveAsSvg(QString file)
save content of scene to an SVG file
virtual void saveSettings(QSettings &settings, QString group)
store view settings to application prefs
virtual void render(QPainter *painter, QRectF target=QRectF())
render the scene into a QPainter used for printing and saving to disk
void setResetButtonEnabled()
enabled reset button
QSlider * zoomSlider
the slider control for zoom
GraphicsHoverLineItem(QLineF line, Location loc, int a, int b, QGraphicsItemGroup *group)
default constructor
virtual void dropUnusedItems()
clean up graphics scene items after free-space is modified implemented by FreeSpaceView.
friend class GraphicsView
Location
location of the polygon segment
int zoomStepDefault
default zoom step
double max(double a, double b)
maximum function with checks for NAN
static void setPenWidth(QGraphicsItem *item, double width)
update the pen width of a graphics item
static const QStringList OUTPUT_FILTERS
file name filters for save dialog
static void addLine(QPainterPath &ppath, const QLineF &line)
add a line segment to a QPainterPath