Commit cd5e7a370bb89c2d27d47b329bb8def59d0d82e3

Authored by oliverhaag
1 parent 2e9e87f4

Fixed small bugs and added csv export

openhantek/ChangeLog
@@ -73,3 +73,8 @@ @@ -73,3 +73,8 @@
73 * Added manual command sending with Shift+C when bulding as debug binary 73 * Added manual command sending with Shift+C when bulding as debug binary
74 * Fixed some uninitialized values in Hantek::Control 74 * Fixed some uninitialized values in Hantek::Control
75 * Added debug messages for capture state when building as debug binary 75 * Added debug messages for capture state when building as debug binary
  76 +
  77 +2010-09-15 Oliver Haag <oliver.haag@gmail.com>
  78 +* Made export dialog title translatable
  79 +* Fixed export shortcut
  80 +* Added csv export
openhantek/src/dsowidget.cpp
@@ -441,7 +441,7 @@ bool DsoWidget::exportAs() { @@ -441,7 +441,7 @@ bool DsoWidget::exportAs() {
441 << tr("Image (*.png *.xpm *.jpg)") 441 << tr("Image (*.png *.xpm *.jpg)")
442 << tr("Comma-Separated Values (*.csv)"); 442 << tr("Comma-Separated Values (*.csv)");
443 443
444 - QFileDialog fileDialog((QWidget *) this->parent(), "Export file...", QString(), filters.join(";;")); 444 + QFileDialog fileDialog((QWidget *) this->parent(), tr("Export file..."), QString(), filters.join(";;"));
445 fileDialog.setFileMode(QFileDialog::AnyFile); 445 fileDialog.setFileMode(QFileDialog::AnyFile);
446 if(fileDialog.exec() != QDialog::Accepted) 446 if(fileDialog.exec() != QDialog::Accepted)
447 return false; 447 return false;
openhantek/src/exporter.cpp
@@ -24,12 +24,14 @@ @@ -24,12 +24,14 @@
24 24
25 #include <cmath> 25 #include <cmath>
26 26
  27 +#include <QFile>
27 #include <QImage> 28 #include <QImage>
28 #include <QMutex> 29 #include <QMutex>
29 #include <QPainter> 30 #include <QPainter>
30 #include <QPixmap> 31 #include <QPixmap>
31 #include <QPrintDialog> 32 #include <QPrintDialog>
32 #include <QPrinter> 33 #include <QPrinter>
  34 +#include <QTextStream>
33 35
34 36
35 #include "exporter.h" 37 #include "exporter.h"
@@ -76,289 +78,314 @@ void Exporter::setSize(QSize size) { @@ -76,289 +78,314 @@ void Exporter::setSize(QSize size) {
76 78
77 /// \brief Print the document (May be a file too) 79 /// \brief Print the document (May be a file too)
78 bool Exporter::doExport() { 80 bool Exporter::doExport() {
79 - // Choose the color values we need  
80 - DsoSettingsColorValues *colorValues;  
81 - if(this->format == EXPORT_FORMAT_IMAGE && this->settings->view.screenColorImages)  
82 - colorValues = &(this->settings->view.color.screen);  
83 - else  
84 - colorValues = &(this->settings->view.color.print);  
85 -  
86 - QPaintDevice *paintDevice;  
87 -  
88 - if(this->format < EXPORT_FORMAT_IMAGE) {  
89 - // We need a QPrinter for printing, pdf- and ps-export  
90 - paintDevice = new QPrinter(QPrinter::HighResolution);  
91 - ((QPrinter *) paintDevice)->setOrientation(this->settings->view.zoom ? QPrinter::Portrait : QPrinter::Landscape);  
92 - ((QPrinter *) paintDevice)->setPageMargins(20, 20, 20, 20, QPrinter::Millimeter); 81 + if(this->format < EXPORT_FORMAT_CSV) {
  82 + // Choose the color values we need
  83 + DsoSettingsColorValues *colorValues;
  84 + if(this->format == EXPORT_FORMAT_IMAGE && this->settings->view.screenColorImages)
  85 + colorValues = &(this->settings->view.color.screen);
  86 + else
  87 + colorValues = &(this->settings->view.color.print);
  88 +
  89 + QPaintDevice *paintDevice;
93 90
94 - if(this->format == EXPORT_FORMAT_PRINTER) {  
95 - // Show the printing dialog  
96 - QPrintDialog *dialog = new QPrintDialog((QPrinter *) paintDevice, (QWidget *) this->parent());  
97 - dialog->setWindowTitle(tr("Print oscillograph"));  
98 - if(dialog->exec() != QDialog::Accepted)  
99 - return false; 91 + if(this->format < EXPORT_FORMAT_IMAGE) {
  92 + // We need a QPrinter for printing, pdf- and ps-export
  93 + paintDevice = new QPrinter(QPrinter::HighResolution);
  94 + ((QPrinter *) paintDevice)->setOrientation(this->settings->view.zoom ? QPrinter::Portrait : QPrinter::Landscape);
  95 + ((QPrinter *) paintDevice)->setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
  96 +
  97 + if(this->format == EXPORT_FORMAT_PRINTER) {
  98 + // Show the printing dialog
  99 + QPrintDialog *dialog = new QPrintDialog((QPrinter *) paintDevice, (QWidget *) this->parent());
  100 + dialog->setWindowTitle(tr("Print oscillograph"));
  101 + if(dialog->exec() != QDialog::Accepted)
  102 + return false;
  103 + }
  104 + else {
  105 + // Configure the QPrinter
  106 + ((QPrinter *) paintDevice)->setOutputFileName(this->filename);
  107 + ((QPrinter *) paintDevice)->setOutputFormat((this->format == EXPORT_FORMAT_PDF) ? QPrinter::PdfFormat : QPrinter::PostScriptFormat);
  108 + }
100 } 109 }
101 else { 110 else {
102 - // Configure the QPrinter  
103 - ((QPrinter *) paintDevice)->setOutputFileName(this->filename);  
104 - ((QPrinter *) paintDevice)->setOutputFormat((this->format == EXPORT_FORMAT_PDF) ? QPrinter::PdfFormat : QPrinter::PostScriptFormat); 111 + // We need a QPixmap for image-export
  112 + paintDevice = new QPixmap(this->size);
  113 + ((QPixmap *) paintDevice)->fill(colorValues->background);
105 } 114 }
106 - }  
107 - else {  
108 - // We need a QPixmap for image-export  
109 - paintDevice = new QPixmap(this->size);  
110 - ((QPixmap *) paintDevice)->fill(colorValues->background);  
111 - }  
112 -  
113 - // Create a painter for our device  
114 - QPainter painter(paintDevice);  
115 -  
116 - // Get line height  
117 - QFont font;  
118 - QFontMetrics fontMetrics(font, paintDevice);  
119 - double lineHeight = fontMetrics.height();  
120 -  
121 - painter.setBrush(Qt::SolidPattern);  
122 -  
123 - this->dataAnalyzer->mutex()->lock();  
124 -  
125 - // Draw the settings table  
126 - double stretchBase = (double) (paintDevice->width() - lineHeight * 10) / 4;  
127 -  
128 - // Print trigger details  
129 - painter.setPen(colorValues->voltage[this->settings->scope.trigger.source]);  
130 - QString levelString = Helper::valueToString(this->settings->scope.voltage[this->settings->scope.trigger.source].trigger, Helper::UNIT_VOLTS, 3);  
131 - QString pretriggerString = tr("%L1%").arg((int) (this->settings->scope.trigger.position * 100 + 0.5));  
132 - painter.drawText(QRectF(0, 0, lineHeight * 10, lineHeight), tr("%1 %2 %3 %4").arg(this->settings->scope.voltage[this->settings->scope.trigger.source].name, Dso::slopeString(this->settings->scope.trigger.slope), levelString, pretriggerString));  
133 -  
134 - // Print sample count  
135 - painter.setPen(colorValues->text);  
136 - painter.drawText(QRectF(lineHeight * 10, 0, stretchBase, lineHeight), tr("%1 S").arg(this->dataAnalyzer->sampleCount()), QTextOption(Qt::AlignRight));  
137 - // Print samplerate  
138 - painter.drawText(QRectF(lineHeight * 10 + stretchBase, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.samplerate, Helper::UNIT_SAMPLES) + tr("/s"), QTextOption(Qt::AlignRight));  
139 - // Print timebase  
140 - painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.timebase, Helper::UNIT_SECONDS, 0) + tr("/div"), QTextOption(Qt::AlignRight));  
141 - // Print frequencybase  
142 - painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.frequencybase, Helper::UNIT_HERTZ, 0) + tr("/div"), QTextOption(Qt::AlignRight));  
143 -  
144 - // Draw the measurement table  
145 - stretchBase = (double) (paintDevice->width() - lineHeight * 6) / 10;  
146 - int channelCount = 0;  
147 - for(int channel = this->settings->scope.voltage.count() - 1; channel >= 0; channel--) {  
148 - if(this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used) {  
149 - channelCount++;  
150 - double top = (double) paintDevice->height() - channelCount * lineHeight; 115 +
  116 + // Create a painter for our device
  117 + QPainter painter(paintDevice);
  118 +
  119 + // Get line height
  120 + QFont font;
  121 + QFontMetrics fontMetrics(font, paintDevice);
  122 + double lineHeight = fontMetrics.height();
  123 +
  124 + painter.setBrush(Qt::SolidPattern);
  125 +
  126 + this->dataAnalyzer->mutex()->lock();
  127 +
  128 + // Draw the settings table
  129 + double stretchBase = (double) (paintDevice->width() - lineHeight * 10) / 4;
  130 +
  131 + // Print trigger details
  132 + painter.setPen(colorValues->voltage[this->settings->scope.trigger.source]);
  133 + QString levelString = Helper::valueToString(this->settings->scope.voltage[this->settings->scope.trigger.source].trigger, Helper::UNIT_VOLTS, 3);
  134 + QString pretriggerString = tr("%L1%").arg((int) (this->settings->scope.trigger.position * 100 + 0.5));
  135 + painter.drawText(QRectF(0, 0, lineHeight * 10, lineHeight), tr("%1 %2 %3 %4").arg(this->settings->scope.voltage[this->settings->scope.trigger.source].name, Dso::slopeString(this->settings->scope.trigger.slope), levelString, pretriggerString));
  136 +
  137 + // Print sample count
  138 + painter.setPen(colorValues->text);
  139 + painter.drawText(QRectF(lineHeight * 10, 0, stretchBase, lineHeight), tr("%1 S").arg(this->dataAnalyzer->sampleCount()), QTextOption(Qt::AlignRight));
  140 + // Print samplerate
  141 + painter.drawText(QRectF(lineHeight * 10 + stretchBase, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.samplerate, Helper::UNIT_SAMPLES) + tr("/s"), QTextOption(Qt::AlignRight));
  142 + // Print timebase
  143 + painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.timebase, Helper::UNIT_SECONDS, 0) + tr("/div"), QTextOption(Qt::AlignRight));
  144 + // Print frequencybase
  145 + painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, 0, stretchBase, lineHeight), Helper::valueToString(this->settings->scope.horizontal.frequencybase, Helper::UNIT_HERTZ, 0) + tr("/div"), QTextOption(Qt::AlignRight));
  146 +
  147 + // Draw the measurement table
  148 + stretchBase = (double) (paintDevice->width() - lineHeight * 6) / 10;
  149 + int channelCount = 0;
  150 + for(int channel = this->settings->scope.voltage.count() - 1; channel >= 0; channel--) {
  151 + if(this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used) {
  152 + channelCount++;
  153 + double top = (double) paintDevice->height() - channelCount * lineHeight;
  154 +
  155 + // Print label
  156 + painter.setPen(colorValues->voltage[channel]);
  157 + painter.drawText(QRectF(0, top, lineHeight * 4, lineHeight), this->settings->scope.voltage[channel].name);
  158 + // Print coupling/math mode
  159 + if((unsigned int) channel < this->settings->scope.physicalChannels)
  160 + painter.drawText(QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight), Dso::couplingString((Dso::Coupling) this->settings->scope.voltage[channel].misc));
  161 + else
  162 + painter.drawText(QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight), Dso::mathModeString((Dso::MathMode) this->settings->scope.voltage[channel].misc));
  163 +
  164 + // Print voltage gain
  165 + painter.drawText(QRectF(lineHeight * 6, top, stretchBase * 2, lineHeight), Helper::valueToString(this->settings->scope.voltage[channel].gain, Helper::UNIT_VOLTS, 0) + tr("/div"), QTextOption(Qt::AlignRight));
  166 + // Print spectrum magnitude
  167 + painter.setPen(colorValues->spectrum[channel]);
  168 + painter.drawText(QRectF(lineHeight * 6 + stretchBase * 2, top, stretchBase * 2, lineHeight), Helper::valueToString(this->settings->scope.spectrum[channel].magnitude, Helper::UNIT_DECIBEL, 0) + tr("/div"), QTextOption(Qt::AlignRight));
  169 +
  170 + // Amplitude string representation (4 significant digits)
  171 + painter.setPen(colorValues->text);
  172 + painter.drawText(QRectF(lineHeight * 6 + stretchBase * 4, top, stretchBase * 3, lineHeight), Helper::valueToString(this->dataAnalyzer->data(channel)->amplitude, Helper::UNIT_VOLTS, 4), QTextOption(Qt::AlignRight));
  173 + // Frequency string representation (5 significant digits)
  174 + painter.drawText(QRectF(lineHeight * 6 + stretchBase * 7, top, stretchBase * 3, lineHeight), Helper::valueToString(this->dataAnalyzer->data(channel)->frequency, Helper::UNIT_HERTZ, 5), QTextOption(Qt::AlignRight));
  175 + }
  176 + }
  177 +
  178 + // Draw the marker table
  179 + double scopeHeight;
  180 + stretchBase = (double) (paintDevice->width() - lineHeight * 10) / 4;
  181 + painter.setPen(colorValues->text);
  182 +
  183 + // Calculate variables needed for zoomed scope
  184 + double divs = fabs(this->settings->scope.horizontal.marker[1] - this->settings->scope.horizontal.marker[0]);
  185 + double time = divs * this->settings->scope.horizontal.timebase;
  186 + double zoomFactor = DIVS_TIME / divs;
  187 + double zoomOffset = (this->settings->scope.horizontal.marker[0] + this->settings->scope.horizontal.marker[1]) / 2;
  188 +
  189 + if(this->settings->view.zoom) {
  190 + scopeHeight = (double) (paintDevice->height() - (channelCount + 5) * lineHeight) / 2;
  191 + double top = 2.5 * lineHeight + scopeHeight;
151 192
152 - // Print label  
153 - painter.setPen(colorValues->voltage[channel]);  
154 - painter.drawText(QRectF(0, top, lineHeight * 4, lineHeight), this->settings->scope.voltage[channel].name);  
155 - // Print coupling/math mode  
156 - if((unsigned int) channel < this->settings->scope.physicalChannels)  
157 - painter.drawText(QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight), Dso::couplingString((Dso::Coupling) this->settings->scope.voltage[channel].misc));  
158 - else  
159 - painter.drawText(QRectF(lineHeight * 4, top, lineHeight * 2, lineHeight), Dso::mathModeString((Dso::MathMode) this->settings->scope.voltage[channel].misc)); 193 + painter.drawText(QRectF(0, top, stretchBase, lineHeight), tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3));
160 194
161 - // Print voltage gain  
162 - painter.drawText(QRectF(lineHeight * 6, top, stretchBase * 2, lineHeight), Helper::valueToString(this->settings->scope.voltage[channel].gain, Helper::UNIT_VOLTS, 0) + tr("/div"), QTextOption(Qt::AlignRight));  
163 - // Print spectrum magnitude  
164 - painter.setPen(colorValues->spectrum[channel]);  
165 - painter.drawText(QRectF(lineHeight * 6 + stretchBase * 2, top, stretchBase * 2, lineHeight), Helper::valueToString(this->settings->scope.spectrum[channel].magnitude, Helper::UNIT_DECIBEL, 0) + tr("/div"), QTextOption(Qt::AlignRight)); 195 + painter.drawText(QRectF(lineHeight * 10, top, stretchBase, lineHeight), Helper::valueToString(time, Helper::UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));
  196 + painter.drawText(QRectF(lineHeight * 10 + stretchBase, top, stretchBase, lineHeight), Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));
