diff options
Diffstat (limited to 'qt-ui')
35 files changed, 497 insertions, 168 deletions
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index ab4e301ad..d9f5eb93b 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -582,14 +582,26 @@ void DiveListView::newTripAbove() restoreSelection(); } +void DiveListView::addToTripBelow() +{ + addToTrip(true); +} + void DiveListView::addToTripAbove() { + addToTrip(false); +} + +void DiveListView::addToTrip(bool below) +{ int idx, delta = (currentOrder == Qt::AscendingOrder) ? -1 : +1; dive_trip_t *trip = NULL; struct dive *pd = NULL; struct dive *d = (struct dive *)contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<void *>(); if (!d) // shouldn't happen as we only are setting up this action if this is a dive return; + if (below) // Should we add to the trip below instead? + delta *= -1; rememberSelection(); if (d->selected) { // we are right-clicking on one of possibly many selected dive(s) // find the top selected dive, depending on the list order @@ -714,6 +726,7 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event) popup.addAction(tr("remove dive(s) from trip"), this, SLOT(removeFromTrip())); popup.addAction(tr("create new trip above"), this, SLOT(newTripAbove())); popup.addAction(tr("add dive(s) to trip immediately above"), this, SLOT(addToTripAbove())); + popup.addAction(tr("add dive(s) to trip immediately below"), this, SLOT(addToTripBelow())); } if (trip) { popup.addAction(tr("merge trip with trip above"), this, SLOT(mergeTripAbove())); diff --git a/qt-ui/divelistview.h b/qt-ui/divelistview.h index f395720bd..3079cddab 100644 --- a/qt-ui/divelistview.h +++ b/qt-ui/divelistview.h @@ -46,6 +46,7 @@ slots: void mergeTripBelow(); void newTripAbove(); void addToTripAbove(); + void addToTripBelow(); void mergeDives(); void saveSelectedDivesAs(); void exportSelectedDivesAsUDDF(); @@ -77,6 +78,7 @@ private: void updateLastUsedImageDir(const QString &s); void updateLastImageTimeOffset(int offset); int lastImageTimeOffset(); + void addToTrip(bool); }; #endif // DIVELISTVIEW_H diff --git a/qt-ui/divelogimportdialog.cpp b/qt-ui/divelogimportdialog.cpp index bff49156f..3de08b003 100644 --- a/qt-ui/divelogimportdialog.cpp +++ b/qt-ui/divelogimportdialog.cpp @@ -54,8 +54,6 @@ DiveLogImportDialog::~DiveLogImportDialog() #define VALUE_IF_CHECKED(x) (ui->x->isEnabled() ? ui->x->value() - 1 : -1) void DiveLogImportDialog::on_buttonBox_accepted() { - char *error = NULL; - if (ui->tabWidget->currentIndex() == 0) { for (int i = 0; i < fileNames.size(); ++i) { parse_csv_file(fileNames[i].toUtf8().data(), ui->CSVTime->value() - 1, @@ -65,13 +63,7 @@ void DiveLogImportDialog::on_buttonBox_accepted() VALUE_IF_CHECKED(CSVstopdepth), ui->CSVSeparator->currentIndex(), specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv", - ui->CSVUnits->currentIndex(), - &error); - if (error != NULL) { - MainWindow::instance()->showError(error); - free(error); - error = NULL; - } + ui->CSVUnits->currentIndex()); } } else { for (int i = 0; i < fileNames.size(); ++i) { @@ -84,13 +76,7 @@ void DiveLogImportDialog::on_buttonBox_accepted() VALUE_IF_CHECKED(Gps), VALUE_IF_CHECKED(MaxDepth), VALUE_IF_CHECKED(MeanDepth), VALUE_IF_CHECKED(Buddy), VALUE_IF_CHECKED(Notes), VALUE_IF_CHECKED(Weight), - VALUE_IF_CHECKED(Tags), - &error); - if (error != NULL) { - MainWindow::instance()->showError(error); - free(error); - error = NULL; - } + VALUE_IF_CHECKED(Tags)); } } process_dives(true, false); diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index ad950f262..a7d5ee7c6 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -5,7 +5,6 @@ #include "mainwindow.h" #include "maintab.h" #include "tableview.h" -#include "graphicsview-common.h" #include "../dive.h" #include "../divelist.h" @@ -1067,8 +1066,9 @@ DivePlannerWidget::DivePlannerWidget(QWidget *parent, Qt::WindowFlags f) : QWidg QTableView *view = ui.cylinderTableWidget->view(); view->setColumnHidden(CylindersModel::START, true); view->setColumnHidden(CylindersModel::END, true); - // disabled as pointless outside of the disabled planner - // view->setColumnHidden(CylindersModel::DEPTH, false); +#ifdef ENABLE_PLANNER + view->setColumnHidden(CylindersModel::DEPTH, false); +#endif view->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this)); connect(ui.cylinderTableWidget, SIGNAL(addButtonClicked()), DivePlannerPointsModel::instance(), SLOT(addCylinder_clicked())); connect(ui.tableWidget, SIGNAL(addButtonClicked()), DivePlannerPointsModel::instance(), SLOT(addStop())); @@ -1546,7 +1546,6 @@ void DivePlannerPointsModel::createTemporaryPlan() } char *cache = NULL; tempDive = NULL; - const char *errorString = NULL; struct divedatapoint *dp = NULL; for (int i = 0; i < MAX_CYLINDERS; i++) { cylinder_t *cyl = &stagingDive->cylinder[i]; @@ -1564,7 +1563,7 @@ void DivePlannerPointsModel::createTemporaryPlan() #if DEBUG_PLAN dump_plan(&diveplan); #endif - plan(&diveplan, &cache, &tempDive, isPlanner(), &errorString); + plan(&diveplan, &cache, &tempDive, isPlanner()); if (mode == ADD) { // copy the samples and events, but don't overwrite the cylinders copy_samples(tempDive, current_dive); @@ -1600,13 +1599,15 @@ void DivePlannerPointsModel::createPlan() // to not delete it later. mumble. ;p char *cache = NULL; tempDive = NULL; - const char *errorString = NULL; + + if (!diveplan.dp) + return cancelPlan(); createTemporaryPlan(); - plan(&diveplan, &cache, &tempDive, isPlanner(), &errorString); + plan(&diveplan, &cache, &tempDive, isPlanner()); copy_cylinders(stagingDive, tempDive); int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS]; - per_cylinder_mean_depth(tempDive, select_dc(&tempDive->dc), mean, duration); + per_cylinder_mean_depth(tempDive, select_dc(tempDive), mean, duration); for (int i = 0; i < MAX_CYLINDERS; i++) { cylinder_t *cyl = tempDive->cylinder + i; if (cylinder_none(cyl)) diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index 4c6743770..961e0dbe5 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -1,4 +1,5 @@ #include "globe.h" +#ifndef NO_MARBLE #include "kmessagewidget.h" #include "mainwindow.h" #include "ui_mainwindow.h" @@ -295,3 +296,12 @@ void GlobeGPS::resizeEvent(QResizeEvent *event) messageWidget->setGeometry(5, 5, size - 10, 0); messageWidget->setMaximumHeight(500); } +#else + +GlobeGPS::GlobeGPS(QWidget* parent) { setText("MARBLE DISABLED AT BUILD TIME"); } +void GlobeGPS::repopulateLabels() {} +void GlobeGPS::centerOn(dive* dive) {} +bool GlobeGPS::eventFilter(QObject *obj, QEvent *ev) {} +void GlobeGPS::prepareForGetDiveCoordinates() {} +void GlobeGPS::reload() {} +#endif diff --git a/qt-ui/globe.h b/qt-ui/globe.h index 80d9613dd..f5a1e4053 100644 --- a/qt-ui/globe.h +++ b/qt-ui/globe.h @@ -1,5 +1,6 @@ #ifndef GLOBE_H #define GLOBE_H +#ifndef NO_MARBLE #include <marble/MarbleWidget.h> #include <marble/GeoDataCoordinates.h> @@ -41,4 +42,21 @@ slots: void prepareForGetDiveCoordinates(); }; +#else // NO_MARBLE +/* Dummy widget for when we don't have MarbleWidget */ +#include <QLabel> + +class GlobeGPS : public QLabel { + Q_OBJECT +public: + GlobeGPS(QWidget *parent); + void reload(); + void repopulateLabels(); + void centerOn(struct dive* dive); + bool eventFilter(QObject*, QEvent*); +public slots: + void prepareForGetDiveCoordinates(); +}; + +#endif // NO_MARBLE #endif // GLOBE_H diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 45483f177..9ff5e9f31 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -88,8 +88,9 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), ui.cylinders->view()->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this)); ui.weights->view()->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate(this)); - // disabled as this column is pointless outside the disabled planner - // ui.cylinders->view()->setColumnHidden(CylindersModel::DEPTH, true); +#ifdef ENABLE_PLANNER + ui.cylinders->view()->setColumnHidden(CylindersModel::DEPTH, true); +#endif completers.buddy = new QCompleter(&buddyModel, ui.buddy); completers.divemaster = new QCompleter(&diveMasterModel, ui.divemaster); completers.location = new QCompleter(&locationModel, ui.location); @@ -229,11 +230,11 @@ void MainTab::displayMessage(QString str) void MainTab::updateTextLabels(bool showUnits) { if (showUnits && prefs.text_label_with_units) { - ui.airTempLabel->setText(QApplication::translate("MainTab", "Air temp [%1]").arg(get_temp_unit())); - ui.waterTempLabel->setText(QApplication::translate("MainTab", "Water temp [%1]").arg(get_temp_unit())); + ui.airTempLabel->setText(tr("Air temp [%1]").arg(get_temp_unit())); + ui.waterTempLabel->setText(tr("Water temp [%1]").arg(get_temp_unit())); } else { - ui.airTempLabel->setText(QApplication::translate("MainTab", "Air temp", 0, QApplication::UnicodeUTF8)); - ui.waterTempLabel->setText(QApplication::translate("MainTab", "Water temp", 0, QApplication::UnicodeUTF8)); + ui.airTempLabel->setText(tr("Air temp")); + ui.waterTempLabel->setText(tr("Water temp")); } } @@ -483,7 +484,7 @@ void MainTab::updateDiveInfo(int dive) get_gas_used(d, gases); QString volumes = get_volume_string(gases[0], true); int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS]; - per_cylinder_mean_depth(d, select_dc(&d->dc), mean, duration); + per_cylinder_mean_depth(d, select_dc(d), mean, duration); volume_t sac; QString SACs; if (mean[0] && duration[0]) { @@ -585,6 +586,7 @@ void MainTab::reload() void MainTab::acceptChanges() { MainWindow::instance()->dive_list()->setEnabled(true); + MainWindow::instance()->setFocus(); tabBar()->setTabIcon(0, QIcon()); // Notes tabBar()->setTabIcon(1, QIcon()); // Equipment hideMessage(); @@ -632,6 +634,7 @@ void MainTab::acceptChanges() d->cylinder[i] = multiEditEquipmentPlaceholder.cylinder[i]; } } + MainWindow::instance()->graphics()->replot(); } if (weightModel->changed) { @@ -850,27 +853,33 @@ void markChangedWidget(QWidget *w) void MainTab::on_buddy_textChanged() { - QString text = ui.buddy->toPlainText().split(",", QString::SkipEmptyParts).join(", "); + QStringList text_list = ui.buddy->toPlainText().split(",", QString::SkipEmptyParts); + for (int i = 0; i < text_list.size(); i++) + text_list[i] = text_list[i].trimmed(); + QString text = text_list.join(", "); EDIT_SELECTED_DIVES(EDIT_TEXT(mydive->buddy, text)); markChangedWidget(ui.buddy); } void MainTab::on_divemaster_textChanged() { - QString text = ui.divemaster->toPlainText().split(",", QString::SkipEmptyParts).join(", "); + QStringList text_list = ui.divemaster->toPlainText().split(",", QString::SkipEmptyParts); + for (int i = 0; i < text_list.size(); i++) + text_list[i] = text_list[i].trimmed(); + QString text = text_list.join(", "); EDIT_SELECTED_DIVES(EDIT_TEXT(mydive->divemaster, text)); markChangedWidget(ui.divemaster); } void MainTab::on_airtemp_textChanged(const QString &text) { - EDIT_SELECTED_DIVES(select_dc(&mydive->dc)->airtemp.mkelvin = parseTemperatureToMkelvin(text)); + EDIT_SELECTED_DIVES(select_dc(mydive)->airtemp.mkelvin = parseTemperatureToMkelvin(text)); markChangedWidget(ui.airtemp); } void MainTab::on_watertemp_textChanged(const QString &text) { - EDIT_SELECTED_DIVES(select_dc(&mydive->dc)->watertemp.mkelvin = parseTemperatureToMkelvin(text)); + EDIT_SELECTED_DIVES(select_dc(mydive)->watertemp.mkelvin = parseTemperatureToMkelvin(text)); markChangedWidget(ui.watertemp); } @@ -977,11 +986,15 @@ void MainTab::on_visibility_valueChanged(int value) void MainTab::editCylinderWidget(const QModelIndex &index) { - if (editMode == NONE) + if (cylindersModel->changed && editMode == NONE) { enableEdition(); - - if (index.isValid() && index.column() != CylindersModel::REMOVE) + return; + } + if (index.isValid() && index.column() != CylindersModel::REMOVE) { + if (editMode == NONE) + enableEdition(); ui.cylinders->edit(index); + } } void MainTab::editWeightWidget(const QModelIndex &index) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index a6a6c14cf..b63225295 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -23,6 +23,7 @@ #include "starwidget.h" #include "../dive.h" +#include "../display.h" #include "../divelist.h" #include "../pref.h" #include "../helpers.h" @@ -35,8 +36,14 @@ #include "simplewidgets.h" #include "diveplanner.h" #include "about.h" +#include "worldmap-save.h" +#ifndef NO_PRINTING #include "printdialog.h" +#endif #include "divelogimportdialog.h" +#ifndef NO_USERMANUAL +#include "usermanual.h" +#endif MainWindow *MainWindow::m_Instance = NULL; @@ -80,6 +87,16 @@ MainWindow::MainWindow() : QMainWindow(), #ifndef ENABLE_PLANNER // ui.menuLog->removeAction(ui.actionDivePlanner); #endif +#ifdef NO_MARBLE + ui.layoutWidget->hide(); + ui.menuView->removeAction(ui.actionViewGlobe); +#endif +#ifdef NO_USERMANUAL + ui.menuHelp->removeAction(ui.actionUserManual); +#endif +#ifdef NO_PRINTING + ui.menuFile->removeAction(ui.actionPrint); +#endif } MainWindow::~MainWindow() @@ -105,6 +122,7 @@ MainWindow *MainWindow::instance() // this gets called after we download dives from a divecomputer void MainWindow::refreshDisplay(bool recreateDiveList) { + showError(get_error_string()); ui.InfoWidget->reload(); TankInfoModel::instance()->update(); ui.globe->reload(); @@ -214,6 +232,7 @@ void MainWindow::on_actionClose_triggered() ui.newProfile->setEmptyState(); /* free the dives and trips */ + clear_git_id(); while (dive_table.nr) delete_single_dive(0); @@ -259,11 +278,22 @@ void MainWindow::on_actionExportUDDF_triggered() export_dives_uddf(filename.toUtf8(), false); } +void MainWindow::on_actionExportHTMLworldmap_triggered() +{ + QFileInfo fi(system_default_filename()); + QString filename = QFileDialog::getSaveFileName(this, tr("Export World Map"), fi.absolutePath(), + tr("HTML files (*.html)")); + if (!filename.isNull() && !filename.isEmpty()) + export_worldmap_HTML(filename.toUtf8().data()); +} + void MainWindow::on_actionPrint_triggered() { +#ifndef NO_PRINTING PrintDialog dlg(this); dlg.exec(); +#endif } void MainWindow::disableDcShortcuts() @@ -505,14 +535,16 @@ void MainWindow::saveSplitterSizes() void MainWindow::on_actionPreviousDC_triggered() { - dc_number--; + unsigned nrdc = number_of_computers(current_dive); + dc_number = (dc_number + nrdc - 1) % nrdc; ui.InfoWidget->updateDiveInfo(selected_dive); ui.newProfile->plotDives(QList<struct dive *>() << (current_dive)); } void MainWindow::on_actionNextDC_triggered() { - dc_number++; + unsigned nrdc = number_of_computers(current_dive); + dc_number = (dc_number + 1) % nrdc; ui.InfoWidget->updateDiveInfo(selected_dive); ui.newProfile->plotDives(QList<struct dive *>() << (current_dive)); } @@ -545,10 +577,12 @@ void MainWindow::on_actionAboutSubsurface_triggered() void MainWindow::on_actionUserManual_triggered() { +#ifndef NO_USERMANUAL if (!helpView) { helpView = new UserManual(); } helpView->show(); +#endif } QString MainWindow::filter() @@ -575,7 +609,7 @@ QString MainWindow::filter() bool MainWindow::askSaveChanges() { QString message; - QMessageBox response; + QMessageBox response(MainWindow::instance()); if (existing_filename) message = tr("Do you want to save the changes you made in the file %1?").arg(existing_filename); @@ -588,6 +622,7 @@ bool MainWindow::askSaveChanges() response.setWindowTitle(tr("Save Changes?")); // Not displayed on MacOSX as described in Qt API response.setInformativeText(tr("Changes will be lost if you don't save them.")); response.setIcon(QMessageBox::Warning); + response.setWindowModality(Qt::WindowModal); int ret = response.exec(); switch (ret) { @@ -639,8 +674,9 @@ void MainWindow::readSettings() { QSettings s; s.beginGroup("Display"); - QFont defaultFont = s.value("divelist_font", qApp->font()).value<QFont>(); - defaultFont.setPointSizeF(s.value("font_size", qApp->font().pointSizeF()).toFloat()); + QFont defaultFont = QFont(default_prefs.divelist_font); + defaultFont = s.value("divelist_font", defaultFont).value<QFont>(); + defaultFont.setPointSizeF(s.value("font_size", default_prefs.font_size).toFloat()); qApp->setFont(defaultFont); s.endGroup(); @@ -881,7 +917,7 @@ void MainWindow::recentFileTriggered(bool checked) loadFiles(QStringList() << filename); } -void MainWindow::file_save_as(void) +int MainWindow::file_save_as(void) { QString filename; const char *default_filename; @@ -892,20 +928,26 @@ void MainWindow::file_save_as(void) default_filename = prefs.default_filename; filename = QFileDialog::getSaveFileName(this, tr("Save File as"), default_filename, tr("Subsurface XML files (*.ssrf *.xml *.XML)")); - if (!filename.isNull() && !filename.isEmpty()) { + if (filename.isNull() || filename.isEmpty()) + return report_error("No filename to save into"); - if (ui.InfoWidget->isEditing()) - ui.InfoWidget->acceptChanges(); + if (ui.InfoWidget->isEditing()) + ui.InfoWidget->acceptChanges(); - save_dives(filename.toUtf8().data()); - set_filename(filename.toUtf8().data(), true); - setTitle(MWTF_FILENAME); - mark_divelist_changed(false); - addRecentFile(QStringList() << filename); + if (save_dives(filename.toUtf8().data())) { + showError(get_error_string()); + return -1; } + + showError(get_error_string()); + set_filename(filename.toUtf8().data(), true); + setTitle(MWTF_FILENAME); + mark_divelist_changed(false); + addRecentFile(QStringList() << filename); + return 0; } -void MainWindow::file_save(void) +int MainWindow::file_save(void) { const char *current_default; @@ -923,9 +965,14 @@ void MainWindow::file_save(void) if (!current_def_dir.exists()) current_def_dir.mkpath(current_def_dir.absolutePath()); } - save_dives(existing_filename); + if (save_dives(existing_filename)) { + showError(get_error_string()); + return -1; + } + showError(get_error_string()); mark_divelist_changed(false); addRecentFile(QStringList() << QString(existing_filename)); + return 0; } void MainWindow::showError(QString message) @@ -963,15 +1010,10 @@ void MainWindow::importFiles(const QStringList fileNames) return; QByteArray fileNamePtr; - char *error = NULL; + for (int i = 0; i < fileNames.size(); ++i) { fileNamePtr = QFile::encodeName(fileNames.at(i)); - parse_file(fileNamePtr.data(), &error); - if (error != NULL) { - showError(error); - free(error); - error = NULL; - } + parse_file(fileNamePtr.data()); } process_dives(true, false); refreshDisplay(); @@ -982,21 +1024,19 @@ void MainWindow::loadFiles(const QStringList fileNames) if (fileNames.isEmpty()) return; - char *error = NULL; QByteArray fileNamePtr; QStringList failedParses; for (int i = 0; i < fileNames.size(); ++i) { - fileNamePtr = QFile::encodeName(fileNames.at(i)); - parse_file(fileNamePtr.data(), &error); - set_filename(fileNamePtr.data(), true); - setTitle(MWTF_FILENAME); + int error; - if (error != NULL) { + fileNamePtr = QFile::encodeName(fileNames.at(i)); + error = parse_file(fileNamePtr.data()); + if (!error) { + set_filename(fileNamePtr.data(), true); + setTitle(MWTF_FILENAME); + } else { failedParses.append(fileNames.at(i)); - showError(error); - free(error); - error = NULL; } } diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 8244d0a0f..a0c5be333 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -12,7 +12,6 @@ #include <QUrl> #include "ui_mainwindow.h" -#include "usermanual.h" struct DiveList; class QSortFilterProxyModel; @@ -28,6 +27,7 @@ class GlobeGPS; class MainTab; class ProfileGraphicsView; class QWebView; +class QSettings; enum MainWindowTitleFormat { MWTF_DEFAULT, @@ -90,6 +90,7 @@ slots: void on_actionSaveAs_triggered(); void on_actionClose_triggered(); void on_actionExportUDDF_triggered(); + void on_actionExportHTMLworldmap_triggered(); void on_actionPrint_triggered(); void on_actionPreferences_triggered(); void on_actionQuit_triggered(); @@ -155,7 +156,7 @@ private: Ui::MainWindow ui; QAction *actionNextDive; QAction *actionPreviousDive; - UserManual *helpView; + QMainWindow *helpView; QTreeView *yearlyStats; QAbstractItemModel *yearlyStatsModel; CurrentState state; @@ -163,8 +164,8 @@ private: static MainWindow *m_Instance; bool askSaveChanges(); void writeSettings(); - void file_save(); - void file_save_as(); + int file_save(); + int file_save_as(); void beginChangeState(CurrentState s); void saveSplitterSizes(); QString lastUsedDir(); diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui index a933a2de9..2bf249683 100644 --- a/qt-ui/mainwindow.ui +++ b/qt-ui/mainwindow.ui @@ -551,6 +551,7 @@ <addaction name="separator"/> <addaction name="actionClose"/> <addaction name="actionExportUDDF"/> + <addaction name="actionExportHTMLworldmap"/> <addaction name="actionPrint"/> <addaction name="actionPreferences"/> <addaction name="separator"/> @@ -681,6 +682,11 @@ <string>Ctrl+U</string> </property> </action> + <action name="actionExportHTMLworldmap"> + <property name="text"> + <string>Export HTML World Map</string> + </property> + </action> <action name="actionPrint"> <property name="text"> <string>&Print</string> diff --git a/qt-ui/modeldelegates.cpp b/qt-ui/modeldelegates.cpp index 85542f0f9..7ddfb9a16 100644 --- a/qt-ui/modeldelegates.cpp +++ b/qt-ui/modeldelegates.cpp @@ -162,7 +162,10 @@ bool ComboBoxDelegate::eventFilter(QObject *object, QEvent *event) QKeyEvent *ev = static_cast<QKeyEvent *>(event); if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) { currCombo.ignoreSelection = true; - currCombo.comboEditor->showPopup(); + if (!currCombo.comboEditor->completer()->popup()->isVisible()){ + currCombo.comboEditor->showPopup(); + return true; + } } if (ev->key() == Qt::Key_Tab || ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) { currCombo.activeText = currCombo.comboEditor->currentText(); diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp index 01a3c33b3..5b011d747 100644 --- a/qt-ui/models.cpp +++ b/qt-ui/models.cpp @@ -67,7 +67,9 @@ CylindersModel::CylindersModel(QObject *parent) : current(0), rows(0) { // enum {REMOVE, TYPE, SIZE, WORKINGPRESS, START, END, O2, HE, DEPTH}; setHeaderDataStrings(QStringList() << "" << tr("Type") << tr("Size") << tr("WorkPress") << tr("StartPress") << tr("EndPress") << trUtf8("O" UTF8_SUBSCRIPT_2 "%") << tr("He%") - // while the planner is disabled, we don't need this column: << tr("Switch at") +#ifdef ENABLE_PLANNER + << tr("Switch at") +#endif ); } @@ -143,9 +145,11 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const case HE: ret = percent_string(cyl->gasmix.he); break; - // case DEPTH: - // ret = get_depth_string(cyl->depth, true); - // break; +#ifdef ENABLE_PLANNER + case DEPTH: + ret = get_depth_string(cyl->depth, true); + break; +#endif } break; case Qt::DecorationRole: @@ -258,9 +262,13 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in changed = true; } break; - // case DEPTH: - // if (CHANGED()) - // cyl->depth = string_to_depth(vString.toUtf8().data()); +#ifdef ENABLE_PLANNER + case DEPTH: + if (CHANGED()) { + cyl->depth = string_to_depth(vString.toUtf8().data()); + changed = true; + } +#endif } dataChanged(index, index); if (addDiveMode) @@ -336,7 +344,10 @@ void CylindersModel::remove(const QModelIndex &index) return; } cylinder_t *cyl = ¤t->cylinder[index.row()]; - if (DivePlannerPointsModel::instance()->tankInUse(cyl->gasmix.o2.permille, cyl->gasmix.he.permille)) { + if ((DivePlannerPointsModel::instance()->currentMode() != DivePlannerPointsModel::NOTHING && + DivePlannerPointsModel::instance()->tankInUse(cyl->gasmix.o2.permille, cyl->gasmix.he.permille)) || + (DivePlannerPointsModel::instance()->currentMode() == DivePlannerPointsModel::NOTHING && cyl->used)) + { QMessageBox::warning(MainWindow::instance(), TITLE_OR_TEXT( tr("Cylinder cannot be removed"), tr("This gas in use. Only cylinders that are not used in the dive can be removed.")), diff --git a/qt-ui/models.h b/qt-ui/models.h index 9a198f657..14969f8f4 100644 --- a/qt-ui/models.h +++ b/qt-ui/models.h @@ -102,7 +102,10 @@ public: END, O2, HE, - /* DEPTH, */ COLUMNS +#ifdef ENABLE_PLANNER + DEPTH, +#endif + COLUMNS }; explicit CylindersModel(QObject *parent = 0); diff --git a/qt-ui/preferences.cpp b/qt-ui/preferences.cpp index e2473d66b..7c74b15a6 100644 --- a/qt-ui/preferences.cpp +++ b/qt-ui/preferences.cpp @@ -88,6 +88,7 @@ void PreferencesDialog::setUiFromPrefs() } ui.displayinvalid->setChecked(prefs.display_invalid_dives); ui.display_unused_tanks->setChecked(prefs.display_unused_tanks); + ui.show_average_depth->setChecked(prefs.show_average_depth); ui.vertical_speed_minutes->setChecked(prefs.units.vertical_speed_time == units::MINUTES); ui.vertical_speed_seconds->setChecked(prefs.units.vertical_speed_time == units::SECONDS); @@ -184,6 +185,7 @@ void PreferencesDialog::syncSettings() s.setValue("gfhigh", ui.gfhigh->value()); SB("gf_low_at_maxdepth", ui.gf_low_at_maxdepth); SB("display_unused_tanks", ui.display_unused_tanks); + SB("show_average_depth", ui.show_average_depth); s.endGroup(); // Units @@ -278,6 +280,7 @@ void PreferencesDialog::loadSettings() set_gf(prefs.gflow, prefs.gfhigh, prefs.gf_low_at_maxdepth); GET_BOOL("show_sac", show_sac); GET_BOOL("display_unused_tanks", display_unused_tanks); + GET_BOOL("show_average_depth", show_average_depth); s.endGroup(); s.beginGroup("GeneralSettings"); diff --git a/qt-ui/preferences.ui b/qt-ui/preferences.ui index e0bd4c27d..06e000141 100644 --- a/qt-ui/preferences.ui +++ b/qt-ui/preferences.ui @@ -657,7 +657,18 @@ </widget> </item> </layout> - </item> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_11d"> + <item> + <widget class="QCheckBox" name="show_average_depth"> + <property name="text"> + <string>show average depth</string> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> </item> diff --git a/qt-ui/printdialog.h b/qt-ui/printdialog.h index 33cc25f03..32069a278 100644 --- a/qt-ui/printdialog.h +++ b/qt-ui/printdialog.h @@ -29,5 +29,4 @@ slots: void printClicked(); void onPaintRequested(QPrinter *); }; - #endif // PRINTDIALOG_H diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp index 4723701b7..d146ee063 100644 --- a/qt-ui/printlayout.cpp +++ b/qt-ui/printlayout.cpp @@ -131,9 +131,11 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) painter.scale(scaleX, scaleY); // setup the profile widget - ProfileWidget2 profile; - profile.setFrameStyle(QFrame::NoFrame); -// profile->setPrintMode(true, !printOptions->color_selected); + QPointer<ProfileWidget2> profile = MainWindow::instance()->graphics(); + const int profileFrameStyle = profile->frameStyle(); + profile->setFrameStyle(QFrame::NoFrame); + profile->setPrintMode(true, !printOptions->color_selected); + QSize originalSize = profile->size(); // swap rows/col for landscape if (printer->orientation() == QPrinter::Landscape) { int swap = divesPerColumn; @@ -156,7 +158,7 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) // profilePrintTableMaxH updates after the table is created const int tableH = profilePrintTableMaxH; // resize the profile widget - profile.resize(scaledW, scaledH - tableH - padPT); + profile->resize(scaledW, scaledH - tableH - padPT); // offset table or profile on top int yOffsetProfile = 0, yOffsetTable = 0; if (printOptions->notes_up) @@ -180,8 +182,8 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) // draw a profile painter.translate((scaledW + padW) * col, (scaledH + padH) * row + yOffsetProfile); - profile.plotDives( QList<struct dive*>() << dive); - profile.render(&painter, QRect(0, 0, scaledW, scaledH - tableH - padPT)); + profile->plotDives(QList<struct dive*>() << dive); + profile->render(&painter, QRect(0, 0, scaledW, scaledH - tableH - padPT)); painter.setTransform(origTransform); // draw a table @@ -193,6 +195,13 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) printed++; emit signalProgress((printed * 100) / total); } + // cleanup + painter.end(); + delete table; + profile->setFrameStyle(profileFrameStyle); + profile->setPrintMode(false); + profile->resize(originalSize); + profile->plotDives(QList<struct dive*>() << current_dive); } /* we create a table that has a fixed height, but can stretch to fit certain width */ diff --git a/qt-ui/profile/diveeventitem.cpp b/qt-ui/profile/diveeventitem.cpp index 1fd4ef07a..3f75ab10a 100644 --- a/qt-ui/profile/diveeventitem.cpp +++ b/qt-ui/profile/diveeventitem.cpp @@ -4,8 +4,12 @@ #include "animationfunctions.h" #include "libdivecomputer.h" #include "dive.h" +#include "profile.h" #include <QDebug> +extern struct ev_select *ev_namelist; +extern int evn_used; + DiveEventItem::DiveEventItem(QObject *parent) : DivePixmapItem(parent), vAxis(NULL), hAxis(NULL), @@ -105,6 +109,15 @@ void DiveEventItem::eventVisibilityChanged(const QString &eventName, bool visibl { } +bool DiveEventItem::shouldBeHidden() +{ + for (int i = 0; i < evn_used; i++) { + if (!strcmp(internalEvent->name, ev_namelist[i].ev_name) && ev_namelist[i].plot_ev == false) + return true; + } + return false; +} + void DiveEventItem::recalculatePos(bool instant) { if (!vAxis || !hAxis || !internalEvent || !dataModel) @@ -116,9 +129,8 @@ void DiveEventItem::recalculatePos(bool instant) hide(); return; } - if (!isVisible()) + if (!isVisible() && !shouldBeHidden()) show(); - int depth = dataModel->data(dataModel->index(result.first().row(), DivePlotDataModel::DEPTH)).toInt(); qreal x = hAxis->posAtValue(internalEvent->time.seconds); qreal y = vAxis->posAtValue(depth); @@ -126,4 +138,6 @@ void DiveEventItem::recalculatePos(bool instant) Animations::moveTo(this, x, y); else setPos(x, y); + if (isVisible() && shouldBeHidden()) + hide(); } diff --git a/qt-ui/profile/diveeventitem.h b/qt-ui/profile/diveeventitem.h index 1b138163c..f358fee6d 100644 --- a/qt-ui/profile/diveeventitem.h +++ b/qt-ui/profile/diveeventitem.h @@ -17,6 +17,7 @@ public: void setVerticalAxis(DiveCartesianAxis *axis); void setHorizontalAxis(DiveCartesianAxis *axis); void setModel(DivePlotDataModel *model); + bool shouldBeHidden(); public slots: void recalculatePos(bool instant = false); diff --git a/qt-ui/profile/diveplotdatamodel.cpp b/qt-ui/profile/diveplotdatamodel.cpp index 7412a7764..ad2859b9e 100644 --- a/qt-ui/profile/diveplotdatamodel.cpp +++ b/qt-ui/profile/diveplotdatamodel.cpp @@ -3,8 +3,6 @@ #include "display.h" #include "profile.h" #include "graphicsview-common.h" -#include "dive.h" -#include "display.h" #include "divelist.h" #include <QDebug> @@ -153,7 +151,7 @@ int DivePlotDataModel::id() const return diveId; } -int DivePlotDataModel::dcShown() const +unsigned int DivePlotDataModel::dcShown() const { return dcNr; } @@ -183,7 +181,7 @@ void DivePlotDataModel::calculateDecompression() struct dive *d = getDiveById(id()); if (!d) return; - struct divecomputer *dc = select_dc(&d->dc); + struct divecomputer *dc = select_dc(d); init_decompression(d); calculate_deco_information(d, dc, &pInfo, false); dataChanged(index(0, CEILING), index(pInfo.nr - 1, TISSUE_16)); diff --git a/qt-ui/profile/diveplotdatamodel.h b/qt-ui/profile/diveplotdatamodel.h index 272c0d1c3..35805256d 100644 --- a/qt-ui/profile/diveplotdatamodel.h +++ b/qt-ui/profile/diveplotdatamodel.h @@ -55,7 +55,7 @@ public: void setDive(struct dive *d, const plot_info &pInfo); const plot_info &data() const; int id() const; - int dcShown() const; + unsigned int dcShown() const; double pheMax(); double pn2Max(); double po2Max(); @@ -65,7 +65,7 @@ public: private: plot_info pInfo; int diveId; - int dcNr; + unsigned int dcNr; }; #endif // DIVEPLOTDATAMODEL_H diff --git a/qt-ui/profile/diveprofileitem.cpp b/qt-ui/profile/diveprofileitem.cpp index b84f2928d..2ffc7ec02 100644 --- a/qt-ui/profile/diveprofileitem.cpp +++ b/qt-ui/profile/diveprofileitem.cpp @@ -636,17 +636,29 @@ void PartialPressureGasItem::modelDataChanged(const QModelIndex &topLeft, const plot_data *entry = dataModel->data().entry; QPolygonF poly; - alertPoly.clear(); + QPolygonF alertpoly; + alertPolygons.clear(); QSettings s; s.beginGroup("TecDetails"); double threshould = s.value(threshouldKey).toDouble(); + bool inAlertFragment = false; for (int i = 0; i < dataModel->rowCount(); i++, entry++) { double value = dataModel->index(i, vDataColumn).data().toDouble(); int time = dataModel->index(i, hDataColumn).data().toInt(); QPointF point(hAxis->posAtValue(time), vAxis->posAtValue(value)); poly.push_back(point); - if (value >= threshould) - alertPoly.push_back(point); + if (value >= threshould) { + if (inAlertFragment) { + alertPolygons.back().push_back(point); + } else { + alertpoly.clear(); + alertpoly.push_back(point); + alertPolygons.append(alertpoly); + inAlertFragment = true; + } + } else { + inAlertFragment = false; + } } setPolygon(poly); /* @@ -656,10 +668,15 @@ void PartialPressureGasItem::modelDataChanged(const QModelIndex &topLeft, const void PartialPressureGasItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - painter->setPen(normalColor); + const qreal pWidth = 0.0; + painter->setPen(QPen(normalColor, pWidth)); painter->drawPolyline(polygon()); - painter->setPen(alertColor); - painter->drawPolyline(alertPoly); + + QPolygonF poly; + painter->setPen(QPen(alertColor, pWidth)); + Q_FOREACH(const QPolygonF & poly, alertPolygons) + painter->drawPolyline(poly); + } void PartialPressureGasItem::setThreshouldSettingsKey(const QString &threshouldSettingsKey) diff --git a/qt-ui/profile/diveprofileitem.h b/qt-ui/profile/diveprofileitem.h index ee7132c40..480776546 100644 --- a/qt-ui/profile/diveprofileitem.h +++ b/qt-ui/profile/diveprofileitem.h @@ -177,7 +177,7 @@ public: void setColors(const QColor &normalColor, const QColor &alertColor); private: - QPolygonF alertPoly; + QVector<QPolygonF> alertPolygons; QString threshouldKey; QString visibilityKey; QColor normalColor; diff --git a/qt-ui/profile/divetooltipitem.cpp b/qt-ui/profile/divetooltipitem.cpp index c11266a5a..0e68685b9 100644 --- a/qt-ui/profile/divetooltipitem.cpp +++ b/qt-ui/profile/divetooltipitem.cpp @@ -184,10 +184,9 @@ void ToolTipItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void ToolTipItem::persistPos() { - QPoint currentPos = scene()->views().at(0)->mapFromScene(pos()); QSettings s; s.beginGroup("ProfileMap"); - s.setValue("tooltip_position", currentPos); + s.setValue("tooltip_position", pos()); s.endGroup(); } @@ -195,8 +194,7 @@ void ToolTipItem::readPos() { QSettings s; s.beginGroup("ProfileMap"); - QPointF value = scene()->views().at(0)->mapToScene( - s.value("tooltip_position").toPoint()); + QPointF value = s.value("tooltip_position").toPoint(); if (!scene()->sceneRect().contains(value)) { value = QPointF(0, 0); } diff --git a/qt-ui/profile/profilewidget2.cpp b/qt-ui/profile/profilewidget2.cpp index 2cdff1cff..a58244689 100644 --- a/qt-ui/profile/profilewidget2.cpp +++ b/qt-ui/profile/profilewidget2.cpp @@ -13,6 +13,7 @@ #include "planner.h" #include "device.h" #include "ruleritem.h" +#include <libdivecomputer/parser.h> #include <QSignalTransition> #include <QPropertyAnimation> #include <QMenu> @@ -21,6 +22,7 @@ #include <QSettings> #include <QScrollBar> #include <QtCore/qmath.h> +#include <QMessageBox> #ifndef QT_NO_DEBUG #include <QTableView> @@ -81,7 +83,9 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), po2GasItem(new PartialPressureGasItem()), heartBeatAxis(new DiveCartesianAxis()), heartBeatItem(new DiveHeartrateItem()), - rulerItem(new RulerItem2()) + rulerItem(new RulerItem2()), + isGrayscale(false), + printMode(false) { memset(&plotInfo, 0, sizeof(plotInfo)); @@ -139,10 +143,11 @@ void ProfileWidget2::setupItemOnScene() profileYAxis->setOrientation(DiveCartesianAxis::TopToBottom); profileYAxis->setMinimum(0); profileYAxis->setTickInterval(M_OR_FT(10, 30)); - profileYAxis->setTickSize(1); + profileYAxis->setTickSize(0.5); profileYAxis->setLineSize(96); timeAxis->setLineSize(92); + timeAxis->setTickSize(-0.5); gasYAxis->setOrientation(DiveCartesianAxis::BottomToTop); gasYAxis->setTickInterval(1); @@ -173,7 +178,7 @@ void ProfileWidget2::setupItemOnScene() meanDepth->setAxis(profileYAxis); diveComputerText->setAlignment(Qt::AlignRight | Qt::AlignTop); - diveComputerText->setBrush(getColor(TIME_TEXT)); + diveComputerText->setBrush(getColor(TIME_TEXT, isGrayscale)); rulerItem->setAxis(timeAxis, profileYAxis); @@ -193,7 +198,7 @@ void ProfileWidget2::setupItemOnScene() setupItem(ITEM, timeAxis, gasYAxis, dataModel, DivePlotDataModel::VERTICAL_COLUMN, DivePlotDataModel::TIME, 0); \ ITEM->setThreshouldSettingsKey(THRESHOULD_SETTINGS); \ ITEM->setVisibilitySettingsKey(VISIBILITY_SETTINGS); \ - ITEM->setColors(getColor(COLOR), getColor(COLOR_ALERT)); \ + ITEM->setColors(getColor(COLOR, isGrayscale), getColor(COLOR_ALERT, isGrayscale)); \ ITEM->preferencesChanged(); \ ITEM->setZValue(99); @@ -335,13 +340,21 @@ void ProfileWidget2::plotDives(QList<dive *> dives) firstCall = false; } - // restore default zoom level and tooltip position + // restore default zoom level if (zoomLevel) { const qreal defScale = 1.0 / qPow(zoomFactor, (qreal)zoomLevel); scale(defScale, defScale); zoomLevel = 0; } - toolTipItem->setPos(0, 0); + + // reset some item visibility on printMode changes + toolTipItem->setVisible(!printMode); + QSettings s; + s.beginGroup("TecDetails"); + const bool rulerVisible = s.value("rulergraph", false).toBool() && !printMode; + rulerItem->setVisible(rulerVisible); + rulerItem->sourceNode()->setVisible(rulerVisible); + rulerItem->destNode()->setVisible(rulerVisible); // No need to do this again if we are already showing the same dive // computer of the same dive, so we check the unique id of the dive @@ -357,7 +370,7 @@ void ProfileWidget2::plotDives(QList<dive *> dives) // next get the dive computer structure - if there are no samples // let's create a fake profile that's somewhat reasonable for the // data that we have - struct divecomputer *currentdc = select_dc(&d->dc); + struct divecomputer *currentdc = select_dc(d); Q_ASSERT(currentdc); if (!currentdc || !currentdc->samples) { currentdc = fake_dc(currentdc); @@ -416,6 +429,10 @@ void ProfileWidget2::plotDives(QList<dive *> dives) cylinderPressureAxis->setMaximum(pInfo.maxpressure); rulerItem->setPlotInfo(pInfo); + if (prefs.show_average_depth) + meanDepth->setVisible(true); + else + meanDepth->setVisible(false); meanDepth->setMeanDepth(pInfo.meandepth); meanDepth->setLine(0, 0, timeAxis->posAtValue(d->duration.seconds), 0); meanDepth->animateMoveTo(3, profileYAxis->posAtValue(pInfo.meandepth)); @@ -438,10 +455,10 @@ void ProfileWidget2::plotDives(QList<dive *> dives) eventItems.push_back(item); event = event->next; } - // Only set visible the ones that should be visible, but how? + // Only set visible the events that should be visible Q_FOREACH(DiveEventItem * event, eventItems) { - event->setVisible(true); - // qDebug() << event->getEvent()->name << "@" << event->getEvent()->time.seconds; + event->setVisible(!event->shouldBeHidden()); + // qDebug() << event->getEvent()->name << "@" << event->getEvent()->time.seconds << "is hidden:" << event->isHidden(); } diveComputerText->setText(currentdc->model); if (MainWindow::instance()->filesFromCommandLine() && animSpeedBackup != -1){ @@ -474,6 +491,7 @@ void ProfileWidget2::settingsChanged() rulerItem->setVisible(rulerVisible); rulerItem->destNode()->setVisible(rulerVisible); rulerItem->sourceNode()->setVisible(rulerVisible); + replot(); } else { rulerItem->setVisible(false); rulerItem->destNode()->setVisible(false); @@ -581,6 +599,9 @@ void ProfileWidget2::setEmptyState() rulerItem->setVisible(false); rulerItem->destNode()->setVisible(false); rulerItem->sourceNode()->setVisible(false); + pn2GasItem->setVisible(false); + po2GasItem->setVisible(false); + pheGasItem->setVisible(false); Q_FOREACH(DiveCalculatedTissue * tissue, allTissues) { tissue->setVisible(false); } @@ -598,7 +619,7 @@ void ProfileWidget2::setProfileState() currentState = PROFILE; MainWindow::instance()->setToolButtonsEnabled(true); toolTipItem->readPos(); - setBackgroundBrush(getColor(::BACKGROUND)); + setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); background->setVisible(false); toolTipItem->setVisible(true); @@ -620,6 +641,9 @@ void ProfileWidget2::setProfileState() temperatureAxis->setLine(itemPos.temperature.expanded); cylinderPressureAxis->setLine(itemPos.cylinder.expanded); } + pn2GasItem->setVisible(s.value("pn2graph").toBool()); + po2GasItem->setVisible(s.value("po2graph").toBool()); + pheGasItem->setVisible(s.value("phegraph").toBool()); gasYAxis->setPos(itemPos.partialPressure.pos.on); gasYAxis->setLine(itemPos.partialPressure.expanded); @@ -673,11 +697,8 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) } QAction *action = m.addAction(tr("Add Bookmark"), this, SLOT(addBookmark())); action->setData(event->globalPos()); - QList<QGraphicsItem *> itemsAtPos = scene()->items(mapToScene(mapFromGlobal(event->globalPos()))); - Q_FOREACH(QGraphicsItem * i, itemsAtPos) { - DiveEventItem *item = dynamic_cast<DiveEventItem *>(i); - if (!item) - continue; + QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); + if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) { action = new QAction(&m); action->setText(tr("Remove Event")); action->setData(QVariant::fromValue<void *>(item)); // so we know what to remove. @@ -688,7 +709,6 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) action->setData(QVariant::fromValue<void *>(item)); connect(action, SIGNAL(triggered(bool)), this, SLOT(hideEvents())); m.addAction(action); - break; } bool some_hidden = false; for (int i = 0; i < evn_used; i++) { @@ -704,13 +724,73 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) m.exec(event->globalPos()); } +void ProfileWidget2::hideEvents() +{ + QAction *action = qobject_cast<QAction *>(sender()); + DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); + struct event *event = item->getEvent(); + + if (QMessageBox::question(MainWindow::instance(), + TITLE_OR_TEXT(tr("Hide events"), tr("Hide all %1 events?").arg(event->name)), + QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { + if (event->name) { + for (int i = 0; i < evn_used; i++) { + if (!strcmp(event->name, ev_namelist[i].ev_name)) { + ev_namelist[i].plot_ev = false; + break; + } + } + } + item->hide(); + replot(); + } +} + +void ProfileWidget2::unhideEvents() +{ + for (int i = 0; i < evn_used; i++) { + ev_namelist[i].plot_ev = true; + } + replot(); +} + +void ProfileWidget2::removeEvent() +{ + QAction *action = qobject_cast<QAction *>(sender()); + DiveEventItem *item = static_cast<DiveEventItem *>(action->data().value<void *>()); + struct event *event = item->getEvent(); + + if (QMessageBox::question(MainWindow::instance(), TITLE_OR_TEXT( + tr("Remove the selected event?"), + tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))), + QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { + struct event **ep = ¤t_dc->events; + while (ep && *ep != event) + ep = &(*ep)->next; + if (ep) { + *ep = event->next; + free(event); + } + mark_divelist_changed(true); + replot(); + } +} + +void ProfileWidget2::addBookmark() +{ + QAction *action = qobject_cast<QAction *>(sender()); + QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); + add_event(current_dc, timeAxis->valueAt(scenePos), SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"); + replot(); +} + void ProfileWidget2::changeGas() { QAction *action = qobject_cast<QAction *>(sender()); QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); QString gas = action->text(); // backup the things on the dataModel, since we will clear that out. - int diveComputer = dataModel->dcShown(); + unsigned int diveComputer = dataModel->dcShown(); int diveId = dataModel->id(); int o2, he; int seconds = timeAxis->valueAt(scenePos); @@ -724,3 +804,9 @@ void ProfileWidget2::changeGas() mark_divelist_changed(true); replot(); } + +void ProfileWidget2::setPrintMode(bool mode, bool grayscale) +{ + printMode = mode; + isGrayscale = mode ? grayscale : false; +} diff --git a/qt-ui/profile/profilewidget2.h b/qt-ui/profile/profilewidget2.h index b5339edef..eb7486e8d 100644 --- a/qt-ui/profile/profilewidget2.h +++ b/qt-ui/profile/profilewidget2.h @@ -67,6 +67,7 @@ public: void replot(); virtual bool eventFilter(QObject *, QEvent *); void setupItem(AbstractProfilePolygonItem *item, DiveCartesianAxis *hAxis, DiveCartesianAxis *vAxis, DivePlotDataModel *model, int vData, int hData, int zValue); + void setPrintMode(bool mode, bool grayscale = false); public slots: // Necessary to call from QAction's signals. @@ -74,6 +75,10 @@ slots: // Necessary to call from QAction's signals. void setEmptyState(); void setProfileState(); void changeGas(); + void addBookmark(); + void hideEvents(); + void unhideEvents(); + void removeEvent(); protected: virtual void resizeEvent(QResizeEvent *event); @@ -122,6 +127,8 @@ private: DiveCartesianAxis *heartBeatAxis; DiveHeartrateItem *heartBeatItem; RulerItem2 *rulerItem; + bool isGrayscale; + bool printMode; }; #endif // PROFILEWIDGET2_H diff --git a/qt-ui/profile/ruleritem.cpp b/qt-ui/profile/ruleritem.cpp index 627958e37..768d912e9 100644 --- a/qt-ui/profile/ruleritem.cpp +++ b/qt-ui/profile/ruleritem.cpp @@ -42,7 +42,7 @@ void RulerNodeItem2::recalculate() if (x() < 0) { setPos(0, y()); } else if (x() > timeAxis->posAtValue(data->sec)) { - setPos(timeAxis->posAtValue(data->sec), y()); + setPos(timeAxis->posAtValue(data->sec), depthAxis->posAtValue(data->depth)); } else { data = pInfo.entry; count = 0; @@ -77,6 +77,8 @@ RulerItem2::RulerItem2() : source(new RulerNodeItem2()), textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); textItemBack->setBrush(QColor(0xff, 0xff, 0xff, 190)); textItemBack->setPen(QColor(Qt::white)); + textItemBack->setFlag(QGraphicsItem::ItemIgnoresTransformations); + setPen(QPen(QColor(Qt::black), 0.0)); } void RulerItem2::recalculate() @@ -116,13 +118,13 @@ void RulerItem2::recalculate() } // always show the text bellow the lowest of the start and end points qreal tgtY = (startPoint.y() >= endPoint.y()) ? startPoint.y() : endPoint.y(); - textItem->setPos(tgtX - 1, tgtY + 4); + // this isn't exactly optimal, since we want to scale the 1.0, 4.0 distances as well + textItem->setPos(tgtX - 1.0, tgtY + 4.0); // setup the text background textItemBack->setVisible(startPoint.x() != endPoint.x()); - QPointF wh = mapFromScene(view->mapToScene(QPoint(textItem->boundingRect().width(), - textItem->boundingRect().height()))); - textItemBack->setRect(tgtX - 2, tgtY + 3, wh.x() + 2, wh.y() + 3); + textItemBack->setPos(textItem->x(), textItem->y()); + textItemBack->setRect(0, 0, textItem->boundingRect().width(), textItem->boundingRect().height()); } RulerNodeItem2 *RulerItem2::sourceNode() const diff --git a/qt-ui/shifttimes.ui b/qt-ui/shifttimes.ui index 55932a2d3..8aaa247ce 100644 --- a/qt-ui/shifttimes.ui +++ b/qt-ui/shifttimes.ui @@ -10,7 +10,7 @@ <x>0</x> <y>0</y> <width>343</width> - <height>177</height> + <height>224</height> </rect> </property> <property name="sizePolicy"> @@ -65,6 +65,38 @@ <number>9</number> </property> <item> + <layout class="QFormLayout" name="formLayout"> + <item row="2" column="0"> + <widget class="QLabel" name="shiftedTimeLabel"> + <property name="text"> + <string>Shifted time:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="currentTimeLabel"> + <property name="text"> + <string>Current time:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="currentTime"> + <property name="text"> + <string>0:0</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="shiftedTime"> + <property name="text"> + <string>0:0</string> + </property> + </widget> + </item> + </layout> + </item> + <item> <widget class="QTimeEdit" name="timeEdit"> <property name="date"> <date> @@ -166,5 +198,17 @@ </hint> </hints> </connection> + <connection> + <sender>timeEdit</sender> + <signal>timeChanged(const QTime)</signal> + <receiver>ShiftTimesDialog</receiver> + <slot>changeTime()</slot> + </connection> + <connection> + <sender>backwards</sender> + <signal>toggled(bool)</signal> + <receiver>ShiftTimesDialog</receiver> + <slot>changeTime()</slot> + </connection> </connections> </ui> diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 2ec984b7a..be3add815 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -18,6 +18,7 @@ #include "../dive.h" #include "../file.h" #include "mainwindow.h" +#include "helpers.h" class MinMaxAvgWidgetPrivate { public: @@ -155,10 +156,31 @@ void ShiftTimesDialog::buttonClicked(QAbstractButton *button) } } +void ShiftTimesDialog::showEvent(QShowEvent * event) +{ + ui.timeEdit->setTime(QTime(0, 0, 0, 0)); + when = get_times();//get time of first selected dive + ui.currentTime->setText(get_dive_date_string(when)); + ui.shiftedTime->setText(get_dive_date_string(when)); +} + +void ShiftTimesDialog::changeTime() +{ + int amount; + + amount = ui.timeEdit->time().hour() * 3600 + ui.timeEdit->time().minute() * 60; + if (ui.backwards->isChecked()) + amount *= -1; + + ui.shiftedTime->setText (get_dive_date_string(amount+when)); +} + ShiftTimesDialog::ShiftTimesDialog(QWidget *parent) : QDialog(parent) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); + connect(ui.timeEdit, SIGNAL(timeChanged(const QTime)), this, SLOT(changeTime())); + connect(ui.backwards, SIGNAL(toggled(bool)), this, SLOT(changeTime())); } void ShiftImageTimesDialog::buttonClicked(QAbstractButton *button) diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 6e4166f35..d43d2bbcc 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -6,6 +6,7 @@ class QAbstractButton; #include <QWidget> #include <QDialog> +#include <stdint.h> #include "ui_renumber.h" #include "ui_shifttimes.h" @@ -52,12 +53,15 @@ class ShiftTimesDialog : public QDialog { Q_OBJECT public: static ShiftTimesDialog *instance(); + void showEvent ( QShowEvent * event ); private slots: void buttonClicked(QAbstractButton *button); + void changeTime (); private: explicit ShiftTimesDialog(QWidget *parent); + int64_t when; Ui::ShiftTimesDialog ui; }; diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index 93b452475..707746573 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -103,11 +103,11 @@ static void clear_table(struct dive_table *table) table->nr = 0; } -bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, const bool selected, QString *errorMsg) +bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, const bool selected) { static const char errPrefix[] = "divelog.de-upload:"; if (!amount_selected) { - *errorMsg = tr("no dives were selected"); + report_error(tr("no dives were selected").toUtf8()); return false; } @@ -126,8 +126,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, if (!zip) { char buffer[1024]; zip_error_to_str(buffer, sizeof buffer, error_code, errno); - *errorMsg = tr("failed to create zip file for upload: %1") - .arg(QString::fromLocal8Bit(buffer)); + report_error(tr("failed to create zip file for upload: %s").toUtf8(), buffer); return false; } @@ -151,7 +150,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, continue; f = tmpfile(); if (!f) { - *errorMsg = tr("cannot create temporary file: %1").arg(qt_error_string()); + report_error(tr("cannot create temporary file: %s").toUtf8(), qt_error_string().toUtf8().data()); goto error_close_zip; } save_dive(f, dive); @@ -161,7 +160,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, membuf = (char *)malloc(streamsize + 1); if (!membuf || (streamsize = fread(membuf, streamsize, 1, f)) == 0) { - *errorMsg = tr("internal error: %1").arg(qt_error_string()); + report_error(tr("internal error: %s").toUtf8(), qt_error_string().toUtf8().data()); fclose(f); free((void *)membuf); goto error_close_zip; @@ -177,7 +176,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, xmlDoc *doc = xmlReadMemory(membuf, streamsize, "divelog", NULL, 0); if (!doc) { qWarning() << errPrefix << "could not parse back into memory the XML file we've just created!"; - *errorMsg = tr("internal error"); + report_error(tr("internal error").toUtf8()); free((void *)membuf); goto error_close_zip; } @@ -328,7 +327,7 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button) case QDialogButtonBox::ApplyRole: { clear_table(&gps_location_table); QByteArray url = tr("Webservice").toLocal8Bit(); - parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL, NULL); + parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL); /* now merge the data in the gps_location table into the dive_table */ if (merge_locations_into_dives()) { @@ -580,11 +579,9 @@ void DivelogsDeWebServices::downloadDives() void DivelogsDeWebServices::prepareDivesForUpload() { - QString errorText; - /* generate a random filename and create/open that file with zip_open */ QString filename = QDir::tempPath() + "/import-" + QString::number(qrand() % 99999999) + ".dld"; - if (prepare_dives_for_divelogs(filename, true, &errorText)) { + if (prepare_dives_for_divelogs(filename, true)) { QFile f(filename); if (f.open(QIODevice::ReadOnly)) { uploadDives((QIODevice *)&f); @@ -593,7 +590,7 @@ void DivelogsDeWebServices::prepareDivesForUpload() return; } } - MainWindow::instance()->showError(errorText); + MainWindow::instance()->showError(get_error_string()); } void DivelogsDeWebServices::uploadDives(QIODevice *dldContent) @@ -861,12 +858,7 @@ void DivelogsDeWebServices::buttonClicked(QAbstractButton *button) break; } /* parse file and import dives */ - char *error = NULL; - parse_file(QFile::encodeName(zipFile.fileName()), &error); - if (error != NULL) { - MainWindow::instance()->showError(error); - free(error); - } + parse_file(QFile::encodeName(zipFile.fileName())); process_dives(true, false); MainWindow::instance()->refreshDisplay(); diff --git a/qt-ui/subsurfacewebservices.h b/qt-ui/subsurfacewebservices.h index 872cf377d..175c99109 100644 --- a/qt-ui/subsurfacewebservices.h +++ b/qt-ui/subsurfacewebservices.h @@ -89,7 +89,7 @@ private: void uploadDives(QIODevice *dldContent); explicit DivelogsDeWebServices(QWidget *parent = 0, Qt::WindowFlags f = 0); void setStatusText(int status); - bool prepare_dives_for_divelogs(const QString &filename, bool selected, QString *errorMsg); + bool prepare_dives_for_divelogs(const QString &filename, bool selected); void download_dialog_traverse_xml(xmlNodePtr node, unsigned int *download_status); unsigned int download_dialog_parse_response(const QByteArray &length); diff --git a/qt-ui/tagwidget.cpp b/qt-ui/tagwidget.cpp index 6ba4a0404..fbebe3f35 100644 --- a/qt-ui/tagwidget.cpp +++ b/qt-ui/tagwidget.cpp @@ -35,7 +35,7 @@ void TagWidget::setCompleter(QCompleter *completer) m_completer = completer; m_completer->setWidget(this); connect(m_completer, SIGNAL(activated(QString)), this, SLOT(completionSelected(QString))); - connect(m_completer, SIGNAL(highlighted(QString)), this, SLOT(completionSelected(QString))); + connect(m_completer, SIGNAL(highlighted(QString)), this, SLOT(completionHighlighted(QString))); } QPair<int, int> TagWidget::getCursorTagPosition() @@ -120,8 +120,7 @@ void TagWidget::reparse() QString currentText; if (pos.first >= 0 && pos.second > 0) currentText = text().mid(pos.first, pos.second - pos.first).trimmed(); - else - currentText = ""; + if (m_completer) { m_completer->setCompletionPrefix(currentText); if (m_completer->completionCount() == 1) { @@ -138,18 +137,22 @@ void TagWidget::reparse() } } -void TagWidget::completionSelected(QString completion) +void TagWidget::completionSelected(const QString& completion) { - QPair<int, int> pos; - pos = getCursorTagPosition(); + completionHighlighted(completion); + emit textChanged(); +} + +void TagWidget::completionHighlighted(const QString& completion) +{ + QPair<int, int> pos = getCursorTagPosition(); if (pos.first >= 0 && pos.second > 0) { setText(text().remove(pos.first, pos.second - pos.first).insert(pos.first, completion)); setCursorPosition(pos.first + completion.length()); } else { - setText(completion.append(", ")); + setText(completion + QString(", ")); setCursorPosition(text().length()); } - emit(textChanged()); } void TagWidget::setCursorPosition(int position) @@ -159,7 +162,7 @@ void TagWidget::setCursorPosition(int position) blockSignals(false); } -void TagWidget::setText(QString text) +void TagWidget::setText(const QString& text) { blockSignals(true); GroupedLineEdit::setText(text); @@ -176,7 +179,19 @@ void TagWidget::clear() void TagWidget::keyPressEvent(QKeyEvent *e) { + QPair<int, int> pos; + QAbstractItemView *popup; switch (e->key()) { + case Qt::Key_Escape: + pos = getCursorTagPosition(); + if (pos.first >= 0 && pos.second > 0) { + setText(text().remove(pos.first, pos.second - pos.first)); + setCursorPosition(pos.first); + } + popup= m_completer->popup(); + if (popup) + popup->hide(); + return; case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Tab: @@ -185,12 +200,12 @@ void TagWidget::keyPressEvent(QKeyEvent *e) * closing the QAbstractViewitem */ if (m_completer) { - QAbstractItemView *popup = m_completer->popup(); + popup = m_completer->popup(); if (popup) popup->hide(); } } - if (e->key() == Qt::Key_Tab) { // let's pretend this is a comma instead + if (e->key() == Qt::Key_Tab || e->key() == Qt::Key_Return) { // let's pretend this is a comma instead QKeyEvent fakeEvent(e->type(), Qt::Key_Comma, e->modifiers(), QString(",")); GroupedLineEdit::keyPressEvent(&fakeEvent); } else { diff --git a/qt-ui/tagwidget.h b/qt-ui/tagwidget.h index 161ec0601..62fa36f30 100644 --- a/qt-ui/tagwidget.h +++ b/qt-ui/tagwidget.h @@ -12,14 +12,15 @@ public: void setCompleter(QCompleter *completer); QPair<int, int> getCursorTagPosition(); void highlight(); - void setText(QString text); + void setText(const QString& text); void clear(); void setCursorPosition(int position); void wheelEvent(QWheelEvent *event); public slots: void reparse(); - void completionSelected(QString); + void completionSelected(const QString& text); + void completionHighlighted(const QString& text); protected: void keyPressEvent(QKeyEvent *e); diff --git a/qt-ui/usermanual.h b/qt-ui/usermanual.h index 280ca3896..7692a1143 100644 --- a/qt-ui/usermanual.h +++ b/qt-ui/usermanual.h @@ -29,5 +29,4 @@ private: Ui::UserManual *ui; void search(QString, QWebPage::FindFlags); }; - #endif // USERMANUAL_H |