Merge branch 'master' into checkupdates-fix

This commit is contained in:
Jeff Norman 2023-09-14 11:11:50 -04:00
commit c161ad13ce
13 changed files with 258 additions and 46 deletions

View File

@ -26,6 +26,7 @@
#define EXTRA_ASSERTS 1 #define EXTRA_ASSERTS 1
#if 0
QDataStream & operator<<(QDataStream & stream, const DottedLine & dot) QDataStream & operator<<(QDataStream & stream, const DottedLine & dot)
{ {
stream << dot.code; stream << dot.code;
@ -46,6 +47,7 @@ QDataStream & operator>>(QDataStream & stream, DottedLine & dot)
dot.type = (ChannelCalcType)tmp; dot.type = (ChannelCalcType)tmp;
return stream; return stream;
} }
#endif
QColor darken(QColor color, float p) QColor darken(QColor color, float p)
{ {

View File

@ -129,7 +129,7 @@ public:
//! \brief Returns true if Graphical animations & Transitions will be drawn //! \brief Returns true if Graphical animations & Transitions will be drawn
bool animations() const { return m_animations; } bool animations() const { return m_animations; }
//! \brief Returns true if PixmapCaching acceleration will be used //! \brief Returns true if PixmapCaching acceleration will be used
inline bool usePixmapCaching() const { return m_usePixmapCaching; } inline bool usePixmapCaching() const { return /*m_usePixmapCaching*/false; } //disables use pixmap caching without modifing any code.
//! \brief Returns true if Square Wave plots are preferred (where possible) //! \brief Returns true if Square Wave plots are preferred (where possible)
inline bool squareWavePlots() const { return m_squareWavePlots; } inline bool squareWavePlots() const { return m_squareWavePlots; }
//! \brief Whether to allow double clicking on Y-Axis labels to change vertical scaling mode //! \brief Whether to allow double clicking on Y-Axis labels to change vertical scaling mode

View File

@ -1049,6 +1049,8 @@ Profile *Get()
return profiles[getUserName()];; return profiles[getUserName()];;
} }
//profiles.xml is never read so it does not need to be saved.
#if 0
void saveProfileList() void saveProfileList()
{ {
QString filename = p_pref->Get("{home}/profiles.xml"); QString filename = p_pref->Get("{home}/profiles.xml");
@ -1078,6 +1080,7 @@ void saveProfileList()
file.close(); file.close();
} }
#endif
int CleanupProfile(Profile *prof) int CleanupProfile(Profile *prof)
{ {
@ -1157,7 +1160,8 @@ void Scan()
p_pref->Save(); p_pref->Save();
} }
// Update profiles.xml for mobile version // Update profiles.xml for mobile version
saveProfileList(); // profiles.xml is never read so it does not need to be saved.
// saveProfileList();
} }
@ -1993,7 +1997,8 @@ const quint16 chandata_version = 1;
void Profile::saveChannels() void Profile::saveChannels()
{ {
// First save the XML version for Mobile versions // First save the XML version for Mobile versions
schema::channel.Save(Get("{DataFolder}/") + "channels.xml"); // Profile/User/chanels.xml is not read so it does not need to be saved
// schema::channel.Save(Get("{DataFolder}/") + "channels.xml");
QString filename = Get("{DataFolder}/") + "channels.dat"; QString filename = Get("{DataFolder}/") + "channels.dat";
QFile f(filename); QFile f(filename);

View File

@ -47,7 +47,7 @@ void resetChannels();
ChannelList channel; ChannelList channel;
Channel EmptyChannel; Channel EmptyChannel;
Channel *SessionEnabledChannel; // SessionEnabledChannel is not used//Channel *SessionEnabledChannel;
QHash<QString, ChanType> ChanTypes; QHash<QString, ChanType> ChanTypes;
QHash<QString, DataType> DataTypes; QHash<QString, DataType> DataTypes;
@ -91,11 +91,13 @@ void init()
schema_initialized = true; schema_initialized = true;
EmptyChannel = Channel(0, DATA, MT_UNKNOWN, DAY, "Empty", "Empty", "Empty Channel", "", ""); EmptyChannel = Channel(0, DATA, MT_UNKNOWN, DAY, "Empty", "Empty", "Empty Channel", "", "");
#if 0 // SessionEnabledChannel is not used
SessionEnabledChannel = new Channel(1, DATA, MT_UNKNOWN, DAY, "Enabled", "Enabled", "Session Enabled", "", ""); SessionEnabledChannel = new Channel(1, DATA, MT_UNKNOWN, DAY, "Enabled", "Enabled", "Session Enabled", "", "");
channel.channels[1] = SessionEnabledChannel; channel.channels[1] = SessionEnabledChannel;
channel.names["Enabled"] = SessionEnabledChannel; channel.names["Enabled"] = SessionEnabledChannel;
SESSION_ENABLED = 1; SESSION_ENABLED = 1;
#endif // SessionEnabledChannel is not used
ChanTypes["data"] = DATA; ChanTypes["data"] = DATA;
//Types["waveform"]=WAVEFORM; //Types["waveform"]=WAVEFORM;
ChanTypes["setting"] = SETTING; ChanTypes["setting"] = SETTING;
@ -695,6 +697,7 @@ void ChannelList::add(QString group, Channel *chan)
} }
} }
#if 0 // Profile/User/chanels.xml is not read so it does not need to be saved
bool ChannelList::Save(QString filename) bool ChannelList::Save(QString filename)
{ {
if (filename.isEmpty()) if (filename.isEmpty())
@ -757,6 +760,7 @@ bool ChannelList::Save(QString filename)
return true; return true;
} }
#endif // Profile/User/chanels.xml is not read so it does not need to be saved
} // namespace } // namespace