166 197
167 - // Amplitude string representation (4 significant digits)  
168 - painter.setPen(colorValues->text);  
169 - painter.drawText(QRectF(lineHeight * 6 + stretchBase * 4, top, stretchBase * 3, lineHeight), Helper::valueToString(this->dataAnalyzer->data(channel)->amplitude, Helper::UNIT_VOLTS, 4), QTextOption(Qt::AlignRight));  
170 - // Frequency string representation (5 significant digits)  
171 - painter.drawText(QRectF(lineHeight * 6 + stretchBase * 7, top, stretchBase * 3, lineHeight), Helper::valueToString(this->dataAnalyzer->data(channel)->frequency, Helper::UNIT_HERTZ, 5), QTextOption(Qt::AlignRight)); 198 + painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase, lineHeight), Helper::valueToString(time / DIVS_TIME, Helper::UNIT_SECONDS, 3) + tr("/div"), QTextOption(Qt::AlignRight));
  199 + painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, top, stretchBase, lineHeight), Helper::valueToString(divs * this->settings->scope.horizontal.frequencybase / DIVS_TIME, Helper::UNIT_HERTZ, 3) + tr("/div"), QTextOption(Qt::AlignRight));
  200 + }
  201 + else {
  202 + scopeHeight = (double) paintDevice->height() - (channelCount + 4) * lineHeight;
  203 + double top = 2.5 * lineHeight + scopeHeight;
  204 +
  205 + painter.drawText(QRectF(0, top, stretchBase, lineHeight), tr("Marker 1/2"));
  206 +
  207 + painter.drawText(QRectF(lineHeight * 10, top, stretchBase * 2, lineHeight), Helper::valueToString(time, Helper::UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));
  208 + painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase * 2, lineHeight), Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));
