aboutsummaryrefslogtreecommitdiffstats
path: root/qt-ui
diff options
context:
space:
mode:
Diffstat (limited to 'qt-ui')
-rw-r--r--qt-ui/about.cpp2
-rw-r--r--qt-ui/completionmodels.cpp37
-rw-r--r--qt-ui/completionmodels.h34
-rw-r--r--qt-ui/css/tableviews.css28
-rw-r--r--qt-ui/divelistview.cpp9
-rw-r--r--qt-ui/diveplanner.cpp785
-rw-r--r--qt-ui/diveplanner.h113
-rw-r--r--qt-ui/diveplanner.ui135
-rw-r--r--qt-ui/downloadfromdivecomputer.cpp190
-rw-r--r--qt-ui/downloadfromdivecomputer.h43
-rw-r--r--qt-ui/graphicsview-common.cpp8
-rw-r--r--qt-ui/graphicsview-common.h1
-rw-r--r--qt-ui/maintab.cpp354
-rw-r--r--qt-ui/maintab.h25
-rw-r--r--qt-ui/maintab.ui134
-rw-r--r--qt-ui/mainwindow.cpp99
-rw-r--r--qt-ui/mainwindow.h6
-rw-r--r--qt-ui/mainwindow.ui57
-rw-r--r--qt-ui/modeldelegates.cpp36
-rw-r--r--qt-ui/modeldelegates.h9
-rw-r--r--qt-ui/models.cpp141
-rw-r--r--qt-ui/models.h42
-rw-r--r--qt-ui/preferences.ui2
-rw-r--r--qt-ui/printdialog.cpp1
-rw-r--r--qt-ui/printlayout.cpp259
-rw-r--r--qt-ui/printlayout.h22
-rw-r--r--qt-ui/profilegraphics.cpp128
-rw-r--r--qt-ui/profilegraphics.h13
-rw-r--r--qt-ui/tableview.cpp90
-rw-r--r--qt-ui/tableview.h45
-rw-r--r--qt-ui/tableview.ui63
31 files changed, 2083 insertions, 828 deletions
diff --git a/qt-ui/about.cpp b/qt-ui/about.cpp
index 1a96b6257..821835f3e 100644
--- a/qt-ui/about.cpp
+++ b/qt-ui/about.cpp
@@ -1,6 +1,6 @@
#include "about.h"
#include "ui_about.h"
-#include "../version.h"
+#include "version.h"
#include <QDebug>
#include <QDialogButtonBox>
#include <QNetworkReply>
diff --git a/qt-ui/completionmodels.cpp b/qt-ui/completionmodels.cpp
new file mode 100644
index 000000000..8bd4f5441
--- /dev/null
+++ b/qt-ui/completionmodels.cpp
@@ -0,0 +1,37 @@
+#include "completionmodels.h"
+#include "dive.h"
+
+#define CREATE_SINGLETON(X) \
+X* X::instance() \
+{ \
+ static X* self = new X(); \
+ return self; \
+}
+
+CREATE_SINGLETON(BuddyCompletionModel);
+CREATE_SINGLETON(DiveMasterCompletionModel);
+CREATE_SINGLETON(LocationCompletionModel);
+CREATE_SINGLETON(SuitCompletionModel);
+
+#undef CREATE_SINGLETON
+
+#define CREATE_UPDATE_METHOD(Class, diveStructMember) \
+void Class::updateModel() \
+{ \
+ QStringList list; \
+ struct dive* dive; \
+ int i = 0; \
+ for_each_dive(i, dive){ \
+ QString buddy(dive->diveStructMember); \
+ if (!list.contains(buddy)){ \
+ list.append(buddy); \
+ } \
+ } \
+ setStringList(list); \
+}
+
+CREATE_UPDATE_METHOD(BuddyCompletionModel, buddy);
+CREATE_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
+CREATE_UPDATE_METHOD(LocationCompletionModel, location);
+CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
+
diff --git a/qt-ui/completionmodels.h b/qt-ui/completionmodels.h
new file mode 100644
index 000000000..42b81946c
--- /dev/null
+++ b/qt-ui/completionmodels.h
@@ -0,0 +1,34 @@
+#ifndef COMPLETIONMODELS_H
+#define COMPLETIONMODELS_H
+
+#include <QStringListModel>
+
+class BuddyCompletionModel : public QStringListModel {
+ Q_OBJECT
+public:
+ static BuddyCompletionModel* instance();
+ void updateModel();
+};
+
+class DiveMasterCompletionModel : public QStringListModel {
+ Q_OBJECT
+public:
+ static DiveMasterCompletionModel* instance();
+ void updateModel();
+};
+
+class LocationCompletionModel : public QStringListModel {
+ Q_OBJECT
+public:
+ static LocationCompletionModel* instance();
+ void updateModel();
+};
+
+class SuitCompletionModel : public QStringListModel {
+ Q_OBJECT
+public:
+ static SuitCompletionModel* instance();
+ void updateModel();
+};
+
+#endif
diff --git a/qt-ui/css/tableviews.css b/qt-ui/css/tableviews.css
new file mode 100644
index 000000000..4e8396886
--- /dev/null
+++ b/qt-ui/css/tableviews.css
@@ -0,0 +1,28 @@
+ QTableView {
+ show-decoration-selected: 1;
+ }
+
+ QTableView::item {
+ border: 1px solid #d9d9d9;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ padding: 2px;
+ }
+
+ QTableView::item:hover {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
+ border: 1px solid #bfcde4;
+ }
+
+ QTableView::item:selected {
+ border: 1px solid #567dbc;
+ }
+
+ QTableView::item:selected:active{
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
+ }
+
+ QTableView::item:selected:!active {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
+ }
+
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp
index 4b856f601..2e40678ad 100644
--- a/qt-ui/divelistview.cpp
+++ b/qt-ui/divelistview.cpp
@@ -226,16 +226,7 @@ void DiveListView::currentChanged(const QModelIndex& current, const QModelIndex&
{
if (!current.isValid())
return;
- const QAbstractItemModel *model = current.model();
- int selectedDive = 0;
- struct dive *dive = (struct dive*) model->data(current, DiveTripModel::DIVE_ROLE).value<void*>();
- if (!dive) // it's a trip! select first child.
- dive = (struct dive*) model->data(current.child(0,0), DiveTripModel::DIVE_ROLE).value<void*>();
- selectedDive = get_divenr(dive);
scrollTo(current);
- if (selectedDive == selected_dive)
- return;
- Q_EMIT currentDiveChanged(selectedDive);
}
void DiveListView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp
index 1cabdfacf..ceb5ebdba 100644
--- a/qt-ui/diveplanner.cpp
+++ b/qt-ui/diveplanner.cpp
@@ -1,28 +1,54 @@
#include "diveplanner.h"
#include "graphicsview-common.h"
+#include "models.h"
+#include "modeldelegates.h"
+#include "ui_diveplanner.h"
+#include "mainwindow.h"
+#include "tableview.h"
+#include "graphicsview-common.h"
#include "../dive.h"
-#include <cmath>
+#include "../divelist.h"
+#include "../planner.h"
+
#include <QMouseEvent>
#include <QDebug>
-#include <QGraphicsWidget>
-#include <QGraphicsProxyWidget>
-#include <QPushButton>
#include <QGraphicsSceneMouseEvent>
#include <QMessageBox>
-
-#include "ui_diveplanner.h"
-#include "mainwindow.h"
+#include <QStringListModel>
+#include <QListView>
+#include <QModelIndex>
+#include <QSettings>
+#include <QTableView>
+#include <QColor>
#define TIME_INITIAL_MAX 30
#define MAX_DEEPNESS 150
#define MIN_DEEPNESS 40
-bool handlerLessThenMinutes(DiveHandler *d1, DiveHandler *d2){
- return d1->sec < d2->sec;
+QStringListModel *airTypes(){
+ static QStringListModel *self = new QStringListModel(QStringList()
+ << QObject::tr("AIR")
+ << QObject::tr("EAN32")
+ << QObject::tr("EAN36"));
+ return self;
+}
+
+QString strForAir(const divedatapoint& p){
+ return p.o2 == 209 ? QObject::tr("AIR")
+ : p.o2 == 320 ? QObject::tr("EAN32")
+ : p.o2 == 360 ? QObject::tr("EAN36")
+ : QObject::tr("Choose Gas");
}
+QColor getColor(const color_indice_t i)
+{
+ return profile_color[i].at(0);
+}
+
+static DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
+
DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent), activeDraggedHandler(0)
{
fill_profile_color();
@@ -47,6 +73,7 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
fromPercent(100, Qt::Horizontal),
fromPercent(0, Qt::Vertical)
);
+
horizontalLine->setPen(QPen(Qt::DotLine));
scene()->addItem(horizontalLine);
@@ -54,6 +81,7 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
timeLine->setMinimum(0);
timeLine->setMaximum(TIME_INITIAL_MAX);
timeLine->setTickInterval(10);
+ timeLine->setColor(getColor(TIME_GRID));
timeLine->setLine(
fromPercent(10, Qt::Horizontal),
fromPercent(90, Qt::Vertical),
@@ -62,7 +90,7 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
);
timeLine->setOrientation(Qt::Horizontal);
timeLine->setTickSize(fromPercent(1, Qt::Vertical));
- timeLine->setColor(profile_color[TIME_GRID].at(0));
+ timeLine->setTextColor(getColor(TIME_TEXT));
timeLine->updateTicks();
scene()->addItem(timeLine);
@@ -78,7 +106,8 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
);
depthLine->setOrientation(Qt::Vertical);
depthLine->setTickSize(fromPercent(1, Qt::Horizontal));
- depthLine->setColor(profile_color[DEPTH_GRID].at(0));
+ depthLine->setColor(getColor(DEPTH_GRID));
+ depthLine->setTextColor(getColor(SAMPLE_DEEP));
depthLine->updateTicks();
scene()->addItem(depthLine);
@@ -96,33 +125,19 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
diveBg->setPen(QPen(QBrush(),0));
scene()->addItem(diveBg);
- plusDepth = new Button();
- plusDepth->setPixmap(QPixmap(":plus"));
- plusDepth->setPos(fromPercent(5, Qt::Horizontal), fromPercent(5, Qt::Vertical));
- plusDepth->setToolTip("Increase maximum depth by 10m");
- scene()->addItem(plusDepth);
- connect(plusDepth, SIGNAL(clicked()), this, SLOT(increaseDepth()));
-
- plusTime = new Button();
- plusTime->setPixmap(QPixmap(":plus"));
- plusTime->setPos(fromPercent(95, Qt::Horizontal), fromPercent(95, Qt::Vertical));
- plusTime->setToolTip("Increase minimum dive time by 10m");
- scene()->addItem(plusTime);
- connect(plusTime, SIGNAL(clicked()), this, SLOT(increaseTime()));
-
- okBtn = new Button();
- okBtn->setText(tr("Ok"));
- okBtn->setPos(fromPercent(1, Qt::Horizontal), fromPercent(95, Qt::Vertical));
- scene()->addItem(okBtn);
- connect(okBtn, SIGNAL(clicked()), this, SLOT(okClicked()));
-
- cancelBtn = new Button();
- cancelBtn->setText(tr("Cancel"));
- cancelBtn->setPos(okBtn->pos().x() + okBtn->boundingRect().width() + fromPercent(2, Qt::Horizontal),
- fromPercent(95, Qt::Vertical));
- scene()->addItem(cancelBtn);
- connect(cancelBtn, SIGNAL(clicked()), this, SLOT(cancelClicked()));
-
+#define ADDBTN(obj, icon, text, horizontal, vertical, tooltip, slot) \
+ obj = new Button(); \
+ obj->setPixmap(QPixmap(icon)); \
+ obj->setPos(fromPercent(horizontal, Qt::Horizontal), fromPercent(vertical, Qt::Vertical)); \
+ obj->setToolTip(tooltip); \
+ scene()->addItem(obj); \
+ connect(obj, SIGNAL(clicked()), this, SLOT(slot));
+
+ ADDBTN(plusDepth, ":plus", "" , 5, 5, tr("Increase maximum depth by 10m"), increaseDepth());
+ ADDBTN(plusTime, ":plus", "" , 95, 95, tr("Increase minimum time by 10m"), increaseTime());
+ ADDBTN(lessDepth, ":minimum","" , 2, 5, tr("Decreases maximum depth by 10m"), decreaseDepth());
+ ADDBTN(lessTime, ":minimum","" , 92, 95, tr("Decreases minimum time by 10m"), decreaseTime());
+#undef ADDBTN
minMinutes = TIME_INITIAL_MAX;
QAction *action = NULL;
@@ -142,23 +157,51 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
ADD_ACTION(Qt::Key_Right, keyRightAction());
#undef ADD_ACTION
+ // Prepare the stuff for the gas-choices.
+ gasListView = new QListView();
+ gasListView->setWindowFlags(Qt::Popup);
+ gasListView->setModel(airTypes());
+ gasListView->hide();
+
+ connect(gasListView, SIGNAL(activated(QModelIndex)), this, SLOT(selectGas(QModelIndex)));
+ connect(plannerModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(createDecoStops()));
+
+ connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex&,int,int)),
+ this, SLOT(pointInserted(const QModelIndex&, int, int)));
+ connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ this, SLOT(pointsRemoved(const QModelIndex&, int, int)));
setRenderHint(QPainter::Antialiasing);
}
+void DivePlannerGraphics::pointInserted(const QModelIndex& parent, int start , int end)
+{
+ DiveHandler *item = new DiveHandler ();
+ scene()->addItem(item);
+ handles << item;
+
+ Button *gasChooseBtn = new Button();
+ scene()->addItem(gasChooseBtn);
+ gasChooseBtn->setZValue(10);
+ connect(gasChooseBtn, SIGNAL(clicked()), this, SLOT(prepareSelectGas()));
+
+ gases << gasChooseBtn;
+ createDecoStops();
+}
+
void DivePlannerGraphics::keyDownAction()
{
if(scene()->selectedItems().count()){
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->mm / 1000 >= depthLine->maximum())
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+ if (dp.depth / 1000 >= depthLine->maximum())
continue;
- handler->mm += 1000;
- double ypos = depthLine->posAtValue(handler->mm / 1000);
- handler->setPos(handler->pos().x(), ypos);
+ dp.depth += 1000;
+ plannerModel->editStop(row, dp);
}
}
- createDecoStops();
}
}
@@ -166,12 +209,14 @@ void DivePlannerGraphics::keyUpAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->mm / 1000 <= 0)
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+
+ if (dp.depth / 1000 <= 0)
continue;
- handler->mm -= 1000;
- double ypos = depthLine->posAtValue(handler->mm / 1000);
- handler->setPos(handler->pos().x(), ypos);
+ dp.depth -= 1000;
+ plannerModel->editStop(row, dp);
}
}
createDecoStops();
@@ -181,12 +226,15 @@ void DivePlannerGraphics::keyLeftAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->sec / 60 <= 0)
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+
+ if (dp.time / 60 <= 0)
continue;
// don't overlap positions.
// maybe this is a good place for a 'goto'?
- double xpos = timeLine->posAtValue((handler->sec - 60) / 60);
+ double xpos = timeLine->posAtValue((dp.time - 60) / 60);
bool nextStep = false;
Q_FOREACH(DiveHandler *h, handles){
if (h->pos().x() == xpos){
@@ -197,23 +245,24 @@ void DivePlannerGraphics::keyLeftAction()
if(nextStep)
continue;
- handler->sec -= 60;
- handler->setPos(xpos, handler->pos().y());
+ dp.time -= 60;
+ plannerModel->editStop(row, dp);
}
}
- createDecoStops();
}
void DivePlannerGraphics::keyRightAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->sec / 60 >= timeLine->maximum())
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+ if (dp.time / 60 >= timeLine->maximum())
continue;
// don't overlap positions.
// maybe this is a good place for a 'goto'?
- double xpos = timeLine->posAtValue((handler->sec + 60) / 60);
+ double xpos = timeLine->posAtValue((dp.time + 60) / 60);
bool nextStep = false;
Q_FOREACH(DiveHandler *h, handles){
if (h->pos().x() == xpos){
@@ -224,34 +273,61 @@ void DivePlannerGraphics::keyRightAction()
if(nextStep)
continue;
- handler->sec += 60;
- handler->setPos(xpos, handler->pos().y());
+ dp.time += 60;
+ plannerModel->editStop(row, dp);
}
- } createDecoStops();
+ }
}
void DivePlannerGraphics::keyDeleteAction()
{
- if(scene()->selectedItems().count()){
+ int selCount = scene()->selectedItems().count();
+ if(selCount){
+ QVector<int> selectedIndexes;
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- handles.removeAll(handler);
- scene()->removeItem(handler);
- delete i;
+ selectedIndexes.push_back(handles.indexOf(handler));
}
}
- createDecoStops();
+ plannerModel->removeSelectedPoints(selectedIndexes);
}
}
+void DivePlannerGraphics::pointsRemoved(const QModelIndex& , int start, int end)
+{ // start and end are inclusive.
+ int num = (end - start) + 1;
+ for(int i = num; i != 0; i--){
+ delete handles.back();
+ handles.pop_back();
+ delete gases.back();
+ gases.pop_back();
+ }
+ scene()->clearSelection();
+ createDecoStops();
+}
+
+bool intLessThan(int a, int b){
+ return a <= b;
+}
+void DivePlannerPointsModel::removeSelectedPoints(const QVector< int >& rows)
+{
+ int firstRow = rowCount() - rows.count();
+ QVector<int> v2 = rows;
+ std::sort(v2.begin(), v2.end(), intLessThan);
+ beginRemoveRows(QModelIndex(), firstRow, rowCount()-1);
+ for(int i = v2.count()-1; i >= 0; i--){
+ divepoints.remove(v2[i]);
+ }
+ endRemoveRows();
+}
+
void DivePlannerGraphics::keyEscAction()
{
if (scene()->selectedItems().count()){
scene()->clearSelection();
return;
}
-
- cancelClicked();
+ plannerModel->cancelPlan();
}
qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientation)
@@ -261,23 +337,6 @@ qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientatio
return result;
}
-void DivePlannerGraphics::cancelClicked()
-{
- if (handles.size()){
- if (QMessageBox::warning(mainWindow(), tr("Save the Plan?"),
- tr("You have a working plan, \n are you sure that you wanna cancel it?"),
- QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok){
- return;
- }
- }
- mainWindow()->showProfile();
-}
-
-void DivePlannerGraphics::okClicked()
-{
- // todo.
-}
-
void DivePlannerGraphics::increaseDepth()
{
if (depthLine->maximum() + 10 > MAX_DEEPNESS)
@@ -295,6 +354,40 @@ void DivePlannerGraphics::increaseTime()
createDecoStops();
}
+void DivePlannerGraphics::decreaseDepth()
+{
+ if (depthLine->maximum() - 10 < MIN_DEEPNESS)
+ return;
+
+ Q_FOREACH(DiveHandler *d, handles){
+ if (depthLine->valueAt(d->pos()) > depthLine->maximum() - 10){
+ QMessageBox::warning(mainWindow(),
+ tr("Handler Position Error"),
+ tr("One or more of your stops will be lost with this operations, \n"
+ "Please, remove them first."));
+ return;
+ }
+ }
+ depthLine->setMaximum(depthLine->maximum() - 10);
+ depthLine->updateTicks();
+ createDecoStops();
+}
+
+void DivePlannerGraphics::decreaseTime()
+{
+ if (timeLine->maximum() -10 < TIME_INITIAL_MAX){
+ return;
+ }
+ if (timeLine->maximum() - 10 < dpMaxTime){
+ qDebug() << timeLine->maximum() << dpMaxTime;
+ return;
+ }
+ minMinutes -= 10;
+ timeLine->setMaximum(timeLine->maximum() -10);
+ timeLine->updateTicks();
+ createDecoStops();
+}
+
void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event)
{
QPointF mappedPos = mapToScene(event->pos());
@@ -303,78 +396,54 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event)
int minutes = rint(timeLine->valueAt(mappedPos));
int meters = rint(depthLine->valueAt(mappedPos));
- double xpos = timeLine->posAtValue(minutes);
- double ypos = depthLine->posAtValue(meters);
- Q_FOREACH(DiveHandler* handler, handles){
- if (xpos == handler->pos().x()){
- qDebug() << "There's already an point at that place.";
- //TODO: Move this later to a KMessageWidget.
- return;
- }
- }
+ plannerModel->addStop(meters * 1000, minutes * 60, tr("Air"), 0);
+}
- DiveHandler *item = new DiveHandler ();
- item->sec = minutes * 60;
- item->mm = meters * 1000;
- item->setPos(QPointF(xpos, ypos));
- scene()->addItem(item);
- handles << item;
- createDecoStops();
+void DivePlannerGraphics::prepareSelectGas()
+{
+ currentGasChoice = static_cast<Button*>(sender());
+ QPoint c = QCursor::pos();
+ gasListView->setGeometry(c.x(), c.y(), 150, 100);
+ gasListView->show();
+}
+
+void DivePlannerGraphics::selectGas(const QModelIndex& index)
+{
+ QString gasSelected = gasListView->model()->data(index, Qt::DisplayRole).toString();
+ int idx = gases.indexOf(currentGasChoice);
+ plannerModel->setData(plannerModel->index(idx, DivePlannerPointsModel::GAS), gasSelected);
+ gasListView->hide();
}
void DivePlannerGraphics::createDecoStops()
{
qDeleteAll(lines);
lines.clear();
- qSort(handles.begin(), handles.end(), handlerLessThenMinutes);
-
- // This needs to be done in the following steps:
- // Get the user-input and calculate the dive info
- // Not sure if this is the place to create the diveplan...
- // We just start with a surface node at time = 0
- struct diveplan diveplan;
- struct divedatapoint *dp = create_dp(0, 0, 209, 0, 0);
- dp->entered = TRUE;
- diveplan.dp = dp;
- diveplan.gflow = 30;
- diveplan.gfhigh = 70;
- diveplan.surface_pressure = 1013;
- DiveHandler *lastH = NULL;
- Q_FOREACH(DiveHandler *h, handles) {
- // these values need to come from the planner UI, eventually
- int o2 = 209;
- int he = 0;
- int po2 = 0;
- int deltaT = lastH ? h->sec - lastH->sec : h->sec;
- lastH = h;
- dp = plan_add_segment(&diveplan, deltaT, h->mm, o2, he, po2);
- dp->entered = TRUE;
- qDebug("time %d, depth %d", h->sec, h->mm);
- }
-#if DEBUG_PLAN
- dump_plan(&diveplan);
-#endif
- char *cache = NULL;
- struct dive *dive = NULL;
- char *errorString = NULL;
- plan(&diveplan, &cache, &dive, &errorString);
-#if DEBUG_PLAN
- dump_plan(&diveplan);
-#endif
- while(dp->next)
+ plannerModel->createTemporaryPlan();
+ struct diveplan diveplan = plannerModel->getDiveplan();
+ struct divedatapoint *dp = diveplan.dp;
+ while(dp->next){
dp = dp->next;
+ }
- if (timeLine->maximum() < dp->time / 60.0 + 5 ||
- dp->time / 60.0 + 15 < timeLine->maximum()) {
+ if (timeLine->maximum() < dp->time / 60.0 + 5 || dp->time / 60.0 + 15 < timeLine->maximum()) {
double newMax = fmax(dp->time / 60.0 + 5, minMinutes);
timeLine->setMaximum(newMax);
timeLine->updateTicks();
}
// Re-position the user generated dive handlers
- Q_FOREACH(DiveHandler *h, handles){
- h->setPos(timeLine->posAtValue(h->sec / 60), depthLine->posAtValue(h->mm / 1000));
+ for(int i = 0; i < plannerModel->rowCount(); i++){
+ divedatapoint dp = plannerModel->at(i);
+ DiveHandler *h = handles.at(i);
+ h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth / 1000));
+ QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos();
+ QPointF p2 = handles[i]->pos();
+ QLineF line(p1, p2);
+ QPointF pos = line.pointAt(0.5);
+ gases[i]->setPos(pos);
+ gases[i]->setText( strForAir(dp));
}
// (re-) create the profile with different colors for segments that were
@@ -384,6 +453,7 @@ void DivePlannerGraphics::createDecoStops()
QPolygonF poly;
poly.append(QPointF(lastx, lasty));
+
for (dp = diveplan.dp; dp != NULL; dp = dp->next) {
double xpos = timeLine->posAtValue(dp->time / 60.0);
double ypos = depthLine->posAtValue(dp->depth / 1000.0);
@@ -411,15 +481,7 @@ void DivePlannerGraphics::createDecoStops()
pat.setColorAt(0, profile_color[DEPTH_TOP].first());
diveBg->setBrush(pat);
- deleteTemporaryDivePlan(diveplan.dp);
-}
-
-void DivePlannerGraphics::deleteTemporaryDivePlan(divedatapoint* dp)
-{
- if (!dp)
- return;
- deleteTemporaryDivePlan(dp->next);
- free(dp);
+ plannerModel->deleteTemporaryPlan();
}
void DivePlannerGraphics::resizeEvent(QResizeEvent* event)
@@ -532,8 +594,14 @@ void DivePlannerGraphics::mouseReleaseEvent(QMouseEvent* event)
}
}
- activeDraggedHandler->sec = rint(timeLine->valueAt(mappedPos)) * 60;
- activeDraggedHandler->mm = rint(depthLine->valueAt(mappedPos)) * 1000;
+ int pos = handles.indexOf(activeDraggedHandler);
+ divedatapoint data = plannerModel->at(pos);
+
+ data.depth = rint(depthLine->valueAt(mappedPos)) * 1000;
+ data.time = rint(timeLine->valueAt(mappedPos)) * 60;
+
+ plannerModel->editStop(pos, data);
+
activeDraggedHandler->setBrush(QBrush(Qt::white));
activeDraggedHandler->setPos(QPointF(xpos, ypos));
@@ -542,7 +610,7 @@ void DivePlannerGraphics::mouseReleaseEvent(QMouseEvent* event)
}
}
-DiveHandler::DiveHandler(): QGraphicsEllipseItem(), from(0), to(0)
+DiveHandler::DiveHandler(): QGraphicsEllipseItem()
{
setRect(-5,-5,10,10);
setFlag(QGraphicsItem::ItemIgnoresTransformations);
@@ -558,6 +626,10 @@ void DiveHandler::mousePressEvent(QGraphicsSceneMouseEvent* event)
}
// mousePressEvent 'grabs' the mouse and keyboard, annoying.
ungrabMouse();
+
+ /* hack. Sometimes the keyboard is grabbed, sometime it's not,
+ so, let's force a grab and release, to get rid of a warning. */
+ grabKeyboard();
ungrabKeyboard();
}
@@ -571,6 +643,11 @@ void Ruler::setMinimum(double minimum)
min = minimum;
}
+void Ruler::setTextColor(const QColor& color)
+{
+ textColor = color;
+}
+
Ruler::Ruler() : orientation(Qt::Horizontal)
{
}
@@ -578,39 +655,70 @@ Ruler::Ruler() : orientation(Qt::Horizontal)
void Ruler::setOrientation(Qt::Orientation o)
{
orientation = o;
+ // position the elements on the screen.
+ setMinimum(minimum());
+ setMaximum(maximum());
}
void Ruler::updateTicks()
{
qDeleteAll(ticks);
ticks.clear();
+ qDeleteAll(labels);
+ labels.clear();
+
QLineF m = line();
QGraphicsLineItem *item = NULL;
+ QGraphicsSimpleTextItem *label = NULL;
+
+ double steps = (max - min) / interval;
+ qreal pos;
+ double currValue = min;
if (orientation == Qt::Horizontal) {
- double steps = (max - min) / interval;
double stepSize = (m.x2() - m.x1()) / steps;
- qreal pos;
- for (pos = m.x1(); pos < m.x2(); pos += stepSize) {
+ for (pos = m.x1(); pos < m.x2(); pos += stepSize, currValue += interval) {
item = new QGraphicsLineItem(pos, m.y1(), pos, m.y1() + tickSize, this);
item->setPen(pen());
ticks.push_back(item);
+
+ label = new QGraphicsSimpleTextItem(QString::number(currValue), this);
+ label->setBrush(QBrush(textColor));
+ label->setFlag(ItemIgnoresTransformations);
+ label->setPos(pos - label->boundingRect().width()/2, m.y1() + tickSize + 5);
+ labels.push_back(label);
}
item = new QGraphicsLineItem(pos, m.y1(), pos, m.y1() + tickSize, this);
item->setPen(pen());
ticks.push_back(item);
+
+ label = new QGraphicsSimpleTextItem(QString::number(currValue), this);
+ label->setBrush(QBrush(textColor));
+ label->setFlag(ItemIgnoresTransformations);
+ label->setPos(pos - label->boundingRect().width()/2, m.y1() + tickSize + 5);
+ labels.push_back(label);
} else {
- double steps = (max - min) / interval;
double stepSize = (m.y2() - m.y1()) / steps;
- qreal pos;
- for (pos = m.y1(); pos < m.y2(); pos += stepSize) {
+ for (pos = m.y1(); pos < m.y2(); pos += stepSize, currValue += interval) {
item = new QGraphicsLineItem(m.x1(), pos, m.x1() - tickSize, pos, this);
item->setPen(pen());
ticks.push_back(item);
+
+ label = new QGraphicsSimpleTextItem(QString::number(currValue), this);
+ label->setBrush(QBrush(textColor));
+ label->setFlag(ItemIgnoresTransformations);
+ label->setPos(m.x2() - 80, pos);
+ labels.push_back(label);
}
item = new QGraphicsLineItem(m.x1(), pos, m.x1() - tickSize, pos, this);
item->setPen(pen());
ticks.push_back(item);
+
+ label = new QGraphicsSimpleTextItem(QString::number(currValue), this);
+ label->setBrush(QBrush(textColor));
+ label->setFlag(ItemIgnoresTransformations);
+ label->setPos(m.x2() - 80, pos);
+ labels.push_back(label);
}
}
@@ -670,12 +778,17 @@ double Ruler::minimum() const
void Ruler::setColor(const QColor& color)
{
- setPen(QPen(color));
+ QPen defaultPen(color);
+ defaultPen.setJoinStyle(Qt::RoundJoin);
+ defaultPen.setCapStyle(Qt::RoundCap);
+ defaultPen.setWidth(2);
+ defaultPen.setCosmetic(true);
+ setPen(defaultPen);
}
Button::Button(QObject* parent): QObject(parent), QGraphicsRectItem()
{
- icon = new QGraphicsPixmapItem(this);
+ icon = new QGraphicsPixmapItem(this);
text = new QGraphicsSimpleTextItem(this);
icon->setPos(0,0);
text->setPos(0,0);
@@ -712,3 +825,361 @@ void Button::mousePressEvent(QGraphicsSceneMouseEvent* event)
event->ignore();
emit clicked();
}
+
+DivePlannerWidget::DivePlannerWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f), ui(new Ui::DivePlanner())
+{
+ ui->setupUi(this);
+ ui->tableWidget->setTitle(tr("Dive Planner Points"));
+ ui->tableWidget->setModel(DivePlannerPointsModel::instance());
+ ui->tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(this));
+
+ connect(ui->tableWidget, SIGNAL(addButtonClicked()), DivePlannerPointsModel::instance(), SLOT(addStop()));
+ connect(ui->startTime, SIGNAL(timeChanged(QTime)), this, SLOT(startTimeChanged(QTime)));
+ connect(ui->ATMPressure, SIGNAL(textChanged(QString)), this, SLOT(atmPressureChanged(QString)));
+ connect(ui->bottomSAC, SIGNAL(textChanged(QString)), this, SLOT(bottomSacChanged(QString)));
+ connect(ui->decoStopSAC, SIGNAL(textChanged(QString)), this, SLOT(decoSacChanged(QString)));
+ connect(ui->highGF, SIGNAL(textChanged(QString)), this, SLOT(gfhighChanged(QString)));
+ connect(ui->lowGF, SIGNAL(textChanged(QString)), this, SLOT(gflowChanged(QString)));
+ connect(ui->highGF, SIGNAL(textChanged(QString)), this, SLOT(gfhighChanged(QString)));
+ connect(ui->lastStop, SIGNAL(toggled(bool)), this, SLOT(lastStopChanged(bool)));
+
+ // Creating the plan
+ connect(ui->buttonBox, SIGNAL(accepted()), plannerModel, SLOT(createPlan()));
+ connect(ui->buttonBox, SIGNAL(rejected()), plannerModel, SLOT(cancelPlan()));
+ connect(plannerModel, SIGNAL(planCreated()), mainWindow(), SLOT(showProfile()));
+ connect(plannerModel, SIGNAL(planCreated()), mainWindow(), SLOT(refreshDisplay()));
+ connect(plannerModel, SIGNAL(planCanceled()), mainWindow(), SLOT(showProfile()));
+
+ /* set defaults. */
+ ui->startTime->setTime( QTime(1, 0) );
+ ui->ATMPressure->setText( "1013" );
+ ui->bottomSAC->setText("20");
+ ui->decoStopSAC->setText("17");
+ ui->lowGF->setText("30");
+ ui->highGF->setText("75");
+}
+
+void DivePlannerWidget::startTimeChanged(const QTime& time)
+{
+ plannerModel->setStartTime(time);
+}
+
+void DivePlannerWidget::atmPressureChanged(const QString& pressure)
+{
+ plannerModel->setSurfacePressure(pressure.toInt());
+}
+
+void DivePlannerWidget::bottomSacChanged(const QString& bottomSac)
+{
+ plannerModel->setBottomSac(bottomSac.toInt());
+}
+
+void DivePlannerWidget::decoSacChanged(const QString& decosac)
+{
+ plannerModel->setDecoSac(decosac.toInt());
+}
+
+void DivePlannerWidget::gfhighChanged(const QString& gfhigh)
+{
+ plannerModel->setGFHigh(gfhigh.toShort());
+}
+
+void DivePlannerWidget::gflowChanged(const QString& gflow)
+{
+ plannerModel->setGFLow(gflow.toShort());
+}
+
+void DivePlannerWidget::lastStopChanged(bool checked)
+{
+ plannerModel->setLastStop6m(checked);
+}
+
+int DivePlannerPointsModel::columnCount(const QModelIndex& parent) const
+{
+ return COLUMNS;
+}
+
+QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const
+{
+ if(role == Qt::DisplayRole){
+ divedatapoint p = divepoints.at(index.row());
+ switch(index.column()){
+ case CCSETPOINT: return p.po2;
+ case DEPTH: return p.depth / 1000;
+ case DURATION: return p.time / 60;
+ case GAS: return strForAir(p);
+ }
+ }
+ else if (role == Qt::DecorationRole){
+ switch(index.column()){
+ case REMOVE : return QIcon(":trash");
+ }
+ }
+ else if (role == Qt::FontRole){
+ return defaultModelFont();
+ }
+ return QVariant();
+}
+
+bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& value, int role)
+{
+ if(role == Qt::EditRole){
+ divedatapoint& p = divepoints[index.row()];
+ switch(index.column()){
+ case DEPTH: p.depth = value.toInt() * 1000; break;
+ case DURATION: p.time = value.toInt() * 60; break;
+ case CCSETPOINT:{
+ int po2 = 0;
+ QByteArray gasv = value.toByteArray();
+ if (validate_po2(gasv.data(), &po2))
+ p.po2 = po2;
+ } break;
+ case GAS: {
+ int o2 = 0;
+ int he = 0;
+ QByteArray gasv = value.toByteArray();
+ if (validate_gas(gasv.data(), &o2, &he)) {
+ p.o2 = o2;
+ p.he = he;
+ }break;
+ }
+ }
+ editStop(index.row(), p);
+ }
+ return QAbstractItemModel::setData(index, value, role);
+}
+
+QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal){
+ switch(section){
+ case DEPTH: return tr("Final Depth");
+ case DURATION: return tr("Duration");
+ case GAS: return tr("Used Gas");
+ case CCSETPOINT: return tr("CC Set Point");
+ }
+ }
+ else if (role == Qt::FontRole){
+ return defaultModelFont();
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags DivePlannerPointsModel::flags(const QModelIndex& index) const
+{
+ return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+}
+
+int DivePlannerPointsModel::rowCount(const QModelIndex& parent) const
+{
+ return divepoints.count();
+}
+
+DivePlannerPointsModel::DivePlannerPointsModel(QObject* parent): QAbstractTableModel(parent)
+{
+}
+
+DivePlannerPointsModel* DivePlannerPointsModel::instance()
+{
+ static DivePlannerPointsModel* self = new DivePlannerPointsModel();
+ return self;
+}
+
+void DivePlannerPointsModel::setBottomSac(int sac)
+{
+ diveplan.bottomsac = sac;
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+void DivePlannerPointsModel::setDecoSac(int sac)
+{
+ diveplan.decosac = sac;
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+void DivePlannerPointsModel::setGFHigh(short int gfhigh)
+{
+ diveplan.gfhigh = gfhigh;
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+void DivePlannerPointsModel::setGFLow(short int ghflow)
+{
+ diveplan.gflow = ghflow;
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+void DivePlannerPointsModel::setSurfacePressure(int pressure)
+{
+ diveplan.surface_pressure = pressure;
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+void DivePlannerPointsModel::setLastStop6m(bool value)
+{
+}
+
+void DivePlannerPointsModel::setStartTime(const QTime& t)
+{
+ diveplan.when = t.msec();
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2){
+ return p1.time <= p2.time;
+}
+int DivePlannerPointsModel::addStop(int meters, int minutes, const QString& gas, int ccpoint)
+{
+ int row = divepoints.count();
+ if(meters == 0 && minutes == 0){
+ if(row == 0){
+ meters = 10000;
+ minutes = 600;
+ }
+ else{
+ divedatapoint p = at(row-1);
+ meters = p.depth;
+ minutes = p.time + 600;
+ }
+ }
+
+ // check if there's already a new stop before this one:
+ for(int i = 0; i < divepoints.count(); i++){
+ const divedatapoint& dp = divepoints.at(i);
+ if (dp.time > minutes ){
+ row = i;
+ break;
+ }
+ }
+
+ // add the new stop
+ beginInsertRows(QModelIndex(), row, row);
+ divedatapoint point;
+ point.depth = meters;
+ point.time = minutes;
+ if (row == 0){
+ point.o2 = 209;
+ point.he = 0;
+ point.po2 = 0;
+ }else{
+ divedatapoint before = at(row-1);
+ point.o2 = before.o2;
+ point.he = before.he;
+ point.po2 = 0;
+ }
+ divepoints.append( point );
+ std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan);
+ endInsertRows();
+ return row;
+}
+
+void DivePlannerPointsModel::editStop(int row, divedatapoint newData)
+{
+ divepoints[row] = newData;
+ std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan);
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+divedatapoint DivePlannerPointsModel::at(int row)
+{
+ return divepoints.at(row);
+}
+
+void DivePlannerPointsModel::remove(const QModelIndex& index)
+{
+ if (index.column() != REMOVE)
+ return;
+
+ beginRemoveRows(QModelIndex(), index.row(), index.row());
+ divepoints.remove(index.row());
+ endRemoveRows();
+}
+
+struct diveplan DivePlannerPointsModel::getDiveplan()
+{
+ return diveplan;
+}
+
+void DivePlannerPointsModel::cancelPlan()
+{
+ if(rowCount()){
+ if (QMessageBox::warning(mainWindow(), tr("Save the Plan?"),
+ tr("You have a working plan, \n are you sure that you wanna cancel it?"),
+ QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok){
+ return;
+ }
+ }
+
+ beginRemoveRows(QModelIndex(), 0, rowCount()-1);
+ divepoints.clear();
+ endRemoveRows();
+ emit planCanceled();
+}
+
+void DivePlannerPointsModel::createTemporaryPlan()
+{
+ // This needs to be done in the following steps:
+ // Get the user-input and calculate the dive info
+ // Not sure if this is the place to create the diveplan...
+ // We just start with a surface node at time = 0
+ struct divedatapoint *dp = create_dp(0, 0, 209, 0, 0);
+ dp->entered = TRUE;
+ diveplan.dp = dp;
+ int lastIndex = -1;
+ for(int i = 0; i < rowCount(); i++){
+ divedatapoint p = at(i);
+ int deltaT = lastIndex != -1 ? p.time - at(lastIndex).time : p.time;
+ lastIndex = i;
+ dp = plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2);
+ }
+#if DEBUG_PLAN
+ dump_plan(&diveplan);
+#endif
+ char *cache = NULL;
+ tempDive = NULL;
+ char *errorString = NULL;
+ plan(&diveplan, &cache, &tempDive, &errorString);
+#if DEBUG_PLAN
+ dump_plan(&diveplan);
+#endif
+}
+
+void DivePlannerPointsModel::deleteTemporaryPlan()
+{
+ deleteTemporaryPlan(diveplan.dp);
+ delete_single_dive(get_divenr(tempDive));
+ tempDive = NULL;
+}
+
+void DivePlannerPointsModel::deleteTemporaryPlan(struct divedatapoint *dp)
+{
+ if (!dp){
+ return;
+ }
+
+ deleteTemporaryPlan(dp->next);
+ free(dp);
+}
+
+void DivePlannerPointsModel::createPlan()
+{
+ // Ok, so, here the diveplan creates a dive,
+ // puts it on the dive list, and we need to remember
+ // to not delete it later. mumble. ;p
+ char *cache = NULL;
+ tempDive = NULL;
+ char *errorString = NULL;
+
+ createTemporaryPlan();
+ plan(&diveplan, &cache, &tempDive, &errorString);
+ mark_divelist_changed(TRUE);
+
+ // Remove and clean the diveplan, so we don't delete
+ // the dive by mistake.
+ diveplan.dp = NULL;
+ beginRemoveRows(QModelIndex(), 0, rowCount() -1 );
+ divepoints.clear();
+ endRemoveRows();
+
+ planCreated();
+}
diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h
index 7f33f044b..8dd8db3e3 100644
--- a/qt-ui/diveplanner.h
+++ b/qt-ui/diveplanner.h
@@ -4,6 +4,67 @@
#include <QGraphicsView>
#include <QGraphicsPathItem>
#include <QDialog>
+#include <QAbstractTableModel>
+#include <QDateTime>
+
+#include "dive.h"
+
+namespace Ui{
+ class DivePlanner;
+};
+
+class QListView;
+class QStringListModel;
+class QModelIndex;
+
+// Return a Model containing the air types.
+QStringListModel *airTypes();
+
+class DivePlannerPointsModel : public QAbstractTableModel{
+ Q_OBJECT
+public:
+ static DivePlannerPointsModel* instance();
+ enum Sections{REMOVE, DEPTH, DURATION, GAS, CCSETPOINT, COLUMNS};
+ virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
+ virtual Qt::ItemFlags flags(const QModelIndex& index) const;
+ void removeSelectedPoints(const QVector<int>& rows);
+
+ /**
+ * @return the row number.
+ */
+ void editStop(int row, divedatapoint newData );
+ divedatapoint at(int row);
+ struct diveplan getDiveplan();
+public slots:
+ int addStop(int meters = 0, int minutes = 0,const QString& gas = QString(), int ccpoint = 0 );
+ void setGFHigh(short gfhigh);
+ void setGFLow(short ghflow);
+ void setSurfacePressure(int pressure);
+ void setBottomSac(int sac);
+ void setDecoSac(int sac);
+ void setStartTime(const QTime& t);
+ void setLastStop6m(bool value);
+ void createPlan();
+ void remove(const QModelIndex& index);
+ void cancelPlan();
+ void createTemporaryPlan();
+ void deleteTemporaryPlan();
+
+signals:
+ void planCreated();
+ void planCanceled();
+
+private:
+ explicit DivePlannerPointsModel(QObject* parent = 0);
+ struct diveplan diveplan;
+ QVector<divedatapoint> divepoints;
+ struct dive *tempDive;
+ void deleteTemporaryPlan(struct divedatapoint *dp);
+};
class Button : public QObject, public QGraphicsRectItem {
Q_OBJECT
@@ -24,13 +85,8 @@ private:
class DiveHandler : public QGraphicsEllipseItem{
public:
DiveHandler();
- QGraphicsLineItem *from;
- QGraphicsLineItem *to;
- int sec;
- int mm;
protected:
- void mousePressEvent(QGraphicsSceneMouseEvent* event);
-
+ void mousePressEvent(QGraphicsSceneMouseEvent* event);
};
class Ruler : public QGraphicsLineItem{
@@ -48,16 +104,19 @@ public:
qreal percentAt(const QPointF& p);
qreal posAtValue(qreal value);
void setColor(const QColor& color);
+ void setTextColor(const QColor& color);
private:
Qt::Orientation orientation;
QList<QGraphicsLineItem*> ticks;
+ QList<QGraphicsSimpleTextItem*> labels;
double min;
double max;
double interval;
double posBegin;
double posEnd;
double tickSize;
+ QColor textColor;
};
class DivePlannerGraphics : public QGraphicsView {
@@ -71,10 +130,7 @@ protected:
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
-
- void createDecoStops();
bool isPointOutOfBoundaries(const QPointF& point);
- void deleteTemporaryDivePlan(struct divedatapoint* dp);
qreal fromPercent(qreal percent, Qt::Orientation orientation);
private slots:
void keyEscAction();
@@ -85,9 +141,13 @@ private slots:
void keyRightAction();
void increaseTime();
void increaseDepth();
- void okClicked();
- void cancelClicked();
-
+ void decreaseTime();
+ void decreaseDepth();;
+ void createDecoStops();
+ void prepareSelectGas();
+ void selectGas(const QModelIndex& index);
+ void pointInserted(const QModelIndex&, int start, int end);
+ void pointsRemoved(const QModelIndex&, int start, int end);
private:
void moveActiveHandler(const QPointF& pos);
@@ -97,6 +157,15 @@ private:
/* This is the user-entered handles. */
QList<DiveHandler *> handles;
+ /* this is the user-entered gases.
+ This must be a button, so the
+ user cna click to choose a new gas.
+ */
+ QList<Button*> gases;
+ QListView *gasListView;
+ QStringListModel *gasChoices;
+ Button *currentGasChoice;
+
/* those are the lines that follows the mouse. */
QGraphicsLineItem *verticalLine;
QGraphicsLineItem *horizontalLine;
@@ -124,10 +193,26 @@ private:
Button *plusDepth; // adds 10 meters to the depth ruler.
Button *lessTime; // remove 10 minutes to the time ruler.
Button *lessDepth; // remove 10 meters to the depth ruler.
- Button *okBtn; // accepts, and creates a new dive based on the plan.
- Button *cancelBtn; // rejects, and clears the dive plan.
int minMinutes; // this holds the minimum duration of the dive.
+ int dpMaxTime; // this is the time of the dive calculated by the deco.
+};
+
+class DivePlannerWidget : public QWidget {
+ Q_OBJECT
+public:
+ explicit DivePlannerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
+
+public slots:
+ void startTimeChanged(const QTime& time);
+ void atmPressureChanged(const QString& pressure);
+ void bottomSacChanged(const QString& bottomSac);
+ void decoSacChanged(const QString& decosac);
+ void gflowChanged(const QString& gflow);
+ void gfhighChanged(const QString& gfhigh);
+ void lastStopChanged(bool checked);
+private:
+ Ui::DivePlanner *ui;
};
#endif
diff --git a/qt-ui/diveplanner.ui b/qt-ui/diveplanner.ui
index e4903f0f8..1bcd912a4 100644
--- a/qt-ui/diveplanner.ui
+++ b/qt-ui/diveplanner.ui
@@ -1,74 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DivePlanner</class>
- <widget class="QDialog" name="DivePlanner">
+ <widget class="QWidget" name="DivePlanner">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>575</width>
- <height>451</height>
+ <width>400</width>
+ <height>352</height>
</rect>
</property>
<property name="windowTitle">
- <string>Dialog</string>
+ <string>Form</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="DivePlannerGraphics" name="graphicsView"/>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Start Time</string>
+ </property>
+ </widget>
</item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>ATM Pressure</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QTimeEdit" name="startTime"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="ATMPressure"/>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="decoStopSAC"/>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLineEdit" name="lowGF"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Low GF</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Bottom SAC</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLineEdit" name="bottomSAC"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>High GF</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLineEdit" name="highGF"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>SAC on DECO Stop</string>
</property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QCheckBox" name="lastStop">
+ <property name="text">
+ <string>Last Stop at 6m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
+ <item row="7" column="0" colspan="2">
+ <widget class="TableView" name="tableWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
<customwidget>
- <class>DivePlannerGraphics</class>
- <extends>QGraphicsView</extends>
- <header>diveplanner.h</header>
+ <class>TableView</class>
+ <extends>QWidget</extends>
+ <header>tableview.h</header>
+ <container>1</container>
</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>
+ <connections/>
</ui>
diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp
index 65e7a16e2..acdca89d3 100644
--- a/qt-ui/downloadfromdivecomputer.cpp
+++ b/qt-ui/downloadfromdivecomputer.cpp
@@ -10,6 +10,8 @@
#include <QThread>
#include <QDebug>
#include <QStringListModel>
+#include <QTimer>
+#include <QMessageBox>
struct product {
const char *product;
@@ -42,7 +44,8 @@ DownloadFromDCWidget *DownloadFromDCWidget::instance()
}
DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
- QDialog(parent, f), ui(new Ui::DownloadFromDiveComputer), thread(0), downloading(false)
+ QDialog(parent, f), ui(new Ui::DownloadFromDiveComputer), thread(0), timer(new QTimer(this)),
+ currentState(INITIAL)
{
ui->setupUi(this);
ui->progressBar->hide();
@@ -61,17 +64,86 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
}
if (default_dive_computer_device)
ui->device->setText(default_dive_computer_device);
+
+ timer->setInterval(200);
+ connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
+
+ updateState(INITIAL);
}
void DownloadFromDCWidget::runDialog()
{
- ui->progressBar->hide();
+ updateState(INITIAL);
+
exec();
}
-void DownloadFromDCWidget::stoppedDownloading()
+void DownloadFromDCWidget::updateProgressBar()
+{
+ ui->progressBar->setValue(progress_bar_fraction *100);
+}
+
+void DownloadFromDCWidget::updateState(states state)
{
- downloading = false;
+ if (state == currentState)
+ return;
+
+ if (state == INITIAL) {
+ ui->progressBar->hide();
+ markChildrenAsEnabled();
+ timer->stop();
+ }
+
+ // tries to cancel an on going download
+ else if (currentState == DOWNLOADING && state == CANCELLING) {
+ import_thread_cancelled = true;
+ ui->cancel->setEnabled(false);
+ }
+
+ // user pressed cancel but the application isn't doing anything.
+ // means close the window
+ else if ((currentState == INITIAL || currentState == CANCELLED || currentState == DONE || currentState == ERROR)
+ && state == CANCELLING) {
+ timer->stop();
+ reject();
+ }
+
+ // the cancelation process is finished
+ else if (currentState == CANCELLING && (state == DONE || state == CANCELLED)) {
+ timer->stop();
+ state = CANCELLED;
+ ui->progressBar->setValue(0);
+ ui->progressBar->hide();
+ markChildrenAsEnabled();
+ }
+
+ // DOWNLOAD is finally done, close the dialog and go back to the main window
+ else if (currentState == DOWNLOADING && state == DONE) {
+ timer->stop();
+ ui->progressBar->setValue(100);
+ markChildrenAsEnabled();
+ accept();
+ }
+
+ // DOWNLOAD is started.
+ else if (state == DOWNLOADING) {
+ timer->start();
+ ui->progressBar->setValue(0);
+ ui->progressBar->show();
+ markChildrenAsDisabled();
+ }
+
+ // got an error
+ else if (state == ERROR) {
+ QMessageBox::critical(this, tr("Error"), this->thread->error, QMessageBox::Ok);
+
+ markChildrenAsEnabled();
+ ui->progressBar->hide();
+ ui->ok->setText(tr("retry"));
+ }
+
+ // properly updating the widget state
+ currentState = state;
}
void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString& vendor)
@@ -132,23 +204,15 @@ void DownloadFromDCWidget::fill_computer_list()
void DownloadFromDCWidget::on_cancel_clicked()
{
- import_thread_cancelled = true;
- if (thread) {
- thread->wait();
- thread->deleteLater();
- thread = 0;
- }
- close();
+ updateState(CANCELLING);
}
void DownloadFromDCWidget::on_ok_clicked()
{
- if (downloading)
- return;
-
- ui->progressBar->setValue(0);
- ui->progressBar->show();
+ updateState(DOWNLOADING);
+ // I don't really think that create/destroy the thread
+ // is really necessary.
if (thread) {
thread->deleteLater();
}
@@ -156,20 +220,22 @@ void DownloadFromDCWidget::on_ok_clicked()
data.devname = strdup(ui->device->text().toUtf8().data());
data.vendor = strdup(ui->vendor->currentText().toUtf8().data());
data.product = strdup(ui->product->currentText().toUtf8().data());
+
data.descriptor = descriptorLookup[ui->vendor->currentText() + ui->product->currentText()];
data.force_download = ui->forceDownload->isChecked();
data.deviceid = data.diveid = 0;
set_default_dive_computer(data.vendor, data.product);
set_default_dive_computer_device(data.devname);
- thread = new InterfaceThread(this, &data);
- connect(thread, SIGNAL(updateInterface(int)),
- ui->progressBar, SLOT(setValue(int)), Qt::QueuedConnection); // Qt::QueuedConnection == threadsafe.
+ thread = new DownloadThread(this, &data);
- connect(thread, SIGNAL(finished()), this, SLOT(close()));
+ connect(thread, SIGNAL(finished()),
+ this, SLOT(onDownloadThreadFinished()), Qt::QueuedConnection);
+
+ MainWindow *w = mainWindow();
+ connect(thread, SIGNAL(finished()), w, SLOT(refreshDisplay()));
thread->start();
- downloading = true;
}
bool DownloadFromDCWidget::preferDownloaded()
@@ -177,34 +243,78 @@ bool DownloadFromDCWidget::preferDownloaded()
return ui->preferDownloaded->isChecked();
}
-DownloadThread::DownloadThread(device_data_t* data): data(data)
+void DownloadFromDCWidget::reject()
{
+ // we don't want the download window being able to close
+ // while we're still downloading.
+ if (currentState != DOWNLOADING && currentState != CANCELLING)
+ QDialog::reject();
}
-void DownloadThread::run()
+void DownloadFromDCWidget::onDownloadThreadFinished()
{
- DownloadFromDCWidget *dfdcw = DownloadFromDCWidget::instance();
- if (!strcmp(data->vendor, "Uemis"))
- do_uemis_import(data->devname, data->force_download);
- else
- do_libdivecomputer_import(data);
- process_dives(TRUE, dfdcw->preferDownloaded());
- dfdcw->stoppedDownloading();
+ if (currentState == DOWNLOADING) {
+ if (thread->error.isEmpty())
+ updateState(DONE);
+ else
+ updateState(ERROR);
+ } else
+ updateState(CANCELLED);
}
-InterfaceThread::InterfaceThread(QObject* parent, device_data_t* data): QThread(parent), data(data)
+void DownloadFromDCWidget::markChildrenAsDisabled()
{
+ ui->device->setDisabled(true);
+ ui->vendor->setDisabled(true);
+ ui->product->setDisabled(true);
+ ui->forceDownload->setDisabled(true);
+ ui->preferDownloaded->setDisabled(true);
+ ui->ok->setDisabled(true);
+ ui->search->setDisabled(true);
}
-void InterfaceThread::run()
+void DownloadFromDCWidget::markChildrenAsEnabled()
{
- DownloadThread *download = new DownloadThread(data);
- MainWindow *w = mainWindow();
- connect(download, SIGNAL(finished()), w, SLOT(refreshDisplay()));
- download->start();
- while (download->isRunning()) {
- msleep(200);
- updateInterface(progress_bar_fraction *100);
+ ui->device->setDisabled(false);
+ ui->vendor->setDisabled(false);
+ ui->product->setDisabled(false);
+ ui->forceDownload->setDisabled(false);
+ ui->preferDownloaded->setDisabled(false);
+ ui->ok->setDisabled(false);
+ ui->cancel->setDisabled(false);
+ ui->search->setDisabled(false);
+}
+
+DownloadThread::DownloadThread(QObject* parent, device_data_t* data): QThread(parent),
+ data(data)
+{
+}
+
+static QString str_error(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ const QString str = QString().vsprintf( fmt, args );
+ va_end(args);
+
+ return str;
+}
+
+void DownloadThread::run()
+{
+ DownloadFromDCWidget *dfdcw = DownloadFromDCWidget::instance();
+ const char *error;
+
+ if (!strcmp(data->vendor, "Uemis"))
+ error = do_uemis_import(data->devname, data->force_download);
+ else
+ error = do_libdivecomputer_import(data);
+
+ if (error) {
+ this->error = str_error(error, data->devname, data->vendor, data->product);
}
- updateInterface(100);
+
+ // I'm not sure if we should really call process_dives even
+ // if there's an error or a cancelation
+ process_dives(TRUE, dfdcw->preferDownloaded());
}
diff --git a/qt-ui/downloadfromdivecomputer.h b/qt-ui/downloadfromdivecomputer.h
index 444c03e81..e10d61b38 100644
--- a/qt-ui/downloadfromdivecomputer.h
+++ b/qt-ui/downloadfromdivecomputer.h
@@ -15,20 +15,10 @@ struct device_data_t;
class DownloadThread : public QThread{
Q_OBJECT
public:
- explicit DownloadThread(device_data_t* data);
+ DownloadThread(QObject* parent, device_data_t* data);
virtual void run();
-private:
- device_data_t *data;
-};
-class InterfaceThread : public QThread{
- Q_OBJECT
-public:
- InterfaceThread(QObject *parent, device_data_t *data) ;
- virtual void run();
-
-signals:
- void updateInterface(int value);
+ QString error;
private:
device_data_t *data;
};
@@ -39,15 +29,32 @@ class DownloadFromDCWidget : public QDialog{
public:
explicit DownloadFromDCWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
static DownloadFromDCWidget *instance();
+ void reject();
+
+ enum states {
+ INITIAL,
+ DOWNLOADING,
+ CANCELLING,
+ CANCELLED,
+ ERROR,
+ DONE,
+ };
+
public slots:
void on_ok_clicked();
void on_cancel_clicked();
- void runDialog();
- void stoppedDownloading();
void on_vendor_currentIndexChanged(const QString& vendor);
+
+ void onDownloadThreadFinished();
+ void updateProgressBar();
+ void runDialog();
+
private:
+ void markChildrenAsDisabled();
+ void markChildrenAsEnabled();
+
Ui::DownloadFromDiveComputer *ui;
- InterfaceThread *thread;
+ DownloadThread *thread;
bool downloading;
QStringList vendorList;
@@ -58,8 +65,14 @@ private:
QStringListModel *vendorModel;
QStringListModel *productModel;
void fill_computer_list();
+
+ QTimer *timer;
+
public:
bool preferDownloaded();
+ void updateState(states state);
+ states currentState;
+
};
#endif
diff --git a/qt-ui/graphicsview-common.cpp b/qt-ui/graphicsview-common.cpp
index 464626f4b..30b9ccb08 100644
--- a/qt-ui/graphicsview-common.cpp
+++ b/qt-ui/graphicsview-common.cpp
@@ -31,7 +31,7 @@ void fill_profile_color()
profile_color[TEXT_BACKGROUND] = COLOR(CONCRETE1_LOWER_TRANS, WHITE1, CONCRETE1_LOWER_TRANS);
profile_color[ALERT_BG] = COLOR(BROOM1_LOWER_TRANS, BLACK1_LOW_TRANS, BROOM1_LOWER_TRANS);
- profile_color[ALERT_FG] = COLOR(BLACK1_LOW_TRANS, BLACK1_LOW_TRANS, BLACK1_LOW_TRANS);
+ profile_color[ALERT_FG] = COLOR(BLACK1_LOW_TRANS, WHITE1, BLACK1_LOW_TRANS);
profile_color[EVENTS] = COLOR(REDORANGE1, BLACK1_LOW_TRANS, REDORANGE1);
profile_color[SAMPLE_DEEP] = COLOR(QColor(Qt::red).darker(), BLACK1_LOW_TRANS, PERSIANRED1);
profile_color[SAMPLE_SHALLOW] = COLOR(QColor(Qt::red).lighter(), BLACK1_LOW_TRANS, PERSIANRED1);
@@ -48,7 +48,7 @@ void fill_profile_color()
profile_color[SAC_DEFAULT] = COLOR(WHITE1, BLACK1_LOW_TRANS, FORESTGREEN1);
profile_color[BOUNDING_BOX] = COLOR(WHITE1, BLACK1_LOW_TRANS, TUNDORA1_MED_TRANS);
profile_color[PRESSURE_TEXT] = COLOR(KILLARNEY1, BLACK1_LOW_TRANS, KILLARNEY1);
- profile_color[BACKGROUND] = COLOR(SPRINGWOOD1, BLACK1_LOW_TRANS, SPRINGWOOD1);
+ profile_color[BACKGROUND] = COLOR(SPRINGWOOD1, WHITE1, SPRINGWOOD1);
profile_color[CEILING_SHALLOW] = COLOR(REDORANGE1_HIGH_TRANS, BLACK1_HIGH_TRANS, REDORANGE1_HIGH_TRANS);
profile_color[CEILING_DEEP] = COLOR(RED1_MED_TRANS, BLACK1_HIGH_TRANS, RED1_MED_TRANS);
profile_color[CALC_CEILING_SHALLOW] = COLOR(FUNGREEN1_HIGH_TRANS, BLACK1_HIGH_TRANS, FUNGREEN1_HIGH_TRANS);
@@ -56,3 +56,7 @@ void fill_profile_color()
#undef COLOR
}
+QColor getColor(const color_indice_t i, bool isGrayscale = false)
+{
+ return profile_color[i].at((isGrayscale) ? 1 : 0);
+}
diff --git a/qt-ui/graphicsview-common.h b/qt-ui/graphicsview-common.h
index 96cecc8e6..d2499c823 100644
--- a/qt-ui/graphicsview-common.h
+++ b/qt-ui/graphicsview-common.h
@@ -33,7 +33,6 @@ typedef enum {
/* profile_color[color indice] = COLOR(screen color, b/w printer color, color printer}} printer & screen colours could be different */
extern QMap<color_indice_t, QVector<QColor> > profile_color;
-
void fill_profile_color();
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index f9d36342f..42250b42c 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -12,17 +12,20 @@
#include "divelistview.h"
#include "modeldelegates.h"
#include "globe.h"
+#include "completionmodels.h"
#include <QLabel>
+#include <QCompleter>
#include <QDebug>
#include <QSet>
+#include <QTableView>
#include <QSettings>
+#include <QPalette>
MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui(new Ui::MainTab()),
weightModel(new WeightModel()),
cylindersModel(new CylindersModel()),
- currentDive(0),
editMode(NONE)
{
ui->setupUi(this);
@@ -52,7 +55,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui->divemaster->installEventFilter(this);
ui->buddy->installEventFilter(this);
ui->suit->installEventFilter(this);
- ui->notes->installEventFilter(this);
+ ui->notes->viewport()->installEventFilter(this);
ui->rating->installEventFilter(this);
ui->visibility->installEventFilter(this);
@@ -62,82 +65,51 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
if (label)
label->setAlignment(Qt::AlignHCenter);
}
-
- /*Thid couldn't be done on the ui file because element
- is floating, instead of being fixed on the layout. */
- QIcon plusIcon(":plus");
- addCylinder = new QPushButton(plusIcon, QString(), ui->cylindersGroup);
- addCylinder->setFlat(true);
- addCylinder->setToolTip(tr("Add Cylinder"));
- connect(addCylinder, SIGNAL(clicked(bool)), this, SLOT(addCylinder_clicked()));
- addCylinder->setEnabled(false);
- addWeight = new QPushButton(plusIcon, QString(), ui->weightGroup);
- addWeight->setFlat(true);
- addWeight->setToolTip(tr("Add Weight System"));
- connect(addWeight, SIGNAL(clicked(bool)), this, SLOT(addWeight_clicked()));
- addWeight->setEnabled(false);
-
- connect(ui->cylinders, SIGNAL(clicked(QModelIndex)), ui->cylinders->model(), SLOT(remove(QModelIndex)));
- connect(ui->cylinders, SIGNAL(clicked(QModelIndex)), this, SLOT(editCylinderWidget(QModelIndex)));
- connect(ui->weights, SIGNAL(clicked(QModelIndex)), ui->weights->model(), SLOT(remove(QModelIndex)));
- connect(ui->weights, SIGNAL(clicked(QModelIndex)), this, SLOT(editWeigthWidget(QModelIndex)));
-
- QFontMetrics metrics(defaultModelFont());
- QFontMetrics metrics2(font());
-
- ui->cylinders->horizontalHeader()->setResizeMode(CylindersModel::REMOVE, QHeaderView::Fixed);
- ui->cylinders->verticalHeader()->setDefaultSectionSize( metrics.height() +8 );
- ui->cylinders->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate());
-
- ui->weights->horizontalHeader()->setResizeMode (WeightModel::REMOVE , QHeaderView::Fixed);
- ui->weights->verticalHeader()->setDefaultSectionSize( metrics.height() +8 );
- ui->weights->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate());
-
- connect(this, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
- initialUiSetup();
-}
-
-// We need to manually position the 'plus' on cylinder and weight.
-void MainTab::resizeEvent(QResizeEvent* event)
-{
- equipmentPlusUpdate();
- QTabWidget::resizeEvent(event);
-}
-
-void MainTab::showEvent(QShowEvent* event)
-{
- QTabWidget::showEvent(event);
- equipmentPlusUpdate();
+ ui->cylinders->setTitle(tr("Cylinders"));
+ ui->cylinders->setBtnToolTip(tr("Add Cylinder"));
+ connect(ui->cylinders, SIGNAL(addButtonClicked()), this, SLOT(addCylinder_clicked()));
+
+ ui->weights->setTitle(tr("Weights"));
+ ui->weights->setBtnToolTip(tr("Add Weight System"));
+ connect(ui->weights, SIGNAL(addButtonClicked()), this, SLOT(addWeight_clicked()));
+
+ connect(ui->cylinders->view(), SIGNAL(clicked(QModelIndex)), this, SLOT(editCylinderWidget(QModelIndex)));
+ connect(ui->weights->view(), SIGNAL(clicked(QModelIndex)), this, SLOT(editWeigthWidget(QModelIndex)));
+
+ ui->cylinders->view()->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate());
+ ui->weights->view()->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate());
+
+ completers.buddy = new QCompleter(BuddyCompletionModel::instance(), ui->buddy);
+ completers.divemaster = new QCompleter(DiveMasterCompletionModel::instance(), ui->divemaster);
+ completers.location = new QCompleter(LocationCompletionModel::instance(), ui->location);
+ completers.suit = new QCompleter(SuitCompletionModel::instance(), ui->suit);
+ ui->buddy->setCompleter(completers.buddy);
+ ui->divemaster->setCompleter(completers.divemaster);
+ ui->location->setCompleter(completers.location);
+ ui->suit->setCompleter(completers.suit);
}
-void MainTab::tabChanged(int idx)
+void MainTab::enableEdition()
{
- /* if the current tab has become of index 1 (i.e. the equipment tab) call update
- * for the plus signs */
- if (idx == 1)
- equipmentPlusUpdate();
-}
+ if (ui->editAccept->isVisible() || !selected_dive)
+ return;
-void MainTab::equipmentPlusUpdate()
-{
- if (ui->cylindersGroup->isVisible())
- addCylinder->setGeometry(ui->cylindersGroup->contentsRect().width() - 30, 2, 24,24);
- if (ui->weightGroup->isVisible())
- addWeight->setGeometry(ui->weightGroup->contentsRect().width() - 30, 2, 24,24);
+ ui->editAccept->setChecked(true);
+ ui->editAccept->show();
+ ui->editReset->show();
+ on_editAccept_clicked(true);
}
bool MainTab::eventFilter(QObject* object, QEvent* event)
{
- if (event->type() == QEvent::FocusIn || event->type() == QEvent::MouseButtonPress) {
- if (ui->editAccept->isVisible() || !currentDive)
- return false;
-
- ui->editAccept->setChecked(true);
- ui->editAccept->show();
- ui->editReset->show();
- on_editAccept_clicked(true);
+ if (event->type() == QEvent::FocusIn && (object == ui->rating || object == ui->visibility)){
+ enableEdition();
}
- return false;
+
+ if (event->type() == QEvent::MouseButtonPress) {
+ enableEdition();
+ }
+ return false; // don't "eat" the event.
}
void MainTab::clearEquipment()
@@ -170,15 +142,15 @@ void MainTab::clearStats()
ui->timeLimits->clear();
}
-#define UPDATE_TEXT(d, field) \
+#define UPDATE_TEXT(d, field) \
if (!d || !d->field) \
ui->field->setText(""); \
- else \
+ else \
ui->field->setText(d->field)
-
void MainTab::updateDiveInfo(int dive)
{
+ editMode = NONE;
// This method updates ALL tabs whenever a new dive or trip is
// selected.
// If exactly one trip has been selected, we show the location / notes
@@ -191,7 +163,7 @@ void MainTab::updateDiveInfo(int dive)
process_selected_dives();
process_all_dives(d, &prevd);
- currentDive = d;
+
UPDATE_TEXT(d, notes);
UPDATE_TEXT(d, location);
UPDATE_TEXT(d, suit);
@@ -225,6 +197,8 @@ void MainTab::updateDiveInfo(int dive)
ui->suit->setVisible(true);
ui->rating->setVisible(true);
ui->visibility->setVisible(true);
+ ui->BuddyLabel->setVisible(true);
+ ui->DivemasterLabel->setVisible(true);
ui->divemaster->setReadOnly(false);
ui->buddy->setReadOnly(false);
ui->suit->setReadOnly(false);
@@ -284,8 +258,6 @@ void MainTab::updateDiveInfo(int dive)
ui->timeLimits->setMinimum(get_time_string(stats_selection.shortest_time.seconds, 0));
cylindersModel->setDive(d);
weightModel->setDive(d);
- addCylinder->setEnabled(true);
- addWeight->setEnabled(true);
} else {
/* make the fields read-only */
ui->location->setReadOnly(true);
@@ -312,8 +284,6 @@ void MainTab::updateDiveInfo(int dive)
ui->airPressureText->clear();
cylindersModel->clear();
weightModel->clear();
- addCylinder->setEnabled(false);
- addWeight->setEnabled(false);
ui->depthLimits->clear();
ui->sacLimits->clear();
ui->divesAllText->clear();
@@ -337,6 +307,10 @@ void MainTab::addWeight_clicked()
void MainTab::reload()
{
+ SuitCompletionModel::instance()->updateModel();
+ BuddyCompletionModel::instance()->updateModel();
+ LocationCompletionModel::instance()->updateModel();
+ DiveMasterCompletionModel::instance()->updateModel();
}
void MainTab::on_editAccept_clicked(bool edit)
@@ -352,24 +326,39 @@ void MainTab::on_editAccept_clicked(bool edit)
mainWindow()->dive_list()->setEnabled(!edit);
if (edit) {
+
+ // We may be editing one or more dives here. backup everything.
+ notesBackup.clear();
+
if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
// we are editing trip location and notes
ui->diveNotesMessage->setText(tr("This trip is being edited. Select Save or Undo when ready."));
ui->diveNotesMessage->animatedShow();
- notesBackup.notes = ui->notes->toPlainText();
- notesBackup.location = ui->location->text();
+ notesBackup[NULL].notes = ui->notes->toPlainText();
+ notesBackup[NULL].location = ui->location->text();
editMode = TRIP;
} else {
ui->diveNotesMessage->setText(tr("This dive is being edited. Select Save or Undo when ready."));
ui->diveNotesMessage->animatedShow();
- notesBackup.buddy = ui->buddy->text();
- notesBackup.suit = ui->suit->text();
- notesBackup.notes = ui->notes->toPlainText();
- notesBackup.divemaster = ui->divemaster->text();
- notesBackup.location = ui->location->text();
- notesBackup.rating = ui->rating->currentStars();
- notesBackup.visibility = ui->visibility->currentStars();
- editMode = DIVE;
+
+ // We may be editing one or more dives here. backup everything.
+ struct dive *mydive;
+ for (int i = 0; i < dive_table.nr; i++) {
+ mydive = get_dive(i);
+ if (!mydive)
+ continue;
+ if (!mydive->selected)
+ continue;
+
+ notesBackup[mydive].buddy = QString(mydive->buddy);
+ notesBackup[mydive].suit = QString(mydive->suit);
+ notesBackup[mydive].notes = QString(mydive->notes);
+ notesBackup[mydive].divemaster = QString(mydive->divemaster);
+ notesBackup[mydive].location = QString(mydive->location);
+ notesBackup[mydive].rating = mydive->rating;
+ notesBackup[mydive].visibility = mydive->visibility;
+ }
+ editMode = DIVE;
}
} else {
ui->diveNotesMessage->animatedHide();
@@ -377,38 +366,78 @@ void MainTab::on_editAccept_clicked(bool edit)
ui->editReset->hide();
/* now figure out if things have changed */
if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
- if (notesBackup.notes != ui->notes->toPlainText() ||
- notesBackup.location != ui->location->text())
+ if (notesBackup[NULL].notes != ui->notes->toPlainText() ||
+ notesBackup[NULL].location != ui->location->text())
mark_divelist_changed(TRUE);
} else {
- if (notesBackup.buddy != ui->buddy->text() ||
- notesBackup.suit != ui->suit->text() ||
- notesBackup.notes != ui->notes->toPlainText() ||
- notesBackup.divemaster != ui->divemaster->text() ||
- notesBackup.location != ui->location->text() ||
- notesBackup.visibility != ui->visibility->currentStars() ||
- notesBackup.rating != ui->rating->currentStars())
+ struct dive *curr = current_dive;
+ if (notesBackup[curr].buddy != ui->buddy->text() ||
+ notesBackup[curr].suit != ui->suit->text() ||
+ notesBackup[curr].notes != ui->notes->toPlainText() ||
+ notesBackup[curr].divemaster != ui->divemaster->text() ||
+ notesBackup[curr].location != ui->location->text() ||
+ notesBackup[curr].rating != ui->visibility->currentStars() ||
+ notesBackup[curr].visibility != ui->rating->currentStars())
+
mark_divelist_changed(TRUE);
- if (notesBackup.location != ui->location->text())
+ if (notesBackup[curr].location != ui->location->text())
mainWindow()->globe()->reload();
}
editMode = NONE;
}
+ QPalette p;
+ ui->buddy->setPalette(p);
+ ui->notes->setPalette(p);
+ ui->location->setPalette(p);
+ ui->divemaster->setPalette(p);
+ ui->suit->setPalette(p);
}
+#define EDIT_TEXT2(what, text) \
+ textByteArray = text.toLocal8Bit(); \
+ free(what);\
+ what = strdup(textByteArray.data());
+
+#define EDIT_TEXT(what, text) \
+ QByteArray textByteArray = text.toLocal8Bit(); \
+ free(what);\
+ what = strdup(textByteArray.data());
+
void MainTab::on_editReset_clicked()
{
if (!ui->editAccept->isChecked())
return;
- ui->notes->setText(notesBackup.notes);
- ui->location->setText(notesBackup.location);
- if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() != 1) {
- ui->buddy->setText(notesBackup.buddy);
- ui->suit->setText(notesBackup.suit);
- ui->divemaster->setText(notesBackup.divemaster);
- ui->rating->setCurrentStars(notesBackup.rating);
- ui->visibility->setCurrentStars(notesBackup.visibility);
+ if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1){
+ ui->notes->setText(notesBackup[NULL].notes );
+ ui->location->setText(notesBackup[NULL].location);
+ }else{
+ struct dive *curr = current_dive;
+ ui->notes->setText(notesBackup[curr].notes );
+ ui->location->setText(notesBackup[curr].location);
+ ui->buddy->setText(notesBackup[curr].buddy);
+ ui->suit->setText(notesBackup[curr].suit);
+ ui->divemaster->setText(notesBackup[curr].divemaster);
+ ui->rating->setCurrentStars(notesBackup[curr].rating);
+ ui->visibility->setCurrentStars(notesBackup[curr].visibility);
+
+ struct dive *mydive;
+ for (int i = 0; i < dive_table.nr; i++) {
+ mydive = get_dive(i);
+ if (!mydive)
+ continue;
+ if (!mydive->selected)
+ continue;
+
+ QByteArray textByteArray;
+ EDIT_TEXT2(mydive->buddy, notesBackup[mydive].buddy);
+ EDIT_TEXT2(mydive->suit, notesBackup[mydive].suit);
+ EDIT_TEXT2(mydive->notes, notesBackup[mydive].notes);
+ EDIT_TEXT2(mydive->divemaster, notesBackup[mydive].divemaster);
+ EDIT_TEXT2(mydive->location, notesBackup[mydive].location);
+ mydive->rating = notesBackup[mydive].rating;
+ mydive->visibility = notesBackup[mydive].visibility;
+ }
}
ui->editAccept->setChecked(false);
ui->diveNotesMessage->animatedHide();
@@ -424,126 +453,105 @@ void MainTab::on_editReset_clicked()
ui->editAccept->hide();
ui->editReset->hide();
+ notesBackup.clear();
+ QPalette p;
+ ui->buddy->setPalette(p);
+ ui->notes->setPalette(p);
+ ui->location->setPalette(p);
+ ui->divemaster->setPalette(p);
+ ui->suit->setPalette(p);
editMode = NONE;
}
+#undef EDIT_TEXT2
+
+#define EDIT_SELECTED_DIVES( WHAT ) \
+ if (editMode == NONE) \
+ return; \
+ struct dive *mydive; \
+\
+ for (int i = 0; i < dive_table.nr; i++) { \
+ mydive = get_dive(i); \
+ if (!mydive) \
+ continue; \
+ if (!mydive->selected) \
+ continue; \
+\
+ WHAT; \
+ }
-#define EDIT_TEXT(what, text) \
- QByteArray textByteArray = text.toLocal8Bit(); \
- free(what);\
- what = strdup(textByteArray.data());
+void markChangedWidget(QWidget *w){
+ QPalette p;
+ p.setBrush(QPalette::Base, QColor(Qt::yellow).lighter());
+ w->setPalette(p);
+}
void MainTab::on_buddy_textChanged(const QString& text)
{
- if (!currentDive)
- return;
- EDIT_TEXT(currentDive->buddy, text);
+ EDIT_SELECTED_DIVES( EDIT_TEXT(mydive->buddy, text) );
+ markChangedWidget(ui->buddy);
}
void MainTab::on_divemaster_textChanged(const QString& text)
{
- if (!currentDive)
- return;
- EDIT_TEXT(currentDive->divemaster, text);
+ EDIT_SELECTED_DIVES( EDIT_TEXT(mydive->divemaster, text) );
+ markChangedWidget(ui->divemaster);
}
void MainTab::on_location_textChanged(const QString& text)
{
+ if (editMode == NONE)
+ return;
if (editMode == TRIP && mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
// we are editing a trip
dive_trip_t *currentTrip = *mainWindow()->dive_list()->selectedTrips.begin();
EDIT_TEXT(currentTrip->location, text);
} else if (editMode == DIVE){
- if (!currentDive)
- return;
- EDIT_TEXT(currentDive->location, text);
+ EDIT_SELECTED_DIVES( EDIT_TEXT(mydive->location, text) )
}
+
+ markChangedWidget(ui->location);
}
void MainTab::on_suit_textChanged(const QString& text)
{
- if (!currentDive)
- return;
- EDIT_TEXT(currentDive->suit, text);
+ EDIT_SELECTED_DIVES( EDIT_TEXT(mydive->suit, text) );
+ markChangedWidget(ui->suit);
}
void MainTab::on_notes_textChanged()
{
+ if (editMode == NONE)
+ return;
if (editMode == TRIP && mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
// we are editing a trip
dive_trip_t *currentTrip = *mainWindow()->dive_list()->selectedTrips.begin();
EDIT_TEXT(currentTrip->notes, ui->notes->toPlainText());
} else if (editMode == DIVE) {
- if (!currentDive)
- return;
- EDIT_TEXT(currentDive->notes, ui->notes->toPlainText());
+ EDIT_SELECTED_DIVES( EDIT_TEXT(mydive->notes, ui->notes->toPlainText()) );
}
+ markChangedWidget(ui->notes);
}
#undef EDIT_TEXT
void MainTab::on_rating_valueChanged(int value)
{
- if (!currentDive)
- return;
- currentDive->rating = value;
+ EDIT_SELECTED_DIVES(mydive->rating = value );
}
void MainTab::on_visibility_valueChanged(int value)
{
- if (!currentDive)
- return;
- currentDive->visibility = value;
-}
-
-void MainTab::hideEvent(QHideEvent* event)
-{
- QSettings s;
- s.beginGroup("MainTab");
- s.beginGroup("Cylinders");
- for (int i = 0; i < CylindersModel::COLUMNS; i++) {
- s.setValue(QString("colwidth%1").arg(i), ui->cylinders->columnWidth(i));
- }
- s.endGroup();
- s.beginGroup("Weights");
- for (int i = 0; i < WeightModel::COLUMNS; i++) {
- s.setValue(QString("colwidth%1").arg(i), ui->weights->columnWidth(i));
- }
- s.endGroup();
- s.sync();
-}
-
-void MainTab::initialUiSetup()
-{
- QSettings s;
- s.beginGroup("MainTab");
- s.beginGroup("Cylinders");
- for (int i = 0; i < CylindersModel::COLUMNS; i++) {
- QVariant width = s.value(QString("colwidth%1").arg(i));
- if (width.isValid())
- ui->cylinders->setColumnWidth(i, width.toInt());
- else
- ui->cylinders->resizeColumnToContents(i);
- }
- s.endGroup();
- s.beginGroup("Weights");
- for (int i = 0; i < WeightModel::COLUMNS; i++) {
- QVariant width = s.value(QString("colwidth%1").arg(i));
- if (width.isValid())
- ui->weights->setColumnWidth(i, width.toInt());
- else
- ui->weights->resizeColumnToContents(i);
- }
- s.endGroup();
+ EDIT_SELECTED_DIVES( mydive->visibility = value );
}
void MainTab::editCylinderWidget(const QModelIndex& index)
{
- if (index.column() != CylindersModel::REMOVE)
+ if (index.isValid() && index.column() != CylindersModel::REMOVE)
ui->cylinders->edit(index);
}
void MainTab::editWeigthWidget(const QModelIndex& index)
{
- if (index.column() != WeightModel::REMOVE)
+ if (index.isValid() && index.column() != WeightModel::REMOVE)
ui->weights->edit(index);
}
diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h
index af76fbb67..f9f65a3ff 100644
--- a/qt-ui/maintab.h
+++ b/qt-ui/maintab.h
@@ -9,9 +9,12 @@
#include <QTabWidget>
#include <QDialog>
+#include <QMap>
#include "models.h"
+class QCompleter;
+struct dive;
namespace Ui
{
class MainTab;
@@ -27,6 +30,13 @@ struct NotesBackup{
QString divemaster;
};
+struct Completers{
+ QCompleter *location;
+ QCompleter *divemaster;
+ QCompleter *buddy;
+ QCompleter *suit;
+};
+
class MainTab : public QTabWidget
{
Q_OBJECT
@@ -36,16 +46,9 @@ public:
void clearInfo();
void clearEquipment();
void reload();
-
bool eventFilter(QObject* , QEvent*);
- virtual void resizeEvent(QResizeEvent*);
- virtual void showEvent(QShowEvent*);
- virtual void hideEvent(QHideEvent* );
-
void initialUiSetup();
void equipmentPlusUpdate();
-
-
public slots:
void addCylinder_clicked();
void addWeight_clicked();
@@ -59,7 +62,6 @@ public slots:
void on_notes_textChanged();
void on_rating_valueChanged(int value);
void on_visibility_valueChanged(int value);
- void tabChanged(int idx);
void editCylinderWidget(const QModelIndex& index);
void editWeigthWidget(const QModelIndex& index);
@@ -67,11 +69,10 @@ private:
Ui::MainTab *ui;
WeightModel *weightModel;
CylindersModel *cylindersModel;
- NotesBackup notesBackup;
- struct dive* currentDive;
- QPushButton *addCylinder;
- QPushButton *addWeight;
+ QMap<dive*, NotesBackup> notesBackup;
enum { NONE, DIVE, TRIP } editMode;
+ Completers completers;
+ void enableEdition();
};
#endif
diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui
index cdddc4cf9..a1f5a718a 100644
--- a/qt-ui/maintab.ui
+++ b/qt-ui/maintab.ui
@@ -14,7 +14,7 @@
<string>TabWidget</string>
</property>
<property name="currentIndex">
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="notesTab">
<attribute name="title">
@@ -147,109 +147,33 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
- <widget class="QSplitter" name="splitter_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <widget class="QGroupBox" name="cylindersGroup">
- <property name="title">
- <string>Cylinders</string>
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QTableView" name="cylinders">
- <property name="styleSheet">
- <string notr="true"> QTableView {
- show-decoration-selected: 1;
- }
-
- QTableView::item {
- border: 1px solid #d9d9d9;
- border-top-color: transparent;
- border-bottom-color: transparent;
- padding: 2px;
- }
-
- QTableView::item:hover {
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
- border: 1px solid #bfcde4;
- }
-
- QTableView::item:selected {
- border: 1px solid #567dbc;
- }
-
- QTableView::item:selected:active{
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
- }
-
- QTableView::item:selected:!active {
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
- }
-
-</string>
- </property>
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- <property name="showGrid">
- <bool>false</bool>
- </property>
- <attribute name="verticalHeaderVisible">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QGroupBox" name="weightGroup">
- <property name="title">
- <string>Weight</string>
+ <property name="bottomMargin">
+ <number>0</number>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QTableView" name="weights">
- <property name="styleSheet">
- <string notr="true"> QTableView {
- show-decoration-selected: 1;
- }
-
- QTableView::item {
- border: 1px solid #d9d9d9;
- border-top-color: transparent;
- border-bottom-color: transparent;
- padding: 2px;
- }
-
- QTableView::item:hover {
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
- border: 1px solid #bfcde4;
- }
-
- QTableView::item:selected {
- border: 1px solid #567dbc;
- }
-
- QTableView::item:selected:active{
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
- }
-
- QTableView::item:selected:!active {
- background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
- }
-
-</string>
- </property>
- <property name="showGrid">
- <bool>false</bool>
- </property>
- <attribute name="verticalHeaderVisible">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </widget>
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="TableView" name="cylinders" native="true"/>
+ <widget class="TableView" name="weights" native="true"/>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
</layout>
@@ -602,6 +526,12 @@
<header>simplewidgets.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>TableView</class>
+ <extends>QWidget</extends>
+ <header>tableview.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp
index a78b84565..740849033 100644
--- a/qt-ui/mainwindow.cpp
+++ b/qt-ui/mainwindow.cpp
@@ -15,7 +15,7 @@
#include <QCloseEvent>
#include <QApplication>
#include <QFontMetrics>
-#include <QTextBrowser>
+#include <QWebView>
#include <QTableView>
#include "divelistview.h"
#include "starwidget.h"
@@ -45,6 +45,7 @@ MainWindow* mainWindow()
MainWindow::MainWindow() : ui(new Ui::MainWindow()), helpView(0)
{
+ instance = this;
ui->setupUi(this);
setWindowIcon(QIcon(":subsurface-icon"));
connect(ui->ListWidget, SIGNAL(currentDiveChanged(int)), this, SLOT(current_dive_changed(int)));
@@ -59,7 +60,6 @@ MainWindow::MainWindow() : ui(new Ui::MainWindow()), helpView(0)
ui->ListWidget->reloadHeaderActions();
ui->ListWidget->setFocus();
ui->globe->reload();
- instance = this;
}
// this gets called after we download dives from a divecomputer
@@ -117,22 +117,7 @@ void MainWindow::on_actionOpen_triggered()
QByteArray fileNamePtr = filename.toLocal8Bit();
on_actionClose_triggered();
-
- char *error = NULL;
- parse_file(fileNamePtr.data(), &error);
- set_filename(fileNamePtr.data(), TRUE);
- setTitle(MWTF_FILENAME);
-
- if (error != NULL) {
- showError(error);
- free(error);
- }
- process_dives(FALSE, FALSE);
-
- ui->InfoWidget->reload();
- ui->globe->reload();
- ui->ListWidget->reload(DiveTripModel::TREE);
- ui->ListWidget->setFocus();
+ loadFiles( QStringList() << filename );
}
void MainWindow::on_actionSave_triggered()
@@ -193,23 +178,7 @@ void MainWindow::on_actionImport_triggered()
settings.setValue("LastDir", fileInfo.dir().path());
settings.endGroup();
- QByteArray fileNamePtr;
- char *error = NULL;
- for (int i = 0; i < fileNames.size(); ++i) {
- fileNamePtr = fileNames.at(i).toLocal8Bit();
- parse_file(fileNamePtr.data(), &error);
- if (error != NULL) {
- showError(error);
- free(error);
- error = NULL;
- }
- }
- process_dives(FALSE, FALSE);
-
- ui->InfoWidget->reload();
- ui->globe->reload();
- ui->ListWidget->reload(DiveTripModel::TREE);
- ui->ListWidget->setFocus();
+ importFiles(fileNames);
}
void MainWindow::on_actionExportUDDF_triggered()
@@ -238,12 +207,14 @@ void MainWindow::on_actionDivePlanner_triggered()
{
disableDcShortcuts();
ui->stackedWidget->setCurrentIndex(1);
+ ui->infoPane->setCurrentIndex(1);
}
void MainWindow::showProfile()
{
enableDcShortcuts();
ui->stackedWidget->setCurrentIndex(0);
+ ui->infoPane->setCurrentIndex(0);
}
@@ -324,8 +295,6 @@ void MainWindow::on_mainSplitter_splitterMoved(int pos, int idx)
void MainWindow::on_infoProfileSplitter_splitterMoved(int pos, int idx)
{
- /* always update the floating plus sign icons in the equipment tab */
- ui->InfoWidget->equipmentPlusUpdate();
redrawProfile();
}
@@ -411,14 +380,14 @@ void MainWindow::on_actionAboutSubsurface_triggered()
void MainWindow::on_actionUserManual_triggered()
{
if(!helpView){
- helpView = new QTextBrowser();
+ helpView = new QWebView();
}
QString searchPath = getSubsurfaceDataPath("Documentation");
if (searchPath != "") {
QUrl url(searchPath.append("/user-manual.html"));
- helpView->setSource(url);
+ helpView->setUrl(url);
} else {
- helpView->setText(tr("Cannot find the Subsurface manual"));
+ helpView->setHtml(tr("Cannot find the Subsurface manual"));
}
helpView->show();
}
@@ -755,3 +724,53 @@ void MainWindow::setTitle(enum MainWindowTitleFormat format)
break;
}
}
+
+void MainWindow::importFiles(const QStringList fileNames)
+{
+ QByteArray fileNamePtr;
+ char *error = NULL;
+ for (int i = 0; i < fileNames.size(); ++i) {
+ fileNamePtr = fileNames.at(i).toLocal8Bit();
+ parse_file(fileNamePtr.data(), &error);
+ if (error != NULL) {
+ showError(error);
+ free(error);
+ error = NULL;
+ }
+ }
+ process_dives(TRUE, FALSE);
+
+ ui->InfoWidget->reload();
+ ui->globe->reload();
+ ui->ListWidget->reload(DiveTripModel::TREE);
+ ui->ListWidget->setFocus();
+ WSInfoModel *wsim = WSInfoModel::instance();
+ wsim->updateInfo();
+}
+
+void MainWindow::loadFiles(const QStringList fileNames)
+{
+ char *error = NULL;
+ QByteArray fileNamePtr;
+
+ for (int i = 0; i < fileNames.size(); ++i) {
+ fileNamePtr = fileNames.at(i).toLocal8Bit();
+ parse_file(fileNamePtr.data(), &error);
+ set_filename(fileNamePtr.data(), TRUE);
+ setTitle(MWTF_FILENAME);
+
+ if (error != NULL) {
+ showError(error);
+ free(error);
+ }
+ }
+
+ process_dives(FALSE, FALSE);
+
+ ui->InfoWidget->reload();
+ ui->globe->reload();
+ ui->ListWidget->reload(DiveTripModel::TREE);
+ ui->ListWidget->setFocus();
+ WSInfoModel *wsim = WSInfoModel::instance();
+ wsim->updateInfo();
+}
diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h
index 2009740fe..6cc99db96 100644
--- a/qt-ui/mainwindow.h
+++ b/qt-ui/mainwindow.h
@@ -29,7 +29,7 @@ class DiveListView;
class GlobeGPS;
class MainTab;
class ProfileGraphicsView;
-class QTextBrowser;
+class QWebView;
enum MainWindowTitleFormat { MWTF_DEFAULT, MWTF_FILENAME };
@@ -51,6 +51,8 @@ public:
// when the profile's visible.
void disableDcShortcuts();
void enableDcShortcuts();
+ void loadFiles(const QStringList files);
+ void importFiles(const QStringList importFiles);
private slots:
/* file menu action */
@@ -110,7 +112,7 @@ private:
Ui::MainWindow *ui;
QAction *actionNextDive;
QAction *actionPreviousDive;
- QTextBrowser *helpView;
+ QWebView *helpView;
QString filter();
bool askSaveChanges();
void writeSettings();
diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui
index 731013538..05a59524e 100644
--- a/qt-ui/mainwindow.ui
+++ b/qt-ui/mainwindow.ui
@@ -24,7 +24,25 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <widget class="MainTab" name="InfoWidget" native="true"/>
+ <widget class="QStackedWidget" name="infoPane">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="MainTab" name="InfoWidget" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="DivePlannerWidget" name="widget" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
@@ -34,7 +52,16 @@
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -47,7 +74,16 @@
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -123,10 +159,7 @@
</widget>
</item>
<item>
- <widget class="KMessageWidget" name="mainErrorMessage" native="true">
- <zorder>mainSplitter</zorder>
- <zorder>mainSplitter</zorder>
- </widget>
+ <widget class="KMessageWidget" name="mainErrorMessage" native="true"/>
</item>
</layout>
</widget>
@@ -136,7 +169,7 @@
<x>0</x>
<y>0</y>
<width>763</width>
- <height>20</height>
+ <height>19</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -419,7 +452,7 @@
<customwidget>
<class>MainTab</class>
<extends>QWidget</extends>
- <header>maintab.h</header>
+ <header>qt-ui/maintab.h</header>
<container>1</container>
</customwidget>
<customwidget>
@@ -443,6 +476,12 @@
<extends>QGraphicsView</extends>
<header>diveplanner.h</header>
</customwidget>
+ <customwidget>
+ <class>DivePlannerWidget</class>
+ <extends>QWidget</extends>
+ <header>diveplanner.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/qt-ui/modeldelegates.cpp b/qt-ui/modeldelegates.cpp
index 9ccf6608f..13201e436 100644
--- a/qt-ui/modeldelegates.cpp
+++ b/qt-ui/modeldelegates.cpp
@@ -3,6 +3,7 @@
#include "../divelist.h"
#include "starwidget.h"
#include "models.h"
+#include "diveplanner.h"
#include <QtDebug>
#include <QPainter>
@@ -14,7 +15,7 @@
#include <QLineEdit>
#include <QKeyEvent>
#include <QAbstractItemView>
-#include <boost/concept_check.hpp>
+#include <QStringListModel>
// Gets the index of the model in the currentRow and column.
// currCombo is defined below.
@@ -107,7 +108,7 @@ void ComboBoxDelegate::testActivation(const QString& s)
bool ComboBoxDelegate::eventFilter(QObject* object, QEvent* event)
{
// Reacts on Key_UP and Key_DOWN to show the QComboBox - list of choices.
- if (event->type() == QEvent::KeyPress){
+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::ShortcutOverride){
if (object == currCombo.comboEditor){ // the 'LineEdit' part
QKeyEvent *ev = static_cast<QKeyEvent*>(event);
if(ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down){
@@ -200,17 +201,17 @@ QWidget* TankInfoDelegate::createEditor(QWidget* parent, const QStyleOptionViewI
return delegate;
}
-struct RevertWeigthData {
+struct RevertWeightData {
QString type;
- int weigth;
-} currWeigth;
+ int weight;
+} currWeight;
void WSInfoDelegate::revertModelData(QWidget* widget, QAbstractItemDelegate::EndEditHint hint)
{
if (hint == QAbstractItemDelegate::NoHint || hint == QAbstractItemDelegate::RevertModelCache){
WeightModel *mymodel = qobject_cast<WeightModel *>(currCombo.model);
- mymodel->setData(IDX(WeightModel::TYPE), currWeigth.type, Qt::EditRole);
- mymodel->passInData(IDX(WeightModel::WEIGHT), currWeigth.weigth);
+ mymodel->setData(IDX(WeightModel::TYPE), currWeight.type, Qt::EditRole);
+ mymodel->passInData(IDX(WeightModel::WEIGHT), currWeight.weight);
}
}
@@ -237,7 +238,6 @@ void WSInfoDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, co
}
mymodel->setData(IDX(WeightModel::TYPE), v, Qt::EditRole);
mymodel->passInData(IDX(WeightModel::WEIGHT), grams);
- qDebug() << "Fixme, every weigth is 0.0 grams. see:" << grams;
}
WSInfoDelegate::WSInfoDelegate(QObject* parent): ComboBoxDelegate(WSInfoModel::instance(), parent)
@@ -250,7 +250,23 @@ QWidget* WSInfoDelegate::createEditor(QWidget* parent, const QStyleOptionViewIte
QWidget *editor = ComboBoxDelegate::createEditor(parent, option, index);
WeightModel *mymodel = qobject_cast<WeightModel *>(currCombo.model);
weightsystem_t *ws = mymodel->weightSystemAt(index);
- currWeigth.type = ws->description;
- currWeigth.weigth = ws->weight.grams;
+ currWeight.type = ws->description;
+ currWeight.weight = ws->weight.grams;
return editor;
}
+
+void AirTypesDelegate::revertModelData(QWidget* widget, QAbstractItemDelegate::EndEditHint hint)
+{
+}
+
+void AirTypesDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
+{
+ if (!index.isValid())
+ return;
+ QComboBox *combo = qobject_cast<QComboBox*>(editor);
+ model->setData(index, QVariant(combo->currentText()));
+}
+
+AirTypesDelegate::AirTypesDelegate(QObject* parent) : ComboBoxDelegate(airTypes(), parent)
+{
+}
diff --git a/qt-ui/modeldelegates.h b/qt-ui/modeldelegates.h
index 9603d5dce..29d4f3717 100644
--- a/qt-ui/modeldelegates.h
+++ b/qt-ui/modeldelegates.h
@@ -49,4 +49,13 @@ public slots:
void revertModelData(QWidget* widget, QAbstractItemDelegate::EndEditHint hint);
};
+class AirTypesDelegate : public ComboBoxDelegate{
+ Q_OBJECT
+public:
+ explicit AirTypesDelegate(QObject* parent = 0);
+ virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
+public slots:
+ void revertModelData(QWidget* widget, QAbstractItemDelegate::EndEditHint hint);
+};
+
#endif
diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp
index 0af5c7019..fc91e0558 100644
--- a/qt-ui/models.cpp
+++ b/qt-ui/models.cpp
@@ -549,7 +549,7 @@ bool WSInfoModel::insertRows(int row, int count, const QModelIndex& parent)
bool WSInfoModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
- struct ws_info *info = &ws_info[index.row()];
+ struct ws_info_t *info = &ws_info[index.row()];
switch(index.column()) {
case DESCRIPTION:
info->name = strdup(value.toByteArray().data());
@@ -577,7 +577,7 @@ QVariant WSInfoModel::data(const QModelIndex& index, int role) const
if (!index.isValid()) {
return ret;
}
- struct ws_info *info = &ws_info[index.row()];
+ struct ws_info_t *info = &ws_info[index.row()];
int gr = info->grams;
switch(role){
@@ -636,7 +636,26 @@ const QString& WSInfoModel::biggerString() const
WSInfoModel::WSInfoModel() : QAbstractTableModel(), rows(-1)
{
- struct ws_info *info = ws_info;
+ struct ws_info_t *info = ws_info;
+ for (info = ws_info; info->name; info++, rows++){
+ QString wsInfoName(info->name);
+ if( wsInfoName.count() > biggerEntry.count()){
+ biggerEntry = wsInfoName;
+ }
+ }
+
+ if (rows > -1) {
+ beginInsertRows(QModelIndex(), 0, rows);
+ endInsertRows();
+ }
+}
+
+void WSInfoModel::updateInfo()
+{
+ struct ws_info_t *info = ws_info;
+ beginRemoveRows(QModelIndex(), 0, this->rows);
+ endRemoveRows();
+ rows = -1;
for (info = ws_info; info->name; info++, rows++){
QString wsInfoName(info->name);
if( wsInfoName.count() > biggerEntry.count()){
@@ -657,7 +676,7 @@ void WSInfoModel::update()
endRemoveRows();
rows = -1;
}
- struct ws_info *info = ws_info;
+ struct ws_info_t *info = ws_info;
for (info = ws_info; info->name; info++, rows++);
if (rows > -1) {
@@ -687,7 +706,7 @@ bool TankInfoModel::insertRows(int row, int count, const QModelIndex& parent)
bool TankInfoModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
- struct tank_info *info = &tank_info[index.row()];
+ struct tank_info_t *info = &tank_info[index.row()];
switch(index.column()) {
case DESCRIPTION:
info->name = strdup(value.toByteArray().data());
@@ -722,7 +741,7 @@ QVariant TankInfoModel::data(const QModelIndex& index, int role) const
return defaultModelFont();
}
if (role == Qt::DisplayRole || role == Qt::EditRole) {
- struct tank_info *info = &tank_info[index.row()];
+ struct tank_info_t *info = &tank_info[index.row()];
int ml = info->ml;
double bar = (info->psi) ? psi_to_bar(info->psi) : info->bar;
@@ -779,7 +798,7 @@ int TankInfoModel::rowCount(const QModelIndex& parent) const
TankInfoModel::TankInfoModel() : QAbstractTableModel(), rows(-1)
{
- struct tank_info *info = tank_info;
+ struct tank_info_t *info = tank_info;
for (info = tank_info; info->name; info++, rows++){
QString infoName(info->name);
if (infoName.count() > biggerEntry.count()){
@@ -800,7 +819,7 @@ void TankInfoModel::update()
endRemoveRows();
rows = -1;
}
- struct tank_info *info = tank_info;
+ struct tank_info_t *info = tank_info;
for (info = tank_info; info->name; info++, rows++);
if (rows > -1) {
@@ -1438,3 +1457,109 @@ void YearlyStatisticsModel::update_yearly_stats()
item->parent = rootItem;
}
}
+
+/*#################################################################
+ * #
+ * # Table Print Model
+ * #
+ * ################################################################
+ */
+TablePrintModel::TablePrintModel()
+{
+ columns = 7;
+ rows = 0;
+}
+
+TablePrintModel::~TablePrintModel()
+{
+ for (int i = 0; i < list.size(); i++)
+ delete list.at(i);
+}
+
+void TablePrintModel::insertRow(int index)
+{
+ struct TablePrintItem *item = new struct TablePrintItem();
+ item->colorBackground = 0xffffffff;
+ if (index == -1) {
+ beginInsertRows(QModelIndex(), rows, rows);
+ list.append(item);
+ } else {
+ beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, item);
+ }
+ endInsertRows();
+ rows++;
+}
+
+void TablePrintModel::callReset()
+{
+ reset();
+}
+
+QVariant TablePrintModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+ if (role == Qt::BackgroundRole)
+ return QColor(list.at(index.row())->colorBackground);
+ if (role == Qt::DisplayRole)
+ switch (index.column()) {
+ case 0:
+ return list.at(index.row())->number;
+ case 1:
+ return list.at(index.row())->date;
+ case 2:
+ return list.at(index.row())->depth;
+ case 3:
+ return list.at(index.row())->duration;
+ case 4:
+ return list.at(index.row())->divemaster;
+ case 5:
+ return list.at(index.row())->buddy;
+ case 6:
+ return list.at(index.row())->location;
+ }
+ return QVariant();
+}
+
+bool TablePrintModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid()) {
+ if (role == Qt::DisplayRole) {
+ switch (index.column()) {
+ case 0:
+ list.at(index.row())->number = value.toString();
+ case 1:
+ list.at(index.row())->date = value.toString();
+ case 2:
+ list.at(index.row())->depth = value.toString();
+ case 3:
+ list.at(index.row())->duration = value.toString();
+ case 4:
+ list.at(index.row())->divemaster = value.toString();
+ case 5:
+ list.at(index.row())->buddy = value.toString();
+ case 6:
+ list.at(index.row())->location = value.toString();
+ }
+ return true;
+ }
+ if (role == Qt::BackgroundRole) {
+ list.at(index.row())->colorBackground = value.value<unsigned int>();
+ return true;
+ }
+ }
+ return false;
+}
+
+int TablePrintModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return rows;
+}
+
+int TablePrintModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return columns;
+}
diff --git a/qt-ui/models.h b/qt-ui/models.h
index e8a7daaf3..c60856478 100644
--- a/qt-ui/models.h
+++ b/qt-ui/models.h
@@ -59,6 +59,7 @@ public:
const QString& biggerString() const;
void clear();
void update();
+ void updateInfo();
private:
int rows;
QString biggerEntry;
@@ -230,4 +231,45 @@ public:
YearlyStatisticsModel(QObject* parent = 0);
void update_yearly_stats();
};
+
+/* TablePrintModel:
+ * for now we use a blank table model with row items TablePrintItem.
+ * these are pretty much the same as DiveItem, but have color
+ * properties, as well. perhaps later one a more unified model has to be
+ * considered, but the current TablePrintModel idea has to be extended
+ * to support variadic column lists and column list orders that can
+ * be controlled by the user.
+ */
+struct TablePrintItem {
+ QString number;
+ QString date;
+ QString depth;
+ QString duration;
+ QString divemaster;
+ QString buddy;
+ QString location;
+ unsigned int colorBackground;
+};
+
+class TablePrintModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+private:
+ QList<struct TablePrintItem *> list;
+
+public:
+ ~TablePrintModel();
+ TablePrintModel();
+
+ int rows, columns;
+ void insertRow(int index = -1);
+ void callReset();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+};
+
#endif
diff --git a/qt-ui/preferences.ui b/qt-ui/preferences.ui
index 07a423834..2ecd0963c 100644
--- a/qt-ui/preferences.ui
+++ b/qt-ui/preferences.ui
@@ -374,7 +374,7 @@
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
- <string>Weigth</string>
+ <string>Weight</string>
</property>
</widget>
</item>
diff --git a/qt-ui/printdialog.cpp b/qt-ui/printdialog.cpp
index 542590707..f4bf16d05 100644
--- a/qt-ui/printdialog.cpp
+++ b/qt-ui/printdialog.cpp
@@ -47,6 +47,7 @@ void PrintDialog::printClicked(void)
// printer.setOutputFileName("print.pdf");
// printer.setOutputFormat(QPrinter::PdfFormat);
// temporary: use a preview dialog
+ printer.setResolution(300);
QPrintPreviewDialog previewDialog(&printer, this);
QObject::connect(&previewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(onPaintRequested(QPrinter *)));
previewDialog.exec();
diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp
index 2184f7366..7a4944ede 100644
--- a/qt-ui/printlayout.cpp
+++ b/qt-ui/printlayout.cpp
@@ -1,9 +1,12 @@
+#include <QtCore/qmath.h>
#include <QDebug>
#include <QPainter>
#include <QDesktopWidget>
#include <QApplication>
-#include <QTextDocument>
+#include <QTableView>
+#include <QHeaderView>
#include "mainwindow.h"
+#include "profilegraphics.h"
#include "printlayout.h"
#include "../dive.h"
#include "../display.h"
@@ -19,41 +22,34 @@ struct options {
};
*/
-#define TABLE_PRINT_COL 7
-
PrintLayout::PrintLayout(PrintDialog *dialogPtr, QPrinter *printerPtr, struct options *optionsPtr)
{
dialog = dialogPtr;
printer = printerPtr;
printOptions = optionsPtr;
- // painter = new QPainter(printer);
// table print settings
- tableColumnNames.append(tr("Dive#"));
- tableColumnNames.append(tr("Date"));
- tableColumnNames.append(tr("Depth"));
- tableColumnNames.append(tr("Duration"));
- tableColumnNames.append(tr("Master"));
- tableColumnNames.append(tr("Buddy"));
- tableColumnNames.append(tr("Location"));
- tableColumnWidths.append("7");
- tableColumnWidths.append("10");
- tableColumnWidths.append("10");
- tableColumnWidths.append("10");
- tableColumnWidths.append("15");
- tableColumnWidths.append("15");
- tableColumnWidths.append("100");
+ tablePrintHeadingBackground = 0xffeeeeee;
+ tablePrintColumnNames.append(tr("Dive#"));
+ tablePrintColumnNames.append(tr("Date"));
+ tablePrintColumnNames.append(tr("Depth"));
+ tablePrintColumnNames.append(tr("Duration"));
+ tablePrintColumnNames.append(tr("Master"));
+ tablePrintColumnNames.append(tr("Buddy"));
+ tablePrintColumnNames.append(tr("Location"));
+ tablePrintColumnWidths.append(7);
+ tablePrintColumnWidths.append(10);
+ tablePrintColumnWidths.append(10);
+ tablePrintColumnWidths.append(10);
+ tablePrintColumnWidths.append(15);
+ tablePrintColumnWidths.append(15);
+ tablePrintColumnWidths.append(33);
}
void PrintLayout::print()
{
// we call setup each time to check if the printer properties have changed
setup();
-
- // temp / debug
- printTable();
- return;
- // ------------
switch (printOptions->type) {
case options::PRETTY:
printSixDives();
@@ -78,11 +74,51 @@ void PrintLayout::setup()
scaleX = (qreal)printerDpi/(qreal)screenDpiX;
scaleY = (qreal)printerDpi/(qreal)screenDpiY;
+
+ // a printer page scalled to screen DPI
+ scaledPageW = pageRect.width() / scaleX;
+ scaledPageH = pageRect.height() / scaleY;
}
+// experimental
void PrintLayout::printSixDives() const
{
- // nop
+ ProfileGraphicsView *profile = mainWindow()->graphics();
+ QPainter painter;
+ painter.begin(printer);
+ painter.setRenderHint(QPainter::Antialiasing);
+ // painter.setRenderHint(QPainter::HighQualityAntialiasing);
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ painter.scale(scaleX, scaleY);
+
+ profile->clear();
+ profile->setPrintMode(true, !printOptions->color_selected);
+ QSize originalSize = profile->size();
+ profile->resize(scaledPageW, scaledPageH);
+
+ int i;
+ struct dive *dive;
+ bool firstPage = true;
+ for_each_dive(i, dive) {
+ if (!dive->selected && printOptions->print_selected)
+ continue;
+ // don't create a new page if still on first page
+ if (!firstPage)
+ printer->newPage();
+ else
+ firstPage = false;
+ profile->plot(dive, true);
+ QPixmap pm = QPixmap::grabWidget(profile);
+ QTransform transform;
+ transform.rotate(270);
+ pm = QPixmap(pm.transformed(transform));
+ painter.drawPixmap(0, 0, pm);
+ }
+ painter.end();
+ profile->setPrintMode(false);
+ profile->resize(originalSize);
+ profile->clear();
+ profile->plot(current_dive, true);
}
void PrintLayout::printTwoDives() const
@@ -90,105 +126,112 @@ void PrintLayout::printTwoDives() const
// nop
}
-void PrintLayout::printTable() const
+void PrintLayout::printTable()
{
- QTextDocument doc;
- QSizeF pageSize;
- pageSize.setWidth(pageRect.width());
- pageSize.setHeight(pageRect.height());
- doc.setPageSize(pageSize);
-
- QString styleSheet(
- "<style type='text/css'>"
- "table {"
- " border-width: 1px;"
- " border-style: solid;"
- " border-color: #999999;"
- "}"
- "th {"
- " background-color: #eeeeee;"
- " font-size: small;"
- " padding: 3px 5px 3px 5px;"
- "}"
- "td {"
- " font-size: small;"
- " padding: 3px 5px 3px 5px;"
- "}"
- "</style>"
- );
- // setDefaultStyleSheet() doesn't work here?
- QString htmlText = styleSheet + "<table cellspacing='0' width='100%'>";
- QString htmlTextPrev;
- int pageCountNew = 1, pageCount;
- bool insertHeading = true;
-
- int i;
+ // create and setup a table
+ QTableView table;
+ table.setAttribute(Qt::WA_DontShowOnScreen);
+ table.setSelectionMode(QAbstractItemView::NoSelection);
+ table.setFocusPolicy(Qt::NoFocus);
+ table.horizontalHeader()->setVisible(false);
+ table.horizontalHeader()->setResizeMode(QHeaderView::Fixed);
+ table.verticalHeader()->setVisible(false);
+ table.verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ table.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ table.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ // fit table to one page initially
+ table.resize(scaledPageW, scaledPageH);
+
+ // create and fill a table model
+ TablePrintModel model;
struct dive *dive;
+ int i, row = 0;
+ addTablePrintHeadingRow(&model, row); // add one heading row
+ row++;
for_each_dive(i, dive) {
if (!dive->selected && printOptions->print_selected)
continue;
- if (insertHeading) {
- htmlText += insertTableHeadingRow();
- insertHeading = false;
- }
- htmlTextPrev = htmlText;
- htmlText += insertTableDataRow(dive);
- doc.setHtml(htmlText);
- pageCount = pageCountNew;
- pageCountNew = doc.pageCount();
- /* if the page count increases after adding this row we 'revert'
- * and add a heading instead. */
- if (pageCountNew > pageCount) {
- htmlText = htmlTextPrev;
- insertHeading = true;
+ addTablePrintDataRow(&model, row, dive);
+ row++;
+ }
+ table.setModel(&model); // set model to table
+ // resize columns to percentages from page width
+ for (int i = 0; i < model.columns; i++) {
+ int pw = qCeil((qreal)(tablePrintColumnWidths.at(i) * table.width()) / 100);
+ table.horizontalHeader()->resizeSection(i, pw);
+ }
+ // reset the model at this point
+ model.callReset();
+
+ // a list of vertical offsets where pages begin and some helpers
+ QList<unsigned int> pageIndexes;
+ pageIndexes.append(0);
+ int tableHeight = 0, rowH = 0, accH = 0;
+
+ // process all rows
+ for (int i = 0; i < model.rows; i++) {
+ rowH = table.rowHeight(i);
+ accH += rowH;
+ if (accH > scaledPageH) { // push a new page index and add a heading
+ pageIndexes.append(pageIndexes.last() + (accH - rowH));
+ addTablePrintHeadingRow(&model, i);
+ accH = 0;
i--;
}
+ tableHeight += rowH;
+ }
+ pageIndexes.append(pageIndexes.last() + accH);
+ // resize the whole widget so that it can be rendered
+ table.resize(scaledPageW, tableHeight);
+
+ // attach a painter and render pages by using pageIndexes
+ QPainter painter(printer);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ painter.scale(scaleX, scaleY);
+ for (int i = 0; i < pageIndexes.size() - 1; i++) {
+ if (i > 0)
+ printer->newPage();
+ QRegion region(0, pageIndexes.at(i) - 1,
+ table.width(),
+ pageIndexes.at(i + 1) - pageIndexes.at(i) + 2);
+ table.render(&painter, QPoint(0, 0), region);
}
- htmlText += "</table>";
- doc.setHtml(htmlText);
- doc.print(printer);
-}
-
-QString PrintLayout::insertTableHeadingRow() const
-{
- int i;
- QString ret("<tr>");
- for (i = 0; i < TABLE_PRINT_COL; i++)
- ret += insertTableHeadingCol(i);
- ret += "</tr>";
- return ret;
-}
-
-QString PrintLayout::insertTableHeadingCol(int col) const
-{
- QString ret("<th align='left' width='");
- ret += tableColumnWidths.at(col);
- ret += "%'>";
- ret += tableColumnNames.at(col);
- ret += "</th>";
- return ret;
}
-QString PrintLayout::insertTableDataRow(struct dive *dive) const
+void PrintLayout::addTablePrintDataRow(TablePrintModel *model, int row, struct dive *dive) const
{
- // use the DiveItem class
struct DiveItem di;
di.dive = dive;
+ model->insertRow();
+ model->setData(model->index(row, 0), QString::number(dive->number), Qt::DisplayRole);
+ model->setData(model->index(row, 1), di.displayDate(), Qt::DisplayRole);
+ model->setData(model->index(row, 2), di.displayDepth(), Qt::DisplayRole);
+ model->setData(model->index(row, 3), di.displayDuration(), Qt::DisplayRole);
+ model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole);
+ model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole);
+ model->setData(model->index(row, 6), dive->location, Qt::DisplayRole);
+}
- // fill row
- QString ret("<tr>");
- ret += insertTableDataCol(QString::number(dive->number));
- ret += insertTableDataCol(di.displayDate());
- ret += insertTableDataCol(di.displayDepth());
- ret += insertTableDataCol(di.displayDuration());
- ret += insertTableDataCol(dive->divemaster);
- ret += insertTableDataCol(dive->buddy);
- ret += insertTableDataCol(dive->location);
- ret += "</tr>";
- return ret;
+void PrintLayout::addTablePrintHeadingRow(TablePrintModel *model, int row) const
+{
+ model->insertRow(row);
+ for (int i = 0; i < model->columns; i++) {
+ model->setData(model->index(row, i), tablePrintColumnNames.at(i), Qt::DisplayRole);
+ model->setData(model->index(row, i), tablePrintHeadingBackground, Qt::BackgroundRole);
+ }
}
-QString PrintLayout::insertTableDataCol(QString data) const
+// experimental
+QPixmap PrintLayout::convertPixmapToGrayscale(QPixmap pixmap) const
{
- return "<td>" + data + "</td>";
+ QImage image = pixmap.toImage();
+ int gray, width = pixmap.width(), height = pixmap.height();
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ gray = qGray(image.pixel(i, j));
+ image.setPixel(i, j, qRgb(gray, gray, gray));
+ }
+ }
+ return pixmap.fromImage(image);
}
diff --git a/qt-ui/printlayout.h b/qt-ui/printlayout.h
index cbb1e42ac..ac363ab8d 100644
--- a/qt-ui/printlayout.h
+++ b/qt-ui/printlayout.h
@@ -1,10 +1,13 @@
#ifndef PRINTLAYOUT_H
#define PRINTLAYOUT_H
+#include <QObject>
#include <QPrinter>
-#include <QStringList>
+#include <QList>
class PrintDialog;
+class TablePrintModel;
+struct dive;
class PrintLayout : public QObject {
Q_OBJECT
@@ -19,21 +22,22 @@ private:
struct options *printOptions;
QPainter *painter;
- int screenDpiX, screenDpiY, printerDpi;
+ int screenDpiX, screenDpiY, printerDpi, scaledPageW, scaledPageH;
qreal scaleX, scaleY;
QRect pageRect;
- QStringList tableColumnNames;
- QStringList tableColumnWidths;
+ QList<QString> tablePrintColumnNames;
+ QList<unsigned int> tablePrintColumnWidths;
+ unsigned int tablePrintHeadingBackground;
void setup();
void printSixDives() const;
void printTwoDives() const;
- void printTable() const;
- QString insertTableHeadingRow() const;
- QString insertTableHeadingCol(int) const;
- QString insertTableDataRow(struct dive *) const;
- QString insertTableDataCol(QString) const;
+ void printTable();
+ void addTablePrintDataRow(TablePrintModel *model, int row, struct dive *dive) const;
+ void addTablePrintHeadingRow(TablePrintModel *model, int row) const;
+
+ QPixmap convertPixmapToGrayscale(QPixmap) const;
};
#endif
diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp
index 264e02d96..ad412e4b0 100644
--- a/qt-ui/profilegraphics.cpp
+++ b/qt-ui/profilegraphics.cpp
@@ -1,7 +1,6 @@
#include "profilegraphics.h"
#include "mainwindow.h"
#include "divelistview.h"
-#include "graphicsview-common.h"
#include <QGraphicsScene>
#include <QResizeEvent>
@@ -46,11 +45,12 @@ extern int evn_used;
ProfileGraphicsView::ProfileGraphicsView(QWidget* parent) : QGraphicsView(parent), toolTip(0) , dive(0), diveDC(0)
{
+ printMode = false;
+ isGrayscale = false;
gc.printer = false;
fill_profile_color();
setScene(new QGraphicsScene());
- setBackgroundBrush(profile_color[BACKGROUND].at(0));
scene()->installEventFilter(this);
setRenderHint(QPainter::Antialiasing);
@@ -189,6 +189,17 @@ void ProfileGraphicsView::refresh()
plot(current_dive, TRUE);
}
+void ProfileGraphicsView::setPrintMode(bool mode, bool grayscale)
+{
+ printMode = mode;
+ isGrayscale = grayscale;
+}
+
+QColor ProfileGraphicsView::getColor(const color_indice_t i)
+{
+ return profile_color[i].at((isGrayscale) ? 1 : 0);
+}
+
void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
{
struct divecomputer *dc;
@@ -206,6 +217,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
if (!isVisible() || !dive) {
return;
}
+ setBackgroundBrush(getColor(BACKGROUND));
// best place to put the focus stealer code.
setFocusProxy(mainWindow()->dive_list());
@@ -214,6 +226,8 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
toolTip = new ToolTipItem();
installEventFilter(toolTip);
scene()->addItem(toolTip);
+ if (printMode)
+ toolTip->setVisible(false);
// Fix this for printing / screen later.
// plot_set_scale(scale_mode_t);
@@ -250,7 +264,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
/* Bounding box */
QPen pen = defaultPen;
- pen.setColor(profile_color[TIME_GRID].at(0));
+ pen.setColor(getColor(TIME_GRID));
QGraphicsRectItem *rect = new QGraphicsRectItem(profile_grid_area);
rect->setPen(pen);
scene()->addItem(rect);
@@ -338,7 +352,7 @@ void ProfileGraphicsView::plot_depth_scale()
case units::FEET: marker = 9144; break; /* 30 ft */
}
- QColor c(profile_color[DEPTH_GRID].first());
+ QColor c(getColor(DEPTH_GRID));
/* don't write depth labels all the way to the bottom as
* there may be other graphs below the depth plot (like
@@ -364,7 +378,7 @@ void ProfileGraphicsView::plot_pp_text()
pp = floor(gc.pi.maxpp * 10.0) / 10.0 + 0.2;
dpp = pp > 4 ? 1.0 : 0.5;
hpos = gc.pi.entry[gc.pi.nr - 1].sec;
- QColor c = profile_color[PP_LINES].first();
+ QColor c = getColor(PP_LINES);
for (m = 0.0; m <= pp; m += dpp) {
QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, m), SCALEGC(hpos, m));
@@ -397,7 +411,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
QColor c;
QPointF from, to;
if (prefs.pp_graphs.pn2) {
- c = profile_color[PN2].first();
+ c = getColor(PN2);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->pn2));
for (i = 1; i < pi->nr; i++) {
@@ -408,7 +422,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->pn2));
}
- c = profile_color[PN2_ALERT].first();
+ c = getColor(PN2_ALERT);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->pn2));
for (i = 1; i < pi->nr; i++) {
@@ -421,7 +435,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
}
if (prefs.pp_graphs.phe) {
- c = profile_color[PHE].first();
+ c = getColor(PHE);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->phe));
@@ -433,7 +447,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->phe));
}
- c = profile_color[PHE_ALERT].first();
+ c = getColor(PHE_ALERT);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->phe));
for (i = 1; i < pi->nr; i++) {
@@ -445,7 +459,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
}
}
if (prefs.pp_graphs.po2) {
- c = profile_color[PO2].first();
+ c = getColor(PO2);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->po2));
for (i = 1; i < pi->nr; i++) {
@@ -456,7 +470,7 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->po2));
}
- c = profile_color[PO2_ALERT].first();
+ c = getColor(PO2_ALERT);
entry = pi->entry;
from = QPointF(SCALEGC(entry->sec, entry->po2));
for (i = 1; i < pi->nr; i++) {
@@ -739,9 +753,9 @@ QColor ProfileGraphicsView::get_sac_color(int sac, int avg_sac)
sac_index = 0;
if (sac_index > SAC_COLORS - 1)
sac_index = SAC_COLORS - 1;
- return profile_color[ (color_indice_t) (SAC_COLORS_START_IDX + sac_index)].first();
+ return getColor((color_indice_t)(SAC_COLORS_START_IDX + sac_index));
}
- return profile_color[SAC_DEFAULT].first();
+ return getColor(SAC_DEFAULT);
}
void ProfileGraphicsView::plot_events(struct divecomputer *dc)
@@ -792,7 +806,7 @@ void ProfileGraphicsView::plot_one_event(struct event *ev)
int x = SCALEXGC(ev->time.seconds);
int y = SCALEYGC(depth);
- EventItem *item = new EventItem();
+ EventItem *item = new EventItem(0, isGrayscale);
item->setPos(x, y);
scene()->addItem(item);
@@ -816,8 +830,8 @@ void ProfileGraphicsView::plot_one_event(struct event *ev)
} else if (ev->name && name == "SP change") {
name += tr("Bailing out to OC");
} else {
- name += ev->flags == SAMPLE_FLAGS_BEGIN ? tr("Starts with space!"," begin") :
- ev->flags == SAMPLE_FLAGS_END ? tr("Starts with space!", " end") : "";
+ name += ev->flags == SAMPLE_FLAGS_BEGIN ? tr(" begin", "Starts with space!") :
+ ev->flags == SAMPLE_FLAGS_END ? tr(" end", "Starts with space!") : "";
}
//item->setToolTipController(toolTip);
@@ -858,7 +872,7 @@ void ProfileGraphicsView::plot_depth_profile()
last_gc = gc;
- QColor c = profile_color[TIME_GRID].at(0);
+ QColor c = getColor(TIME_GRID);
for (i = incr; i < maxtime; i += incr) {
QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(i, 0), SCALEGC(i, 1));
QPen pen(defaultPen);
@@ -895,7 +909,7 @@ void ProfileGraphicsView::plot_depth_profile()
}
maxline = MAX(gc.pi.maxdepth + marker, maxdepth * 2 / 3);
- c = profile_color[DEPTH_GRID].at(0);
+ c = getColor(DEPTH_GRID);
for (i = marker; i < maxline; i += marker) {
QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, i), SCALEGC(1, i));
@@ -906,7 +920,7 @@ void ProfileGraphicsView::plot_depth_profile()
}
gc.leftx = 0; gc.rightx = maxtime;
- c = profile_color[MEAN_DEPTH].at(0);
+ c = getColor(MEAN_DEPTH);
/* Show mean depth */
if (! gc.printer) {
@@ -955,8 +969,8 @@ void ProfileGraphicsView::plot_depth_profile()
}
}
}
- pat.setColorAt(1, profile_color[DEPTH_BOTTOM].first());
- pat.setColorAt(0, profile_color[DEPTH_TOP].first());
+ pat.setColorAt(1, getColor(DEPTH_BOTTOM));
+ pat.setColorAt(0, getColor(DEPTH_TOP));
neatFill = new QGraphicsPolygonItem();
neatFill->setPolygon(p);
@@ -970,8 +984,8 @@ void ProfileGraphicsView::plot_depth_profile()
* through so far) */
if (prefs.profile_dc_ceiling && prefs.profile_red_ceiling) {
p.clear();
- pat.setColorAt(0, profile_color[CEILING_SHALLOW].first());
- pat.setColorAt(1, profile_color[CEILING_DEEP].first());
+ pat.setColorAt(0, getColor(CEILING_SHALLOW));
+ pat.setColorAt(1, getColor(CEILING_DEEP));
entry = gc.pi.entry;
p.append(QPointF(SCALEGC(0, 0)));
@@ -996,8 +1010,8 @@ void ProfileGraphicsView::plot_depth_profile()
/* finally, plot the calculated ceiling over all this */
if (prefs.profile_calc_ceiling) {
- pat.setColorAt(0, profile_color[CALC_CEILING_SHALLOW].first());
- pat.setColorAt(1, profile_color[CALC_CEILING_DEEP].first());
+ pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
+ pat.setColorAt(1, getColor(CALC_CEILING_DEEP));
entry = gc.pi.entry;
p.clear();
@@ -1020,7 +1034,7 @@ void ProfileGraphicsView::plot_depth_profile()
if (prefs.profile_calc_ceiling && prefs.calc_all_tissues){
int k;
for (k=0; k<16; k++){
- pat.setColorAt(0, profile_color[CALC_CEILING_SHALLOW].first());
+ pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW));
pat.setColorAt(1, QColor(100, 100, 100, 50));
entry = gc.pi.entry;
@@ -1041,8 +1055,8 @@ void ProfileGraphicsView::plot_depth_profile()
}
/* next show where we have been bad and crossed the dc's ceiling */
if (prefs.profile_dc_ceiling) {
- pat.setColorAt(0, profile_color[CEILING_SHALLOW].first());
- pat.setColorAt(1, profile_color[CEILING_DEEP].first());
+ pat.setColorAt(0, getColor(CEILING_SHALLOW));
+ pat.setColorAt(1, getColor(CEILING_DEEP));
entry = gc.pi.entry;
p.clear();
@@ -1075,7 +1089,7 @@ void ProfileGraphicsView::plot_depth_profile()
depth = entry->depth;
QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(entry[-1].sec, entry[-1].depth), SCALEGC(sec, depth));
QPen pen(defaultPen);
- pen.setColor(profile_color[ (color_indice_t) (VELOCITY_COLORS_START_IDX + entry->velocity)].first());
+ pen.setColor(getColor((color_indice_t)(VELOCITY_COLORS_START_IDX + entry->velocity)));
item->setPen(pen);
scene()->addItem(item);
}
@@ -1098,15 +1112,16 @@ QGraphicsItemGroup *ProfileGraphicsView::plot_text(text_render_options_t *tro,co
QPainterPathStroker stroker;
stroker.setWidth(3);
QGraphicsPathItem *strokedItem = new QGraphicsPathItem(stroker.createStroke(textPath), group);
- strokedItem->setBrush(QBrush(profile_color[TEXT_BACKGROUND].first()));
+ strokedItem->setBrush(QBrush(getColor(TEXT_BACKGROUND)));
strokedItem->setPen(Qt::NoPen);
QGraphicsPathItem *textItem = new QGraphicsPathItem(textPath, group);
- textItem->setBrush(QBrush(profile_color[tro->color].first()));
+ textItem->setBrush(QBrush(getColor(tro->color)));
textItem->setPen(Qt::NoPen);
group->setPos(point.x() + dx, point.y() + dy);
- group->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ if (!printMode)
+ group->setFlag(QGraphicsItem::ItemIgnoresTransformations);
if (!parent)
scene()->addItem(group);
@@ -1127,7 +1142,7 @@ void ProfileGraphicsView::plot_temperature_profile()
QPointF from;
QPointF to;
- QColor color = profile_color[TEMP_PLOT].first();
+ QColor color = getColor(TEMP_PLOT);
for (int i = 0; i < gc.pi.nr; i++) {
struct plot_data *entry = gc.pi.entry + i;
@@ -1175,36 +1190,14 @@ void ToolTipItem::addToolTip(const QString& toolTip, const QIcon& icon)
textItem->setPos(SPACING + ICON_SMALL + SPACING, yValue);
textItem->setBrush(QBrush(Qt::white));
textItem->setFlag(ItemIgnoresTransformations);
- toolTips[toolTip] = qMakePair(iconItem, textItem);
+ toolTips.push_back(qMakePair(iconItem, textItem));
expand();
}
-void ToolTipItem::removeToolTip(const QString& toolTip)
-{
- ToolTip toBeRemoved = toolTips[toolTip];
- delete toBeRemoved.first;
- delete toBeRemoved.second;
- toolTips.remove(toolTip);
-
- int toolTipIndex = 0;
-
- // We removed a toolTip, let's move the others to the correct location
- Q_FOREACH(ToolTip t, toolTips) {
- double yValue = title->boundingRect().height() + SPACING + toolTipIndex * ICON_SMALL + SPACING;
-
- // Icons can be null.
- if (t.first)
- t.first->setPos(SPACING, yValue);
-
- t.second->setPos(SPACING + ICON_SMALL + SPACING, yValue);
- toolTipIndex++;
- }
-}
-
void ToolTipItem::refresh(struct graphics_context *gc, QPointF pos)
{
clear();
- int time = (pos.x() * gc->maxtime) / scene()->sceneRect().width();
+ int time = (pos.x() * gc->maxtime) / gc->maxx;
char buffer[500];
get_plot_details(gc, time, buffer, 500);
addToolTip(QString(buffer));
@@ -1397,8 +1390,14 @@ bool ToolTipItem::eventFilter(QObject* view, QEvent* event)
return false;
}
-EventItem::EventItem(QGraphicsItem* parent): QGraphicsPolygonItem(parent)
+QColor EventItem::getColor(const color_indice_t i)
+{
+ return profile_color[i].at((isGrayscale) ? 1 : 0);
+}
+
+EventItem::EventItem(QGraphicsItem* parent, bool grayscale): QGraphicsPolygonItem(parent)
{
+ isGrayscale = grayscale;
setFlag(ItemIgnoresTransformations);
setFlag(ItemIsFocusable);
setAcceptHoverEvents(true);
@@ -1416,17 +1415,18 @@ EventItem::EventItem(QGraphicsItem* parent): QGraphicsPolygonItem(parent)
defaultPen.setCosmetic(true);
QPen pen = defaultPen;
- pen.setBrush(QBrush(profile_color[ALERT_BG].first()));
+ pen.setBrush(QBrush(getColor(ALERT_BG)));
setPolygon(poly);
- setBrush(QBrush(profile_color[ALERT_BG].first()));
+ setBrush(QBrush(getColor(ALERT_BG)));
setPen(pen);
- QGraphicsLineItem *line = new QGraphicsLineItem(0,5,0,10, this);
- line->setPen(QPen(Qt::black, 2));
+ QGraphicsLineItem *line = new QGraphicsLineItem(0, 5, 0, 10, this);
+ line->setPen(QPen(getColor(ALERT_FG), 2));
- QGraphicsEllipseItem *ball = new QGraphicsEllipseItem(-1, 12, 2,2, this);
- ball->setBrush(QBrush(Qt::black));
+ QGraphicsEllipseItem *ball = new QGraphicsEllipseItem(-1, 12, 2, 2, this);
+ ball->setBrush(QBrush(getColor(ALERT_FG)));
+ ball->setPen(QPen(getColor(ALERT_FG)));
}
GraphicsTextEditor::GraphicsTextEditor(QGraphicsItem* parent): QGraphicsTextItem(parent)
diff --git a/qt-ui/profilegraphics.h b/qt-ui/profilegraphics.h
index b6df52dec..0bcbf7529 100644
--- a/qt-ui/profilegraphics.h
+++ b/qt-ui/profilegraphics.h
@@ -1,6 +1,7 @@
#ifndef PROFILEGRAPHICS_H
#define PROFILEGRAPHICS_H
+#include "graphicsview-common.h"
#include "../display.h"
#include <QGraphicsView>
#include <QGraphicsItem>
@@ -34,7 +35,6 @@ public:
void expand();
void clear();
void addToolTip(const QString& toolTip, const QIcon& icon = QIcon());
- void removeToolTip(const QString& toolTip);
void refresh(struct graphics_context* gc, QPointF pos);
bool isExpanded();
void persistPos();
@@ -47,7 +47,7 @@ public slots:
private:
typedef QPair<QGraphicsPixmapItem*, QGraphicsSimpleTextItem*> ToolTip;
- QMap<QString, ToolTip > toolTips;
+ QList<ToolTip> toolTips;
QGraphicsPathItem *background;
QGraphicsLineItem *separator;
QGraphicsSimpleTextItem *title;
@@ -60,12 +60,15 @@ private:
class EventItem : public QGraphicsPolygonItem
{
public:
- explicit EventItem(QGraphicsItem* parent = 0);
+ explicit EventItem(QGraphicsItem* parent = 0, bool grayscale = FALSE);
private:
ToolTipItem *controller;
QString text;
QIcon icon;
+ bool isGrayscale;
+
+ QColor getColor(const color_indice_t i);
};
class GraphicsTextEditor : public QGraphicsTextItem{
@@ -92,6 +95,7 @@ public:
void plot(struct dive *d, bool forceRedraw = FALSE);
bool eventFilter(QObject* obj, QEvent* event);
void clear();
+ void setPrintMode(bool mode, bool grayscale = FALSE);
protected:
void resizeEvent(QResizeEvent *event);
@@ -124,6 +128,7 @@ private:
void plot_pp_text();
void plot_depth_scale();
+ QColor getColor(const color_indice_t i);
QColor get_sac_color(int sac, int avg_sac);
void scrollViewTo(const QPoint pos);
@@ -134,6 +139,8 @@ private:
struct dive *dive;
struct divecomputer *diveDC;
int zoomLevel;
+ bool printMode;
+ bool isGrayscale;
// Top Level Items.
QGraphicsItem* profileGrid;
diff --git a/qt-ui/tableview.cpp b/qt-ui/tableview.cpp
new file mode 100644
index 000000000..6956d3941
--- /dev/null
+++ b/qt-ui/tableview.cpp
@@ -0,0 +1,90 @@
+#include "tableview.h"
+#include "ui_tableview.h"
+#include "models.h"
+
+#include <QPushButton>
+#include <QFile>
+#include <QTextStream>
+#include <QSettings>
+
+TableView::TableView(QWidget *parent) : QWidget(parent), ui(new Ui::TableView){
+ ui->setupUi(this);
+ QFile cssFile(":table-css");
+ cssFile.open(QIODevice::ReadOnly);
+ QTextStream reader(&cssFile);
+ QString css = reader.readAll();
+ ui->tableView->setStyleSheet(css);
+
+ QIcon plusIcon(":plus");
+ plusBtn = new QPushButton(plusIcon, QString(), ui->groupBox);
+ plusBtn->setFlat(true);
+ plusBtn->setToolTip(tr("Add Cylinder"));
+ connect(plusBtn, SIGNAL(clicked(bool)), this, SIGNAL(addButtonClicked()));
+}
+
+TableView::~TableView()
+{
+ QSettings s;
+ s.beginGroup(objectName());
+ for (int i = 0; i < ui->tableView->model()->columnCount(); i++) {
+ s.setValue(QString("colwidth%1").arg(i), ui->tableView->columnWidth(i));
+ }
+ s.endGroup();
+ s.sync();
+}
+
+void TableView::setBtnToolTip(const QString& tooltip)
+{
+ plusBtn->setToolTip(tooltip);
+}
+
+void TableView::setTitle(const QString& title)
+{
+ ui->groupBox->setTitle(title);
+}
+
+void TableView::setModel(QAbstractItemModel *model){
+ ui->tableView->setModel(model);
+ connect(ui->tableView, SIGNAL(clicked(QModelIndex)), model, SLOT(remove(QModelIndex)));
+
+ QSettings s;
+ s.beginGroup(objectName());
+ for (int i = 0; i < ui->tableView->model()->columnCount(); i++) {
+ QVariant width = s.value(QString("colwidth%1").arg(i));
+ if (width.isValid())
+ ui->tableView->setColumnWidth(i, width.toInt());
+ else
+ ui->tableView->resizeColumnToContents(i);
+ }
+ s.endGroup();
+
+ ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
+ QFontMetrics metrics(defaultModelFont());
+ ui->tableView->verticalHeader()->setDefaultSectionSize( metrics.height() + 8 );
+}
+
+void TableView::fixPlusPosition()
+{
+ plusBtn->setGeometry(ui->groupBox->contentsRect().width() - 30, 2, 24,24);
+}
+
+// We need to manually position the 'plus' on cylinder and weight.
+void TableView::resizeEvent(QResizeEvent* event)
+{
+ fixPlusPosition();
+ QWidget::resizeEvent(event);
+}
+
+void TableView::showEvent(QShowEvent* event)
+{
+ QWidget::showEvent(event);
+ fixPlusPosition();
+}
+
+void TableView::edit(const QModelIndex& index){
+ ui->tableView->edit(index);
+}
+
+QTableView *TableView::view(){
+ return ui->tableView;
+}
diff --git a/qt-ui/tableview.h b/qt-ui/tableview.h
new file mode 100644
index 000000000..d22f466b5
--- /dev/null
+++ b/qt-ui/tableview.h
@@ -0,0 +1,45 @@
+#ifndef TABLEVIEW_H
+#define TABLEVIEW_H
+
+/* This TableView is prepared to have the CSS,
+ * the methods to restore / save the state of
+ * the column widths and the 'plus' button.
+ */
+#include <QWidget>
+
+class QPushButton;
+class QAbstractItemModel;
+class QModelIndex;
+class QTableView;
+namespace Ui{
+ class TableView;
+};
+
+class TableView : public QWidget {
+Q_OBJECT
+public:
+ TableView(QWidget *parent = 0);
+ virtual ~TableView();
+ void setTitle(const QString& title);
+ /* The model is expected to have a 'remove' slot, that takes a QModelIndex as parameter.
+ * It's also expected to have the column '1' as a trash icon. I most probably should create a
+ * proxy model and add that column, will mark that as TODO. see? marked.
+ */
+ void setModel(QAbstractItemModel* model);
+ void setBtnToolTip(const QString& tooltip);
+ void fixPlusPosition();
+ void edit(const QModelIndex& index);
+ QTableView *view();
+protected:
+ virtual void showEvent(QShowEvent* );
+ virtual void resizeEvent(QResizeEvent* );
+
+signals:
+ void addButtonClicked();
+
+private:
+ Ui::TableView *ui;
+ QPushButton *plusBtn;
+};
+
+#endif
diff --git a/qt-ui/tableview.ui b/qt-ui/tableview.ui
new file mode 100644
index 000000000..10b5f79f9
--- /dev/null
+++ b/qt-ui/tableview.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TableView</class>
+ <widget class="QWidget" name="TableView">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTableView" name="tableView"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>