diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2013-06-22 15:57:26 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-06-22 15:57:26 -0700 |
commit | 31449dca22873e500842ab1cfcca3a211764d98a (patch) | |
tree | 51142e5b4148f25d5e416b6b621ed83447cc43cc /qt-ui | |
parent | 81858167ac3f69e99a1108fa305f2865417e2b81 (diff) | |
parent | 880b98ed35c2dbf3b5a015784323894c59bc7feb (diff) | |
download | subsurface-31449dca22873e500842ab1cfcca3a211764d98a.tar.gz |
Merge branch 'divePlannerTry3' of github.com:tcanabrava/subsurface
Diffstat (limited to 'qt-ui')
-rw-r--r-- | qt-ui/diveplanner.cpp | 385 | ||||
-rw-r--r-- | qt-ui/diveplanner.h | 106 | ||||
-rw-r--r-- | qt-ui/diveplanner.ui | 74 | ||||
-rw-r--r-- | qt-ui/mainwindow.cpp | 11 | ||||
-rw-r--r-- | qt-ui/mainwindow.h | 1 | ||||
-rw-r--r-- | qt-ui/mainwindow.ui | 9 |
6 files changed, 585 insertions, 1 deletions
diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp new file mode 100644 index 000000000..d6096f4bb --- /dev/null +++ b/qt-ui/diveplanner.cpp @@ -0,0 +1,385 @@ +#include "diveplanner.h" +#include <cmath> +#include <QMouseEvent> +#include <QDebug> +#include "ui_diveplanner.h" + +DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent), activeDraggedHandler(0) +{ + setMouseTracking(true); + setScene( new QGraphicsScene()); + scene()->setSceneRect(0,0,100,100); + + verticalLine = new QGraphicsLineItem(0,0,0, 100); + verticalLine->setPen(QPen(Qt::DotLine)); + scene()->addItem(verticalLine); + + horizontalLine = new QGraphicsLineItem(0,0,100,0); + horizontalLine->setPen(QPen(Qt::DotLine)); + scene()->addItem(horizontalLine); + + timeLine = new Ruler(); + timeLine->setMinimum(0); + timeLine->setMaximum(20); + timeLine->setTickInterval(10); + timeLine->setLine( 10, 90, 99, 90); + timeLine->setOrientation(Qt::Horizontal); + timeLine->updateTicks(); + scene()->addItem(timeLine); + + depthLine = new Ruler(); + depthLine->setMinimum(0); + depthLine->setMaximum(10); + depthLine->setTickInterval(10); + depthLine->setLine( 10, 1, 10, 90); + depthLine->setOrientation(Qt::Vertical); + depthLine->updateTicks(); + scene()->addItem(depthLine); + + timeString = new QGraphicsSimpleTextItem(); + timeString->setFlag(QGraphicsItem::ItemIgnoresTransformations); + scene()->addItem(timeString); + + depthString = new QGraphicsSimpleTextItem(); + depthString->setFlag(QGraphicsItem::ItemIgnoresTransformations); + scene()->addItem(depthString); + + plusDepth = new Button(); + plusDepth->setPos(15, 1); + scene()->addItem(plusDepth); + connect(plusDepth, SIGNAL(clicked()), this, SLOT(increaseDepth())); + + plusTime = new Button(); + plusTime->setPos( 95, 90); + scene()->addItem(plusTime); + connect(plusTime, SIGNAL(clicked()), this, SLOT(increaseTime())); +} + +void DivePlannerGraphics::increaseDepth() +{ + qDebug() << "Increase Depth Clicked"; +} + +void DivePlannerGraphics::increaseTime() +{ + qDebug() << "Increase Time Clicked"; +} + +void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event) +{ + QPointF mappedPos = mapToScene(event->pos()); + if(isPointOutOfBoundaries(mappedPos)) + return; + + if(handles.count() && handles.last()->x() > mappedPos.x()){ + return; + } + + DiveHandler *item = new DiveHandler (); + item->setRect(-5,-5,10,10); + item->setFlag(QGraphicsItem::ItemIgnoresTransformations); + + double xpos = timeLine->posAtValue(rint(timeLine->valueAt(mappedPos))); + double ypos = depthLine->posAtValue(rint(depthLine->valueAt(mappedPos))); + item->setPos( QPointF(xpos, ypos)); + scene()->addItem(item); + handles << item; + + if (lines.empty()){ + double xpos = timeLine->posAtValue(0); + double ypos = depthLine->posAtValue(0); + QGraphicsLineItem *first = new QGraphicsLineItem(xpos,ypos, mappedPos.x(), mappedPos.y()); + item->from = first; + lines.push_back(first); + create_deco_stop(); + scene()->addItem(first); + }else{ + clear_generated_deco(); + DiveHandler *prevHandle = handles.at( handles.count()-2); + QGraphicsLineItem *line = new QGraphicsLineItem(prevHandle->x(), prevHandle->y(), item->x(), item->y()); + prevHandle->to = line; + item->from = line; + lines.push_back(line); + scene()->addItem(line); + create_deco_stop(); + } + item->time = (timeLine->valueAt(mappedPos)); + item->depth = (depthLine->valueAt(mappedPos)); +} + +void DivePlannerGraphics::clear_generated_deco() +{ + for(int i = handles.count(); i <= lines.count(); i++){ + scene()->removeItem(lines.last()); + delete lines.last(); + lines.removeLast(); + } +} + +void DivePlannerGraphics::create_deco_stop() +{ + // This needs to be done in the following steps: + // Get the user-input and calculate the dive info + Q_FOREACH(DiveHandler *h, handles){ + // use this somewhere. + h->time; + h->depth; + } + // create the dive info here. + + // set the new 'end time' of the dive. + // note that this is not the user end, + // but the real end of the dive. + timeLine->setMaximum(60); + timeLine->updateTicks(); + + // Re-position the user generated dive handlers + Q_FOREACH(DiveHandler *h, handles){ + // uncomment this as soon as the posAtValue is implemented. + // h->setPos( timeLine->posAtValue(h->time), + // depthLine->posAtValue(h->depth)); + } + + // Create all 'deco' GraphicsLineItems and put it on the canvas.This following three lines will + // most probably need to enter on a loop. + double xpos = timeLine->posAtValue(timeLine->maximum()); + double ypos = depthLine->posAtValue(depthLine->minimum()); + QGraphicsLineItem *item = new QGraphicsLineItem(handles.last()->x(), handles.last()->y(), xpos, ypos); + scene()->addItem(item); + lines << item; +} + +void DivePlannerGraphics::resizeEvent(QResizeEvent* event) +{ + QGraphicsView::resizeEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); +} + +void DivePlannerGraphics::showEvent(QShowEvent* event) +{ + QGraphicsView::showEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); +} + +void DivePlannerGraphics::mouseMoveEvent(QMouseEvent* event) +{ + QPointF mappedPos = mapToScene(event->pos()); + if (isPointOutOfBoundaries(mappedPos)) + return; + + verticalLine->setLine(mappedPos.x(), 0, mappedPos.x(), 100); + horizontalLine->setLine(0, mappedPos.y(), 100, mappedPos.y()); + depthString->setText(QString::number( (int) depthLine->valueAt(mappedPos)) + "m" ); + depthString->setPos(0, mappedPos.y()); + timeString->setText(QString::number( (int) timeLine->valueAt(mappedPos)) + "min"); + timeString->setPos(mappedPos.x()+1, 90); + + if(activeDraggedHandler) + moveActiveHandler(mappedPos); + if (!handles.count()) + return; + + if (handles.last()->x() > mappedPos.x()){ + verticalLine->setPen( QPen(QBrush(Qt::red), 0, Qt::SolidLine)); + horizontalLine->setPen( QPen(QBrush(Qt::red), 0, Qt::SolidLine)); + }else{ + verticalLine->setPen(QPen(Qt::DotLine)); + horizontalLine->setPen(QPen(Qt::DotLine)); + } +} + +void DivePlannerGraphics::moveActiveHandler(const QPointF& pos) +{ + int idx = handles.indexOf(activeDraggedHandler); + + double xpos = timeLine->posAtValue(rint(timeLine->valueAt(pos))); + double ypos = depthLine->posAtValue(rint(depthLine->valueAt(pos))); + + QPointF newPos(xpos, ypos); + bool moveLines = false;; + // do not allow it to move between handlers. + if (handles.count() > 1){ + if (idx == 0 ){ // first + if (newPos.x() < handles[1]->x()){ + activeDraggedHandler->setPos(newPos); + moveLines = true; + } + }else if (idx == handles.count()-1){ // last + if (newPos.x() > handles[idx-1]->x()){ + activeDraggedHandler->setPos(newPos); + moveLines = true; + } + }else{ // middle + if (newPos.x() > handles[idx-1]->x() && newPos.x() < handles[idx+1]->x()){ + activeDraggedHandler->setPos(newPos); + moveLines = true; + } + } + }else{ + activeDraggedHandler->setPos(newPos); + moveLines = true; + } + if (moveLines){ + if (activeDraggedHandler->from){ + QLineF f = activeDraggedHandler->from->line(); + activeDraggedHandler->from->setLine(f.x1(), f.y1(), newPos.x(), newPos.y()); + } + + if (activeDraggedHandler->to){ + QLineF f = activeDraggedHandler->to->line(); + activeDraggedHandler->to->setLine(newPos.x(), newPos.y(), f.x2(), f.y2()); + } + + if(activeDraggedHandler == handles.last()){ + clear_generated_deco(); + create_deco_stop(); + } + } +} + +bool DivePlannerGraphics::isPointOutOfBoundaries(const QPointF& point) +{ + double xpos = timeLine->valueAt(point); + double ypos = depthLine->valueAt(point); + + if (xpos > timeLine->maximum() + || xpos < timeLine->minimum() + || ypos > depthLine->maximum() + || ypos < depthLine->minimum()) + { + return true; + } + return false; +} + +void DivePlannerGraphics::mousePressEvent(QMouseEvent* event) +{ + QPointF mappedPos = mapToScene(event->pos()); + Q_FOREACH(QGraphicsItem *item, scene()->items(mappedPos)){ + if (DiveHandler *h = qgraphicsitem_cast<DiveHandler*>(item)){ + activeDraggedHandler = h; + activeDraggedHandler->setBrush(Qt::red); + } + } + QGraphicsView::mousePressEvent(event); +} + +void DivePlannerGraphics::mouseReleaseEvent(QMouseEvent* event) +{ + if (activeDraggedHandler){ + QPointF mappedPos = mapToScene(event->pos()); + activeDraggedHandler->time = (timeLine->valueAt(mappedPos)); + activeDraggedHandler->depth = (depthLine->valueAt(mappedPos)); + activeDraggedHandler->setBrush(QBrush()); + activeDraggedHandler = 0; + } +} + +DiveHandler::DiveHandler(): QGraphicsEllipseItem(), from(0), to(0) +{ +} + +void Ruler::setMaximum(double maximum) +{ + max = maximum; +} + +void Ruler::setMinimum(double minimum) +{ + min = minimum; +} + +Ruler::Ruler() : orientation(Qt::Horizontal) +{ +} + +void Ruler::setOrientation(Qt::Orientation o) +{ + orientation = o; +} + +void Ruler::updateTicks() +{ + qDeleteAll(ticks); + QLineF m = line(); + if(orientation == Qt::Horizontal){ + double steps = (max - min) / interval; + double stepSize = (m.x2() - m.x1()) / steps; + for(qreal pos = m.x1(); pos < m.x2(); pos += stepSize){ + QGraphicsLineItem *l = new QGraphicsLineItem(pos, m.y1(), pos, m.y1() + 1, this); + + } + }else{ + double steps = (max - min) / interval; + double stepSize = (m.y2() - m.y1()) / steps; + for(qreal pos = m.y1(); pos < m.y2(); pos += stepSize){ + QGraphicsLineItem *l = new QGraphicsLineItem(m.x1(), pos, m.x1() - 1, pos, this); + } + } +} + +void Ruler::setTickInterval(double i) +{ + interval = i; +} + +qreal Ruler::valueAt(const QPointF& p) +{ + QLineF m = line(); + double retValue = orientation == Qt::Horizontal + ? max * (p.x() - m.x1()) / (m.x2() - m.x1()) + : max * (p.y() - m.y1()) / (m.y2() - m.y1()); + return retValue; +} + +qreal Ruler::posAtValue(qreal value) +{ + QLineF m = line(); + double size = max - min; + double percent = value / size; + double realSize = orientation == Qt::Horizontal + ? m.x2() - m.x1() + : m.y2() - m.y1(); + double retValue = realSize * percent; + retValue = (orientation == Qt::Horizontal) + ? retValue + m.x1() + : retValue + m.y1(); + return retValue; +} + +DivePlanner::DivePlanner() : ui(new Ui::DivePlanner()) +{ + ui->setupUi(this); +} + +struct dive* DivePlanner::getDive() +{ + return 0; +} + +DivePlanner* DivePlanner::instance() +{ + static DivePlanner *self = new DivePlanner(); + return self; +} + +double Ruler::maximum() const +{ + return max; +} + +double Ruler::minimum() const +{ + return min; +} + +Button::Button(QObject* parent): QObject(parent), QGraphicsPixmapItem() +{ + setPixmap(QPixmap(":plus").scaled(20,20)); + setFlag(ItemIgnoresTransformations); +} + +void Button::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ + emit clicked(); +} diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h new file mode 100644 index 000000000..453cec63e --- /dev/null +++ b/qt-ui/diveplanner.h @@ -0,0 +1,106 @@ +#ifndef DIVEPLANNER_H +#define DIVEPLANNER_H + +#include <QGraphicsView> +#include <QGraphicsPathItem> +#include <QDialog> + +class Button : public QObject, public QGraphicsPixmapItem { + Q_OBJECT +public: + explicit Button(QObject* parent = 0); +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); +signals: + void clicked(); +}; + +class DiveHandler : public QGraphicsEllipseItem{ +public: + DiveHandler(); + QGraphicsLineItem *from; + QGraphicsLineItem *to; + qreal time; + qreal depth; +}; + +class Ruler : public QGraphicsLineItem{ +public: + Ruler(); + void setMinimum(double minimum); + void setMaximum(double maximum); + void setTickInterval(double interval); + void setOrientation(Qt::Orientation orientation); + void updateTicks(); + double minimum() const; + double maximum() const; + qreal valueAt(const QPointF& p); + qreal posAtValue(qreal value); + +private: + Qt::Orientation orientation; + QList<QGraphicsLineItem*> ticks; + double min; + double max; + double interval; + double posBegin; + double posEnd; +}; + +class DivePlannerGraphics : public QGraphicsView { + Q_OBJECT +public: + DivePlannerGraphics(QWidget* parent = 0); +protected: + virtual void mouseDoubleClickEvent(QMouseEvent* event); + virtual void showEvent(QShowEvent* event); + virtual void resizeEvent(QResizeEvent* event); + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + + void clear_generated_deco(); + void create_deco_stop(); + bool isPointOutOfBoundaries(const QPointF& point); + +private slots: + void increaseTime(); + void increaseDepth(); + +private: + + void moveActiveHandler(const QPointF& pos); + QList<QGraphicsLineItem*> lines; + QList<DiveHandler *> handles; + QGraphicsLineItem *verticalLine; + QGraphicsLineItem *horizontalLine; + DiveHandler *activeDraggedHandler; + + Ruler *timeLine; + QGraphicsSimpleTextItem *timeString; + + Ruler *depthLine; + QGraphicsSimpleTextItem *depthString; + + Button *plusTime; + Button *plusDepth; + Button *lessTime; + Button *lessDepth; + +}; + +namespace Ui{ + class DivePlanner; +} + +class DivePlanner : public QDialog{ + Q_OBJECT +public: + static DivePlanner *instance(); + struct dive* getDive(); + +private: + DivePlanner(); + Ui::DivePlanner *ui; +}; +#endif diff --git a/qt-ui/diveplanner.ui b/qt-ui/diveplanner.ui new file mode 100644 index 000000000..e4903f0f8 --- /dev/null +++ b/qt-ui/diveplanner.ui @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DivePlanner</class> + <widget class="QDialog" name="DivePlanner"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>575</width> + <height>451</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="DivePlannerGraphics" name="graphicsView"/> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>DivePlannerGraphics</class> + <extends>QGraphicsView</extends> + <header>diveplanner.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DivePlanner</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DivePlanner</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 06e6b7734..b61f962c4 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -32,6 +32,7 @@ #include "subsurfacewebservices.h" #include "divecomputermanagementdialog.h" #include "simplewidgets.h" +#include "diveplanner.h" static MainWindow* instance = 0; @@ -181,6 +182,16 @@ void MainWindow::on_actionPrint_triggered() qDebug("actionPrint"); } +void MainWindow::on_actionDivePlanner_triggered() +{ + DivePlanner *planner = DivePlanner::instance(); + if (planner->exec() == QDialog::Accepted){ + struct dive *d = planner->getDive(); + qDebug() << "Finish me."; + } +} + + void MainWindow::on_actionPreferences_triggered() { PreferencesDialog::instance()->show(); diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 0693f07fd..85825958d 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -83,6 +83,7 @@ private slots: void on_actionInputPlan_triggered(); void on_actionAboutSubsurface_triggered(); void on_actionUserManual_triggered(); + void on_actionDivePlanner_triggered(); void current_dive_changed(int divenr); void initialUiSetup(); diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui index 1a985f812..1dfb8a27b 100644 --- a/qt-ui/mainwindow.ui +++ b/qt-ui/mainwindow.ui @@ -103,7 +103,7 @@ <x>0</x> <y>0</y> <width>763</width> - <height>34</height> + <height>20</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -152,6 +152,8 @@ <addaction name="separator"/> <addaction name="actionPreviousDC"/> <addaction name="actionNextDC"/> + <addaction name="separator"/> + <addaction name="actionDivePlanner"/> </widget> <widget class="QMenu" name="menuFilter"> <property name="title"> @@ -368,6 +370,11 @@ <string>Ctrl+4</string> </property> </action> + <action name="actionDivePlanner"> + <property name="text"> + <string>Dive Planner</string> + </property> + </action> </widget> <customwidgets> <customwidget> |