172 } 209 }
173 - }  
174 -  
175 - // Draw the marker table  
176 - double scopeHeight;  
177 - stretchBase = (double) (paintDevice->width() - lineHeight * 10) / 4;  
178 - painter.setPen(colorValues->text);  
179 -  
180 - // Calculate variables needed for zoomed scope  
181 - double divs = fabs(this->settings->scope.horizontal.marker[1] - this->settings->scope.horizontal.marker[0]);  
182 - double time = divs * this->settings->scope.horizontal.timebase;  
183 - double zoomFactor = DIVS_TIME / divs;  
184 - double zoomOffset = (this->settings->scope.horizontal.marker[0] + this->settings->scope.horizontal.marker[1]) / 2;  
185 -  
186 - if(this->settings->view.zoom) {  
187 - scopeHeight = (double) (paintDevice->height() - (channelCount + 5) * lineHeight) / 2;  
188 - double top = 2.5 * lineHeight + scopeHeight;  
189 -  
190 - painter.drawText(QRectF(0, top, stretchBase, lineHeight), tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3));  
191 -  
192 - painter.drawText(QRectF(lineHeight * 10, top, stretchBase, lineHeight), Helper::valueToString(time, Helper::UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));  
193 - painter.drawText(QRectF(lineHeight * 10 + stretchBase, top, stretchBase, lineHeight), Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));  
194 210
195 - painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase, lineHeight), Helper::valueToString(time / DIVS_TIME, Helper::UNIT_SECONDS, 3) + tr("/div"), QTextOption(Qt::AlignRight));  
196 - painter.drawText(QRectF(lineHeight * 10 + stretchBase * 3, top, stretchBase, lineHeight), Helper::valueToString(divs * this->settings->scope.horizontal.frequencybase / DIVS_TIME, Helper::UNIT_HERTZ, 3) + tr("/div"), QTextOption(Qt::AlignRight));  
197 - }  
198 - else {  
199 - scopeHeight = (double) paintDevice->height() - (channelCount + 4) * lineHeight;  
200 - double top = 2.5 * lineHeight + scopeHeight; 211 + // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph
  212 + painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2, (scopeHeight - 1) / 2 + lineHeight * 1.5), false);
