2013-04-14 03:44:02 +00:00
|
|
|
/*
|
|
|
|
* mainwindow.cpp
|
|
|
|
*
|
|
|
|
* classes for the main UI window in Subsurface
|
|
|
|
*/
|
2013-04-07 22:20:43 +00:00
|
|
|
#include "mainwindow.h"
|
|
|
|
#include "ui_mainwindow.h"
|
|
|
|
|
|
|
|
#include <QVBoxLayout>
|
2013-04-13 13:17:59 +00:00
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QMessageBox>
|
2013-04-09 08:35:44 +00:00
|
|
|
#include <QtDebug>
|
2013-04-18 07:59:32 +00:00
|
|
|
#include <QDateTime>
|
2013-04-27 09:09:57 +00:00
|
|
|
#include <QSettings>
|
|
|
|
#include <QCloseEvent>
|
2013-05-02 21:05:53 +00:00
|
|
|
#include <QApplication>
|
|
|
|
#include <QFontMetrics>
|
2013-05-30 13:54:06 +00:00
|
|
|
#include <QTextBrowser>
|
2013-06-17 23:02:30 +00:00
|
|
|
#include <QTableView>
|
2013-04-12 07:24:07 +00:00
|
|
|
#include "divelistview.h"
|
2013-04-22 23:00:27 +00:00
|
|
|
#include "starwidget.h"
|
2013-04-12 07:24:07 +00:00
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
#include "glib.h"
|
|
|
|
#include "../dive.h"
|
|
|
|
#include "../divelist.h"
|
|
|
|
#include "../pref.h"
|
2013-05-30 21:26:08 +00:00
|
|
|
#include "../helpers.h"
|
2013-04-27 15:27:27 +00:00
|
|
|
#include "modeldelegates.h"
|
2013-05-02 23:32:57 +00:00
|
|
|
#include "models.h"
|
2013-05-20 19:43:33 +00:00
|
|
|
#include "downloadfromdivecomputer.h"
|
2013-05-24 18:19:48 +00:00
|
|
|
#include "preferences.h"
|
2013-06-06 13:33:15 +00:00
|
|
|
#include "subsurfacewebservices.h"
|
2013-06-07 14:43:45 +00:00
|
|
|
#include "divecomputermanagementdialog.h"
|
2013-06-17 16:41:00 +00:00
|
|
|
#include "simplewidgets.h"
|
2013-06-20 15:33:26 +00:00
|
|
|
#include "diveplanner.h"
|
2013-06-24 11:36:38 +00:00
|
|
|
#include "about.h"
|
2013-07-09 12:37:53 +00:00
|
|
|
#include "printdialog.h"
|
2013-04-13 13:17:59 +00:00
|
|
|
|
2013-05-19 03:09:36 +00:00
|
|
|
static MainWindow* instance = 0;
|
|
|
|
|
|
|
|
MainWindow* mainWindow()
|
|
|
|
{
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
2013-05-30 13:54:06 +00:00
|
|
|
MainWindow::MainWindow() : ui(new Ui::MainWindow()), helpView(0)
|
2013-04-07 22:20:43 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
2013-04-25 23:44:06 +00:00
|
|
|
setWindowIcon(QIcon(":subsurface-icon"));
|
2013-05-14 11:34:16 +00:00
|
|
|
connect(ui->ListWidget, SIGNAL(currentDiveChanged(int)), this, SLOT(current_dive_changed(int)));
|
2013-05-26 18:33:45 +00:00
|
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(readSettings()));
|
2013-06-06 02:22:08 +00:00
|
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ListWidget, SLOT(update()));
|
2013-06-09 23:09:39 +00:00
|
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ListWidget, SLOT(reloadHeaderActions()));
|
2013-05-26 18:33:45 +00:00
|
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ProfileWidget, SLOT(refresh()));
|
2013-05-22 06:13:45 +00:00
|
|
|
ui->mainErrorMessage->hide();
|
2013-06-06 02:22:08 +00:00
|
|
|
ui->ListWidget->reload(DiveTripModel::TREE);
|
2013-06-04 12:40:09 +00:00
|
|
|
initialUiSetup();
|
2013-05-22 01:29:23 +00:00
|
|
|
readSettings();
|
2013-05-26 17:12:45 +00:00
|
|
|
ui->ListWidget->reloadHeaderActions();
|
2013-05-14 11:34:16 +00:00
|
|
|
ui->ListWidget->setFocus();
|
2013-05-18 00:58:49 +00:00
|
|
|
ui->globe->reload();
|
2013-05-19 03:09:36 +00:00
|
|
|
instance = this;
|
2013-05-14 11:18:26 +00:00
|
|
|
}
|
|
|
|
|
2013-05-30 08:58:59 +00:00
|
|
|
// this gets called after we download dives from a divecomputer
|
|
|
|
void MainWindow::refreshDisplay()
|
|
|
|
{
|
2013-06-05 08:15:32 +00:00
|
|
|
if (selected_dive == -1)
|
2013-05-30 08:58:59 +00:00
|
|
|
current_dive_changed(dive_table.nr - 1);
|
2013-06-06 02:22:08 +00:00
|
|
|
ui->ListWidget->reload(DiveTripModel::CURRENT, false);
|
2013-05-30 08:58:59 +00:00
|
|
|
}
|
|
|
|
|
2013-05-14 11:18:26 +00:00
|
|
|
void MainWindow::current_dive_changed(int divenr)
|
|
|
|
{
|
2013-06-05 00:51:40 +00:00
|
|
|
if (divenr >= 0) {
|
2013-05-31 12:05:33 +00:00
|
|
|
select_dive(divenr);
|
|
|
|
ui->globe->centerOn(get_dive(selected_dive));
|
|
|
|
redrawProfile();
|
|
|
|
}
|
2013-05-14 11:18:26 +00:00
|
|
|
ui->InfoWidget->updateDiveInfo(divenr);
|
2013-05-02 23:32:57 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 17:45:13 +00:00
|
|
|
void MainWindow::redrawProfile()
|
|
|
|
{
|
2013-07-05 12:33:51 +00:00
|
|
|
ui->ProfileWidget->refresh();
|
2013-05-10 17:45:13 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 08:35:44 +00:00
|
|
|
void MainWindow::on_actionNew_triggered()
|
|
|
|
{
|
2013-06-26 12:07:50 +00:00
|
|
|
on_actionClose_triggered();
|
2013-04-09 08:35:44 +00:00
|
|
|
}
|
2013-04-09 16:26:23 +00:00
|
|
|
|
|
|
|
void MainWindow::on_actionOpen_triggered()
|
|
|
|
{
|
2013-06-08 03:03:58 +00:00
|
|
|
QSettings settings;
|
|
|
|
QString lastDir = QDir::homePath();
|
|
|
|
|
|
|
|
settings.beginGroup("FileDialog");
|
|
|
|
if (settings.contains("LastDir")) {
|
|
|
|
if(QDir::setCurrent(settings.value("LastDir").toString())) {
|
|
|
|
lastDir = settings.value("LastDir").toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), lastDir, filter());
|
2013-04-28 03:47:47 +00:00
|
|
|
if (filename.isEmpty())
|
2013-04-13 13:17:59 +00:00
|
|
|
return;
|
|
|
|
|
2013-06-08 03:03:58 +00:00
|
|
|
// Keep last open dir
|
|
|
|
QFileInfo fileInfo(filename);
|
|
|
|
settings.beginGroup("FileDialog");
|
|
|
|
settings.setValue("LastDir",fileInfo.dir().path());
|
|
|
|
settings.endGroup();
|
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
// Needed to convert to char*
|
|
|
|
QByteArray fileNamePtr = filename.toLocal8Bit();
|
|
|
|
|
|
|
|
on_actionClose_triggered();
|
|
|
|
|
2013-05-22 06:13:45 +00:00
|
|
|
char *error = NULL;
|
2013-04-13 13:17:59 +00:00
|
|
|
parse_file(fileNamePtr.data(), &error);
|
|
|
|
set_filename(fileNamePtr.data(), TRUE);
|
2013-06-26 12:13:06 +00:00
|
|
|
setTitle(MWTF_FILENAME);
|
2013-04-13 13:17:59 +00:00
|
|
|
|
2013-04-28 03:47:47 +00:00
|
|
|
if (error != NULL) {
|
2013-05-22 06:13:45 +00:00
|
|
|
showError(error);
|
|
|
|
free(error);
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
2013-04-28 03:47:47 +00:00
|
|
|
process_dives(FALSE, FALSE);
|
2013-04-13 13:17:59 +00:00
|
|
|
|
|
|
|
ui->InfoWidget->reload();
|
2013-05-18 00:58:49 +00:00
|
|
|
ui->globe->reload();
|
2013-06-06 02:22:08 +00:00
|
|
|
ui->ListWidget->reload(DiveTripModel::TREE);
|
2013-05-14 11:34:16 +00:00
|
|
|
ui->ListWidget->setFocus();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionSave_triggered()
|
|
|
|
{
|
2013-05-19 22:25:47 +00:00
|
|
|
file_save();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionSaveAs_triggered()
|
|
|
|
{
|
2013-05-19 22:25:47 +00:00
|
|
|
file_save_as();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
void MainWindow::on_actionClose_triggered()
|
|
|
|
{
|
2013-04-13 13:17:59 +00:00
|
|
|
if (unsaved_changes() && (askSaveChanges() == FALSE))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* free the dives and trips */
|
|
|
|
while (dive_table.nr)
|
|
|
|
delete_single_dive(0);
|
2013-04-28 03:47:47 +00:00
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
/* clear the selection and the statistics */
|
2013-05-16 18:42:20 +00:00
|
|
|
selected_dive = -1;
|
2013-04-13 13:17:59 +00:00
|
|
|
|
|
|
|
//WARNING: Port this to Qt.
|
|
|
|
//process_selected_dives();
|
|
|
|
|
|
|
|
ui->InfoWidget->clearStats();
|
|
|
|
ui->InfoWidget->clearInfo();
|
|
|
|
ui->InfoWidget->clearEquipment();
|
2013-05-20 03:46:31 +00:00
|
|
|
ui->InfoWidget->updateDiveInfo(-1);
|
2013-05-16 19:00:33 +00:00
|
|
|
ui->ProfileWidget->clear();
|
2013-06-06 02:22:08 +00:00
|
|
|
ui->ListWidget->reload(DiveTripModel::TREE);
|
2013-05-20 03:46:31 +00:00
|
|
|
ui->globe->reload();
|
2013-06-26 12:13:06 +00:00
|
|
|
setTitle(MWTF_DEFAULT);
|
2013-06-27 12:33:44 +00:00
|
|
|
mark_divelist_changed(FALSE);
|
2013-04-13 13:17:59 +00:00
|
|
|
|
|
|
|
clear_events();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionImport_triggered()
|
|
|
|
{
|
2013-06-25 10:35:04 +00:00
|
|
|
QSettings settings;
|
|
|
|
QString lastDir = QDir::homePath();
|
|
|
|
|
|
|
|
settings.beginGroup("FileDialog");
|
|
|
|
if (settings.contains("LastDir"))
|
|
|
|
if (QDir::setCurrent(settings.value("LastDir").toString()))
|
|
|
|
lastDir = settings.value("LastDir").toString();
|
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Import Files"), lastDir, filter());
|
|
|
|
if (!fileNames.size())
|
|
|
|
return; // no selection
|
|
|
|
|
|
|
|
// Keep last open dir
|
|
|
|
QFileInfo fileInfo(fileNames.at(0));
|
|
|
|
settings.beginGroup("FileDialog");
|
|
|
|
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();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionExportUDDF_triggered()
|
|
|
|
{
|
2013-04-10 06:27:38 +00:00
|
|
|
qDebug("actionExportUDDF");
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionPrint_triggered()
|
|
|
|
{
|
2013-07-09 12:37:53 +00:00
|
|
|
PrintDialog::instance()->runDialog();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
2013-07-04 15:30:05 +00:00
|
|
|
void MainWindow::disableDcShortcuts()
|
|
|
|
{
|
|
|
|
ui->actionPreviousDC->setShortcut(QKeySequence());
|
|
|
|
ui->actionNextDC->setShortcut(QKeySequence());
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::enableDcShortcuts()
|
|
|
|
{
|
|
|
|
ui->actionPreviousDC->setShortcut(Qt::Key_Left);
|
|
|
|
ui->actionNextDC->setShortcut(Qt::Key_Right);
|
|
|
|
}
|
|
|
|
|
2013-06-20 21:48:21 +00:00
|
|
|
void MainWindow::on_actionDivePlanner_triggered()
|
|
|
|
{
|
2013-07-04 15:30:05 +00:00
|
|
|
disableDcShortcuts();
|
2013-06-27 17:48:03 +00:00
|
|
|
ui->stackedWidget->setCurrentIndex(1);
|
2013-08-26 11:43:37 +00:00
|
|
|
ui->infoPane->setCurrentIndex(1);
|
2013-06-27 17:48:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::showProfile()
|
|
|
|
{
|
2013-07-04 15:30:05 +00:00
|
|
|
enableDcShortcuts();
|
2013-06-27 17:48:03 +00:00
|
|
|
ui->stackedWidget->setCurrentIndex(0);
|
2013-08-26 11:43:37 +00:00
|
|
|
ui->infoPane->setCurrentIndex(0);
|
2013-06-20 21:48:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-09 16:26:23 +00:00
|
|
|
void MainWindow::on_actionPreferences_triggered()
|
|
|
|
{
|
2013-05-24 18:19:48 +00:00
|
|
|
PreferencesDialog::instance()->show();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionQuit_triggered()
|
|
|
|
{
|
2013-04-27 09:09:57 +00:00
|
|
|
if (unsaved_changes() && (askSaveChanges() == FALSE))
|
|
|
|
return;
|
2013-05-03 23:30:36 +00:00
|
|
|
writeSettings();
|
|
|
|
QApplication::quit();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionDownloadDC_triggered()
|
|
|
|
{
|
2013-05-30 08:58:59 +00:00
|
|
|
DownloadFromDCWidget* downloadWidget = DownloadFromDCWidget::instance();
|
|
|
|
downloadWidget->runDialog();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionDownloadWeb_triggered()
|
|
|
|
{
|
2013-06-06 13:33:15 +00:00
|
|
|
SubsurfaceWebServices::instance()->runDialog();
|
|
|
|
}
|
2013-04-09 16:26:23 +00:00
|
|
|
|
|
|
|
void MainWindow::on_actionEditDeviceNames_triggered()
|
|
|
|
{
|
2013-06-17 22:58:26 +00:00
|
|
|
DiveComputerManagementDialog::instance()->init();
|
2013-06-07 14:43:45 +00:00
|
|
|
DiveComputerManagementDialog::instance()->update();
|
|
|
|
DiveComputerManagementDialog::instance()->show();
|
2013-06-10 18:34:57 +00:00
|
|
|
}
|
2013-04-09 16:26:23 +00:00
|
|
|
|
|
|
|
void MainWindow::on_actionAddDive_triggered()
|
|
|
|
{
|
2013-06-10 18:34:57 +00:00
|
|
|
struct dive *dive;
|
|
|
|
dive = alloc_dive();
|
|
|
|
record_dive(dive);
|
|
|
|
process_dives(FALSE, FALSE);
|
|
|
|
|
|
|
|
ui->InfoWidget->reload();
|
|
|
|
ui->globe->reload();
|
|
|
|
ui->ListWidget->reload(DiveTripModel::TREE);
|
|
|
|
ui->ListWidget->setFocus();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionRenumber_triggered()
|
|
|
|
{
|
2013-06-17 16:41:00 +00:00
|
|
|
RenumberDialog::instance()->show();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionAutoGroup_triggered()
|
|
|
|
{
|
2013-04-10 06:27:38 +00:00
|
|
|
qDebug("actionAutoGroup");
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionToggleZoom_triggered()
|
|
|
|
{
|
2013-04-10 06:27:38 +00:00
|
|
|
qDebug("actionToggleZoom");
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionYearlyStatistics_triggered()
|
|
|
|
{
|
2013-06-18 00:05:17 +00:00
|
|
|
QTreeView *view = new QTreeView();
|
2013-06-17 23:02:30 +00:00
|
|
|
QAbstractItemModel *model = new YearlyStatisticsModel();
|
|
|
|
view->setModel(model);
|
2013-06-19 17:59:48 +00:00
|
|
|
view->setWindowModality(Qt::NonModal);
|
|
|
|
view->setMinimumWidth(600);
|
2013-06-28 12:20:42 +00:00
|
|
|
view->setAttribute(Qt::WA_QuitOnClose, false);
|
2013-06-17 23:02:30 +00:00
|
|
|
view->show();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
2013-07-05 12:33:51 +00:00
|
|
|
void MainWindow::on_mainSplitter_splitterMoved(int pos, int idx)
|
|
|
|
{
|
|
|
|
redrawProfile();
|
|
|
|
}
|
|
|
|
|
2013-06-27 12:33:43 +00:00
|
|
|
void MainWindow::on_infoProfileSplitter_splitterMoved(int pos, int idx)
|
|
|
|
{
|
|
|
|
/* always update the floating plus sign icons in the equipment tab */
|
|
|
|
ui->InfoWidget->equipmentPlusUpdate();
|
2013-07-05 12:33:51 +00:00
|
|
|
redrawProfile();
|
2013-06-27 12:33:43 +00:00
|
|
|
}
|
|
|
|
|
2013-06-12 18:54:55 +00:00
|
|
|
/**
|
|
|
|
* So, here's the deal.
|
|
|
|
* We have a few QSplitters that takes care of helping us with the
|
|
|
|
* size of a few widgets, they are ok, and we should continue using them
|
|
|
|
* to manage the visibility of them too. But the way that we did before was to
|
|
|
|
* widget->hide(); something, and if you hided something using the splitter,
|
|
|
|
* by holding it's handle and collapsing the widget, then you used the 'ctrl+number'
|
|
|
|
* shortcut to show it, it whould only show a gray panel.
|
|
|
|
*
|
|
|
|
* This patch makes everything behave using the splitters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define BEHAVIOR QList<int>()
|
2013-04-09 16:26:23 +00:00
|
|
|
void MainWindow::on_actionViewList_triggered()
|
|
|
|
{
|
2013-06-12 18:54:55 +00:00
|
|
|
ui->listGlobeSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
|
|
|
|
ui->mainSplitter->setSizes( BEHAVIOR << COLLAPSED << EXPANDED);
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionViewProfile_triggered()
|
|
|
|
{
|
2013-06-12 18:54:55 +00:00
|
|
|
ui->infoProfileSplitter->setSizes(BEHAVIOR << COLLAPSED << EXPANDED);
|
|
|
|
ui->mainSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
|
2013-07-05 12:33:51 +00:00
|
|
|
redrawProfile();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionViewInfo_triggered()
|
|
|
|
{
|
2013-06-12 18:54:55 +00:00
|
|
|
ui->infoProfileSplitter->setSizes(BEHAVIOR << EXPANDED << COLLAPSED);
|
|
|
|
ui->mainSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
|
2013-06-12 18:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionViewGlobe_triggered()
|
|
|
|
{
|
2013-06-26 12:07:51 +00:00
|
|
|
ui->mainSplitter->setSizes(BEHAVIOR << COLLAPSED << EXPANDED);
|
|
|
|
ui->listGlobeSplitter->setSizes(BEHAVIOR << COLLAPSED << EXPANDED);
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
2013-06-12 18:54:55 +00:00
|
|
|
#undef BEHAVIOR
|
2013-04-09 16:26:23 +00:00
|
|
|
|
|
|
|
void MainWindow::on_actionViewAll_triggered()
|
|
|
|
{
|
2013-06-12 18:54:55 +00:00
|
|
|
// big number squash the info profile to it's minimum.
|
|
|
|
ui->infoProfileSplitter->setSizes(QList<int>() << 1 << 20000);
|
|
|
|
|
|
|
|
// big number squash the globe view.
|
|
|
|
ui->listGlobeSplitter->setSizes(QList<int>() << 2000 << 1 );
|
|
|
|
|
|
|
|
// half and half?
|
|
|
|
ui->mainSplitter->setSizes( QList<int>() << 1 << 1);
|
2013-07-05 12:33:51 +00:00
|
|
|
redrawProfile();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionPreviousDC_triggered()
|
|
|
|
{
|
2013-05-10 17:45:13 +00:00
|
|
|
dc_number--;
|
|
|
|
redrawProfile();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionNextDC_triggered()
|
|
|
|
{
|
2013-05-10 17:45:13 +00:00
|
|
|
dc_number++;
|
|
|
|
redrawProfile();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionSelectEvents_triggered()
|
|
|
|
{
|
2013-04-10 06:27:38 +00:00
|
|
|
qDebug("actionSelectEvents");
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionInputPlan_triggered()
|
|
|
|
{
|
2013-04-10 06:27:38 +00:00
|
|
|
qDebug("actionInputPlan");
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionAboutSubsurface_triggered()
|
|
|
|
{
|
2013-06-24 11:36:38 +00:00
|
|
|
SubsurfaceAbout::instance()->show();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::on_actionUserManual_triggered()
|
|
|
|
{
|
2013-05-30 13:54:06 +00:00
|
|
|
if(!helpView){
|
|
|
|
helpView = new QTextBrowser();
|
|
|
|
}
|
2013-05-30 21:26:08 +00:00
|
|
|
QString searchPath = getSubsurfaceDataPath("Documentation");
|
|
|
|
if (searchPath != "") {
|
|
|
|
QUrl url(searchPath.append("/user-manual.html"));
|
|
|
|
helpView->setSource(url);
|
|
|
|
} else {
|
|
|
|
helpView->setText(tr("Cannot find the Subsurface manual"));
|
|
|
|
}
|
2013-05-30 13:54:06 +00:00
|
|
|
helpView->show();
|
2013-04-09 16:26:23 +00:00
|
|
|
}
|
2013-04-13 13:17:59 +00:00
|
|
|
|
|
|
|
QString MainWindow::filter()
|
|
|
|
{
|
|
|
|
QString f;
|
|
|
|
f += "ALL ( *.xml *.XML *.uddf *.udcf *.UDFC *.jlb *.JLB ";
|
|
|
|
#ifdef LIBZIP
|
|
|
|
f += "*.sde *.SDE *.dld *.DLD ";
|
|
|
|
#endif
|
|
|
|
#ifdef SQLITE3
|
|
|
|
f += "*.db";
|
|
|
|
#endif
|
|
|
|
f += ");;";
|
|
|
|
|
|
|
|
f += "XML (*.xml *.XML);;";
|
|
|
|
f += "UDDF (*.uddf);;";
|
|
|
|
f += "UDCF (*.udcf *.UDCF);;";
|
|
|
|
f += "JLB (*.jlb *.JLB);;";
|
|
|
|
|
|
|
|
#ifdef LIBZIP
|
|
|
|
f += "SDE (*.sde *.SDE);;";
|
|
|
|
f += "DLD (*.dld *.DLD);;";
|
|
|
|
#endif
|
|
|
|
#ifdef SQLITE3
|
|
|
|
f += "DB (*.db)";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MainWindow::askSaveChanges()
|
|
|
|
{
|
2013-05-19 21:46:53 +00:00
|
|
|
QString message;
|
2013-05-24 07:28:48 +00:00
|
|
|
QMessageBox response;
|
2013-04-13 13:17:59 +00:00
|
|
|
|
2013-05-19 21:46:53 +00:00
|
|
|
if (existing_filename)
|
2013-05-24 07:28:48 +00:00
|
|
|
message = tr("Do you want to save the changes you made in the file %1?").arg(existing_filename);
|
2013-05-19 21:46:53 +00:00
|
|
|
else
|
2013-05-24 07:28:48 +00:00
|
|
|
message = tr("Do you want to save the changes you made in the datafile?");
|
|
|
|
|
|
|
|
response.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
|
|
response.setDefaultButton(QMessageBox::Save);
|
|
|
|
response.setText(message);
|
|
|
|
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);
|
|
|
|
int ret = response.exec();
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case QMessageBox::Save:
|
2013-05-19 22:25:47 +00:00
|
|
|
file_save();
|
2013-04-13 13:17:59 +00:00
|
|
|
return true;
|
2013-05-24 07:28:48 +00:00
|
|
|
case QMessageBox::Discard:
|
2013-05-19 21:46:53 +00:00
|
|
|
return true;
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-27 09:09:57 +00:00
|
|
|
|
2013-06-04 12:40:09 +00:00
|
|
|
#define GET_UNIT(name, field, f, t) \
|
|
|
|
v = s.value(QString(name)); \
|
2013-05-06 04:06:45 +00:00
|
|
|
if (v.isValid()) \
|
2013-06-04 12:40:09 +00:00
|
|
|
prefs.units.field = (v.toInt() == (t)) ? (t) : (f); \
|
|
|
|
else \
|
|
|
|
prefs.units.field = default_prefs.units.field
|
2013-05-06 04:06:45 +00:00
|
|
|
|
2013-06-04 12:40:09 +00:00
|
|
|
#define GET_BOOL(name, field) \
|
|
|
|
v = s.value(QString(name)); \
|
|
|
|
if (v.isValid()) \
|
|
|
|
prefs.field = v.toInt() ? TRUE : FALSE; \
|
2013-05-06 04:06:45 +00:00
|
|
|
else \
|
2013-06-04 12:40:09 +00:00
|
|
|
prefs.field = default_prefs.field
|
2013-05-06 04:06:45 +00:00
|
|
|
|
2013-06-04 12:40:09 +00:00
|
|
|
#define GET_DOUBLE(name, field) \
|
|
|
|
v = s.value(QString(name)); \
|
|
|
|
if (v.isValid()) \
|
|
|
|
prefs.field = v.toDouble(); \
|
|
|
|
else \
|
|
|
|
prefs.field = default_prefs.field
|
|
|
|
|
|
|
|
#define GET_INT(name, field) \
|
|
|
|
v = s.value(QString(name)); \
|
|
|
|
if (v.isValid()) \
|
|
|
|
prefs.field = v.toInt(); \
|
|
|
|
else \
|
|
|
|
prefs.field = default_prefs.field
|
|
|
|
|
|
|
|
|
|
|
|
void MainWindow::initialUiSetup()
|
2013-04-27 09:09:57 +00:00
|
|
|
{
|
2013-05-22 02:07:19 +00:00
|
|
|
QSettings settings;
|
2013-06-04 12:40:09 +00:00
|
|
|
int i;
|
2013-04-27 09:09:57 +00:00
|
|
|
|
2013-04-28 09:05:37 +00:00
|
|
|
settings.beginGroup("MainWindow");
|
|
|
|
QSize sz = settings.value("size").value<QSize>();
|
2013-04-27 09:09:57 +00:00
|
|
|
resize(sz);
|
2013-04-28 09:05:37 +00:00
|
|
|
ui->mainSplitter->restoreState(settings.value("mainSplitter").toByteArray());
|
|
|
|
ui->infoProfileSplitter->restoreState(settings.value("infoProfileSplitter").toByteArray());
|
2013-06-12 18:54:55 +00:00
|
|
|
ui->listGlobeSplitter->restoreState(settings.value("listGlobeSplitter").toByteArray());
|
2013-04-28 09:05:37 +00:00
|
|
|
settings.endGroup();
|
2013-05-03 05:06:01 +00:00
|
|
|
|
|
|
|
settings.beginGroup("ListWidget");
|
2013-05-03 18:55:22 +00:00
|
|
|
/* if no width are set, use the calculated width for each column;
|
|
|
|
* for that to work we need to temporarily expand all rows */
|
|
|
|
ui->ListWidget->expandAll();
|
2013-06-17 21:59:50 +00:00
|
|
|
for (i = DiveTripModel::NR; i < DiveTripModel::COLUMNS; i++) {
|
2013-05-03 05:06:01 +00:00
|
|
|
QVariant width = settings.value(QString("colwidth%1").arg(i));
|
|
|
|
if (width.isValid())
|
|
|
|
ui->ListWidget->setColumnWidth(i, width.toInt());
|
|
|
|
else
|
|
|
|
ui->ListWidget->resizeColumnToContents(i);
|
|
|
|
}
|
2013-05-03 18:55:22 +00:00
|
|
|
ui->ListWidget->collapseAll();
|
2013-05-22 01:29:23 +00:00
|
|
|
ui->ListWidget->expand(ui->ListWidget->model()->index(0,0));
|
2013-05-16 19:00:33 +00:00
|
|
|
ui->ListWidget->scrollTo(ui->ListWidget->model()->index(0,0), QAbstractItemView::PositionAtCenter);
|
2013-05-03 05:06:01 +00:00
|
|
|
settings.endGroup();
|
2013-06-04 12:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::readSettings()
|
|
|
|
{
|
|
|
|
QVariant v;
|
|
|
|
QSettings s;
|
|
|
|
|
|
|
|
s.beginGroup("Units");
|
|
|
|
if (s.value("unit_system").toString() == "metric") {
|
2013-06-03 12:08:49 +00:00
|
|
|
prefs.unit_system = METRIC;
|
2013-06-02 10:52:18 +00:00
|
|
|
prefs.units = SI_units;
|
2013-06-04 12:40:09 +00:00
|
|
|
} else if (s.value("unit_system").toString() == "imperial") {
|
2013-06-03 12:08:49 +00:00
|
|
|
prefs.unit_system = IMPERIAL;
|
2013-06-02 10:52:18 +00:00
|
|
|
prefs.units = IMPERIAL_units;
|
|
|
|
} else {
|
2013-06-03 12:08:49 +00:00
|
|
|
prefs.unit_system = PERSONALIZE;
|
2013-06-04 12:40:09 +00:00
|
|
|
GET_UNIT("length", length, units::FEET, units::METERS);
|
|
|
|
GET_UNIT("pressure", pressure, units::PSI, units::BAR);
|
|
|
|
GET_UNIT("volume", volume, units::CUFT, units::LITER);
|
|
|
|
GET_UNIT("temperature", temperature, units::FAHRENHEIT, units::CELSIUS);
|
|
|
|
GET_UNIT("weight", weight, units::LBS, units::KG);
|
2013-06-02 10:52:18 +00:00
|
|
|
}
|
2013-06-04 12:40:09 +00:00
|
|
|
s.endGroup();
|
|
|
|
s.beginGroup("DisplayListColumns");
|
|
|
|
GET_BOOL("CYLINDER", visible_cols.cylinder);
|
|
|
|
GET_BOOL("TEMPERATURE", visible_cols.temperature);
|
|
|
|
GET_BOOL("TOTALWEIGHT", visible_cols.totalweight);
|
|
|
|
GET_BOOL("SUIT", visible_cols.suit);
|
|
|
|
GET_BOOL("NITROX", visible_cols.nitrox);
|
|
|
|
GET_BOOL("OTU", visible_cols.otu);
|
|
|
|
GET_BOOL("MAXCNS", visible_cols.maxcns);
|
|
|
|
GET_BOOL("SAC", visible_cols.sac);
|
|
|
|
s.endGroup();
|
|
|
|
s.beginGroup("TecDetails");
|
|
|
|
GET_BOOL("po2graph", pp_graphs.po2);
|
|
|
|
GET_BOOL("pn2graph", pp_graphs.pn2);
|
|
|
|
GET_BOOL("phegraph", pp_graphs.phe);
|
|
|
|
GET_DOUBLE("po2threshold", pp_graphs.po2_threshold);
|
|
|
|
GET_DOUBLE("pn2threshold", pp_graphs.pn2_threshold);
|
|
|
|
GET_DOUBLE("phethreshold", pp_graphs.phe_threshold);
|
|
|
|
GET_BOOL("mod", mod);
|
|
|
|
GET_DOUBLE("modppO2", mod_ppO2);
|
|
|
|
GET_BOOL("ead", ead);
|
|
|
|
GET_BOOL("redceiling", profile_red_ceiling);
|
|
|
|
GET_BOOL("dcceiling", profile_dc_ceiling);
|
|
|
|
GET_BOOL("calcceiling", profile_calc_ceiling);
|
|
|
|
GET_BOOL("calcceiling3m", calc_ceiling_3m_incr);
|
|
|
|
GET_BOOL("calcalltissues", calc_all_tissues);
|
|
|
|
GET_INT("gflow", gflow);
|
|
|
|
GET_INT("gfhigh", gfhigh);
|
2013-05-06 04:06:45 +00:00
|
|
|
set_gf(prefs.gflow, prefs.gfhigh);
|
2013-06-04 12:40:09 +00:00
|
|
|
s.endGroup();
|
2013-05-06 04:06:45 +00:00
|
|
|
|
2013-06-04 12:40:09 +00:00
|
|
|
s.beginGroup("Display");
|
|
|
|
v = s.value(QString("divelist_font"));
|
2013-05-06 04:06:45 +00:00
|
|
|
if (v.isValid())
|
2013-06-04 12:40:09 +00:00
|
|
|
prefs.divelist_font = strdup(v.toString().toUtf8().data());
|
2013-04-27 09:09:57 +00:00
|
|
|
}
|
|
|
|
|
2013-05-06 04:06:45 +00:00
|
|
|
#define SAVE_VALUE(name, field) \
|
|
|
|
if (prefs.field != default_prefs.field) \
|
2013-05-28 18:21:27 +00:00
|
|
|
settings.setValue(name, prefs.field); \
|
|
|
|
else \
|
|
|
|
settings.remove(name)
|
2013-05-06 04:06:45 +00:00
|
|
|
|
2013-04-27 09:09:57 +00:00
|
|
|
void MainWindow::writeSettings()
|
|
|
|
{
|
2013-05-03 05:06:01 +00:00
|
|
|
int i;
|
2013-05-22 02:07:19 +00:00
|
|
|
QSettings settings;
|
2013-05-03 05:06:01 +00:00
|
|
|
|
2013-04-27 09:09:57 +00:00
|
|
|
settings.beginGroup("MainWindow");
|
|
|
|
settings.setValue("size",size());
|
2013-04-28 09:05:37 +00:00
|
|
|
settings.setValue("mainSplitter", ui->mainSplitter->saveState());
|
|
|
|
settings.setValue("infoProfileSplitter", ui->infoProfileSplitter->saveState());
|
2013-06-12 18:54:55 +00:00
|
|
|
settings.setValue("listGlobeSplitter", ui->listGlobeSplitter->saveState());
|
2013-04-27 09:09:57 +00:00
|
|
|
settings.endGroup();
|
2013-05-03 05:06:01 +00:00
|
|
|
|
|
|
|
settings.beginGroup("ListWidget");
|
2013-06-17 21:59:50 +00:00
|
|
|
for (i = DiveTripModel::NR; i < DiveTripModel::COLUMNS; i++)
|
2013-05-26 17:12:45 +00:00
|
|
|
if (!ui->ListWidget->isColumnHidden(i))
|
|
|
|
settings.setValue(QString("colwidth%1").arg(i), ui->ListWidget->columnWidth(i));
|
2013-05-03 05:06:01 +00:00
|
|
|
settings.endGroup();
|
2013-05-06 04:06:45 +00:00
|
|
|
settings.beginGroup("Units");
|
2013-05-26 18:33:45 +00:00
|
|
|
SAVE_VALUE("length", units.length);
|
|
|
|
SAVE_VALUE("pressure", units.pressure);
|
|
|
|
SAVE_VALUE("volume", units.volume);
|
|
|
|
SAVE_VALUE("temperature", units.temperature);
|
|
|
|
SAVE_VALUE("weight", units.weight);
|
2013-05-06 04:06:45 +00:00
|
|
|
settings.endGroup();
|
|
|
|
settings.beginGroup("DisplayListColumns");
|
|
|
|
SAVE_VALUE("TEMPERATURE", visible_cols.temperature);
|
|
|
|
SAVE_VALUE("TOTALWEIGHT", visible_cols.totalweight);
|
|
|
|
SAVE_VALUE("SUIT", visible_cols.suit);
|
|
|
|
SAVE_VALUE("CYLINDER", visible_cols.cylinder);
|
|
|
|
SAVE_VALUE("NITROX", visible_cols.nitrox);
|
|
|
|
SAVE_VALUE("SAC", visible_cols.sac);
|
|
|
|
SAVE_VALUE("OTU", visible_cols.otu);
|
|
|
|
SAVE_VALUE("MAXCNS", visible_cols.maxcns);
|
|
|
|
settings.endGroup();
|
|
|
|
settings.beginGroup("TecDetails");
|
|
|
|
SAVE_VALUE("po2graph", pp_graphs.po2);
|
|
|
|
SAVE_VALUE("pn2graph", pp_graphs.pn2);
|
|
|
|
SAVE_VALUE("phegraph", pp_graphs.phe);
|
|
|
|
SAVE_VALUE("po2threshold", pp_graphs.po2_threshold);
|
|
|
|
SAVE_VALUE("pn2threshold", pp_graphs.pn2_threshold);
|
|
|
|
SAVE_VALUE("phethreshold", pp_graphs.phe_threshold);
|
|
|
|
SAVE_VALUE("mod", mod);
|
|
|
|
SAVE_VALUE("modppO2", mod_ppO2);
|
|
|
|
SAVE_VALUE("ead", ead);
|
|
|
|
SAVE_VALUE("redceiling", profile_red_ceiling);
|
|
|
|
SAVE_VALUE("calcceiling", profile_calc_ceiling);
|
|
|
|
SAVE_VALUE("calcceiling3m", calc_ceiling_3m_incr);
|
2013-05-30 18:56:00 +00:00
|
|
|
SAVE_VALUE("calcalltissues", calc_all_tissues);
|
2013-05-29 06:32:31 +00:00
|
|
|
SAVE_VALUE("dcceiling", profile_dc_ceiling);
|
2013-05-06 04:06:45 +00:00
|
|
|
SAVE_VALUE("gflow", gflow);
|
|
|
|
SAVE_VALUE("gfhigh", gfhigh);
|
|
|
|
settings.endGroup();
|
2013-05-10 04:37:21 +00:00
|
|
|
settings.beginGroup("GeneralSettings");
|
|
|
|
SAVE_VALUE("default_filename", default_filename);
|
|
|
|
settings.endGroup();
|
2013-04-27 09:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::closeEvent(QCloseEvent *event)
|
|
|
|
{
|
2013-05-30 13:54:06 +00:00
|
|
|
if (helpView && helpView->isVisible()){
|
|
|
|
helpView->close();
|
|
|
|
helpView->deleteLater();
|
|
|
|
}
|
2013-05-30 21:26:08 +00:00
|
|
|
|
2013-04-28 03:47:47 +00:00
|
|
|
if (unsaved_changes() && (askSaveChanges() == FALSE)) {
|
2013-04-27 09:09:57 +00:00
|
|
|
event->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event->accept();
|
|
|
|
writeSettings();
|
2013-04-28 03:47:47 +00:00
|
|
|
}
|
2013-05-19 03:09:36 +00:00
|
|
|
|
|
|
|
DiveListView* MainWindow::dive_list()
|
|
|
|
{
|
|
|
|
return ui->ListWidget;
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobeGPS* MainWindow::globe()
|
|
|
|
{
|
|
|
|
return ui->globe;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProfileGraphicsView* MainWindow::graphics()
|
|
|
|
{
|
|
|
|
return ui->ProfileWidget;
|
|
|
|
}
|
|
|
|
|
|
|
|
MainTab* MainWindow::information()
|
|
|
|
{
|
|
|
|
return ui->InfoWidget;
|
|
|
|
}
|
2013-05-19 22:25:47 +00:00
|
|
|
|
|
|
|
void MainWindow::file_save_as(void)
|
|
|
|
{
|
|
|
|
QString filename;
|
|
|
|
const char *default_filename;
|
|
|
|
|
|
|
|
if (existing_filename)
|
|
|
|
default_filename = existing_filename;
|
|
|
|
else
|
|
|
|
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()) {
|
|
|
|
save_dives(filename.toUtf8().data());
|
|
|
|
set_filename(filename.toUtf8().data(), TRUE);
|
2013-06-26 12:13:06 +00:00
|
|
|
setTitle(MWTF_FILENAME);
|
2013-05-19 22:25:47 +00:00
|
|
|
mark_divelist_changed(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::file_save(void)
|
|
|
|
{
|
|
|
|
const char *current_default;
|
|
|
|
|
|
|
|
if (!existing_filename)
|
|
|
|
return file_save_as();
|
|
|
|
|
|
|
|
current_default = prefs.default_filename;
|
|
|
|
if (strcmp(existing_filename, current_default) == 0) {
|
|
|
|
/* if we are using the default filename the directory
|
|
|
|
* that we are creating the file in may not exist */
|
2013-05-20 00:18:44 +00:00
|
|
|
QDir current_def_dir = QFileInfo(current_default).absoluteDir();
|
|
|
|
if (!current_def_dir.exists())
|
|
|
|
current_def_dir.mkpath(current_def_dir.absolutePath());
|
2013-05-19 22:25:47 +00:00
|
|
|
}
|
|
|
|
save_dives(existing_filename);
|
|
|
|
mark_divelist_changed(FALSE);
|
|
|
|
}
|
2013-05-22 06:13:45 +00:00
|
|
|
|
|
|
|
void MainWindow::showError(QString message)
|
|
|
|
{
|
|
|
|
if (message.isEmpty())
|
|
|
|
return;
|
|
|
|
ui->mainErrorMessage->setText(message);
|
|
|
|
ui->mainErrorMessage->setCloseButtonVisible(true);
|
|
|
|
ui->mainErrorMessage->setMessageType(KMessageWidget::Error);
|
|
|
|
ui->mainErrorMessage->animatedShow();
|
|
|
|
}
|
2013-06-26 12:13:06 +00:00
|
|
|
|
|
|
|
void MainWindow::setTitle(enum MainWindowTitleFormat format)
|
|
|
|
{
|
|
|
|
switch (format) {
|
|
|
|
case MWTF_DEFAULT:
|
|
|
|
setWindowTitle("Subsurface");
|
|
|
|
break;
|
|
|
|
case MWTF_FILENAME:
|
|
|
|
QFile f(existing_filename);
|
|
|
|
QFileInfo fileInfo(f);
|
|
|
|
QString fileName(fileInfo.fileName());
|
|
|
|
setWindowTitle("Subsurface: " + fileName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|