mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-31 17:42:55 +08:00
Fix UTF-8 issue with CSV files opened in Excel
This commit is contained in:
parent
d2690de4f9
commit
cf839fd8e7
@ -42,6 +42,8 @@ Widgets.Window {
|
||||
//
|
||||
Settings {
|
||||
category: "Device Manager"
|
||||
property alias dmAuto: commAuto.checked
|
||||
property alias dmManual: commManual.checked
|
||||
property alias dmParity: parity.currentIndex
|
||||
property alias dmStopBits: stopBits.currentIndex
|
||||
property alias dmBaudRate: baudRate.currentIndex
|
||||
|
@ -30,5 +30,9 @@ import Dataset 1.0
|
||||
import "../Widgets"
|
||||
|
||||
Item {
|
||||
|
||||
AccelerometerDelegate {
|
||||
width: 250
|
||||
height: 250
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
@ -127,15 +127,10 @@ Page {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
Item {
|
||||
Components.WidgetGrid {
|
||||
id: widgetGrid
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Widgets.MapDelegate {
|
||||
id: gpsMap
|
||||
anchors.fill: parent
|
||||
anchors.margins: app.spacing * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,91 @@
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
Item {
|
||||
import Group 1.0
|
||||
import Dataset 1.0
|
||||
|
||||
RowLayout {
|
||||
id: accel
|
||||
spacing: app.spacing
|
||||
|
||||
//
|
||||
// Custom properties
|
||||
//
|
||||
property int index: 0
|
||||
property real accX: 0
|
||||
property real accY: 0
|
||||
property real accZ: 0
|
||||
property string title: ""
|
||||
property real meanGForce: 0
|
||||
property real gConstant: 9.80665
|
||||
|
||||
//
|
||||
// Calculates the mean g force for all three axes using the pythagorean theorem
|
||||
//
|
||||
function calculateMeanGForce() {
|
||||
if (CppWidgets.accelerometerGroupCount() > accel.index) {
|
||||
accel.accX = CppWidgets.accelerometerX(accel.index)
|
||||
accel.accY = CppWidgets.accelerometerY(accel.index)
|
||||
accel.accZ = CppWidgets.accelerometerZ(accel.index)
|
||||
accel.title = CppWidgets.accelerometerGroupAt(accel.index).title
|
||||
}
|
||||
|
||||
else {
|
||||
accel.accX = 0
|
||||
accel.accY = 0
|
||||
accel.accZ = 0
|
||||
accel.title = 0
|
||||
}
|
||||
|
||||
var gX = accel.accX / accel.gConstant
|
||||
var gY = accel.accY / accel.gConstant
|
||||
var gZ = accel.accZ / accel.gConstant
|
||||
|
||||
accel.meanGForce = Math.sqrt(Math.pow(gX, 2) + Math.pow(gY, 2) + Math.pow(gZ, 2))
|
||||
}
|
||||
|
||||
//
|
||||
// Accelerometer circle
|
||||
//
|
||||
Rectangle {
|
||||
width: height
|
||||
color: "#444"
|
||||
border.width: 2
|
||||
radius: width / 2
|
||||
border.color: "#bebebe"
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
//
|
||||
// Indicator controls
|
||||
//
|
||||
ColumnLayout {
|
||||
spacing: app.spacing
|
||||
Layout.fillHeight: true
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
LED {
|
||||
onColor: "#f00"
|
||||
text: qsTr("Cont. value")
|
||||
}
|
||||
|
||||
LED {
|
||||
onColor: "#0f0"
|
||||
text: qsTr("Max. value")
|
||||
}
|
||||
|
||||
LED {
|
||||
onColor: "#00f"
|
||||
text: qsTr("Min. value")
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,29 +60,6 @@ ColumnLayout {
|
||||
//
|
||||
readonly property var gpsCoordinates: QtPositioning.coordinate(latitude, longitude)
|
||||
|
||||
//
|
||||
// Center map when connecting with CanSat
|
||||
//
|
||||
Connections {
|
||||
target: CppQmlBridge
|
||||
|
||||
function onUpdated() {
|
||||
if (oldCoordinates === QtPositioning.coordinate(0,0)) {
|
||||
map.center = gpsCoordinates
|
||||
oldCoordinates = gpsCoordinates
|
||||
}
|
||||
|
||||
gps.latitude = CppQmlBridge.gpsLatitude
|
||||
gps.longitude = CppQmlBridge.gpsLongitude
|
||||
}
|
||||
} Connections {
|
||||
target: CppSerialManager
|
||||
|
||||
function onPortChanged() {
|
||||
oldCoordinates = QtPositioning.coordinate(0,0)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Centers the map to Queretaro if the GPS is not working,
|
||||
// otherwise, centers the map to the CanSat's position
|
||||
|
@ -106,6 +106,9 @@ ApplicationWindow {
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 500
|
||||
onTriggered: app.visible = true
|
||||
onTriggered: {
|
||||
app.visible = true
|
||||
CppJsonParser.readSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,8 @@ void Export::closeFile()
|
||||
writeValues();
|
||||
|
||||
m_csvFile.close();
|
||||
m_textStream.setDevice(Q_NULLPTR);
|
||||
|
||||
emit openChanged();
|
||||
}
|
||||
}
|
||||
@ -228,7 +230,7 @@ void Export::writeValues()
|
||||
|
||||
// Open file
|
||||
m_csvFile.setFileName(dir.filePath(fileName));
|
||||
if (!m_csvFile.open(QFile::WriteOnly))
|
||||
if (!m_csvFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
QMessageBox::critical(Q_NULLPTR, tr("CSV File Error"), tr("Cannot open CSV file for writing!"),
|
||||
QMessageBox::Ok);
|
||||
@ -236,14 +238,17 @@ void Export::writeValues()
|
||||
break;
|
||||
}
|
||||
|
||||
// Add cell titles
|
||||
// Add cell titles & force UTF-8 codec
|
||||
m_textStream.setDevice(&m_csvFile);
|
||||
m_textStream.setCodec("UTF-8");
|
||||
m_textStream.setGenerateByteOrderMark(true);
|
||||
for (int i = 0; i < titles.count(); ++i)
|
||||
{
|
||||
m_csvFile.write(titles.at(i).toUtf8());
|
||||
m_textStream << titles.at(i).toUtf8();
|
||||
if (i < titles.count() - 1)
|
||||
m_csvFile.write(",");
|
||||
m_textStream << ",";
|
||||
else
|
||||
m_csvFile.write("\n");
|
||||
m_textStream << "\n";
|
||||
}
|
||||
|
||||
// Update UI
|
||||
@ -253,11 +258,11 @@ void Export::writeValues()
|
||||
// Write cell values
|
||||
for (int i = 0; i < values.count(); ++i)
|
||||
{
|
||||
m_csvFile.write(values.at(i).toUtf8());
|
||||
m_textStream << values.at(i).toUtf8();
|
||||
if (i < values.count() - 1)
|
||||
m_csvFile.write(",");
|
||||
m_textStream << ",";
|
||||
else
|
||||
m_csvFile.write("\n");
|
||||
m_textStream << "\n";
|
||||
}
|
||||
|
||||
// Remove JSON from list
|
||||
|
@ -47,15 +47,16 @@ private:
|
||||
|
||||
public slots:
|
||||
void openCsv();
|
||||
void closeFile();
|
||||
void openCurrentCsv();
|
||||
|
||||
private slots:
|
||||
void closeFile();
|
||||
void writeValues();
|
||||
void updateValues();
|
||||
|
||||
private:
|
||||
QFile m_csvFile;
|
||||
QTextStream m_textStream;
|
||||
QList<QPair<QDateTime, QJsonObject>> m_jsonList;
|
||||
};
|
||||
|
||||
|
@ -139,7 +139,7 @@ void JsonParser::loadJsonMap()
|
||||
/**
|
||||
* Opens, validates & loads into memory the JSON file in the given @a path.
|
||||
*/
|
||||
void JsonParser::loadJsonMap(const QString &path)
|
||||
void JsonParser::loadJsonMap(const QString &path, const bool silent)
|
||||
{
|
||||
// Validate path
|
||||
if (path.isEmpty())
|
||||
@ -163,23 +163,26 @@ void JsonParser::loadJsonMap(const QString &path)
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
m_jsonMap.close();
|
||||
writeSettings("");
|
||||
NiceMessageBox(tr("JSON parse error"), error.errorString());
|
||||
}
|
||||
|
||||
// JSON contains no errors
|
||||
// JSON contains no errors, load data & save settings
|
||||
else
|
||||
{
|
||||
writeSettings(path);
|
||||
m_jsonMapData = QString::fromUtf8(data);
|
||||
NiceMessageBox(tr("JSON map file loaded successfully!"),
|
||||
tr("File \"%1\" loaded into memory").arg(jsonMapFilename()));
|
||||
if (!silent)
|
||||
NiceMessageBox(tr("JSON map file loaded successfully!"),
|
||||
tr("File \"%1\" loaded into memory").arg(jsonMapFilename()));
|
||||
}
|
||||
}
|
||||
|
||||
// Open error
|
||||
else
|
||||
{
|
||||
NiceMessageBox(tr("Cannot read file contents"),
|
||||
tr("Failed to read contents of \"%1\", check file permissions").arg(jsonMapFilename()));
|
||||
writeSettings("");
|
||||
NiceMessageBox(tr("Cannot read JSON file"), tr("Please check file permissions & location"));
|
||||
m_jsonMap.close();
|
||||
}
|
||||
|
||||
@ -204,6 +207,24 @@ void JsonParser::setOperationMode(const OperationMode mode)
|
||||
emit operationModeChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the last saved JSON map file (if any)
|
||||
*/
|
||||
void JsonParser::readSettings()
|
||||
{
|
||||
auto path = m_settings.value("json_map_location", "").toString();
|
||||
if (!path.isEmpty())
|
||||
loadJsonMap(path, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the location of the last valid JSON map file that was opened (if any)
|
||||
*/
|
||||
void JsonParser::writeSettings(const QString &path)
|
||||
{
|
||||
m_settings.setValue("json_map_location", path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to parse the given data as a JSON document according to the selected
|
||||
* operation mode.
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QQmlEngine>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonValue>
|
||||
@ -62,17 +63,22 @@ public:
|
||||
|
||||
public slots:
|
||||
void loadJsonMap();
|
||||
void loadJsonMap(const QString &path);
|
||||
void setOperationMode(const OperationMode mode);
|
||||
void loadJsonMap(const QString &path, const bool silent = false);
|
||||
|
||||
private:
|
||||
JsonParser();
|
||||
|
||||
public slots:
|
||||
void readSettings();
|
||||
void writeSettings(const QString &path);
|
||||
|
||||
private slots:
|
||||
void readData(const QByteArray &data);
|
||||
|
||||
private:
|
||||
QFile m_jsonMap;
|
||||
QSettings m_settings;
|
||||
QString m_jsonMapData;
|
||||
OperationMode m_opMode;
|
||||
QJsonDocument m_document;
|
||||
|
@ -43,8 +43,5 @@ ModuleManager::ModuleManager()
|
||||
*/
|
||||
void ModuleManager::deleteModules()
|
||||
{
|
||||
Export::getInstance()->deleteLater();
|
||||
QmlBridge::getInstance()->deleteLater();
|
||||
GraphProvider::getInstance()->deleteLater();
|
||||
SerialManager::getInstance()->deleteLater();
|
||||
Export::getInstance()->closeFile();
|
||||
}
|
||||
|
@ -44,40 +44,40 @@ public:
|
||||
QList<Group *> gaugeGroup() const;
|
||||
QList<Group *> accelerometerGroup() const;
|
||||
|
||||
int barGroupCount() const;
|
||||
int mapGroupCount() const;
|
||||
int gyroGroupCount() const;
|
||||
int tankGroupCount() const;
|
||||
int gaugeGroupCount() const;
|
||||
int accelerometerGroupCount() const;
|
||||
Q_INVOKABLE int barGroupCount() const;
|
||||
Q_INVOKABLE int mapGroupCount() const;
|
||||
Q_INVOKABLE int gyroGroupCount() const;
|
||||
Q_INVOKABLE int tankGroupCount() const;
|
||||
Q_INVOKABLE int gaugeGroupCount() const;
|
||||
Q_INVOKABLE int accelerometerGroupCount() const;
|
||||
|
||||
Group *barGroupAt(const int index);
|
||||
Group *mapGroupAt(const int index);
|
||||
Group *gyroGroupAt(const int index);
|
||||
Group *tankGroupAt(const int index);
|
||||
Group *gaugeGroupAt(const int index);
|
||||
Group *accelerometerGroupAt(const int index);
|
||||
Q_INVOKABLE Group *barGroupAt(const int index);
|
||||
Q_INVOKABLE Group *mapGroupAt(const int index);
|
||||
Q_INVOKABLE Group *gyroGroupAt(const int index);
|
||||
Q_INVOKABLE Group *tankGroupAt(const int index);
|
||||
Q_INVOKABLE Group *gaugeGroupAt(const int index);
|
||||
Q_INVOKABLE Group *accelerometerGroupAt(const int index);
|
||||
|
||||
double gyroX(const int index);
|
||||
double gyroY(const int index);
|
||||
double gyroZ(const int index);
|
||||
Q_INVOKABLE double gyroX(const int index);
|
||||
Q_INVOKABLE double gyroY(const int index);
|
||||
Q_INVOKABLE double gyroZ(const int index);
|
||||
|
||||
double accelerometerX(const int index);
|
||||
double accelerometerY(const int index);
|
||||
double accelerometerZ(const int index);
|
||||
Q_INVOKABLE double accelerometerX(const int index);
|
||||
Q_INVOKABLE double accelerometerY(const int index);
|
||||
Q_INVOKABLE double accelerometerZ(const int index);
|
||||
|
||||
double bar(const int index);
|
||||
double tank(const int index);
|
||||
double gauge(const int index);
|
||||
double barMin(const int index);
|
||||
double barMax(const int index);
|
||||
double tankMin(const int index);
|
||||
double tankMax(const int index);
|
||||
double gaugeMin(const int index);
|
||||
double gaugeMax(const int index);
|
||||
Q_INVOKABLE double bar(const int index);
|
||||
Q_INVOKABLE double tank(const int index);
|
||||
Q_INVOKABLE double gauge(const int index);
|
||||
Q_INVOKABLE double barMin(const int index);
|
||||
Q_INVOKABLE double barMax(const int index);
|
||||
Q_INVOKABLE double tankMin(const int index);
|
||||
Q_INVOKABLE double tankMax(const int index);
|
||||
Q_INVOKABLE double gaugeMin(const int index);
|
||||
Q_INVOKABLE double gaugeMax(const int index);
|
||||
|
||||
double mapLatitude(const int index);
|
||||
double mapLongitude(const int index);
|
||||
Q_INVOKABLE double mapLatitude(const int index);
|
||||
Q_INVOKABLE double mapLongitude(const int index);
|
||||
|
||||
private slots:
|
||||
void updateModels();
|
||||
|
Loading…
x
Reference in New Issue
Block a user