201 213
202 - painter.drawText(QRectF(0, top, stretchBase, lineHeight), tr("Marker 1/2")); 214 + // Draw the graphs
  215 + painter.setRenderHint(QPainter::Antialiasing);
  216 + painter.setBrush(Qt::NoBrush);
203 217
204 - painter.drawText(QRectF(lineHeight * 10, top, stretchBase * 2, lineHeight), Helper::valueToString(time, Helper::UNIT_SECONDS, 4), QTextOption(Qt::AlignRight));  
205 - painter.drawText(QRectF(lineHeight * 10 + stretchBase * 2, top, stretchBase * 2, lineHeight), Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4), QTextOption(Qt::AlignRight));  
206 - }  
207 -  
208 - // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph  
209 - painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2, (scopeHeight - 1) / 2 + lineHeight * 1.5), false);  
210 -  
211 - // Draw the graphs  
212 - painter.setRenderHint(QPainter::Antialiasing);  
213 - painter.setBrush(Qt::NoBrush);  
214 -  
215 - for(int zoomed = 0; zoomed < (this->settings->view.zoom ? 2 : 1); zoomed++) {  
216 - switch(this->settings->scope.horizontal.format) {  
217 - case Dso::GRAPHFORMAT_TY:  
218 - // Add graphs for channels  
219 - for(int channel = 0 ; channel < this->settings->scope.voltage.count(); channel++) {  
220 - if(this->settings->scope.voltage[channel].used) {  
221 - painter.setPen(colorValues->voltage[channel]);  
222 -  
223 - // What's the horizontal distance between sampling points?  
224 - double horizontalFactor = this->dataAnalyzer->data(channel)->samples.voltage.interval / this->settings->scope.horizontal.timebase;  
225 - // How many samples are visible?  
226 - double centerPosition, centerOffset;  
227 - if(zoomed) {  
228 - centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;  
229 - centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;  
230 - }  
231 - else {  
232 - centerPosition = DIVS_TIME / 2 / horizontalFactor;  
233 - centerOffset = DIVS_TIME / horizontalFactor / 2; 218 + for(int zoomed = 0; zoomed < (this->settings->view.zoom ? 2 : 1); zoomed++) {
  219 + switch(this->settings->scope.horizontal.format) {
  220 + case Dso::GRAPHFORMAT_TY:
  221 + // Add graphs for channels
  222 + for(int channel = 0 ; channel < this->settings->scope.voltage.count(); channel++) {
  223 + if(this->settings->scope.voltage[channel].used) {
  224 + painter.setPen(colorValues->voltage[channel]);
  225 +
  226 + // What's the horizontal distance between sampling points?
  227 + double horizontalFactor = this->dataAnalyzer->data(channel)->samples.voltage.interval / this->settings->scope.horizontal.timebase;
  228 + // How many samples are visible?
  229 + double centerPosition, centerOffset;
  230 + if(zoomed) {
  231 + centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;
  232 + centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;
  233 + }
  234 + else {
  235 + centerPosition = DIVS_TIME / 2 / horizontalFactor;
  236 + centerOffset = DIVS_TIME / horizontalFactor / 2;
  237 + }
  238 + unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);
  239 + unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.voltage.count - 1);
  240 +
  241 + // Draw graph
  242 + QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
  243 + for(unsigned int position = firstPosition; position <= lastPosition; position++)
  244 + graph[position - firstPosition] = QPointF(position * horizontalFactor - DIVS_TIME / 2, this->dataAnalyzer->data(channel)->samples.voltage.sample[position] / this->settings->scope.voltage[channel].gain + this->settings->scope.voltage[channel].offset);
  245 + painter.drawPolyline(graph, lastPosition - firstPosition + 1);
234 } 246 }
235 - unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);  
236 - unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.voltage.count - 1);  
237 -  
238 - // Draw graph  
239 - QPointF *graph = new QPointF[lastPosition - firstPosition + 1];  
240 - for(unsigned int position = firstPosition; position <= lastPosition; position++)  
241 - graph[position - firstPosition] = QPointF(position * horizontalFactor - DIVS_TIME / 2, this->dataAnalyzer->data(channel)->samples.voltage.sample[position] / this->settings->scope.voltage[channel].gain + this->settings->scope.voltage[channel].offset);  
242 - painter.drawPolyline(graph, lastPosition - firstPosition + 1);  
243 } 247 }
244 - }  
245 -  
246 - // Add spectrum graphs  
247 - for (int channel = 0; channel < this->settings->scope.spectrum.count(); channel++) {  
248 - if(this->settings->scope.spectrum[channel].used) {  
249 - painter.setPen(colorValues->spectrum[channel]);  
250 -  
251 - // What's the horizontal distance between sampling points?  
252 - double horizontalFactor = this->dataAnalyzer->data(channel)->samples.spectrum.interval / this->settings->scope.horizontal.frequencybase;  
253 - // How many samples are visible?  
254 - double centerPosition, centerOffset;  
255 - if(zoomed) {  
256 - centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;  
257 - centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;  
258 - }  
259 - else {  
260 - centerPosition = DIVS_TIME / 2 / horizontalFactor;  
261 - centerOffset = DIVS_TIME / horizontalFactor / 2; 248 +
  249 + // Add spectrum graphs
  250 + for (int channel = 0; channel < this->settings->scope.spectrum.count(); channel++) {
  251 + if(this->settings->scope.spectrum[channel].used) {
  252 + painter.setPen(colorValues->spectrum[channel]);
  253 +
  254 + // What's the horizontal distance between sampling points?
  255 + double horizontalFactor = this->dataAnalyzer->data(channel)->samples.spectrum.interval / this->settings->scope.horizontal.frequencybase;
  256 + // How many samples are visible?
  257 + double centerPosition, centerOffset;
  258 + if(zoomed) {
  259 + centerPosition = (zoomOffset + DIVS_TIME / 2) / horizontalFactor;
  260 + centerOffset = DIVS_TIME / horizontalFactor / zoomFactor / 2;
  261 + }
  262 + else {
  263 + centerPosition = DIVS_TIME / 2 / horizontalFactor;
  264 + centerOffset = DIVS_TIME / horizontalFactor / 2;
  265 + }
  266 + unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);
  267 + unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.spectrum.count - 1);
  268 +
  269 + // Draw graph
  270 + QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
  271 + for(unsigned int position = firstPosition; position <= lastPosition; position++)
  272 + graph[position - firstPosition] = QPointF(position * horizontalFactor - DIVS_TIME / 2, this->dataAnalyzer->data(channel)->samples.spectrum.sample[position] / this->settings->scope.spectrum[channel].magnitude + this->settings->scope.spectrum[channel].offset);
  273 + painter.drawPolyline(graph, lastPosition - firstPosition + 1);
262 } 274 }
263 - unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);  
264 - unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.spectrum.count - 1);  
265 -  
266 - // Draw graph  
267 - QPointF *graph = new QPointF[lastPosition - firstPosition + 1];  
268 - for(unsigned int position = firstPosition; position <= lastPosition; position++)  
269 - graph[position - firstPosition] = QPointF(position * horizontalFactor - DIVS_TIME / 2, this->dataAnalyzer->data(channel)->samples.spectrum.sample[position] / this->settings->scope.spectrum[channel].magnitude + this->settings->scope.spectrum[channel].offset);  
270 - painter.drawPolyline(graph, lastPosition - firstPosition + 1);  
271 } 275 }
272 - }  
273 - break; 276 + break;
  277 +
  278 + case Dso::GRAPHFORMAT_XY:
  279 + break;