View File

@ -1,4 +1,5 @@
// Update the string below to set OSCAR's version and release status. // Update the string below to set OSCAR's version and release status.
// See https://semver.org/spec/v2.0.0.html for details on format. // See https://semver.org/spec/v2.0.0.html for details on format.
#define VERSION "1.5.0" #define VERSION "1.5.1-alpha-1"

120
oscar/highresolution.cpp Normal file
View File

@ -0,0 +1,120 @@
/* Hi Resolution Implementation
*
* Copyright (c) 2023 The OSCAR Team
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the source code
* for more details. */
#define TEST_MACROS_ENABLEDoff
#include <test_macros.h>
#include <QMessageBox>
#include <QDebug>
#include <QCheckBox>
#include <QFileDialog>
#include "SleepLib/profiles.h"
#include "highresolution.h"
namespace HighResolution {
const QString HI_RES_FILENAME("hiResolutionMode.txt");
HiResolutionMode hiResolutionNextSessionMode = HRM_INVALID;
HiResolutionMode hiResolutionOperaingMode = HRM_INVALID;
int readMode( QString filename) {
QFile file ( filename );
int mode=0;
if (file.open(QFile::ReadOnly)) {
QTextStream in(&file);
in >> mode;
file.close();
}
return mode;
}
void writeMode( QString filename, int data , QString description) {
QFile file ( filename );
if (file.open(QFile::WriteOnly|QFile::Text)) {
QTextStream out(&file);
out << data << " " << description << "\n" ;
file.close();
}
}
HiResolutionMode setHiResolutionMode(HiResolutionMode value) {
QString filename = GetAppData() + HI_RES_FILENAME;
if (value == HRM_ENABLED ) {
writeMode( filename , HRM_ENABLED ,"HiResolutionMode Enabled");
return HRM_ENABLED;
} else {
writeMode( filename , HRM_DISABLED , "HiResolutionMode Disabled");
}
return HRM_DISABLED;
}
HiResolutionMode getHiResolutionMode() {
QString filename = GetAppData() + HI_RES_FILENAME;
int hiResMode= readMode( filename );
return (hiResMode == HRM_ENABLED ) ? HRM_ENABLED : HRM_DISABLED ;
}
// this function is used to control the text name of the high resolution preference checkbox.
void checkBox(bool set,QCheckBox* button) {
if (set) {
hiResolutionNextSessionMode = button->isChecked()? HRM_ENABLED : HRM_DISABLED ;
setHiResolutionMode(hiResolutionNextSessionMode);
if ( hiResolutionOperaingMode != hiResolutionNextSessionMode ) {
QMessageBox::information(nullptr,
STR_MessageBox_Information,
QObject::tr("High Resolution Mode change will take effect when OSCAR is restarted."));
}
return;
}
QString label;
if (hiResolutionNextSessionMode == HRM_ENABLED ) {
if ( hiResolutionOperaingMode == hiResolutionNextSessionMode ) {
label = QObject::tr("High Resolution Mode is Enabled");
} else {
label = QObject::tr("The High Resolution Mode will be Enabled after Oscar is restarted.");
}
button->setChecked(true);
} else {
if ( hiResolutionOperaingMode == hiResolutionNextSessionMode ) {
label = QObject::tr("High Resolution Mode is Disabled");
} else {
label = QObject::tr("High Resolution Mode will be Disabled after Oscar is restarted.");
}
button->setChecked(false);
}
button->setText(label);
}
// These functions are for main.cpp
void init() {
hiResolutionOperaingMode = getHiResolutionMode();
};
void init(HiResolutionMode mode) {
hiResolutionOperaingMode = mode;
};
bool isEnabled() {
hiResolutionNextSessionMode = hiResolutionOperaingMode ;
return hiResolutionOperaingMode >= HRM_ENABLED;
};
void display(bool actuallyEnabled) {
bool shouldBeEnabled= (hiResolutionOperaingMode >= HRM_ENABLED) ;
if (shouldBeEnabled != actuallyEnabled) {
DEBUGFC O("RESULT MISMATCH") Q(hiResolutionOperaingMode) Q(shouldBeEnabled) Q(actuallyEnabled);
}
if (actuallyEnabled) {
qDebug() << "High Resolution Mode is Enabled";
} else {
qDebug() << "High Resolution Mode is Disabled";
}
}
}

