subsurface/qt-ui/diveplanner.cpp
Tomaz Canabrava 2d683b66a8 Added the code to set the Depth / Time on the user Handlers.
Added the code to set the Depth / Time on the user handlers,
I think this finishes the difficult part. ( well, not really )
the depth and time is being set when handler is added or moved,
but as soon as the deco calculations enters on the code, the
handlers will need to be repositioned - and this code is not ready
yet.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
2013-06-20 17:34:42 -03:00

277 lines
6.7 KiB
C++

#include "diveplanner.h"
#include <QMouseEvent>
#include <QDebug>
DivePlanner* DivePlanner::instance()
{
static DivePlanner *self = new DivePlanner();
return self;
}
DivePlanner::DivePlanner(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(60);
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(400);
depthLine->setTickInterval(10);
depthLine->setLine( 10, 1, 10, 90);
depthLine->setOrientation(Qt::Vertical);
depthLine->updateTicks();
scene()->addItem(depthLine);
}
void DivePlanner::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);
item->setPos( mappedPos );
scene()->addItem(item);
handles << item;
if (lines.empty()){
QGraphicsLineItem *first = new QGraphicsLineItem(0,0, 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->setTime(timeLine->valueAt(mappedPos));
item->setDepth(depthLine->valueAt(mappedPos));
}
void DiveHandler::setDepth(qreal d)
{
depth = d;
}
void DiveHandler::setTime(qreal t)
{
time =t;
}
void DivePlanner::clear_generated_deco()
{
for(int i = handles.count(); i <= lines.count(); i++){
scene()->removeItem(lines.last());
delete lines.last();
lines.removeLast();
}
}
void DivePlanner::create_deco_stop()
{
// this needs to create everything
// for the calculated deco. it should return the *first*
// line that's calculated, so the
QGraphicsLineItem *item = new QGraphicsLineItem(handles.last()->x(), handles.last()->y(), 100, 0);
scene()->addItem(item);
lines << item;
}
void DivePlanner::resizeEvent(QResizeEvent* event)
{
QGraphicsView::resizeEvent(event);
fitInView(sceneRect(), Qt::KeepAspectRatio);
}
void DivePlanner::showEvent(QShowEvent* event)
{
QGraphicsView::showEvent(event);
fitInView(sceneRect(), Qt::KeepAspectRatio);
}
void DivePlanner::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());
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 DivePlanner::moveActiveHandler(QPointF pos)
{
int idx = handles.indexOf(activeDraggedHandler);
bool moveLines = false;;
// do not allow it to move between handlers.
if (handles.count() > 1){
if (idx == 0 ){ // first
if (pos.x() < handles[1]->x()){
activeDraggedHandler->setPos(pos);
moveLines = true;
}
}else if (idx == handles.count()-1){ // last
if (pos.x() > handles[idx-1]->x()){
activeDraggedHandler->setPos(pos);
moveLines = true;
}
}else{ // middle
if (pos.x() > handles[idx-1]->x() && pos.x() < handles[idx+1]->x()){
activeDraggedHandler->setPos(pos);
moveLines = true;
}
}
}else{
activeDraggedHandler->setPos(pos);
moveLines = true;
}
if (moveLines){
if (activeDraggedHandler->from){
QLineF f = activeDraggedHandler->from->line();
activeDraggedHandler->from->setLine(f.x1(), f.y1(), pos.x(), pos.y());
}
if (activeDraggedHandler->to){
QLineF f = activeDraggedHandler->to->line();
activeDraggedHandler->to->setLine(pos.x(), pos.y(), f.x2(), f.y2());
}
if(activeDraggedHandler == handles.last()){
clear_generated_deco();
create_deco_stop();
}
}
}
bool DivePlanner::isPointOutOfBoundaries(QPointF point)
{
if (point.x() > sceneRect().width()
|| point.x() < 0
|| point.y() < 0
|| point.y() > sceneRect().height())
{
return true;
}
return false;
}
void DivePlanner::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);
}
}
}
void DivePlanner::mouseReleaseEvent(QMouseEvent* event)
{
if (activeDraggedHandler){
QPointF mappedPos = mapToScene(event->pos());
activeDraggedHandler ->setTime(timeLine->valueAt(mappedPos));
activeDraggedHandler ->setDepth(depthLine->valueAt(mappedPos));
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();
return orientation == Qt::Horizontal
? max * (p.x() - m.x1()) / (m.x2() - m.x1())
: max * (p.y() - m.y1()) / (m.y2() - m.y1());
}