274 280
275 - case Dso::GRAPHFORMAT_XY:  
276 - break; 281 + default:
  282 + break;
  283 + }
277 284
278 - default:  
279 - break; 285 + // Set DIVS_TIME / zoomFactor x DIVS_VOLTAGE matrix for zoomed oscillograph
  286 + painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME * zoomFactor, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2 - zoomOffset * zoomFactor * (paintDevice->width() - 1) / DIVS_TIME, (scopeHeight - 1) * 1.5 + lineHeight * 4), false);
280 } 287 }
281 288
282 - // Set DIVS_TIME / zoomFactor x DIVS_VOLTAGE matrix for zoomed oscillograph  
283 - painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME * zoomFactor, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2 - zoomOffset * zoomFactor * (paintDevice->width() - 1) / DIVS_TIME, (scopeHeight - 1) * 1.5 + lineHeight * 4), false);  
284 - }  
285 -  
286 - this->dataAnalyzer->mutex()->unlock();  
287 -  
288 - // Draw grids  
289 - painter.setRenderHint(QPainter::Antialiasing, false);  
290 - for(int zoomed = 0; zoomed < (this->settings->view.zoom ? 2 : 1); zoomed++) {  
291 - // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph  
292 - painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2, (scopeHeight - 1) * (zoomed + 0.5) + lineHeight * 1.5 + lineHeight * 2.5 * zoomed), false);  
293 -  
294 - // Grid lines  
295 - painter.setPen(colorValues->grid); 289 + this->dataAnalyzer->mutex()->unlock();
296 290
297 - if(this->format < EXPORT_FORMAT_IMAGE) {  
298 - // Draw vertical lines  
299 - for(int div = 1; div < DIVS_TIME / 2; div++) {  
300 - for(int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; dot++) {  
301 - painter.drawLine(QPointF((double) -div - 0.02, (double) -dot / 5), QPointF((double) -div + 0.02, (double) -dot / 5));  
302 - painter.drawLine(QPointF((double) -div - 0.02, (double) dot / 5), QPointF((double) -div + 0.02, (double) dot / 5));  
303 - painter.drawLine(QPointF((double) div - 0.02, (double) -dot / 5), QPointF((double) div + 0.02, (double) -dot / 5));  
304 - painter.drawLine(QPointF((double) div - 0.02, (double) dot / 5), QPointF((double) div + 0.02, (double) dot / 5)); 291 + // Draw grids
  292 + painter.setRenderHint(QPainter::Antialiasing, false);
  293 + for(int zoomed = 0; zoomed < (this->settings->view.zoom ? 2 : 1); zoomed++) {
  294 + // Set DIVS_TIME x DIVS_VOLTAGE matrix for oscillograph
  295 + painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2, (scopeHeight - 1) * (zoomed + 0.5) + lineHeight * 1.5 + lineHeight * 2.5 * zoomed), false);
  296 +
  297 + // Grid lines
  298 + painter.setPen(colorValues->grid);
  299 +
  300 + if(this->format < EXPORT_FORMAT_IMAGE) {
  301 + // Draw vertical lines
  302 + for(int div = 1; div < DIVS_TIME / 2; div++) {
  303 + for(int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; dot++) {
  304 + painter.drawLine(QPointF((double) -div - 0.02, (double) -dot / 5), QPointF((double) -div + 0.02, (double) -dot / 5));
  305 + painter.drawLine(QPointF((double) -div - 0.02, (double) dot / 5), QPointF((double) -div + 0.02, (double) dot / 5));
  306 + painter.drawLine(QPointF((double) div - 0.02, (double) -dot / 5), QPointF((double) div + 0.02, (double) -dot / 5));
  307 + painter.drawLine(QPointF((double) div - 0.02, (double) dot / 5), QPointF((double) div + 0.02, (double) dot / 5));
  308 + }
305 } 309 }
306 - }  
307 - // Draw horizontal lines  
308 - for(int div = 1; div < DIVS_VOLTAGE / 2; div++) {  
309 - for(int dot = 1; dot < DIVS_TIME / 2 * 5; dot++) {  
310 - painter.drawLine(QPointF((double) -dot / 5, (double) -div - 0.02), QPointF((double) -dot / 5, (double) -div + 0.02));  
311 - painter.drawLine(QPointF((double) dot / 5, (double) -div - 0.02), QPointF((double) dot / 5, (double) -div + 0.02));  
312 - painter.drawLine(QPointF((double) -dot / 5, (double) div - 0.02), QPointF((double) -dot / 5, (double) div + 0.02));  
313 - painter.drawLine(QPointF((double) dot / 5, (double) div - 0.02), QPointF((double) dot / 5, (double) div + 0.02)); 310 + // Draw horizontal lines
  311 + for(int div = 1; div < DIVS_VOLTAGE / 2; div++) {
  312 + for(int dot = 1; dot < DIVS_TIME / 2 * 5; dot++) {
  313 + painter.drawLine(QPointF((double) -dot / 5, (double) -div - 0.02), QPointF((double) -dot / 5, (double) -div + 0.02));
  314 + painter.drawLine(QPointF((double) dot / 5, (double) -div - 0.02), QPointF((double) dot / 5, (double) -div + 0.02));
  315 + painter.drawLine(QPointF((double) -dot / 5, (double) div - 0.02), QPointF((double) -dot / 5, (double) div + 0.02));
  316 + painter.drawLine(QPointF((double) dot / 5, (double) div - 0.02), QPointF((double) dot / 5, (double) div + 0.02));
  317 + }
314 } 318 }
315 } 319 }
316 - }  
317 - else {  
318 - // Draw vertical lines  
319 - for(int div = 1; div < DIVS_TIME / 2; div++) {  
320 - for(int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; dot++) {  
321 - painter.drawPoint(QPointF(-div, (double) -dot / 5));  
322 - painter.drawPoint(QPointF(-div, (double) dot / 5));  
323 - painter.drawPoint(QPointF(div, (double) -dot / 5));  
324 - painter.drawPoint(QPointF(div, (double) dot / 5)); 320 + else {
  321 + // Draw vertical lines
  322 + for(int div = 1; div < DIVS_TIME / 2; div++) {
  323 + for(int dot = 1; dot < DIVS_VOLTAGE / 2 * 5; dot++) {
  324 + painter.drawPoint(QPointF(-div, (double) -dot / 5));
  325 + painter.drawPoint(QPointF(-div, (double) dot / 5));
  326 + painter.drawPoint(QPointF(div, (double) -dot / 5));
  327 + painter.drawPoint(QPointF(div, (double) dot / 5));
  328 + }
325 } 329 }
326 - }  
327 - // Draw horizontal lines  
328 - for(int div = 1; div < DIVS_VOLTAGE / 2; div++) {  
329 - for(int dot = 1; dot < DIVS_TIME / 2 * 5; dot++) {  
330 - if(dot % 5 == 0)  
331 - continue; // Already done by vertical lines  
332 - painter.drawPoint(QPointF((double) -dot / 5, -div));  
333 - painter.drawPoint(QPointF((double) dot / 5, -div));  
334 - painter.drawPoint(QPointF((double) -dot / 5, div));  
335 - painter.drawPoint(QPointF((double) dot / 5, div)); 330 + // Draw horizontal lines
  331 + for(int div = 1; div < DIVS_VOLTAGE / 2; div++) {
  332 + for(int dot = 1; dot < DIVS_TIME / 2 * 5; dot++) {
  333 + if(dot % 5 == 0)
  334 + continue; // Already done by vertical lines
  335 + painter.drawPoint(QPointF((double) -dot / 5, -div));
  336 + painter.drawPoint(QPointF((double) dot / 5, -div));
  337 + painter.drawPoint(QPointF((double) -dot / 5, div));
  338 + painter.drawPoint(QPointF((double) dot / 5, div));
  339 + }
336 } 340 }
337 } 341 }
338 - } 342 +
  343 + // Axes
  344 + painter.setPen(colorValues->axes);
  345 + painter.drawLine(QPointF(-DIVS_TIME / 2, 0), QPointF(DIVS_TIME / 2, 0));
  346 + painter.drawLine(QPointF(0, -DIVS_VOLTAGE / 2), QPointF(0, DIVS_VOLTAGE / 2));
  347 + for(double div = 0.2; div <= DIVS_TIME / 2; div += 0.2) {
  348 + painter.drawLine(QPointF(div, -0.05), QPointF(div, 0.05));
  349 + painter.drawLine(QPointF(-div, -0.05), QPointF(-div, 0.05));
  350 + }
  351 + for(double div = 0.2; div <= DIVS_VOLTAGE / 2; div += 0.2) {
  352 + painter.drawLine(QPointF(-0.05, div), QPointF(0.05, div));
  353 + painter.drawLine(QPointF(-0.05, -div), QPointF(0.05, -div));
  354 + }
