summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/user-manual.txt61
-rw-r--r--dive.h2
-rw-r--r--dives/TestComma.csv27
-rw-r--r--file.c8
-rw-r--r--profile.c11
-rw-r--r--profile.h2
-rw-r--r--qt-ui/csvimportdialog.cpp2
-rw-r--r--qt-ui/divelistview.cpp3
-rw-r--r--qt-ui/diveplanner.cpp18
-rw-r--r--qt-ui/diveplanner.h2
-rw-r--r--qt-ui/diveplanner.ui11
-rw-r--r--qt-ui/globe.cpp15
-rw-r--r--qt-ui/maintab.cpp59
-rw-r--r--qt-ui/mainwindow.cpp5
-rw-r--r--qt-ui/preferences.cpp18
-rw-r--r--qt-ui/preferences.h3
-rw-r--r--qt-ui/preferences.ui18
-rw-r--r--qt-ui/printdialog.cpp51
-rw-r--r--qt-ui/printdialog.h9
-rw-r--r--qt-ui/printlayout.cpp48
-rw-r--r--qt-ui/printlayout.h4
-rw-r--r--qt-ui/profilegraphics.cpp11
-rw-r--r--xslt/csv2xml.xslt8
23 files changed, 312 insertions, 84 deletions
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 193349314..0c67f1202 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -552,6 +552,7 @@ The Dive Info tab gives some summary information about a particular dive that ha
The Stats tab gives summary statistics for more than one dive, assuming that more than one dive have been selected in the *Dive List*. Select more than one dive by the standard Ctrl-click or Shift-click of the mouse. If only one dive has been selected, figures pertaining to only that dive are given. This tab shows the number of dives selected, the total amount of dive time in these dives, as well as the minimum, maximum and mean for the dive duration, dive depth, water temperature and surface air consumption (SAC).
+[[S_DiveProfile]]
=== The *Dive Profile*
image::images/Profile2.png["Typical dive profile",align="left"]
@@ -584,9 +585,10 @@ The graph can also include the dive computer reported *ceiling* (or more precise
For a more detailed explanation of _gradient factors_, use the following links:
-- link:References/GradientFactors1.html[Watts K. 2006. Gradient factors for dummies. Rebreatherworld.].
+- link:http://www.tek-dive.com/portal/upload/M-Values.pdf[Understanding M-values, by Erik Baker, _Immersed_ Vol. 3, No. 3.]
+
+- link:http://www.rebreatherworld.com/general-and-new-to-rebreather-articles/5037-gradient-factors-for-dummies.html[Gradient factors for dummies, by Kevin Watts]
-- link:References/UnderstandingM-values.pdf[Baker EC. 1998. Understanding M-values. _Immersed_ Vol. 3, No. 3.]
== Organising the logbook
@@ -669,6 +671,57 @@ In order to save the WHOLE dive log (i.e. all trips and dives), select *File* fr
In order to save only one or more dives or one or two trips, select the appropriate dives or trips in the *Dive List* panel. Then right-click the selected dives to bring up the context menu. To save in _subsurface_ XML format, select _Save as_ from the context menu. To save in UDDF format, select _Export as UDDF_ from the context menu.
+
+== Setting your *Preferences* for _subsurface_
+
+There are several settings within _subsurface_ that the user can specify. These are found when selecting _File->Preferences_. The settings are performed in three groups: *Defaults*, *Units* and *Graph*. All three sections operate on the same principles: specify the settings you wish to change, then save these using the *Apply* button. After applying the new settings one can leave the settings panel by selecting *OK*.
+
+=== Defaults
+
+There are four settings in the *Defaults* panel:
+
+ ** *Lists and tables*: Here one can specify the font type and font size of the Dive Table panel. By decreasing the font size of the Dive table,
+one can see more dives on a screen.
+
+ ** *Dives*: Here one needs to specify the directory and file name of your electronic dive log book. This is a file with filename extension .xml. _subsurface_ will then automatically load the dive log book specified.
+
+ ** *Display invalid*: [red]#??????????????????????????#
+
+ ** *Use Default cylinder*: Here one can specify the default cylinder listed in the *Equipment* tab of the *Dive Notes* panel.
+
+=== Units
+Here one can choose between metric and imperial measures of depth, pressure, volume, temperature and mass. By selecting the Metric or Imperial radio button at the top, one can specify that all units are in the chosen measurement system. Alternatively, if one selects the *Personalise* radio button, one can select a mixture with some measurements being metric while others are in imperial measures.
+
+=== Graph
+This panel allows two type of selections:
+
+* *Show*: Here one specifies the amount of information that is shown as part of the dive profile:
+** Gas pressure graphs: _subsurface_ can display the pressures of the gases with which you dive. If you dive breathing air, then the only important gas is nitrogen. You can instruct _subsurface_ to plot the nitrogen pressure during your dive. If you dive breathing nitrox, then you acn selct a graph of both the nitrogen and oxygen pressures during your dive. If you dive with trimix or heliox, you can select the display of the helium pressure as well. For each of these graphs you can specify a threshold value on the right-hand side of the panel. If any of the graphs go above this threshold level, the graph is highlighted in red, indicationg that the threshold value has been exceeded (see figure below).
+
+** Ceiling: Ascent ceilings arise when a direct ascent to the surface exposes the diver to decompression sickness (DCS) and it is necessary to either ascend slower or to perform decompression stop(s) before ascending to the surface. _subsurface_ can indicate these ceilings above which the diver should not ascend at a particular point in time (see the green-shaded areas in the figure in the section on <<S_DiveProfile,Dive Profiles>>) and in the figure below:
+
+*** If one checks *Calculted ceiling*, then a ceiling is shown if it exists for a particular dive (*A* in figure below)
+
+*** If one checks *show all tissues*, the ceiling is shown for the tissue compartments following the Bühlmann model (*B* in figure below).
+
+*** If one checks *3m increments*, then the ceiling is indicated in 3m-increments (*C* in figure below).
+
+*** If the dive computer itself calculates a ceiling and makes it available to _subsurface_ during upload of dives, this can be
+shown by checking *Dive computer reported ceiling* and it can be drawn in red by checking *Draw ceiling red*.
+
+** If a _Maximum operating depth (MOD)_ or an _Effective air depth (EAD)_ applies to a dive profile, these can be shown by checking the appropriate boxes.
+
+** If a _Maximum parial pressure of oxygen (maxPPO2)_ applies to dives, then this can be specifies in the appropriate text box. In addition, if a _no-decompression limit(NDL)_ is to be shown in the *info* box, then check the appropriate box.
+
+
+image::images/Ceilings.png["Figure: Ceiling with 3m resolution",align="center"]
+
+
+* *Misc*: Here one can set the _gradient factors_ used while diving. GF_Low is the gradient factor at deep depths and GF_High is used just below the surface. At intermediate depths gradient factor between GF_Low and GF_High are used. Gradient factors add conservatism to the nitrogen exposure during a dive, in a similar way that many dive computers have a conservatism setting. The lower the value of a gradient factor, the more conservative the calculations are with respect to nitrogen loading and the lower the ascent ceilings are. Gradient factors of 25/60 are considered conservative and values of 60/90 are considered harsh. Checking *GFLow at max depth* box causes GF_Low to be used at the deepest depth of a dive. For more information see:
+
+ ** http://www.tek-dive.com/portal/upload/M-Values.pdf[Understanding M-values by Erik Baker, , _Immersed_ Vol. 3, No. 3.]
+
+
== APPENDIX A: Operating system pecific information for importing dive information from dive computer.
=== Make sure that your OS has the required drivers installed
@@ -891,8 +944,6 @@ this, but it is reported to be solved sometimes by one of these steps:
Please add any topics you think are important:
-* Setting the preferences
-
* The Main Menu items need to be covered systematically, providing in-document links where appropriate:
* Importing GPS positions from subsurface mobile API
@@ -900,5 +951,3 @@ Please add any topics you think are important:
* Importing data from other electronic resources - Present information comes from subsurface 3.1.1 manual. How much of it is still valid? Needs to be verified.
* Importing data from dive computers - Appendices A and B come mainly from subsurface 3.1.1 manual. How much of it is still valid? Needs to be verified. Difficult work, but **critical** for the success of subsurface.
-
-* A short technical section on Gradient Factors and GFMin for the uninitiated. This should probably follow the section on dive profiles with in-document link(s) to the Preferences section where GFs are specified.
diff --git a/dive.h b/dive.h
index 7f3a55a99..0ee3a1aa6 100644
--- a/dive.h
+++ b/dive.h
@@ -626,7 +626,7 @@ extern void set_filename(const char *filename, bool force);
extern int parse_dm4_buffer(const char *url, const char *buf, int size, struct dive_table *table, char **error);
extern void parse_file(const char *filename, char **error);
-extern void parse_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int stopdepthf, char **error);
+extern void parse_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int stopdepthf, int sepidx, char **error);
extern void save_dives(const char *filename);
extern void save_dives_logic(const char *filename, bool select_only);
diff --git a/dives/TestComma.csv b/dives/TestComma.csv
new file mode 100644
index 000000000..2294a7001
--- /dev/null
+++ b/dives/TestComma.csv
@@ -0,0 +1,27 @@
+Dive Time (s),Depth (m),PPO2 - Setpoint (Bar),PPO2 - C1 Cell 1 (Bar),PPO2 - C1 Cell 2 (Bar),PPO2 - C1 Cell 3 (Bar),PPO2 - C1 Measured (Bar),PPO2 - C2 Cell 1 (Bar),PPO2 - C2 Cell 2 (Bar),PPO2 - C2 Cell 3 (Bar),PPO2 - C2 Measured (Bar),C1 Battery 1 (Volts),C1 Battery 2 (Volts),C2 Battery 1 (Volts),C2 Battery 2 (Volts),Ambient Temp. (Celcius),OTU Exposure (%),CNS Exposure (%),Deco Ceiling (m),Gradient Factor
+0,0.0,0,0,0,0,0,0,0,0,0,0,0,0,0,19.00,0,0,0,0
+60,2.5,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+120,4.5,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+180,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+240,5.5,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+300,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+360,5.5,0,0,0,0,0,0,0,0,0,0,0,0,0,17.00,0,0,0,0
+420,7.0,0,0,0,0,0,0,0,0,0,0,0,0,0,17.00,0,0,0,0
+480,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,17.00,0,0,0,0
+540,11.5,0,0,0,0,0,0,0,0,0,0,0,0,0,16.00,0,0,0,0
+600,11.5,0,0,0,0,0,0,0,0,0,0,0,0,0,16.00,0,0,0,0
+660,12.5,0,0,0,0,0,0,0,0,0,0,0,0,0,16.00,0,0,0,0
+720,13.5,0,0,0,0,0,0,0,0,0,0,0,0,0,16.00,0,0,0,0
+780,16.0,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+840,17.0,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+900,18.0,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+960,18.5,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+1020,20.0,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+1080,18.5,0,0,0,0,0,0,0,0,0,0,0,0,0,15.00,0,0,0,0
+1140,16.0,0,0,0,0,0,0,0,0,0,0,0,0,0,16.00,0,0,0,0
+1200,10.5,0,0,0,0,0,0,0,0,0,0,0,0,0,17.00,0,0,0,0
+1260,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+1320,4.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+1380,2.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+1440,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
+1460,0.0,0,0,0,0,0,0,0,0,0,0,0,0,0,18.00,0,0,0,0
diff --git a/file.c b/file.c
index 5f9b3d90a..aaf14f3d9 100644
--- a/file.c
+++ b/file.c
@@ -327,17 +327,18 @@ void parse_file(const char *filename, char **error)
#define MAXCOLDIGITS 3
#define MAXCOLS 100
-void parse_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int stopdepthf, char **error)
+void parse_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int stopdepthf, int sepidx, char **error)
{
struct memblock mem;
int pnr=0;
- char *params[17];
+ char *params[19];
char timebuf[MAXCOLDIGITS];
char depthbuf[MAXCOLDIGITS];
char tempbuf[MAXCOLDIGITS];
char po2buf[MAXCOLDIGITS];
char cnsbuf[MAXCOLDIGITS];
char stopdepthbuf[MAXCOLDIGITS];
+ char separator_index[MAXCOLDIGITS];
time_t now;
struct tm *timep;
char curdate[9];
@@ -356,6 +357,7 @@ void parse_csv_file(const char *filename, int timef, int depthf, int tempf, int
snprintf(po2buf, MAXCOLDIGITS, "%d", po2f);
snprintf(cnsbuf, MAXCOLDIGITS, "%d", cnsf);
snprintf(stopdepthbuf, MAXCOLDIGITS, "%d", stopdepthf);
+ snprintf(separator_index, MAXCOLDIGITS, "%d", sepidx);
time(&now);
timep = localtime(&now);
strftime(curdate, sizeof(curdate), "%Y%m%d", timep);
@@ -380,6 +382,8 @@ void parse_csv_file(const char *filename, int timef, int depthf, int tempf, int
params[pnr++] = curdate;
params[pnr++] = "time";
params[pnr++] = curtime;
+ params[pnr++] = "separatorIndex";
+ params[pnr++] = separator_index;
params[pnr++] = NULL;
if (filename == NULL)
diff --git a/profile.c b/profile.c
index 3493b996d..6e3019729 100644
--- a/profile.c
+++ b/profile.c
@@ -1013,7 +1013,7 @@ static void calculate_ndl_tts(double tissue_tolerance, struct plot_data *entry,
/* Let's try to do some deco calculations.
* Needs to be run before calculate_gas_information so we know that if we have a po2, where in ccr-mode.
*/
-static void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
+static void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode)
{
int i;
double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, TRUE)) / 1000.0;
@@ -1034,8 +1034,9 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
for (j=0; j<16; j++)
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
- /* should we do more calculations? */
- if (prefs.calc_ndl_tts) {
+ /* should we do more calculations?
+ * We don't for print-mode because this info doesn't show up there */
+ if (prefs.calc_ndl_tts && !print_mode) {
/* We are going to mess up deco state, so store it for later restore */
char *cache_data = NULL;
cache_deco_state(tissue_tolerance, &cache_data);
@@ -1117,7 +1118,7 @@ static void calculate_gas_information(struct dive *dive, struct plot_info *pi)
* sides, so that you can do end-points without having to worry
* about it.
*/
-struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc)
+struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc, bool print_mode)
{
struct plot_info *pi;
@@ -1147,7 +1148,7 @@ struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, s
/* Then, calculate deco information */
if (prefs.profile_calc_ceiling)
- calculate_deco_information(dive, dc, pi);
+ calculate_deco_information(dive, dc, pi, print_mode);
/* And finaly calculate gas partial pressures */
calculate_gas_information(dive, pi);
diff --git a/profile.h b/profile.h
index 563fa700d..c64ecfbf6 100644
--- a/profile.h
+++ b/profile.h
@@ -44,7 +44,7 @@ struct plot_data {
};
void calculate_max_limits(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc);
-struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc);
+struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc, bool print_mode);
int setup_temperature_limits(struct graphics_context *gc);
int get_cylinder_pressure_range(struct graphics_context *gc);
void compare_samples(struct plot_data *e1, struct plot_data *e2, char *buf, int bufsize, int sum);
diff --git a/qt-ui/csvimportdialog.cpp b/qt-ui/csvimportdialog.cpp
index 91b9ddd40..b3392f421 100644
--- a/qt-ui/csvimportdialog.cpp
+++ b/qt-ui/csvimportdialog.cpp
@@ -22,6 +22,7 @@ CSVImportDialog::CSVImportDialog(QWidget *parent) :
ui->knownImports->addItem(CSVApps[i].name);
ui->CSVSeparator->addItem("Tab");
+ ui->CSVSeparator->addItem(",");
ui->knownImports->setCurrentIndex(1);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@@ -52,6 +53,7 @@ void CSVImportDialog::on_buttonBox_accepted()
VALUE_IF_CHECKED(CSVpo2),
VALUE_IF_CHECKED(CSVcns),
VALUE_IF_CHECKED(CSVstopdepth),
+ ui->CSVSeparator->currentIndex(),
&error);
if (error != NULL) {
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp
index 27027c84b..dc1420f64 100644
--- a/qt-ui/divelistview.cpp
+++ b/qt-ui/divelistview.cpp
@@ -391,10 +391,9 @@ void DiveListView::reloadHeaderActions()
}
s.endGroup();
} else {
- // Skip first QAction item ( static text Visible )
for(int i = 0; i < model()->columnCount(); i++) {
QString title = QString("%1").arg(model()->headerData(i, Qt::Horizontal).toString());
- header()->actions()[i+1]->setText( title );
+ header()->actions()[i]->setText(title);
}
}
}
diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp
index a80ae68ae..5efb7aaed 100644
--- a/qt-ui/diveplanner.cpp
+++ b/qt-ui/diveplanner.cpp
@@ -438,7 +438,7 @@ void DivePlannerPointsModel::loadFromDive(dive* d)
// we start with the first gas and see if it was changed
int o2 = backupDive.cylinder[0].gasmix.o2.permille;
int he = backupDive.cylinder[0].gasmix.he.permille;
- for (int i = 0; i < backupDive.dc.samples; i++) {
+ for (int i = 0; i < backupDive.dc.samples - 1; i++) {
const sample &s = backupDive.dc.sample[i];
if (s.time.seconds == 0)
continue;
@@ -1176,17 +1176,17 @@ bool DivePlannerPointsModel::addGas(int o2, int he)
return false;
}
-int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint)
+int DivePlannerPointsModel::addStop(int milimeters, int seconds, int o2, int he, int ccpoint)
{
int row = divepoints.count();
- if (minutes == 0 && milimeters == 0 && row != 0){
+ if (seconds == 0 && milimeters == 0 && row != 0){
/* this is only possible if the user clicked on the 'plus' sign on the DivePoints Table */
struct divedatapoint& t = divepoints.last();
milimeters = t.depth;
- minutes = t.time + 600; // 10 minutes.
- } else if (minutes == 0 && milimeters == 0 && row == 0) {
+ seconds = t.time + 600; // 10 minutes.
+ } else if (seconds == 0 && milimeters == 0 && row == 0) {
milimeters = M_OR_FT(5, 15); // 5m / 15ft
- minutes = 600; // 10 min
+ seconds = 600; // 10 min
}
if (o2 != -1)
if (!addGas(o2, he))
@@ -1195,14 +1195,14 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he,
// check if there's already a new stop before this one:
for (int i = 0; i < row; i++) {
const divedatapoint& dp = divepoints.at(i);
- if (dp.time == minutes) {
+ if (dp.time == seconds) {
row = i;
beginRemoveRows(QModelIndex(), row, row);
divepoints.remove(row);
endRemoveRows();
break;
}
- if (dp.time > minutes ) {
+ if (dp.time > seconds ) {
row = i;
break;
}
@@ -1230,7 +1230,7 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he,
beginInsertRows(QModelIndex(), row, row);
divedatapoint point;
point.depth = milimeters;
- point.time = minutes;
+ point.time = seconds;
point.o2 = o2;
point.he = he;
point.po2 = ccpoint;
diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h
index bc6f696ad..b5c78a93c 100644
--- a/qt-ui/diveplanner.h
+++ b/qt-ui/diveplanner.h
@@ -46,7 +46,7 @@ public:
QList<QPair<int, int> > collectGases(dive *d);
public slots:
- int addStop(int meters = 0, int minutes = 0, int o2 = 0, int he = 0, int ccpoint = 0 );
+ int addStop(int millimeters = 0, int seconds = 0, int o2 = 0, int he = 0, int ccpoint = 0 );
void addCylinder_clicked();
void setGFHigh(const int gfhigh);
void setGFLow(const int ghflow);
diff --git a/qt-ui/diveplanner.ui b/qt-ui/diveplanner.ui
index 55208abb3..558be069d 100644
--- a/qt-ui/diveplanner.ui
+++ b/qt-ui/diveplanner.ui
@@ -101,25 +101,22 @@
</item>
<item row="5" column="0">
<widget class="QSpinBox" name="gflow">
- <property name="suffix">
- <string>%</string>
- </property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
- <number>100</number>
+ <number>150</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="gfhigh">
- <property name="suffix">
- <string>%</string>
- </property>
<property name="minimum">
<number>1</number>
</property>
+ <property name="maximum">
+ <number>150</number>
+ </property>
</widget>
</item>
<item row="6" column="0">
diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp
index 10ce7058b..e0f94bbd5 100644
--- a/qt-ui/globe.cpp
+++ b/qt-ui/globe.cpp
@@ -197,23 +197,21 @@ void GlobeGPS::reload()
{
editingDiveLocation = false;
if (messageWidget->isVisible())
- messageWidget->animatedHide();
+ messageWidget->hide();
repopulateLabels();
}
void GlobeGPS::centerOn(dive* dive)
{
// dive has changed, if we had the 'editingDive', hide it.
- if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive))) {
- messageWidget->animatedHide();
- }
+ if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive)))
+ messageWidget->hide();
if (!dive)
return;
-
qreal longitude = dive->longitude.udeg / 1000000.0;
qreal latitude = dive->latitude.udeg / 1000000.0;
- if (!longitude || !latitude) {
+ if (!longitude || !latitude || mainWindow()->information()->isEditing()) {
prepareForGetDiveCoordinates();
return;
}
@@ -241,7 +239,7 @@ void GlobeGPS::prepareForGetDiveCoordinates()
{
if (!messageWidget->isVisible()) {
messageWidget->setMessageType(KMessageWidget::Warning);
- messageWidget->setText(QObject::tr("No location data - move the map and double-click to set the dive location"));
+ messageWidget->setText(QObject::tr("Move the map and double-click to set the dive location"));
messageWidget->setWordWrap(true);
messageWidget->animatedShow();
editingDiveLocation = true;
@@ -250,6 +248,8 @@ void GlobeGPS::prepareForGetDiveCoordinates()
void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
{
+ messageWidget->hide();
+
if (mainWindow()->dive_list()->selectionModel()->selection().isEmpty())
return;
@@ -271,7 +271,6 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U
centerOn(lon, lat, true);
editingDiveLocation = false;
mark_divelist_changed(TRUE);
- messageWidget->animatedHide();
mainWindow()->refreshDisplay();
}
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index dad1e8ec6..81c8a0724 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -108,6 +108,27 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui.scrollArea_2->viewport()->setPalette(p);
ui.scrollArea_3->viewport()->setPalette(p);
ui.scrollArea_4->viewport()->setPalette(p);
+
+ // GroupBoxes in Gnome3 looks like I'v drawn them...
+ static const QString gnomeCss(
+ "QGroupBox {"
+ " background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
+ " stop: 0 #E0E0E0, stop: 1 #FFFFFF);"
+ " border: 2px solid gray;"
+ " border-radius: 5px;"
+ " margin-top: 1ex;"
+ "}"
+ "QGroupBox::title {"
+ " subcontrol-origin: margin;"
+ " subcontrol-position: top center;"
+ " padding: 0 3px;"
+ " background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
+ " stop: 0 #0E0E0, stop: 1 #FFFFFF);"
+ "}");
+ Q_FOREACH(QGroupBox *box, findChildren<QGroupBox*>()){
+ box->setStyleSheet(gnomeCss);
+ }
+
}
ui.cylinders->view()->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
@@ -602,11 +623,6 @@ void MainTab::acceptChanges()
else if (selected_dive == dive_table.nr - 1 && get_dive(dive_table.nr - 2)->number)
current_dive->number = get_dive(dive_table.nr - 2)->number + 1;
DivePlannerPointsModel::instance()->cancelPlan();
- // now make sure the selection logic is in a sane state
- // it's ok to hold on to the dive pointer for this short stretch of code
- // unselectDives() doesn't mess with the dive_table at all
- mainWindow()->dive_list()->unselectDives();
- mainWindow()->dive_list()->selectDive(selected_dive, true, true);
mainWindow()->showProfile();
mark_divelist_changed(TRUE);
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
@@ -614,19 +630,32 @@ void MainTab::acceptChanges()
// each dive that was selected might have had the temperatures in its active divecomputer changed
// so re-populate the temperatures - easiest way to do this is by calling fixup_dive
Q_FOREACH(dive *d, notesBackup.keys()) {
- fixup_dive(d);
+ if (d)
+ fixup_dive(d);
}
- editMode = NONE;
-
resetPallete();
- // now comes the scary moment... we need to re-sort dive table in case this dive wasn't the last
- // so now all pointers become invalid
- // fingers crossed that we aren't holding on to anything here
- mainWindow()->dive_list()->rememberSelection();
- sort_table(&dive_table);
- mainWindow()->refreshDisplay();
- mainWindow()->dive_list()->restoreSelection();
+ if(editMode == ADD || editMode == MANUALLY_ADDED_DIVE){
+ mainWindow()->dive_list()->unselectDives();
+ struct dive *d = get_dive(dive_table.nr -1 );
+ // HACK. this shouldn't be here. but apparently it's
+ // how we can know what was the newly added dive.
+ d->selected = true;
+ sort_table(&dive_table);
+ int i = 0;
+ for_each_dive(i,d){
+ if (d->selected) break;
+ }
+ editMode = NONE;
+ mainWindow()->refreshDisplay();
+ mainWindow()->dive_list()->selectDive( i, true );
+ }else{
+ editMode = NONE;
+ mainWindow()->dive_list()->rememberSelection();
+ sort_table(&dive_table);
+ mainWindow()->refreshDisplay();
+ mainWindow()->dive_list()->restoreSelection();
+ }
}
void MainTab::resetPallete()
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp
index b216240fa..e049179e8 100644
--- a/qt-ui/mainwindow.cpp
+++ b/qt-ui/mainwindow.cpp
@@ -295,6 +295,9 @@ void MainWindow::on_actionAddDive_triggered()
struct dive *dive = alloc_dive();
dive->when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset();
dive->dc.model = "manually added dive"; // don't translate! this is stored in the XML file
+
+ dive->latitude.udeg = 0;
+ dive->longitude.udeg = 0;
record_dive(dive);
// this isn't in the UI yet, so let's call the C helper function - we'll fix this up when
// accepting the dive
@@ -306,7 +309,7 @@ void MainWindow::on_actionAddDive_triggered()
ui.infoPane->setCurrentIndex(MAINTAB);
DivePlannerPointsModel::instance()->clear();
DivePlannerPointsModel::instance()->createSimpleDive();
- refreshDisplay();
+ ui.ListWidget->reload(DiveTripModel::CURRENT);
}
void MainWindow::on_actionRenumber_triggered()
diff --git a/qt-ui/preferences.cpp b/qt-ui/preferences.cpp
index 5a1a2a5e2..f8b24da42 100644
--- a/qt-ui/preferences.cpp
+++ b/qt-ui/preferences.cpp
@@ -15,10 +15,28 @@ PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags f) : QDial
{
ui.setupUi(this);
connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*)));
+ connect(ui.gflow, SIGNAL(valueChanged(int)), this, SLOT(gflowChanged(int)));
+ connect(ui.gfhigh, SIGNAL(valueChanged(int)), this, SLOT(gfhighChanged(int)));
setUiFromPrefs();
rememberPrefs();
}
+void PreferencesDialog::gflowChanged(int gf)
+{
+ if (gf > 100)
+ ui.gflow->setStyleSheet("* { color: red; }");
+ else
+ ui.gflow->setStyleSheet("");
+}
+
+void PreferencesDialog::gfhighChanged(int gf)
+{
+ if (gf > 100)
+ ui.gfhigh->setStyleSheet("* { color: red; }");
+ else
+ ui.gfhigh->setStyleSheet("");
+}
+
void PreferencesDialog::showEvent(QShowEvent *event)
{
setUiFromPrefs();
diff --git a/qt-ui/preferences.h b/qt-ui/preferences.h
index fb0fcbc94..dbc17cb9f 100644
--- a/qt-ui/preferences.h
+++ b/qt-ui/preferences.h
@@ -22,6 +22,9 @@ public slots:
void syncSettings();
void restorePrefs();
void rememberPrefs();
+ void gflowChanged(int gf);
+ void gfhighChanged(int gf);
+
private:
explicit PreferencesDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
diff --git a/qt-ui/preferences.ui b/qt-ui/preferences.ui
index e80cc8493..7b6f3e596 100644
--- a/qt-ui/preferences.ui
+++ b/qt-ui/preferences.ui
@@ -779,7 +779,14 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="QSpinBox" name="gflow"/>
+ <widget class="QSpinBox" name="gflow">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>150</number>
+ </property>
+ </widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_20">
@@ -789,7 +796,14 @@
</widget>
</item>
<item row="1" column="1">
- <widget class="QSpinBox" name="gfhigh"/>
+ <widget class="QSpinBox" name="gfhigh">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>150</number>
+ </property>
+ </widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="gf_low_at_maxdepth">
diff --git a/qt-ui/printdialog.cpp b/qt-ui/printdialog.cpp
index 8bf602c34..e029ff09b 100644
--- a/qt-ui/printdialog.cpp
+++ b/qt-ui/printdialog.cpp
@@ -1,10 +1,15 @@
#include "printdialog.h"
+#include "printoptions.h"
+#include "printlayout.h"
#include "mainwindow.h"
#include <QDebug>
#include <QPushButton>
+#include <QProgressBar>
#include <QVBoxLayout>
+#include <QHBoxLayout>
#include <QPrintPreviewDialog>
+#include <QPrintDialog>
PrintDialog *PrintDialog::instance()
{
@@ -22,34 +27,64 @@ PrintDialog::PrintDialog(QWidget *parent, Qt::WindowFlags f)
// create a print layout and pass the printer and options
printLayout = new PrintLayout(this, &printer, &printOptions);
- /* temporary.
- * add the PrintOptions widget and a Print button for testing purposes. */
+ // create a print options object and pass our options struct
optionsWidget = new PrintOptions(this, &printOptions);
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
- QPushButton *printButton = new QPushButton(tr("&Print"));
+ QHBoxLayout *hLayout = new QHBoxLayout();
+ layout->addLayout(hLayout);
+
+ QPushButton *previewButton = new QPushButton(tr("&Preview"));
+ connect(previewButton, SIGNAL(clicked(bool)), this, SLOT(previewClicked()));
+ hLayout->addWidget(previewButton);
+
+ QPushButton *printButton = new QPushButton(tr("P&rint"));
connect(printButton, SIGNAL(clicked(bool)), this, SLOT(printClicked()));
- layout->addWidget(printButton);
+ hLayout->addWidget(printButton);
+
+ QPushButton *closeButton = new QPushButton(tr("&Close"));
+ connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(closeClicked()));
+ hLayout->addWidget(closeButton);
+
+ progressBar = new QProgressBar();
+ connect(printLayout, SIGNAL(signalProgress(int)), progressBar, SLOT(setValue(int)));
+ progressBar->setMinimum(0);
+ progressBar->setMaximum(100);
+ progressBar->setTextVisible(false);
+ layout->addWidget(progressBar);
layout->addWidget(optionsWidget);
- setFixedSize(520, 320);
+ setFixedSize(520, 350);
setWindowTitle(tr("Print"));
setWindowIcon(QIcon(":subsurface-icon"));
}
void PrintDialog::runDialog()
{
+ progressBar->setValue(0);
exec();
}
-void PrintDialog::printClicked(void)
+void PrintDialog::previewClicked(void)
{
QPrintPreviewDialog previewDialog(&printer, this);
- QObject::connect(&previewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(onPaintRequested(QPrinter *)));
- previewDialog.exec();
+ QObject::connect(&previewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(onPaintRequested(QPrinter *)));
+ previewDialog.exec();
+}
+
+void PrintDialog::printClicked(void)
+{
+ QPrintDialog printDialog(&printer, this);
+ if (printDialog.exec() == QDialog::Accepted)
+ printLayout->print();
+}
+
+void PrintDialog::closeClicked(void)
+{
+ close();
}
void PrintDialog::onPaintRequested(QPrinter *printerPtr)
diff --git a/qt-ui/printdialog.h b/qt-ui/printdialog.h
index 097de9531..44bb94669 100644
--- a/qt-ui/printdialog.h
+++ b/qt-ui/printdialog.h
@@ -4,8 +4,10 @@
#include <QDialog>
#include <QPrinter>
#include "../display.h"
-#include "printoptions.h"
-#include "printlayout.h"
+
+class QProgressBar;
+class PrintOptions;
+class PrintLayout;
// should be based on a custom QPrintDialog class
class PrintDialog : public QDialog {
@@ -20,10 +22,13 @@ private:
explicit PrintDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
PrintOptions *optionsWidget;
PrintLayout *printLayout;
+ QProgressBar *progressBar;
QPrinter printer;
private slots:
+ void previewClicked();
void printClicked();
+ void closeClicked();
void onPaintRequested(QPrinter *);
};
diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp
index afc6dd036..556bf139b 100644
--- a/qt-ui/printlayout.cpp
+++ b/qt-ui/printlayout.cpp
@@ -7,9 +7,10 @@
#include <QHeaderView>
#include "mainwindow.h"
#include "profilegraphics.h"
-#include "printlayout.h"
#include "../dive.h"
#include "../display.h"
+#include "printdialog.h"
+#include "printlayout.h"
#include "models.h"
#include "modeldelegates.h"
@@ -91,6 +92,19 @@ void PrintLayout::setup()
scaledPageH = pageRect.height() / scaleY;
}
+// go trought the dive table and find how many dives we are a going to print
+int PrintLayout::estimateTotalDives() const
+{
+ int total = 0, i = 0;
+ struct dive *dive;
+ for_each_dive(i, dive) {
+ if (!dive->selected && printOptions->print_selected)
+ continue;
+ total++;
+ }
+ return total;
+}
+
/* the used formula here is:
* s = (S - (n - 1) * p) / n
* where:
@@ -104,6 +118,11 @@ void PrintLayout::setup()
void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn)
{
+ int i, row = 0, col = 0, printed = 0, total = estimateTotalDives();
+ struct dive *dive;
+ if (!total)
+ return;
+
// setup a painter
QPainter painter;
painter.begin(printer);
@@ -148,8 +167,6 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn)
yOffsetTable = scaledH - tableH;
// plot the dives at specific rows and columns on the page
- int i, row = 0, col = 0;
- struct dive *dive;
for_each_dive(i, dive) {
if (!dive->selected && printOptions->print_selected)
continue;
@@ -175,6 +192,8 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn)
table->render(&painter);
painter.setTransform(origTransform);
col++;
+ printed++;
+ emit signalProgress((printed * 100) / total);
}
// cleanup
@@ -253,6 +272,12 @@ QTableView *PrintLayout::createProfileTable(ProfilePrintModel *model, const int
void PrintLayout::printTable()
{
+ struct dive *dive;
+ const int stage = 33; // there are 3 stages in this routine: 100% / 3 ~= 33%
+ int i, row = 0, progress, total = estimateTotalDives();
+ if (!total)
+ return;
+
// create and setup a table
QTableView table;
table.setAttribute(Qt::WA_DontShowOnScreen);
@@ -274,15 +299,16 @@ void PrintLayout::printTable()
// create and fill a table model
TablePrintModel model;
- struct dive *dive;
- int i, row = 0;
addTablePrintHeadingRow(&model, row); // add one heading row
row++;
+ progress = 0;
for_each_dive(i, dive) {
if (!dive->selected && printOptions->print_selected)
continue;
addTablePrintDataRow(&model, row, dive);
row++;
+ progress++;
+ emit signalProgress((progress * stage) / total);
}
table.setModel(&model); // set model to table
// resize columns to percentages from page width
@@ -305,7 +331,9 @@ void PrintLayout::printTable()
int tableHeight = 0, rowH = 0, accH = 0;
// process all rows
- for (int i = 0; i < model.rows; i++) {
+ progress = 0;
+ total = model.rows;
+ for (int i = 0; i < total; i++) {
rowH = table.rowHeight(i);
accH += rowH;
if (accH > scaledPageH) { // push a new page index and add a heading
@@ -315,6 +343,8 @@ void PrintLayout::printTable()
i--;
}
tableHeight += rowH;
+ progress++;
+ emit signalProgress(stage + (progress * stage) / total);
}
pageIndexes.append(pageIndexes.last() + accH);
// resize the whole widget so that it can be rendered
@@ -325,13 +355,17 @@ void PrintLayout::printTable()
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.scale(scaleX, scaleY);
- for (int i = 0; i < pageIndexes.size() - 1; i++) {
+ total = pageIndexes.size() - 1;
+ progress = 0;
+ for (int i = 0; i < total; i++) {
if (i > 0)
printer->newPage();
QRegion region(0, pageIndexes.at(i) - 1,
table.width(),
pageIndexes.at(i + 1) - pageIndexes.at(i) + 1);
table.render(&painter, QPoint(0, 0), region);
+ progress++;
+ emit signalProgress((stage << 1) + (progress * (stage + 1)) / total);
}
}
diff --git a/qt-ui/printlayout.h b/qt-ui/printlayout.h
index 1ed19e271..077d7ac14 100644
--- a/qt-ui/printlayout.h
+++ b/qt-ui/printlayout.h
@@ -34,11 +34,15 @@ private:
QList<unsigned int> profilePrintColumnWidths, profilePrintRowHeights;
void setup();
+ int estimateTotalDives() const;
void printProfileDives(int divesPerRow, int divesPerColumn);
QTableView *createProfileTable(ProfilePrintModel *model, const int tableW);
void printTable();
void addTablePrintDataRow(TablePrintModel *model, int row, struct dive *dive) const;
void addTablePrintHeadingRow(TablePrintModel *model, int row) const;
+
+signals:
+ void signalProgress(int);
};
#endif
diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp
index 0d38a89f9..00eb9edbe 100644
--- a/qt-ui/profilegraphics.cpp
+++ b/qt-ui/profilegraphics.cpp
@@ -403,7 +403,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
gc.maxy = (profile_grid_area.height() - 2 * profile_grid_area.y());
/* This is per-dive-computer */
- gc.pi = *create_plot_info(dive, dc, &gc);
+ gc.pi = *create_plot_info(dive, dc, &gc, printMode);
/* Bounding box */
QPen pen = defaultPen;
@@ -540,16 +540,16 @@ void ProfileGraphicsView::plot_pp_text()
{
double pp, dpp, m;
int hpos;
- static text_render_options_t tro = {PP_TEXT_SIZE, PP_LINES, LEFT, MIDDLE};
+ static text_render_options_t tro = {PP_TEXT_SIZE, PP_LINES, LEFT, -0.75};
QGraphicsRectItem *pressureMarkers = new QGraphicsRectItem();
setup_pp_limits(&gc);
pp = floor(gc.pi.maxpp * 10.0) / 10.0 + 0.2;
- dpp = pp > 4 ? 0.5 : 0.2;
+ dpp = pp > 4 ? 0.5 : 0.25;
hpos = gc.pi.entry[gc.pi.nr - 1].sec;
QColor c = getColor(PP_LINES);
- bool alt = false;
+ bool alt = true;
for (m = 0.0; m <= pp; m += dpp) {
QGraphicsLineItem *item = new QGraphicsLineItem(SCALEGC(0, m), SCALEGC(hpos, m));
QPen pen(defaultPen);
@@ -562,9 +562,8 @@ void ProfileGraphicsView::plot_pp_text()
scene()->addItem(item);
qreal textPos = hpos;
if (alt)
- textPos += 30;
+ plot_text(&tro, QPointF(textPos, m), QString::number(m), pressureMarkers);
alt = !alt;
- plot_text(&tro, QPointF(textPos, m), QString::number(m), pressureMarkers);
}
scene()->addItem(pressureMarkers);
pressureMarkers->setPos(pressureMarkers->pos().x() + 10, 0);
diff --git a/xslt/csv2xml.xslt b/xslt/csv2xml.xslt
index fda0b6724..7ddbda92d 100644
--- a/xslt/csv2xml.xslt
+++ b/xslt/csv2xml.xslt
@@ -11,11 +11,17 @@
<xsl:param name="stopdepthField" select="stopdepthField"/>
<xsl:param name="date" select="date"/>
<xsl:param name="time" select="time"/>
+ <xsl:param name="separatorIndex" select="separatorIndex"/>
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="lf"><xsl:text>
</xsl:text></xsl:variable>
- <xsl:variable name="fs"><xsl:text> </xsl:text></xsl:variable>
+ <xsl:variable name="fs">
+ <xsl:choose>
+ <xsl:when test="$separatorIndex = 0"><xsl:text> </xsl:text></xsl:when>
+ <xsl:otherwise><xsl:text>,</xsl:text></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
<xsl:template match="/">
<divelog program="subsurface-import" version="2">