mirror of
https://github.com/Indy970/QtHPConnect
synced 2025-01-19 10:26:28 +01:00
Cleaned closing
This commit is contained in:
parent
780e808e5a
commit
725d0c1dab
32 changed files with 303 additions and 165 deletions
167
abstractdata.cpp
167
abstractdata.cpp
|
@ -27,23 +27,23 @@ int BCD2I(quint8 num) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
quint32 TwosComplement2Int(quint32 rawValue)
|
||||
qint32 TwosComplement2Int(quint32 rawValue)
|
||||
{
|
||||
|
||||
quint32 ret;
|
||||
qint32 ret;
|
||||
|
||||
log(QString("2C: %1").arg(rawValue& 0x80000000,1,16));
|
||||
|
||||
// If a positive value, return it
|
||||
if ((rawValue & 0x80000000) == 0)
|
||||
{
|
||||
ret = rawValue;
|
||||
ret = static_cast<qint32>(rawValue);
|
||||
}
|
||||
else {
|
||||
// Otherwise perform the 2's complement math on the value
|
||||
log(QString("List 2C Negative Detected"));
|
||||
|
||||
ret = (quint32)(~(rawValue - 0x01)) * -1;
|
||||
ret = static_cast<qint32>(~(rawValue - 0x01)) * - 1;
|
||||
// ret = ~rawValue;
|
||||
}
|
||||
log(QString("2C: %1 %2").arg(rawValue,1,16).arg(ret,1,16));
|
||||
|
@ -51,7 +51,7 @@ quint32 TwosComplement2Int(quint32 rawValue)
|
|||
return ret;
|
||||
}
|
||||
|
||||
qint16 TwosComp2Int_8(quint16 rawValue)
|
||||
qint16 TwosComp2Int_8(qint16 rawValue)
|
||||
{
|
||||
|
||||
qint16 ret;
|
||||
|
@ -77,11 +77,11 @@ QString value2Str(int sign, double m, double exp) {
|
|||
neg=QStringLiteral("-");
|
||||
}
|
||||
|
||||
if (exp!=0) {
|
||||
if (exp!=0.0) {
|
||||
value=neg+QString("%1E%2").arg(m).arg(exp);
|
||||
}
|
||||
else {
|
||||
if (m==0) {
|
||||
if (m==0.0) {
|
||||
value=neg+QString("0");
|
||||
}
|
||||
else
|
||||
|
@ -128,17 +128,18 @@ itemData extract16(QByteArray item) {
|
|||
// base=BCD2I(item[2]);
|
||||
base=10;
|
||||
|
||||
sign=TwosComplement2Int((quint8)item[3]);
|
||||
sign=TwosComplement2Int(static_cast<qint8>(item[3]));
|
||||
|
||||
exp=(((((((((qint8)item[7]&0xFF)<<8)+((qint8)item[6]&0xFF))<<8)+((qint8)item[5]&0xFF)))<<8)+((qint8)item[4]&0xFF));
|
||||
exp=((((((((static_cast<qint8>(item[7])&0xFF)<<8)+(static_cast<qint8>(item[6])&0xFF))<<8)+(static_cast<qint8>(item[5])&0xFF)))<<8)
|
||||
+(static_cast<qint8>(item[4])&0xFF));
|
||||
log(QString("extract16: exp %1").arg(exp));
|
||||
// exp=TwosComplement2Int(exp);
|
||||
|
||||
m=0;
|
||||
|
||||
for (k=8;k<16;k++) {
|
||||
if((quint8)item[k]!=0) {
|
||||
m=m*0.01+(double)multi*BCD2I((quint8)item[k]);
|
||||
if(static_cast<quint8>(item[k])!=0) {
|
||||
m=m*0.01+static_cast<double>(multi)*BCD2I(static_cast<quint8>(item[k]));
|
||||
}
|
||||
}
|
||||
ret=sign*m*qPow(base,exp);
|
||||
|
@ -162,7 +163,7 @@ itemData extract8(QByteArray item) {
|
|||
itemData listvalue;
|
||||
QString value=QStringLiteral("");;
|
||||
qint8 sign=1;
|
||||
qint8 l;
|
||||
quint8 l;
|
||||
qint8 v;
|
||||
int multi;
|
||||
qint16 exp=0;
|
||||
|
@ -173,7 +174,7 @@ itemData extract8(QByteArray item) {
|
|||
multi=1;
|
||||
base=10;
|
||||
|
||||
exp=((((((qint8)item[1]&0x0F)))<<8)+((qint8)item[0]&0xFF));
|
||||
exp=(((((static_cast<qint8>(item[1])&0x0F)))<<8)+(static_cast<qint8>(item[0])&0xFF));
|
||||
|
||||
exp=TwosComp2Int_8(exp);
|
||||
|
||||
|
@ -194,7 +195,7 @@ itemData extract8(QByteArray item) {
|
|||
v=v&0xF0;
|
||||
}
|
||||
|
||||
n=(double)multi*BCD2I(v);
|
||||
n=static_cast<double>(multi)*BCD2I(v);
|
||||
m=m*0.01+n;
|
||||
if(k!=7) {
|
||||
if ((m>0)||(k>5))
|
||||
|
@ -280,14 +281,22 @@ QByteArray AbstractData::getData() {
|
|||
return data;
|
||||
}
|
||||
|
||||
QByteArray AbstractData::fileOut() {
|
||||
return getData();
|
||||
}
|
||||
|
||||
void AbstractData::parseData() {
|
||||
qDebug()<<"AbstractData::parseData";
|
||||
}
|
||||
|
||||
void AbstractData::parseData(QDataStream& in) {
|
||||
void AbstractData::parseData(QDataStream& ) {
|
||||
qDebug()<<"AbstractData::parseData";
|
||||
}
|
||||
|
||||
AbstractData::~AbstractData() {
|
||||
qDebug()<<"~AbstractData";
|
||||
}
|
||||
|
||||
//REAL
|
||||
//
|
||||
Application::Application(QString name_in, hp_DataType type_in):
|
||||
|
@ -300,7 +309,6 @@ void Application::parseData() {
|
|||
|
||||
}
|
||||
|
||||
|
||||
//REAL
|
||||
//
|
||||
Real::Real(QString name_in, hp_DataType type_in):
|
||||
|
@ -355,7 +363,7 @@ void Real::parseData() {
|
|||
qDebug()<<start;
|
||||
for(j=0;j<len;j++) {
|
||||
item=a1.mid(start,16);
|
||||
if (item[2]==0x13) {
|
||||
if (static_cast<int>(item[2])==0x13) {
|
||||
main_err->dump((uint8_t *)item.constData(),16);
|
||||
value1=extract16(item);
|
||||
j++;
|
||||
|
@ -480,7 +488,7 @@ void Complex::parseData() {
|
|||
qDebug()<<start;
|
||||
for(j=0;j<len;j++) {
|
||||
item=a1.mid(start,16);
|
||||
if (item[2]==0x13) {
|
||||
if (static_cast<int>(item[2])==0x13) {
|
||||
main_err->dump((uint8_t *)item.constData(),16);
|
||||
value1=extract16(item);
|
||||
j++;
|
||||
|
@ -583,7 +591,7 @@ void List::parseData() {
|
|||
name=getName();
|
||||
|
||||
a1=data;
|
||||
ind=a1.indexOf((char *) searchstr,0);
|
||||
ind=a1.indexOf(reinterpret_cast<char *>(searchstr),0);
|
||||
|
||||
//look for FF 16 00
|
||||
|
||||
|
@ -591,8 +599,8 @@ void List::parseData() {
|
|||
|
||||
for(j=0;j<len;j++) {
|
||||
item=a1.mid(start,16);
|
||||
if (item[2]==0x13) {
|
||||
main_err->dump((uint8_t *)item.constData(),16);
|
||||
if (static_cast<int>(item[2])==0x13) {
|
||||
main_err->dump((uint8_t *)(item.constData()),16);
|
||||
value1=extract16(item);
|
||||
j++;
|
||||
start=start+16;
|
||||
|
@ -687,14 +695,13 @@ void Matrix::parseData() {
|
|||
int k,j;
|
||||
int ind;
|
||||
int flag =0;
|
||||
quint8 vtype;
|
||||
qint8 vtype;
|
||||
|
||||
QString ds;
|
||||
// QByteArray searchstr((char *)std::begin<quint8>({0x01,0x00}),2);
|
||||
//Start keeps changing 01 or 02
|
||||
//0x14 real 0x94 Complex
|
||||
|
||||
|
||||
qDebug()<<"Matrix: Parsing a Matrix";
|
||||
|
||||
name=getName();
|
||||
|
@ -705,7 +712,7 @@ void Matrix::parseData() {
|
|||
vtype=a1[ind+2];
|
||||
|
||||
log(QString("vtype=%1").arg(vtype,1,16));
|
||||
if (vtype&0x7F==0x14) {
|
||||
if ((vtype&0x7F)==0x14) {
|
||||
log("matrix found");
|
||||
flag =1;
|
||||
}
|
||||
|
@ -739,7 +746,7 @@ void Matrix::parseData() {
|
|||
item=a1.mid(start,8);
|
||||
start+=8;
|
||||
value2=extract8(item);
|
||||
if (value2.dReal != 0) {
|
||||
if ((value2.dReal) != 0.0) {
|
||||
listvalue.dImaginary=value2.dReal;
|
||||
listvalue.sValue=complex2Str(listvalue.sValue,value2.sValue);
|
||||
}
|
||||
|
@ -845,19 +852,53 @@ void Program::parseData() {
|
|||
|
||||
void Program::parseData(QDataStream& in) {
|
||||
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF8");
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF-16");
|
||||
QByteArrayMatcher matcher;
|
||||
QByteArray search;
|
||||
QByteArray phrase;
|
||||
int ind;
|
||||
int pos;
|
||||
QString str;
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 c;
|
||||
qint8 c;
|
||||
QByteArray a1;
|
||||
uint length;
|
||||
length=16;
|
||||
|
||||
in.startTransaction();
|
||||
while(!in.atEnd()) {
|
||||
in>>c;
|
||||
a1.append(c);
|
||||
in>>c;
|
||||
a1.append(c);
|
||||
}
|
||||
qDebug()<<a1;
|
||||
main_err->dump((uint8_t *)a1.constData(),a1.size());
|
||||
|
||||
// char cstr[20];
|
||||
search="\x7c\x61";
|
||||
matcher.setPattern(search);
|
||||
ind=matcher.indexIn(a1,0);
|
||||
if (ind>-1) {
|
||||
search=QByteArrayLiteral("\x54\x0\x0\x0\x44\x0\x0\x0");
|
||||
main_err->dump((uint8_t *)search.data(),search.length());
|
||||
matcher.setPattern(search);
|
||||
pos=0;
|
||||
while(pos>-1) {
|
||||
pos=matcher.indexIn(a1,ind);
|
||||
if (pos>-1) {
|
||||
ind=pos+10;
|
||||
phrase=a1.mid(ind,16*3);
|
||||
//add array to catch variable list
|
||||
str=codec->toUnicode(phrase);
|
||||
log(QString("TD...%1 %2").arg(pos,0,16).arg(ind));
|
||||
main_err->dump((uint8_t *)phrase.data(),3*16);
|
||||
log(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log("Data is not a program file");
|
||||
}
|
||||
|
||||
|
||||
// char cstr[20];
|
||||
// in.readRawData(cstr,20);
|
||||
// str=QString(cstr);
|
||||
// qDebug()<<str;
|
||||
|
@ -866,6 +907,18 @@ void Program::parseData(QDataStream& in) {
|
|||
text = codec->toUnicode(a1);
|
||||
}
|
||||
|
||||
|
||||
QByteArray Program::fileOut() {
|
||||
QByteArray out;
|
||||
out.clear();
|
||||
out.append("\x7c\x61\x8a\x62\xfe\xff\xff\xff\x00\x00\x00\x00\x08\x00\x00\x00");
|
||||
out.append("\x05\xff\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x05\xff\x3f\x02");
|
||||
out.append(data); //temp should be string text
|
||||
qDebug()<<out;
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
//Notes
|
||||
Notes::Notes(QString name_in, hp_DataType type_in, QString data_in):
|
||||
AbstractData(name_in, type_in) {
|
||||
|
@ -883,22 +936,11 @@ void Notes::parseData() {
|
|||
|
||||
// quint16 len1,len2;
|
||||
int formatstart;
|
||||
quint16 crc;
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF-16LE");
|
||||
|
||||
QByteArray a1,a3;
|
||||
|
||||
a1=getData();
|
||||
// crc=qChecksum(a1.mid(4,-1),a1.size()-4,Qt::ChecksumIso3309);
|
||||
// crc=crc16_block((uint8_t *)a1.mid(4,-1).constData(),a1.size()-4);
|
||||
|
||||
/*
|
||||
QDataStream ds(a1);
|
||||
ds.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
ds >> len1;
|
||||
ds >> len2;
|
||||
*/
|
||||
|
||||
formatstart=a1.indexOf("C\x00S\x00W\x0D\x001\x001\x00");
|
||||
a3=a1.mid(formatstart,-1);
|
||||
|
@ -924,24 +966,10 @@ Variables::Variables(QString name_in, hp_DataType type_in):
|
|||
void Variables::parseData() {
|
||||
|
||||
// quint16 len1,len2;
|
||||
int formatstart;
|
||||
quint16 crc;
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF-16LE");
|
||||
|
||||
QByteArray a1,a3;
|
||||
|
||||
a1=getData();
|
||||
// crc=qChecksum(a1.mid(4,-1),a1.size()-4,Qt::ChecksumIso3309);
|
||||
// crc=crc16_block((uint8_t *)a1.mid(4,-1).constData(),a1.size()-4);
|
||||
|
||||
/*
|
||||
QDataStream ds(a1);
|
||||
ds.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
ds >> len1;
|
||||
ds >> len2;
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -956,23 +984,10 @@ CASVariables::CASVariables(QString name_in, hp_DataType type_in):
|
|||
void CASVariables::parseData() {
|
||||
|
||||
// quint16 len1,len2;
|
||||
int formatstart;
|
||||
quint16 crc;
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF-16LE");
|
||||
|
||||
QByteArray a1,a3;
|
||||
|
||||
a1=getData();
|
||||
// crc=qChecksum(a1.mid(4,-1),a1.size()-4,Qt::ChecksumIso3309);
|
||||
// crc=crc16_block((uint8_t *)a1.mid(4,-1).constData(),a1.size()-4);
|
||||
|
||||
/*
|
||||
QDataStream ds(a1);
|
||||
ds.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
ds >> len1;
|
||||
ds >> len2;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
@ -987,23 +1002,10 @@ Settings::Settings(QString name_in, hp_DataType type_in):
|
|||
void Settings::parseData() {
|
||||
|
||||
// quint16 len1,len2;
|
||||
int formatstart;
|
||||
quint16 crc;
|
||||
QTextCodec * codec = QTextCodec::codecForName("UTF-16LE");
|
||||
|
||||
QByteArray a1,a3;
|
||||
|
||||
a1=getData();
|
||||
// crc=qChecksum(a1.mid(4,-1),a1.size()-4,Qt::ChecksumIso3309);
|
||||
// crc=crc16_block((uint8_t *)a1.mid(4,-1).constData(),a1.size()-4);
|
||||
|
||||
/*
|
||||
QDataStream ds(a1);
|
||||
ds.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
ds >> len1;
|
||||
ds >> len2;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1024,6 @@ void Settings::setData(QByteArray datain) {
|
|||
i++;
|
||||
}
|
||||
|
||||
|
||||
data = datain;
|
||||
len1=data.size();
|
||||
len2=datain.size();
|
||||
|
|
|
@ -48,9 +48,11 @@ public:
|
|||
void setFileCode(hp_pkt_type);
|
||||
hp_pkt_type getFileCode();
|
||||
virtual void setData(QByteArray);
|
||||
virtual QByteArray getData();
|
||||
virtual QByteArray getData(); //data extract
|
||||
virtual void parseData();
|
||||
virtual void parseData(QDataStream& in);
|
||||
virtual QByteArray fileOut(); //full data out in file transmittable format
|
||||
virtual ~AbstractData();
|
||||
};
|
||||
|
||||
|
||||
|
@ -137,6 +139,7 @@ public:
|
|||
QString getProg();
|
||||
void parseData();
|
||||
virtual void parseData(QDataStream& in);
|
||||
virtual QByteArray fileOut();
|
||||
};
|
||||
|
||||
class Notes: public AbstractData
|
||||
|
|
|
@ -203,3 +203,7 @@ hp_DataStruct contentFileSystemModel::getFileType(QFileInfo info) {
|
|||
|
||||
return filedata;
|
||||
}
|
||||
|
||||
contentFileSystemModel::~contentFileSystemModel() {
|
||||
qDebug()<<"contentFileSystemModel::delete";
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
void clickAction(QMdiArea * mdiwin,QModelIndex &index);
|
||||
hp_DataStruct getFileType(QFileInfo info);
|
||||
~contentFileSystemModel();
|
||||
|
||||
private:
|
||||
const static QString filetype_list[][2];
|
||||
|
|
|
@ -67,3 +67,8 @@ QVariant dataModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
dataModel::~dataModel() {
|
||||
|
||||
qDebug()<<"dataModel::close";
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
int rowCount(const QModelIndex &parent = QModelIndex()) const override ;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
~dataModel() override;
|
||||
};
|
||||
|
||||
#endif // DATAMODEL_H
|
||||
|
|
|
@ -42,6 +42,8 @@ int errorHandler::writeLog(QString lineToBeLogged)
|
|||
QTextStream out(&fileLog);
|
||||
out << time.toString("yyyy/MM/dd hh:mm:ss") << " "<< lineToBeLogged << endl;
|
||||
|
||||
fileLog.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -112,3 +114,7 @@ int errorHandler::dump(uint8_t * data, int size)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
errorHandler::~errorHandler() {
|
||||
qDebug()<<"errorHandler::close";
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ private:
|
|||
public:
|
||||
errorHandler();
|
||||
errorHandler(QObject *);
|
||||
~errorHandler();
|
||||
int error(ErrLevel, int, QString, QString Data);
|
||||
int dump(uint8_t *, int);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "eventthread.h"
|
||||
#include <QTimer>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
EventThread::EventThread(MainWindow * parent)
|
||||
|
@ -18,8 +18,27 @@ void EventThread::timerEvent()
|
|||
}
|
||||
|
||||
void EventThread::start() {
|
||||
QTimer* timer = new QTimer(this);
|
||||
timer = new QTimer(this);
|
||||
timer->setInterval(100);
|
||||
timer->connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
|
||||
timer->connect(this, SIGNAL(stop()), this, SLOT(stopTimer()));
|
||||
timer->start();
|
||||
}
|
||||
|
||||
void EventThread::exit() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void EventThread::stopTimer() {
|
||||
timer->stop();
|
||||
}
|
||||
|
||||
EventThread::~EventThread()
|
||||
{
|
||||
|
||||
if (timer!=nullptr) {
|
||||
delete timer;
|
||||
timer=nullptr;
|
||||
}
|
||||
qDebug()<<"delete eventThread";
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef EVENTTHREAD_H
|
||||
#define EVENTTHREAD_H
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include "hpusb.h"
|
||||
|
||||
class MainWindow;
|
||||
|
@ -11,13 +12,18 @@ class EventThread : public QObject
|
|||
private:
|
||||
MainWindow * main;
|
||||
hpusb * hpapi;
|
||||
QTimer * timer=nullptr;
|
||||
public:
|
||||
EventThread(MainWindow * parent);
|
||||
|
||||
~EventThread();
|
||||
public slots:
|
||||
void timerEvent();
|
||||
void start();
|
||||
void exit();
|
||||
void stopTimer();
|
||||
|
||||
signals:
|
||||
void stop();
|
||||
};
|
||||
|
||||
#endif // EVENTTHREAD_H
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "getnumber.h"
|
||||
#include "ui_getnumber.h"
|
||||
#include <QDebug>
|
||||
|
||||
getNumber::getNumber(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
|
@ -10,5 +11,6 @@ getNumber::getNumber(QWidget *parent) :
|
|||
|
||||
getNumber::~getNumber()
|
||||
{
|
||||
// qDebug()<<"Entering ~getNumber()";
|
||||
delete ui;
|
||||
}
|
||||
|
|
13
global.h
13
global.h
|
@ -1,14 +1,13 @@
|
|||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
#include "version.h"
|
||||
#include "errorhandler.h"
|
||||
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
class errorHandler;
|
||||
extern errorHandler *main_err;
|
||||
#define log(a) main_err->error(L7,0,QString(a),QString());
|
||||
#define err(a,b,c) main_err->error(a,b,QString(c),QString());
|
||||
|
||||
class errorHandler;
|
||||
extern errorHandler *main_err;
|
||||
#define log(a) main_err->error(L7,0,QString(a),QString());
|
||||
#define err(a,b,c) main_err->error(a,b,QString(c),QString());
|
||||
|
||||
#endif // GLOBAL_H
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "hp_infodialog.h"
|
||||
#include "ui_hp_infodialog.h"
|
||||
#include <QDebug>
|
||||
|
||||
hp_infoDialog::hp_infoDialog(QWidget *parent, hp_Information info) :
|
||||
QDialog(parent),
|
||||
|
@ -13,5 +14,6 @@ hp_infoDialog::hp_infoDialog(QWidget *parent, hp_Information info) :
|
|||
|
||||
hp_infoDialog::~hp_infoDialog()
|
||||
{
|
||||
// qDebug()<<"Entering ~hp_infoDialog()";
|
||||
delete ui;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ void hp_mdiTextEdit::show() {
|
|||
|
||||
hp_mdiTextEdit::~hp_mdiTextEdit() {
|
||||
|
||||
if (textEdit)
|
||||
qDebug()<<"Entering ~hpmdiTextEdit()";
|
||||
if (textEdit!=nullptr)
|
||||
delete textEdit;
|
||||
|
||||
}
|
||||
|
|
|
@ -39,8 +39,6 @@ void hp_mdiVariableEdit::show() {
|
|||
|
||||
hp_mdiVariableEdit::~hp_mdiVariableEdit() {
|
||||
|
||||
if (tableView)
|
||||
delete tableView;
|
||||
if (varmodel)
|
||||
delete varmodel;
|
||||
// qDebug()<<"Entering ~hpmdiVariableEdit()";
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "hp_mdiwindow.h"
|
||||
#include <QDebug>
|
||||
|
||||
hp_MdiWindow::hp_MdiWindow(QWidget * parent)
|
||||
:QMdiSubWindow(parent)
|
||||
|
@ -25,6 +26,7 @@ void hp_MdiWindow::show() {
|
|||
}
|
||||
|
||||
hp_MdiWindow::~hp_MdiWindow() {
|
||||
if (textEdit)
|
||||
delete textEdit;
|
||||
|
||||
// qDebug()<<"Entering ~hpmdiWindow()";
|
||||
|
||||
}
|
||||
|
|
|
@ -103,5 +103,6 @@ void hp_SettingsDlg::on_clicked(QAbstractButton * button) {
|
|||
|
||||
hp_SettingsDlg::~hp_SettingsDlg()
|
||||
{
|
||||
qDebug()<<"delete hp_SettingsDlf";
|
||||
delete ui;
|
||||
}
|
||||
|
|
|
@ -402,5 +402,5 @@ void hpCalcData::vpkt_send_experiments(int cmd) {
|
|||
}
|
||||
|
||||
hpCalcData::~hpCalcData() {
|
||||
|
||||
// qDebug()<<"Close ~hpCalcData";
|
||||
};
|
||||
|
|
|
@ -70,7 +70,7 @@ void hpTreeItem::setGraphicTree() {
|
|||
int func_num=FUNC_NUM;
|
||||
hpTreeItem * newChild;
|
||||
|
||||
int i,j;
|
||||
int i;
|
||||
|
||||
for (i=1; i<func_num; i++)
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ void hpTreeItem::clickAction(QMdiArea * mdiwin) {
|
|||
hpCalcData * calc;
|
||||
hp_DataStruct hpdata;
|
||||
calc=getDataStore();
|
||||
AbstractData * data;
|
||||
AbstractData * data=nullptr;
|
||||
|
||||
// QString test;
|
||||
// test=data(Qt::DisplayRole).toString();
|
||||
|
@ -266,6 +266,7 @@ int hpTreeItem::dt2int() {
|
|||
case HP_PROG: return 6;
|
||||
case HP_REAL: return 7;
|
||||
case HP_VAR: return 8;
|
||||
default:;
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
@ -315,13 +316,16 @@ void hpTreeItem::dataChange(hp_Change hpchange) {
|
|||
case HP_LIST: {
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
case HP_NOTE: {
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
case HP_PROG: {
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,7 +413,6 @@ void hpTreeItem::addChild(AbstractData *obj) {
|
|||
//Up date the data
|
||||
void hpTreeItem::refresh() {
|
||||
int rows,i,j;
|
||||
int flag=0; //indicate 1 if data matches tree
|
||||
int datalen;
|
||||
hpTreeItem * ti_child;
|
||||
|
||||
|
@ -541,7 +544,7 @@ int hpTreeItem::findFile(QString dataname) {
|
|||
QString name;
|
||||
|
||||
for (i=0; i<rows; i++) {
|
||||
ti_child=(hpTreeItem *)child(i);
|
||||
ti_child=static_cast<hpTreeItem *>(child(i));
|
||||
dataname=ti_child->getFileName();
|
||||
if(name==dataname) {
|
||||
return i;
|
||||
|
@ -551,3 +554,27 @@ int hpTreeItem::findFile(QString dataname) {
|
|||
}
|
||||
|
||||
|
||||
hpTreeItem::~hpTreeItem() {
|
||||
|
||||
/*
|
||||
if (hpvaredit!=nullptr) {
|
||||
hpvaredit->close();
|
||||
delete hpvaredit;
|
||||
hpvaredit=nullptr;
|
||||
}
|
||||
|
||||
if (hptextedit!=nullptr) {
|
||||
hptextedit->close();
|
||||
delete hptextedit;
|
||||
hptextedit=nullptr;
|
||||
}
|
||||
|
||||
if (mdiarea!=nullptr) {
|
||||
mdiarea->close();
|
||||
mdiarea=nullptr;
|
||||
}
|
||||
*/
|
||||
|
||||
qDebug()<<"hpTreeItem:: delete";
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
int findFile(QString);
|
||||
void addFile(AbstractData *);
|
||||
void addChild(AbstractData * obj);
|
||||
|
||||
virtual ~hpTreeItem();
|
||||
|
||||
public slots:
|
||||
void dataChange(hp_Change hpchange);
|
||||
|
|
20
hpusb.cpp
20
hpusb.cpp
|
@ -1221,9 +1221,9 @@ int hpusb::submit_async_transfer(hp_Handle * handle, hp_pkt_in * pktin, hp_pkt_o
|
|||
sigact.sa_handler = sighandler; // sighandler is defined below. It just sets do_exit.
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigact, NULL);
|
||||
sigaction(SIGTERM, &sigact, NULL);
|
||||
sigaction(SIGQUIT, &sigact, NULL);
|
||||
sigaction(SIGINT, &sigact, nullptr);
|
||||
sigaction(SIGTERM, &sigact, nullptr);
|
||||
sigaction(SIGQUIT, &sigact, nullptr);
|
||||
|
||||
printf("Entering loop to process callbacks...\n");
|
||||
|
||||
|
@ -1243,7 +1243,7 @@ int hpusb::submit_async_transfer(hp_Handle * handle, hp_pkt_in * pktin, hp_pkt_o
|
|||
// This implementation uses a blocking call
|
||||
while (!do_exit) {
|
||||
c++;
|
||||
r = libusb_handle_events_completed(ctx, NULL);
|
||||
r = libusb_handle_events_completed(ctx, nullptr);
|
||||
if ((r < 0)||(c>100000)){ // negative values are errors
|
||||
qDebug()<<"At break";
|
||||
exitflag = out_deinit;
|
||||
|
@ -1306,6 +1306,9 @@ int hpusb::submit_async_transfer(hp_Handle * handle, hp_pkt_in * pktin, hp_pkt_o
|
|||
case out_release:
|
||||
libusb_release_interface(devh, 0);
|
||||
break;
|
||||
case out:
|
||||
qDebug()<<"out";
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1359,12 +1362,12 @@ void cb_in(struct libusb_transfer *transfer)
|
|||
|
||||
int hpusb::hotplugcallback(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
libusb_hotplug_event event) {
|
||||
int count;
|
||||
int count=0;
|
||||
qDebug()<<"hpusb::hotplug_callback - Hotplug";;
|
||||
|
||||
static libusb_device_handle *handle = NULL;
|
||||
static libusb_device_handle *handle = nullptr;
|
||||
struct libusb_device_descriptor desc;
|
||||
int rc;
|
||||
|
||||
(void)libusb_get_device_descriptor(dev, &desc);
|
||||
|
||||
if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
|
||||
|
@ -1388,7 +1391,7 @@ int hpusb::eventHandler() {
|
|||
|
||||
int completed;
|
||||
// qDebug()<<"In Eventhandler";
|
||||
libusb_handle_events_completed(NULL, &completed);
|
||||
libusb_handle_events_completed(nullptr, &completed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1404,4 +1407,5 @@ int hpusb::hp_close() {
|
|||
|
||||
hpusb::~hpusb() {
|
||||
libusb_exit(ctx);
|
||||
qDebug()<<"hpusb::close";
|
||||
}
|
||||
|
|
8
main.cpp
8
main.cpp
|
@ -13,6 +13,7 @@ int main(int argc, char *argv[])
|
|||
QCoreApplication::setApplicationName("Linux QtHP Connect");
|
||||
QCoreApplication::setApplicationVersion(HP_VERSION_STRING);
|
||||
QCommandLineParser parser;
|
||||
MainWindow w;
|
||||
|
||||
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||
//REWORK
|
||||
|
@ -21,10 +22,11 @@ int main(int argc, char *argv[])
|
|||
// parser.addPositionalArgument("file", "The file to open.");
|
||||
parser.process(a);
|
||||
|
||||
MainWindow w;
|
||||
// a.setQuitLockEnabled(true);
|
||||
// if (!parser.positionalArguments().isEmpty())
|
||||
// w.loadFile(parser.positionalArguments().first());
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
a.exec();
|
||||
qDebug()<<"Main.cpp:: closing main";
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui->tvCalculators->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
ui->tvCalculators->setDropIndicatorShown(true);
|
||||
ui->tvCalculators->show();
|
||||
QItemSelectionModel *selectionModel= ui->tvCalculators->selectionModel();
|
||||
|
||||
connect(ui->actionOpen,SIGNAL(triggered()),this,SLOT(onOpen()));
|
||||
connect(ui->actionAbout_HP_Connect,SIGNAL(triggered()),this,SLOT(about()));
|
||||
|
@ -121,7 +120,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
|
||||
//setup event handler
|
||||
eventThread = new QThread(this);
|
||||
eventTimer = new EventThread(0);
|
||||
eventTimer = new EventThread(nullptr);
|
||||
eventTimer->moveToThread(eventThread);
|
||||
// connect(eventTimer,SIGNAL(timeout()),this,SLOT(eventHandler()));
|
||||
connect(eventThread,SIGNAL(started()),eventTimer,SLOT(start()));
|
||||
|
@ -172,7 +171,6 @@ void MainWindow::writeChatter(QString line)
|
|||
}
|
||||
|
||||
//eventhandler - for comms events
|
||||
|
||||
void MainWindow::eventHandler() {
|
||||
|
||||
if(hpapi) {
|
||||
|
@ -181,12 +179,6 @@ void MainWindow::eventHandler() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::onOpen()
|
||||
{
|
||||
qDebug()<<"MainWindow::in on Open";
|
||||
|
@ -311,8 +303,6 @@ void MainWindow::selectionChangedSlot(const QItemSelection & /*newSelection*/, c
|
|||
|
||||
void MainWindow::clickedCalculator(QModelIndex index) {
|
||||
|
||||
hp_mdiVariableEdit * hpvaredit;
|
||||
|
||||
QStandardItem * item = hpTreeModel->itemFromIndex(index);
|
||||
|
||||
hpTreeItem * treeItem = dynamic_cast<hpTreeItem *>(hpTreeModel->itemFromIndex(index));
|
||||
|
@ -339,7 +329,6 @@ void MainWindow::clickedContent(QModelIndex index) {
|
|||
contentModel.clickAction(getMdi(),index);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::about()
|
||||
{
|
||||
QMessageBox::about(this, tr("About QtHP Connect"),
|
||||
|
@ -400,6 +389,7 @@ void MainWindow::setContentWindow() {
|
|||
|
||||
}
|
||||
}
|
||||
readSettings();
|
||||
}
|
||||
|
||||
//show or hide calculator window
|
||||
|
@ -454,7 +444,8 @@ void MainWindow::dataChange(hp_Change hpchange) {
|
|||
monitorAddImage(scrn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,11 +484,65 @@ void MainWindow::monitorAddImage(hp_ScreenShot scrnshot) {
|
|||
ui->dwMonitor->show();
|
||||
}
|
||||
|
||||
void MainWindow::exit() {
|
||||
delete treeMenu;
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
|
||||
qDebug()<<"MainWindow:: closeEvent Step 1";
|
||||
writeSettings();
|
||||
event->accept();
|
||||
|
||||
|
||||
if (eventThread!=nullptr) {
|
||||
eventThread->quit();
|
||||
eventThread->wait(100);
|
||||
}
|
||||
|
||||
qDebug()<<"MainWindow:: closeEvent Step 2";
|
||||
|
||||
ui->tvCalculators->close();
|
||||
ui->tvContent->close();
|
||||
ui->dwContent->close();
|
||||
ui->dwMonitor->close();
|
||||
ui->dwMessenger->close();
|
||||
ui->dwCalculator->close();
|
||||
|
||||
qDebug()<<"MainWindow:: closeEvent Step 3";
|
||||
|
||||
if (main_err!=nullptr) {
|
||||
delete main_err;
|
||||
main_err=nullptr;
|
||||
}
|
||||
|
||||
if (treeMenu!=nullptr) {
|
||||
delete treeMenu;
|
||||
treeMenu=nullptr;
|
||||
}
|
||||
if (myModel!=nullptr) {
|
||||
delete myModel;
|
||||
myModel=nullptr;
|
||||
}
|
||||
if (hpapi!=nullptr) {
|
||||
delete hpapi;
|
||||
hpapi=nullptr;
|
||||
}
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void MainWindow::writeSettings()
|
||||
{
|
||||
QSettings appSettings("IRGP","QtHPconnect");
|
||||
}
|
||||
|
||||
void MainWindow::readSettings()
|
||||
{
|
||||
QSettings appSettings("IRGP","QtHPconnect");
|
||||
const QByteArray geometry = appSettings.value("geometry", QByteArray()).toByteArray();
|
||||
if (!geometry.isEmpty()) {
|
||||
restoreGeometry(geometry);
|
||||
}
|
||||
}
|
||||
|
||||
hpusb * MainWindow::getAPI() {
|
||||
return hpapi;
|
||||
}
|
||||
|
@ -526,7 +571,6 @@ QMdiArea * MainWindow::getMdi() {
|
|||
return ui->mdiArea;
|
||||
}
|
||||
|
||||
|
||||
//action on refresh button
|
||||
void MainWindow::refresh(bool clicked) {
|
||||
qDebug()<<"MainWindow:: Refresh";
|
||||
|
@ -580,6 +624,7 @@ void MainWindow::treeMenuAction(bool clicked) {
|
|||
case HP_MAIN:
|
||||
treeItem->contextAction(getMdi(),CT_PREFERENCE);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -606,7 +651,14 @@ void MainWindow::on_tvCalculators_customContextMenuRequested(const QPoint &pos)
|
|||
}
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//destructor
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
qDebug()<<"MainWindow:: closing";
|
||||
}
|
||||
|
|
22
mainwindow.h
22
mainwindow.h
|
@ -1,6 +1,3 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QItemSelection>
|
||||
#include <QModelIndex>
|
||||
|
@ -9,6 +6,9 @@
|
|||
#include <QSettings>
|
||||
#include <QFileSystemModel>
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "global.h"
|
||||
#include "errorhandler.h"
|
||||
#include "hpusb.h"
|
||||
|
@ -32,8 +32,8 @@ class MainWindow : public QMainWindow
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
void openHP();
|
||||
void closeHP();
|
||||
void writeStatus(QString);
|
||||
|
@ -56,9 +56,11 @@ private slots:
|
|||
void dataChange(hp_Change);
|
||||
void clickedCalculator(QModelIndex);
|
||||
void clickedContent(QModelIndex);
|
||||
void exit();
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
void createLogWindow();
|
||||
void testFunction();
|
||||
void writeSettings();
|
||||
void readSettings();
|
||||
treeModel * getTreeModel();
|
||||
|
||||
void treeMenuAction(bool);
|
||||
|
@ -78,10 +80,10 @@ private:
|
|||
EventThread * eventTimer;
|
||||
QMenu * treeMenu=nullptr;
|
||||
hpusb * hpapi;
|
||||
QMdiSubWindow * msgWindow=0;
|
||||
hp_MdiWindow * logWindow=0;
|
||||
QMdiSubWindow * msgWindow=nullptr;
|
||||
hp_MdiWindow * logWindow=nullptr;
|
||||
contentFileSystemModel contentModel;
|
||||
QTextEdit * logEdit=0;
|
||||
QTextEdit * logEdit=nullptr;
|
||||
Ui::MainWindow *ui;
|
||||
void loadTextFile();
|
||||
void createTextWindow();
|
||||
|
@ -89,8 +91,6 @@ private:
|
|||
void setContentWindow();
|
||||
void setTreeMenu();
|
||||
void monitorAddImage(hp_ScreenShot scrnshot);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -230,6 +230,6 @@ int MatrixData::rows()
|
|||
|
||||
MatrixData::~MatrixData()
|
||||
{
|
||||
qDebug()<<"Entering ~MatrixData()";
|
||||
clear();
|
||||
}
|
||||
\
|
||||
|
|
|
@ -31,5 +31,6 @@ void Options::reject() {
|
|||
|
||||
Options::~Options()
|
||||
{
|
||||
qDebug()<<"~Options()";
|
||||
delete ui;
|
||||
}
|
||||
|
|
|
@ -141,5 +141,5 @@ QString textEditor::strippedName(const QString &fullFileName)
|
|||
}
|
||||
|
||||
textEditor::~textEditor() {
|
||||
|
||||
qDebug()<<"textEditor:: delete";
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ treeModel::treeModel(QObject *parent)
|
|||
setItemPrototype(new hpTreeItem());
|
||||
createRoot();
|
||||
setParent(parent);
|
||||
|
||||
}
|
||||
|
||||
int treeModel::createRoot()
|
||||
|
@ -21,8 +20,6 @@ int treeModel::createRoot()
|
|||
//Rework - name should be calc name
|
||||
int treeModel::addCalculator(QString name, hpusb * handle){
|
||||
|
||||
|
||||
hpDataLink hplink;
|
||||
hpCalcData * hpData = new hpCalcData(handle);
|
||||
hpTreeItem * hpCalc = new hpTreeItem(name,hpData,0);
|
||||
hpCalc->setType(HP_MAIN);
|
||||
|
@ -35,6 +32,7 @@ int treeModel::addCalculator(QString name, hpusb * handle){
|
|||
rootNode->appendRow(hpCalc);
|
||||
hpData->readInfo();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
hpCalcData * treeModel::getCalculator(QString name){
|
||||
|
@ -180,10 +178,9 @@ Qt::ItemFlags treeModel::flags(const QModelIndex &index) const
|
|||
return Qt::ItemIsDropEnabled | defaultFlags;
|
||||
}
|
||||
|
||||
|
||||
treeModel::~treeModel() {
|
||||
|
||||
delete rootNode;
|
||||
qDebug()<<"treeModel:: delete";
|
||||
}
|
||||
|
||||
|
||||
|
|
17
treemodel.h
17
treemodel.h
|
@ -21,24 +21,23 @@ class treeModel: public QStandardItemModel
|
|||
|
||||
private:
|
||||
int createRoot();
|
||||
QStandardItem *rootNode;
|
||||
QStandardItem *rootNode=nullptr;
|
||||
QMap<QString,hpDataLink> hpCalcList;
|
||||
hpCalcData * hpdata;
|
||||
hpCalcData * hpdata=nullptr;
|
||||
|
||||
public:
|
||||
treeModel(QObject *parent);
|
||||
~treeModel();
|
||||
virtual ~treeModel() override;
|
||||
int addCalculator(QString name, hpusb * handle);
|
||||
hpCalcData * getCalculator(QString name);
|
||||
hpCalcData * getHpCalcData(QString name);
|
||||
void setHpCalcData(QString name, hpCalcData * , hpTreeItem *);
|
||||
QString getLastDataKey();
|
||||
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row,
|
||||
int column, const QModelIndex &parent);
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const;
|
||||
Qt::DropActions supportedDropActions() const;
|
||||
QMimeData* mimeData(const QModelIndexList &) const;
|
||||
Qt::ItemFlags flags(const QModelIndex&) const;
|
||||
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
QMimeData* mimeData(const QModelIndexList &) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex&) const override;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
#include "variableview.h"
|
||||
#include "ui_variableview.h"
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
variableView::variableView(QWidget *parent)
|
||||
variableView::variableView(QWidget *)
|
||||
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
}
|
||||
|
||||
variableView::~variableView()
|
||||
{
|
||||
qDebug()<<"delete variableView";
|
||||
delete ui;
|
||||
}
|
||||
|
|
|
@ -204,3 +204,7 @@ QVariant varTableModel::headerData(int section, Qt::Orientation orientation, in
|
|||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
varTableModel::~varTableModel() {
|
||||
qDebug()<<"Entering ~varTableModel()";
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
~varTableModel();
|
||||
};
|
||||
|
||||
#endif // VARTABLEMODEL_H
|
||||
|
|
Loading…
Reference in a new issue