339 355
340 - // Axes  
341 - painter.setPen(colorValues->axes);  
342 - painter.drawLine(QPointF(-DIVS_TIME / 2, 0), QPointF(DIVS_TIME / 2, 0));  
343 - painter.drawLine(QPointF(0, -DIVS_VOLTAGE / 2), QPointF(0, DIVS_VOLTAGE / 2));  
344 - for(double div = 0.2; div <= DIVS_TIME / 2; div += 0.2) {  
345 - painter.drawLine(QPointF(div, -0.05), QPointF(div, 0.05));  
346 - painter.drawLine(QPointF(-div, -0.05), QPointF(-div, 0.05)); 356 + // Borders
  357 + painter.setPen(colorValues->border);
  358 + painter.drawRect(QRectF(-DIVS_TIME / 2, -DIVS_VOLTAGE / 2, DIVS_TIME, DIVS_VOLTAGE));
347 } 359 }
348 - for(double div = 0.2; div <= DIVS_VOLTAGE / 2; div += 0.2) {  
349 - painter.drawLine(QPointF(-0.05, div), QPointF(0.05, div));  
350 - painter.drawLine(QPointF(-0.05, -div), QPointF(0.05, -div)); 360 +
  361 + painter.end();
  362 +
  363 + if(this->format == EXPORT_FORMAT_IMAGE)
  364 + ((QPixmap *) paintDevice)->save(this->filename);
  365 +
  366 + return true;
  367 + }
  368 + else {
  369 + QFile csvFile(this->filename);
  370 + if(!csvFile.open(QIODevice::WriteOnly | QIODevice::Text))
  371 + return false;
  372 +
  373 + QTextStream csvStream(&csvFile);
  374 +
  375 + for(int channel = 0 ; channel < this->settings->scope.voltage.count(); channel++) {
  376 + if(this->settings->scope.voltage[channel].used) {
  377 + // Start with channel name and the sample interval
  378 + csvStream << "\"" << this->settings->scope.voltage[channel].name << "\"," << this->dataAnalyzer->data(channel)->samples.voltage.interval;
  379 +
  380 + // And now all sample values in volts
  381 + for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.voltage.count; position++)
  382 + csvStream << "\"," << this->dataAnalyzer->data(channel)->samples.voltage.sample[position];
  383 +
  384 + // Finally a newline
  385 + csvStream << '\n';
  386 + }
351 } 387 }
352 388
353 - // Borders  
354 - painter.setPen(colorValues->border);  
355 - painter.drawRect(QRectF(-DIVS_TIME / 2, -DIVS_VOLTAGE / 2, DIVS_TIME, DIVS_VOLTAGE)); 389 + csvFile.close();
356 } 390 }
357 -  
358 - painter.end();  
359 -  
360 - if(this->format == EXPORT_FORMAT_IMAGE)  
361 - ((QPixmap *) paintDevice)->save(this->filename);  
362 -  
363 - return true;  
364 } 391 }
openhantek/src/exporter.h
@@ -41,7 +41,8 @@ class DataAnalyzer; @@ -41,7 +41,8 @@ class DataAnalyzer;
41 enum ExportFormat { 41 enum ExportFormat {
42 EXPORT_FORMAT_PRINTER, 42 EXPORT_FORMAT_PRINTER,
43 EXPORT_FORMAT_PDF, EXPORT_FORMAT_PS, 43 EXPORT_FORMAT_PDF, EXPORT_FORMAT_PS,
44 - EXPORT_FORMAT_IMAGE 44 + EXPORT_FORMAT_IMAGE,
  45 + EXPORT_FORMAT_CSV
45 }; 46 };
46 47
47 //////////////////////////////////////////////////////////////////////////////// 48 ////////////////////////////////////////////////////////////////////////////////
openhantek/src/openhantek.cpp
@@ -182,7 +182,7 @@ void OpenHantekMainWindow::createActions() { @@ -182,7 +182,7 @@ void OpenHantekMainWindow::createActions() {
182 connect(this->printAction, SIGNAL(triggered()), this->dsoWidget, SLOT(print())); 182 connect(this->printAction, SIGNAL(triggered()), this->dsoWidget, SLOT(print()));
183 183
184 this->exportAsAction = new QAction(QIcon(":actions/export-as.png"), tr("&Export as..."), this); 184 this->exportAsAction = new QAction(QIcon(":actions/export-as.png"), tr("&Export as..."), this);
185 - this->saveAction->setShortcut(tr("Ctrl+E")); 185 + this->exportAsAction->setShortcut(tr("Ctrl+E"));
186 this->exportAsAction->setStatusTip(tr("Export the oscilloscope data to a file")); 186 this->exportAsAction->setStatusTip(tr("Export the oscilloscope data to a file"));
187 connect(this->exportAsAction, SIGNAL(triggered()), this->dsoWidget, SLOT(exportAs())); 187 connect(this->exportAsAction, SIGNAL(triggered()), this->dsoWidget, SLOT(exportAs()));
188 188