26
oscar/highresolution.h Normal file
View File

@ -0,0 +1,26 @@
/* Overview GUI Headers
*
* Copyright (c) 2023-2023 The OSCAR Team
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the source code
* for more details. */
#ifndef HIGHRESOLUTION_H
#define HIGHRESOLUTION_H
namespace HighResolution {
// used by main.cpp
enum HiResolutionMode {HRM_INVALID = 0 , HRM_DISABLED = 1, HRM_ENABLED = 2} ;
void init();
void init(HiResolutionMode);
bool isEnabled();
void display(bool);
// used by preferences
void checkBox(bool set,QCheckBox* button);
}
#endif // HIGHRESOLUTION_H

View File

@ -32,6 +32,7 @@
#include "translation.h" #include "translation.h"
#include "SleepLib/common.h" #include "SleepLib/common.h"
#include "SleepLib/deviceconnection.h" #include "SleepLib/deviceconnection.h"
#include "highresolution.h"
#include <ctime> #include <ctime>
#include <chrono> #include <chrono>
@ -286,13 +287,48 @@ bool shiftKeyPressedAtLaunch(int argc, char *argv[])
} }
#endif #endif
int main(int argc, char *argv[]) {
void optionExit(int exitCode, QString error) {
if (exitCode) {
error.prepend("Command option error: ");
}
qCritical() << error << ( R"(
Help Menu
Option Description
-p Pauses execution for 1 second
--profile <name> Name of profile. if name does not exist then uses last used profile.
--l or --language Force language prompt
--datadir <folderName> Use folderName as Oscar Data folder. For relatve paths: <Documents folder>/<relative path>.
If folder does not exist then prompts user.
--help Displays this menu and exits.
--hires Enables high Resolution
--hiresoff Disables high Resolution
)" );
exit (exitCode);
}
int main(int argc, char *argv[]) {
QString homeDocs = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)+"/"; QString homeDocs = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)+"/";
QCoreApplication::setApplicationName(getAppName()); QCoreApplication::setApplicationName(getAppName());
QCoreApplication::setOrganizationName(getDeveloperName()); QCoreApplication::setOrganizationName(getDeveloperName());
QCoreApplication::setOrganizationDomain(getDeveloperDomain()); QCoreApplication::setOrganizationDomain(getDeveloperDomain());
HighResolution::init();
bool hiResEnabled=false;
for (int i = 1; i < argc; i++) {
if (0 == strcmp(argv[i] ,"--hires")) {
HighResolution::init(HighResolution::HRM_ENABLED);
} else if (0 == strcmp(argv[i] ,"--hiresoff")) {
HighResolution::init(HighResolution::HRM_DISABLED);
} else if (0 == strcmp(argv[i] ,"--datadir")) { i++;
} else if (0 == strcmp(argv[i] ,"-profile")) { i++;
}
}
if (HighResolution::isEnabled()) {
hiResEnabled=true;
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
QSettings settings; QSettings settings;
@ -338,8 +374,8 @@ int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
} }
QApplication a(argc, argv); QApplication mainapp(argc, argv);
QStringList args = a.arguments(); QStringList args = mainapp.arguments();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// QMessageBox must come after the application is created. The graphics engine has to be selected before. // QMessageBox must come after the application is created. The graphics engine has to be selected before.
@ -359,36 +395,18 @@ int main(int argc, char *argv[]) {
// The only time this is really noticeable is when initTranslations() presents its language // The only time this is really noticeable is when initTranslations() presents its language
// selection QDialog, which waits indefinitely for user input before MainWindow is constructed. // selection QDialog, which waits indefinitely for user input before MainWindow is constructed.
QString lastlanguage = settings.value(LangSetting, "").toString();
if (lastlanguage.compare("is", Qt::CaseInsensitive)) // Convert code for Hebrew from 'is' to 'he'
lastlanguage = "he";
bool dont_load_profile = false;
bool force_data_dir = false; bool force_data_dir = false;
bool changing_language = false;
QString load_profile = ""; QString load_profile = "";
if (lastlanguage.isEmpty())
changing_language = true;
for (int i = 1; i < args.size(); i++) { for (int i = 1; i < args.size(); i++) {
if (args[i] == "-l") if ((args[i] == "--language") || (args[i] == "--l") ) {
dont_load_profile = true;
// else if (args[i] == "-d")
// force_data_dir = true;
else if (args[i] == "--language") {
changing_language = true; // reset to force language dialog
settings.setValue(LangSetting,""); settings.setValue(LangSetting,"");
} } else if (args[i] == "-p") {
// "--legacy" is handle above, as it needs to be processed before creating QApplication.
else if (args[i] == "-p")
QThread::msleep(1000); QThread::msleep(1000);
else if (args[i] == "--profile") { } else if (args[i] == "--profile") {
if ((i+1) < args.size()) if ((i+1) < args.size())
load_profile = args[++i]; load_profile = args[++i];
else { else {
fprintf(stderr, "Missing argument to --profile\n"); optionExit(1,"Missing argument to --profile");
exit(1);
} }
} else if (args[i] == "--datadir") { // mltam's idea } else if (args[i] == "--datadir") { // mltam's idea
QString datadir, datadirwas ; QString datadir, datadirwas ;
@ -400,22 +418,30 @@ int main(int argc, char *argv[]) {
|| (datadir.at(0) == '/') // or Linux full path || (datadir.at(0) == '/') // or Linux full path
|| (datadir.at(0) == '\\'); || (datadir.at(0) == '\\');
} }
if (!havefullpath) if (!havefullpath) {
datadir = homeDocs+datadir; datadir = homeDocs+datadir;
qDebug() << "--datadir was:" << datadirwas << "; --datadir is:" << datadir;
}
settings.setValue("Settings/AppData", datadir); settings.setValue("Settings/AppData", datadir);
qDebug() << "--datadir" << datadirwas << "homeDocs:" << homeDocs << "appdata:" << datadir;
// force_data_dir = true; // force_data_dir = true;
} else { } else {
fprintf(stderr, "Missing argument to --datadir\n"); optionExit(2,"Missing argument to --datadir\n");
exit(1);
} }
} else if (0 == strcmp(argv[i] ,"--hires")) { // already handle in 1st scan
} else if (0 == strcmp(argv[i] ,"--hiresoff")) { // already handle in 1st scan
} else if (QString(args[i]).contains("help",Qt::CaseInsensitive)) {
optionExit(0,QString(""));
} else {
optionExit(3,QString("Invalid Argument. %1").arg(args[i]));
} }
} // end of for args loop } // end of for args loop
qDebug().noquote() << "OSCAR starting" << QDateTime::currentDateTime().toString(); qDebug().noquote() << "OSCAR starting" << QDateTime::currentDateTime().toString();
qDebug() << "APP-NAME:" << QCoreApplication::applicationName(); qDebug() << "APP-NAME:" << QCoreApplication::applicationName();
qDebug() << "APP-PATH:" << QCoreApplication::applicationDirPath(); qDebug() << "APP-PATH:" << QCoreApplication::applicationDirPath();
qDebug() << "APP-RESOURCES:" << appResourcePath(); qDebug() << "APP-RESOURCES:" << appResourcePath();
HighResolution::display(hiResEnabled);
#ifdef QT_DEBUG #ifdef QT_DEBUG
QString relinfo = " debug"; QString relinfo = " debug";
@ -564,10 +590,11 @@ int main(int argc, char *argv[]) {
QDir newDir(GetAppData()); QDir newDir(GetAppData());
#if QT_VERSION < QT_VERSION_CHECK(5,9,0) #if QT_VERSION < QT_VERSION_CHECK(5,9,0)
if ( ! newDir.exists() || newDir.count() == 0 ) { // directory doesn't exist yet or is empty, try to migrate old data if ( ! newDir.exists() || newDir.count() == 0 ) // directory doesn't exist yet or is empty, try to migrate old data
#else #else
if ( ! newDir.exists() || newDir.isEmpty() ) { // directory doesn't exist yet or is empty, try to migrate old data if ( ! newDir.exists() || newDir.isEmpty() ) // directory doesn't exist yet or is empty, try to migrate old data
#endif #endif
{
if (QMessageBox::question(nullptr, QObject::tr("Migrate SleepyHead or OSCAR Data?"), if (QMessageBox::question(nullptr, QObject::tr("Migrate SleepyHead or OSCAR Data?"),
QObject::tr("On the next screen OSCAR will ask you to select a folder with SleepyHead or OSCAR data") +"\n" + QObject::tr("On the next screen OSCAR will ask you to select a folder with SleepyHead or OSCAR data") +"\n" +
QObject::tr("Click [OK] to go to the next screen or [No] if you do not wish to use any SleepyHead or OSCAR data."), QObject::tr("Click [OK] to go to the next screen or [No] if you do not wish to use any SleepyHead or OSCAR data."),
@ -605,6 +632,7 @@ int main(int argc, char *argv[]) {
QObject::tr("Unable to write to debug log. You can still use the debug pane (Help/Troubleshooting/Show Debug Pane) but the debug log will not be written to disk.")); QObject::tr("Unable to write to debug log. You can still use the debug pane (Help/Troubleshooting/Show Debug Pane) but the debug log will not be written to disk."));
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Initialize preferences system (Don't use p_pref before this point!) // Initialize preferences system (Don't use p_pref before this point!)
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -720,9 +748,6 @@ int main(int argc, char *argv[]) {
// Scan for user profiles // Scan for user profiles
Profiles::Scan(); Profiles::Scan();
Q_UNUSED(changing_language)
Q_UNUSED(dont_load_profile)
#ifndef NO_CHECKUPDATES #ifndef NO_CHECKUPDATES
if (check_updates) { if (check_updates) {
mainwin->CheckForUpdates(false); mainwin->CheckForUpdates(false);
@ -732,7 +757,7 @@ int main(int argc, char *argv[]) {
mainwin->SetupGUI(); mainwin->SetupGUI();
mainwin->show(); mainwin->show();
int result = a.exec(); int result = mainapp.exec();
DeviceConnectionManager::getInstance().record(nullptr); DeviceConnectionManager::getInstance().record(nullptr);

View File

@ -274,7 +274,7 @@ void MainWindow::closeEvent(QCloseEvent * event)
QThread::msleep(1000); QThread::msleep(1000);
QApplication::processEvents(); QApplication::processEvents();
} }
schema::channel.Save(); // Profile/User/chanels.xml is not read so it does not need to be saved//schema::channel.Save();
if (p_profile) { if (p_profile) {
CloseProfile(); CloseProfile();
} }

View File

@ -255,6 +255,7 @@ lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,12) {
SOURCES += \ SOURCES += \
checkupdates.cpp \ checkupdates.cpp \
highresolution.cpp \
Graphs/gGraph.cpp \ Graphs/gGraph.cpp \
Graphs/gGraphView.cpp \ Graphs/gGraphView.cpp \
dailySearchTab.cpp \ dailySearchTab.cpp \
@ -364,6 +365,7 @@ QMAKE_EXTRA_COMPILERS += optimize
HEADERS += \ HEADERS += \
checkupdates.h \ checkupdates.h \
highresolution.h \
dailySearchTab.h \ dailySearchTab.h \
daily.h \ daily.h \
saveGraphLayoutSettings.h \ saveGraphLayoutSettings.h \

View File

@ -31,6 +31,7 @@
#include <mainwindow.h> #include <mainwindow.h>
#include "ui_preferencesdialog.h" #include "ui_preferencesdialog.h"
#include "SleepLib/machine_common.h" #include "SleepLib/machine_common.h"
#include "highresolution.h"
extern QFont *defaultfont; extern QFont *defaultfont;
extern QFont *mediumfont; extern QFont *mediumfont;
@ -248,6 +249,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent, Profile *_profile) :
// clinicalMode and permissiveMode are radio buttons and must be set to opposite values. Once clinicalMode is used. // clinicalMode and permissiveMode are radio buttons and must be set to opposite values. Once clinicalMode is used.
// Radio Buttons illustrate the operating mode. // Radio Buttons illustrate the operating mode.
ui->permissiveMode->setChecked(!profile->cpap->clinicalMode()); ui->permissiveMode->setChecked(!profile->cpap->clinicalMode());
HighResolution::checkBox(false,ui->highResolution);
ui->autoLaunchImporter->setChecked(AppSetting->autoLaunchImport()); ui->autoLaunchImporter->setChecked(AppSetting->autoLaunchImport());
#ifndef NO_CHECKUPDATES #ifndef NO_CHECKUPDATES
@ -860,6 +862,7 @@ bool PreferencesDialog::Save()
AppSetting->setMonochromePrinting(ui->monochromePrinting->isChecked()); AppSetting->setMonochromePrinting(ui->monochromePrinting->isChecked());
p_profile->appearance->setEventFlagSessionBar(ui->eventFlagSessionBar->isChecked()); p_profile->appearance->setEventFlagSessionBar(ui->eventFlagSessionBar->isChecked());
p_profile->cpap->setClinicalMode(ui->clinicalMode->isChecked()); p_profile->cpap->setClinicalMode(ui->clinicalMode->isChecked());
HighResolution::checkBox(true,ui->highResolution);
AppSetting->setGraphTooltips(ui->graphTooltips->isChecked()); AppSetting->setGraphTooltips(ui->graphTooltips->isChecked());
AppSetting->setAntiAliasing(ui->useAntiAliasing->isChecked()); AppSetting->setAntiAliasing(ui->useAntiAliasing->isChecked());

View File

@ -2835,6 +2835,9 @@ Try it and see if you like it.</string>
<property name="text"> <property name="text">
<string>Use Pixmap Caching</string> <string>Use Pixmap Caching</string>
</property> </property>
<property name="visible" stdset="0">
<bool>false</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -2897,6 +2900,16 @@ Try it and see if you like it.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="highResolution">
<property name="toolTip">
<string> Enables High Resoluton Mode. Changes take effect when Oscar is restarted.</string>
</property>
<property name="text">
<string>Enables High Resolutiom Mode</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">

View File

@ -142,7 +142,18 @@ void Statistics::loadRXChanges()
in >> rxitems; in >> rxitems;
{ // Bug Fix. during testing, a crash occured due to a null machie value. in saveRxChanges. out << rx.machine->loaderName()
QList<QDate> toErase;
for (auto ri = rxitems.begin(); ri != rxitems.end();++ri ) {
RXItem rxitem = ri.value();
if (rxitem.machine==0) toErase.append(ri.key());
}
for (auto date : toErase) {
rxitems.remove(date) ;
}
}
} }
void Statistics::saveRXChanges() void Statistics::saveRXChanges()
{ {
QString path = p_profile->Get("{" + STR_GEN_DataFolder + "}/RXChanges.cache" ); QString path = p_profile->Get("{" + STR_GEN_DataFolder + "}/RXChanges.cache" );