diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2013-09-27 10:03:13 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-09-27 10:03:13 -0700 |
commit | ff0b2745a70f8ae3611fe9eaf98c9ebbb3c2da1f (patch) | |
tree | ab55fc3b0dfa4f9ce2420dc12b5a361146aab8c2 /qt-ui | |
parent | df8107830e24ce3687d37ee245a4e38202deea5f (diff) | |
parent | a3ce871e0ad8981964a189321ac70d021c8ac145 (diff) | |
download | subsurface-ff0b2745a70f8ae3611fe9eaf98c9ebbb3c2da1f.tar.gz |
Merge branch 'toolbar-ruler-rb' of github.com:mguentner/subsurface
Diffstat (limited to 'qt-ui')
-rw-r--r-- | qt-ui/mainwindow.cpp | 3 | ||||
-rw-r--r-- | qt-ui/profilegraphics.cpp | 274 | ||||
-rw-r--r-- | qt-ui/profilegraphics.h | 56 |
3 files changed, 326 insertions, 7 deletions
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 214e41bf0..8f2f8233d 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -294,7 +294,8 @@ void MainWindow::on_actionAutoGroup_triggered() void MainWindow::on_actionToggleZoom_triggered() { - qDebug("actionToggleZoom"); + zoomed_plot = !zoomed_plot; + ui->ProfileWidget->refresh(); } void MainWindow::on_actionYearlyStatistics_triggered() diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp index 07326f475..17598a6af 100644 --- a/qt-ui/profilegraphics.cpp +++ b/qt-ui/profilegraphics.cpp @@ -15,7 +15,9 @@ #include <QPropertyAnimation> #include <QGraphicsSceneHoverEvent> #include <QMouseEvent> +#include <QToolBar> #include <qtextdocument.h> +#include <limits> #include "../color.h" #include "../display.h" @@ -43,10 +45,11 @@ extern struct ev_select *ev_namelist; extern int evn_allocated; extern int evn_used; -ProfileGraphicsView::ProfileGraphicsView(QWidget* parent) : QGraphicsView(parent), toolTip(0) , dive(0), diveDC(0) +ProfileGraphicsView::ProfileGraphicsView(QWidget* parent) : QGraphicsView(parent), toolTip(0) , dive(0), diveDC(0), rulerItem(0), toolBarProxy(0) { printMode = false; isGrayscale = false; + rulerEnabled = false; gc.printer = false; fill_profile_color(); setScene(new QGraphicsScene()); @@ -175,11 +178,23 @@ void ProfileGraphicsView::clear() { resetTransform(); zoomLevel = 0; - if(toolTip){ + if(toolTip) { scene()->removeItem(toolTip); toolTip->deleteLater(); toolTip = 0; } + if(toolBarProxy) { + scene()->removeItem(toolBarProxy); + toolBarProxy->deleteLater(); + toolBarProxy = 0; + } + if(rulerItem) { + remove_ruler(); + rulerItem->destNode()->deleteLater(); + rulerItem->sourceNode()->deleteLater(); + rulerItem->deleteLater(); + rulerItem=0; + } scene()->clear(); } @@ -214,7 +229,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw) dive = d; diveDC = d ? dc : NULL; - if (!isVisible() || !dive) { + if (!isVisible() || !dive || !mainWindow()) { return; } setBackgroundBrush(getColor(BACKGROUND)); @@ -274,6 +289,9 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw) plot_events(dc); + if (rulerEnabled && !printMode) + create_ruler(); + /* Temperature profile */ plot_temperature_profile(); @@ -336,6 +354,12 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw) connect(timeEditor, SIGNAL(editingFinished(QString)), this, SLOT(edit_dive_time(QString))); scene()->addItem(timeEditor); } + + if (!printMode) + addControlItems(); + + if (rulerEnabled && !printMode) + add_ruler(); } void ProfileGraphicsView::plot_depth_scale() @@ -368,11 +392,29 @@ void ProfileGraphicsView::plot_depth_scale() depthMarkers->setPos(depthMarkers->pos().x() - 10, 0); } +void ProfileGraphicsView::addControlItems() +{ + QAction *scaleAction = new QAction(QIcon(":scale"), tr("Scale"), this); + QAction *rulerAction = new QAction(QIcon(":ruler"), tr("Ruler"), this); + QToolBar *toolBar = new QToolBar("", 0); + toolBar->addAction(rulerAction); + toolBar->addAction(scaleAction); + //make toolbar transparent + toolBar->setStyleSheet(QString::fromUtf8 ("background-color: rgba(255,255,255,0);")); + + connect(scaleAction, SIGNAL(triggered()), this, SLOT(on_scaleAction())); + connect(rulerAction, SIGNAL(triggered()), this, SLOT(on_rulerAction())); + toolBarProxy = scene()->addWidget(toolBar); + //Put it into the lower right corner of the profile + toolBarProxy->setPos(gc.maxx-toolBar->width(), gc.maxy-toolBar->height()); +} + void ProfileGraphicsView::plot_pp_text() { double pp, dpp, m; int hpos; static text_render_options_t tro = {PP_TEXT_SIZE, PP_LINES, LEFT, MIDDLE}; + QGraphicsRectItem *pressureMarkers = new QGraphicsRectItem(); setup_pp_limits(&gc); pp = floor(gc.pi.maxpp * 10.0) / 10.0 + 0.2; @@ -386,8 +428,10 @@ void ProfileGraphicsView::plot_pp_text() pen.setColor(c); item->setPen(pen); scene()->addItem(item); - plot_text(&tro, QPointF(hpos + 30, m), QString::number(m)); + plot_text(&tro, QPointF(hpos, m), QString::number(m), pressureMarkers); } + scene()->addItem(pressureMarkers); + pressureMarkers->setPos(pressureMarkers->pos().x() + 10, 0); } void ProfileGraphicsView::plot_add_line(int sec, double val, QColor c, QPointF &from) @@ -840,6 +884,57 @@ void ProfileGraphicsView::plot_one_event(struct event *ev) item->setToolTip(name); } +void ProfileGraphicsView::create_ruler() +{ + int x,y; + struct plot_info *pi = &gc.pi; + struct plot_data *data = pi->entry; + + RulerNodeItem *first = new RulerNodeItem(0, gc); + RulerNodeItem *second = new RulerNodeItem(0, gc); + + x = SCALEXGC(data->sec); + y = data->depth; + + first->setPos(x,y); + + data = pi->entry+(pi->nr-1); + x = SCALEXGC(data->sec); + y = data->depth; + + second->setPos(x,y); + //Make sure that both points already have their entries + first->recalculate(); + second->recalculate(); + + rulerItem = new RulerItem(0, first, second); + first->setRuler(rulerItem); + second->setRuler(rulerItem); +} + +void ProfileGraphicsView::add_ruler() +{ + if (! scene()->items().contains(rulerItem)) { + scene()->addItem(rulerItem->sourceNode()); + scene()->addItem(rulerItem->destNode()); + scene()->addItem(rulerItem); + rulerItem->recalculate(); + } +} + +void ProfileGraphicsView::remove_ruler() +{ + if (rulerItem) { + if (scene()->items().contains(rulerItem)) + scene()->removeItem(rulerItem); + if (scene()->items().contains(rulerItem->sourceNode())) + scene()->removeItem(rulerItem->sourceNode()); + if (scene()->items().contains(rulerItem->destNode())) + scene()->removeItem(rulerItem->destNode()); + } +} + + void ProfileGraphicsView::plot_depth_profile() { int i, incr; @@ -888,7 +983,7 @@ void ProfileGraphicsView::plot_depth_profile() if (maxtime < 600) { /* Be a bit more verbose with shorter dives */ for (i = incr; i < maxtime; i += incr) - plot_text(&tro, QPointF(i, 0), QString("%1:%2").arg(i/60).arg(i%60), timeMarkers); + plot_text(&tro, QPointF(i, 0), QString("%1:%2").arg(i/60).arg(i%60, 2, 10, QChar('0')), timeMarkers); } else { /* Only render the time on every second marker for normal dives */ for (i = incr; i < maxtime; i += 2 * incr) @@ -1131,7 +1226,7 @@ QGraphicsItemGroup *ProfileGraphicsView::plot_text(text_render_options_t *tro,co void ProfileGraphicsView::resizeEvent(QResizeEvent *event) { - fitInView(sceneRect()); + refresh(); } void ProfileGraphicsView::plot_temperature_profile() @@ -1175,6 +1270,18 @@ void ProfileGraphicsView::edit_dive_time(const QString& time) refresh(); } +void ProfileGraphicsView::on_rulerAction() +{ + rulerEnabled = !rulerEnabled; + refresh(); +} + +void ProfileGraphicsView::on_scaleAction() +{ + zoomed_plot = !zoomed_plot; + refresh(); +} + void ToolTipItem::addToolTip(const QString& toolTip, const QIcon& icon) { QGraphicsPixmapItem *iconItem = 0; @@ -1430,6 +1537,161 @@ EventItem::EventItem(QGraphicsItem* parent, bool grayscale): QGraphicsPolygonIte ball->setPen(QPen(getColor(ALERT_FG))); } + + +RulerNodeItem::RulerNodeItem(QGraphicsItem *parent, graphics_context context) : QGraphicsEllipseItem(parent), gc(context), entry(NULL) , ruler(NULL) +{ + setRect(QRect(QPoint(-8,8),QPoint(8,-8))); + setBrush(QColor(0xff, 0, 0, 127)); + setPen(QColor("#FF0000")); + setFlag(QGraphicsItem::ItemIsMovable); + setFlag(ItemSendsGeometryChanges); + setFlag(ItemIgnoresTransformations); +} + +void RulerNodeItem::setRuler(RulerItem *r) +{ + ruler = r; +} + +void RulerNodeItem::recalculate() +{ + struct plot_info *pi = &gc.pi; + struct plot_data *data = pi->entry+(pi->nr-1); + uint16_t count = 0; + if (x() < 0) { + setPos(0, y()); + } + else if (x() > SCALEXGC(data->sec)) { + setPos(SCALEXGC(data->sec), y()); + } + else { + data = pi->entry; + count=0; + while (SCALEXGC(data->sec) < x() && count < pi->nr) { + data = pi->entry+count; + count++; + } + setPos(SCALEGC(data->sec, data->depth)); + entry=data; + } +} + +QVariant RulerNodeItem::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if(change == ItemPositionHasChanged) { + recalculate(); + if(ruler != NULL) + ruler->recalculate(); + if (scene()) { + scene()->update(); + } + } + return QGraphicsEllipseItem::itemChange(change, value); +} + +RulerItem::RulerItem(QGraphicsItem *parent, RulerNodeItem *sourceNode, RulerNodeItem *destNode) : QGraphicsObject(parent), source(sourceNode), dest(destNode) +{ + recalculate(); +} + +void RulerItem::recalculate() +{ + char buffer[500]; + QPointF tmp; + QFont font; + QFontMetrics fm(font); + + if (source == NULL || dest == NULL) + return; + + prepareGeometryChange(); + startPoint = mapFromItem(source, 0, 0); + endPoint = mapFromItem(dest, 0, 0); + if (startPoint.x() > endPoint.x()) { + tmp = endPoint; + endPoint = startPoint; + startPoint = tmp; + } + QLineF line(startPoint, endPoint); + + compare_samples(source->entry, dest->entry, buffer, 500, 1); + text = QString(buffer); + + QRect r = fm.boundingRect(QRect(QPoint(10,-1*INT_MAX), QPoint(line.length()-10, 0)), Qt::TextWordWrap, text); + if (r.height() < 10) + height = 10; + else + height = r.height(); + + QLineF line_n = line.normalVector(); + line_n.setLength(height); + if (scene()) { + /* Determine whether we draw down or upwards */ + if (scene()->sceneRect().contains(line_n.p2()) && + scene()->sceneRect().contains(endPoint+QPointF(line_n.dx(),line_n.dy()))) + paint_direction = -1; + else + paint_direction = 1; + } +} + +RulerNodeItem *RulerItem::sourceNode() const +{ + return source; +} + +RulerNodeItem *RulerItem::destNode() const +{ + return dest; +} + +void RulerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + QLineF line(startPoint, endPoint); + QLineF line_n = line.normalVector(); + painter->setPen(QColor(Qt::black)); + painter->setBrush(Qt::NoBrush); + line_n.setLength(height); + + if (paint_direction == 1) + line_n.setAngle(line_n.angle()+180); + painter->drawLine(line); + painter->drawLine(line_n); + painter->drawLine(line_n.p1() + QPointF(line.dx(), line.dy()), line_n.p2() + QPointF(line.dx(), line.dy())); + + //Draw Text + painter->save(); + painter->translate(startPoint.x(), startPoint.y()); + painter->rotate(line.angle()*-1); + if (paint_direction == 1) + painter->translate(0, height); + painter->setPen(Qt::black); + painter->drawText(QRectF(QPointF(10,-1*height), QPointF(line.length()-10, 0)), Qt::TextWordWrap, text); + painter->restore(); +} + +QRectF RulerItem::boundingRect() const +{ + return shape().controlPointRect(); +} + +QPainterPath RulerItem::shape() const +{ + QPainterPath path; + QLineF line(startPoint, endPoint); + QLineF line_n = line.normalVector(); + line_n.setLength(height); + if (paint_direction == 1) + line_n.setAngle(line_n.angle()+180); + path.moveTo(startPoint); + path.lineTo(line_n.p2()); + path.lineTo(line_n.p2() + QPointF(line.dx(), line.dy())); + path.lineTo(endPoint); + path.lineTo(startPoint); + return path; +} + GraphicsTextEditor::GraphicsTextEditor(QGraphicsItem* parent): QGraphicsTextItem(parent) { } diff --git a/qt-ui/profilegraphics.h b/qt-ui/profilegraphics.h index 0bcbf7529..7cbc53e15 100644 --- a/qt-ui/profilegraphics.h +++ b/qt-ui/profilegraphics.h @@ -57,6 +57,49 @@ private: QRectF nextRectangle; }; +class RulerItem; + +class RulerNodeItem : public QObject, public QGraphicsEllipseItem +{ + Q_OBJECT + friend class RulerItem; +public: + explicit RulerNodeItem(QGraphicsItem* parent, graphics_context gc); + void setRuler(RulerItem *r); + void recalculate(); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant & value ); + +private: + graphics_context gc; + struct plot_data *entry; + RulerItem* ruler; +}; + +class RulerItem : public QGraphicsObject +{ + Q_OBJECT +public: + explicit RulerItem(QGraphicsItem* parent, + RulerNodeItem *sourceMarker, + RulerNodeItem *destMarker); + void recalculate(); + + RulerNodeItem* sourceNode() const; + RulerNodeItem* destNode() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * widget = 0); + QRectF boundingRect() const; + QPainterPath shape() const; + +private: + QPointF startPoint, endPoint; + RulerNodeItem *source, *dest; + QString text; + int height; + int paint_direction; +}; + class EventItem : public QGraphicsPolygonItem { public: @@ -106,6 +149,8 @@ protected: public slots: void refresh(); void edit_dive_time(const QString& time); + void on_rulerAction(); + void on_scaleAction(); private: void plot_depth_profile(); @@ -128,6 +173,13 @@ private: void plot_pp_text(); void plot_depth_scale(); + + void addControlItems(); + + void create_ruler(); + void add_ruler(); + void remove_ruler(); + QColor getColor(const color_indice_t i); QColor get_sac_color(int sac, int avg_sac); void scrollViewTo(const QPoint pos); @@ -139,6 +191,8 @@ private: struct dive *dive; struct divecomputer *diveDC; int zoomLevel; + + bool rulerEnabled; bool printMode; bool isGrayscale; @@ -147,6 +201,8 @@ private: QGraphicsItem* timeMarkers; QGraphicsItem* depthMarkers; QGraphicsItem* diveComputer; + RulerItem *rulerItem; + QGraphicsProxyWidget *toolBarProxy; // For 'Plan' mode.: GraphicsTextEditor *depthEditor; |