diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/QtHPConnect.pro b/QtHPConnect.pro index 0370fc0..0086fd6 100644 --- a/QtHPConnect.pro +++ b/QtHPConnect.pro @@ -1,173 +1,31 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2019-01-21T20:42:03 -# -#------------------------------------------------- - QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -TARGET = QtHPConnect -TEMPLATE = app +CONFIG += c++11 # The following define makes your compiler emit warnings if you use -# any feature of Qt which has been marked as deprecated (the exact warnings +# any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS -VERSION_MAJOR = HP_MAJOR_VERSION -VERSION_MINOR = HP_MINOR_VERSION -VERSION_PATCH = HP_MINOR_PATCH -VERSION_BUILD = HP_MINOR_BUILD - -DEFINES += "VERSION_MAJOR=$$VERSION_MAJOR"\ - "VERSION_MINOR=$$VERSION_MINOR"\ - "VERSION_PATCH=$$VERSION_PATCH"\ - "VERSION_BUILD=$$VERSION_BUILD" - -#Target version -VERSION = $${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_PATCH}$${VERSION_BUILD} - -#QMAKE_CFLAGS += -Wno-unused-parameter -Werror=shadow -Werror=write-strings -Werror=redundant-decls -Werror=format -Werror=format-nonliteral -Werror=date-time -Werror=missing-prototypes -Werror=pointer-arith -Wunreachable-code -Werror=format-security -Werror=declaration-after-statement -Werror=implicit-function-declaration -Werror=return-type -D_FORTIFY_SOURCE=2 -D__LINUX__ -fvisibility=hidden -#QMAKE_CXXFLAGS += -include cctype -include cstdlib -#QMAKE_CXXFLAGS += -Wno-unused-parameter -Werror=shadow -Werror=write-strings -Werror=redundant-decls -Werror=format -Werror=format-nonliteral -Werror=date-time -Werror=missing-prototypes -Werror=pointer-arith -Wunreachable-code -Werror=format-security -Werror=declaration-after-statement -Werror=implicit-function-declaration -Werror=return-type -D_FORTIFY_SOURCE=2 -D__LINUX__ -fvisibility=hidden - -# You can also make your code fail to compile if you use deprecated APIs. +# You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - SOURCES += \ - abstractdata.cpp \ - cntfilesystemmodel.cpp \ - datamodel.cpp \ - errorhandler.cpp \ - eventthread.cpp \ - eventtimer.cpp \ - getnumber.cpp \ - hp_infodialog.cpp \ - hp_mdilogwindow.cpp \ - hp_mditexteditor.cpp \ - hp_mdivariableedit.cpp \ - hp_mdiwindow.cpp \ - hp_settingsdlg.cpp \ - hpdata.cpp \ -# hptoolbox.cpp \ - hptreeitem.cpp \ - hpusb.cpp \ main.cpp \ - mainwindow.cpp \ - matrixdata.cpp \ - options.cpp \ - texteditor.cpp \ - treemodel.cpp \ - variableview.cpp \ - vartablemodel.cpp \ - libhpcalcs/src/calc_none.c \ - libhpcalcs/src/calc_prime.c \ - libhpcalcs/src/error.c \ - libhpcalcs/src/filetypes.c \ - libhpcalcs/src/hpcables.c \ - libhpcalcs/src/hpcalcs.c \ - libhpcalcs/src/hpfiles.c \ - libhpcalcs/src/hpopers.c \ - libhpcalcs/src/link_nul.c \ - libhpcalcs/src/link_prime_hid.c \ - libhpcalcs/src/logging.c \ - libhpcalcs/src/prime_cmd.c \ - libhpcalcs/src/prime_rpkt.c \ - libhpcalcs/src/prime_vpkt.c \ - libhpcalcs/src/type2str.c \ - libhpcalcs/src/typesprime.c \ - libhpcalcs/src/utils.c + mainwindow.cpp HEADERS += \ - hidapi/hidapi.h \ - include/abstractdata.h \ - include/cntfilesystemmodel.h \ - include/datamodel.h \ - include/errorhandler.h \ - include/eventthread.h \ - include/eventtimer.h \ - include/getnumber.h \ - include/global.h \ - include/hp_infodialog.h \ - include/hp_mdilogwindow.h \ - include/hp_mditexteditor.h \ - include/hp_mdivariableedit.h \ - include/hp_mdiwindow.h \ - include/hp_settingsdlg.h \ - include/hp_typedef.h \ - include/hpdata.h \ - include/hpinterface.h \ - include/hptreeitem.h \ - include/hpusb.h \ - include/main.h \ - include/mainwindow.h \ - include/matrixdata.h \ - include/options.h \ - include/texteditor.h \ - include/treemodel.h \ - include/variableview.h \ - include/vartablemodel.h \ - include/version.h \ - libhpcalcs/include/error.h \ - libhpcalcs/include/export.h \ - libhpcalcs/include/filetypes.h \ - libhpcalcs/include/gettext.h \ - libhpcalcs/include/hpcables.h \ - libhpcalcs/include/hpcalcs.h \ - libhpcalcs/include/hpfiles.h \ - libhpcalcs/include/hplibs.h \ - libhpcalcs/include/hpopers.h \ - libhpcalcs/include/internal.h \ - libhpcalcs/include/logging.h \ - libhpcalcs/include/prime_cmd.h \ - libhpcalcs/include/typesprime.h \ - libhpcalcs/include/utils.h + mainwindow.h FORMS += \ - mainwindow.ui \ - variableview.ui \ - hp_mdiwindow.ui \ - getnumber.ui \ - hp_infodialog.ui \ - hp_settingsdlg.ui \ - options.ui + mainwindow.ui -win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../../usr/local/lib/release/ -lhpcalcs -else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../../usr/local/lib/debug/ -lhpcalcs -else:unix: LIBS += - -#-L$$PWD/../../../../usr/local/lib/ -lhpcalcs - -INCLUDEPATH += $$PWD/../../../../usr/local/include -INCLUDEPATH += $$PWD/include -INCLUDEPATH += $$PWD/libhpcalcs/include/ -INCLUDEPATH += $$PWD/hidapi/ - -INCLUDEPATH += /usr/include/libusb-1.0 - - -DEPENDPATH += $$PWD/../../../../usr/local/include - -RESOURCES += \ - qthpconnect.qrc - -DISTFILES += \ - model.qmodel \ - README.md \ - LICENSE \ - CHANGELOG.md \ - NEWS \ - AUTHORS \ - Notes \ - TODO.md - ../hplp-master/libhpcalcs/tests/test_hpcalcs.c - -unix|win32: LIBS += -lhidapi-libusb - -unix|win32: LIBS += -lusb-1.0 +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/input.txt b/input.txt deleted file mode 100644 index 8a0a25d..0000000 --- a/input.txt +++ /dev/null @@ -1,8 +0,0 @@ - -gsdfgdsfgdsfg -dfg -dsf -gs -dfg -sdf -gsdfgsdf diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..676266a --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,21 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + Ui::MainWindow *ui; +}; +#endif // MAINWINDOW_H diff --git a/source/abstractdata.cpp b/source/abstractdata.cpp new file mode 100644 index 0000000..18b552f --- /dev/null +++ b/source/abstractdata.cpp @@ -0,0 +1,1180 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "global.h" +#include "hpusb.h" +#include "matrixdata.h" +#include "abstractdata.h" + +uint16_t crc16_block(const uint8_t * buffer, uint32_t len); + +int BCD2I(quint8 num) { + + int ds,ret; + if(num>0) { + ds=((num&0xF0)>>4)*10; + ds+=(num&0x0F); + ret=ds; + } + else { + ret=0; + } + + errlog(QString("Num= %1 Ret= %2").arg(num,1,16).arg(ret)); + return ret; +} + +quint8 I2BCD(int num) { + + quint8 ret; + int shift =0; + while (num > 0) { + ret |= (num % 10) << (shift++ << 2); + num /= 10; + } + + errlog(QString("Num= %1 Ret= %2").arg(num,1,16).arg(ret)); + + qDebug()<(rawValue); + } + else { + // Otherwise perform the 2's complement math on the value + errlog(QString("List 2C Negative Detected")); + + ret = static_cast(~(rawValue - 0x01)) * - 1; +// ret = ~rawValue; + } + errlog(QString("2C: %1 %2").arg(rawValue,1,16).arg(ret,1,16)); + + return ret; +} + +qint16 TwosComp2Int_8(qint16 rawValue) +{ + + qint16 ret; + + // If a positive value, return it + if ((rawValue & 0x800) == 0) + { + ret = rawValue; + } + else { + // Otherwise perform the 2's complement math on the value + ret = (~(rawValue - 0x01)&(0x0FFF)) * -1; +// ret = ~rawValue; + } + return ret; +} + +QString value2Str(int sign, double m, double exp) { + QString value; + QString neg=QStringLiteral(""); + + if (sign<0) { + neg=QStringLiteral("-"); + } + + if (exp!=0.0) { + value=neg+QString("%1E%2").arg(m).arg(exp); + } + else { + if (m==0.0) { + value=neg+QString("0"); + } + else + value=neg+QString("%1").arg(m); + } + + return value; +} + +QString complex2Str(QString real, QString imag) { + QString value; + + if((imag[0]!="+")&&(imag[0]!="-")) { + value = real+"+"+imag+"*i"; + } + else + { + value = real+imag+"*i"; + } + if(real=="0") { + value = imag+"*i"; + } + if ((real!="0")&&(imag=="0")) { + value = real; + } + + return value; +} + +itemData extract16(QByteArray item) { +; + itemData listvalue; + QString msg; + QString value=QStringLiteral(""); + QString neg=QStringLiteral(""); + qint8 sign; + int multi; + long exp; + double base; + double m,ret; + int k; + + multi=1; +// base=BCD2I(item[2]); + base=10; + + sign=TwosComplement2Int(static_cast(item[3])); + + exp=((((((((static_cast(item[7])&0xFF)<<8)+(static_cast(item[6])&0xFF))<<8)+(static_cast(item[5])&0xFF)))<<8) + +(static_cast(item[4])&0xFF)); + errlog(QString("extract16: exp %1").arg(exp)); +// exp=TwosComplement2Int(exp); + + m=0; + + for (k=8;k<16;k++) { + if(static_cast(item[k])!=0) { + m=m*0.01+static_cast(multi)*BCD2I(static_cast(item[k])); + } + } + ret=sign*m*qPow(base,exp); + + value = value2Str(sign,m,exp); + + msg=QString("multi:%1 base:%2 sign:%3 exp:%4 m:%5").arg(multi).arg(base).arg(sign).arg(exp).arg(m); +// msg=QString("value: %1").arg(value); + + errlog(msg); + errlog((QString("Ans: %1").arg(ret))); + + listvalue.dReal=ret; + listvalue.sValue=value; + + return listvalue; +} + +itemData extract8(QByteArray item) { +; + itemData listvalue; + QString value=QStringLiteral("");; + qint8 sign=1; + quint8 l; + qint8 v; + int multi; + qint16 exp=0; + double base; + double m,ret,n; + int k; + + multi=1; + base=10; + + exp=(((((static_cast(item[1])&0x0F)))<<8)+(static_cast(item[0])&0xFF)); + + exp=TwosComp2Int_8(exp); + + m=0; + + l=item[7]&0xF0; + + if ((l&0xFF)==0x90) { + + sign=-1; + } + for (k=1;k<8;k++) { + v=item[k]; + if (k==7) { + v=v&0x0F; + } + if (k==1) { + v=v&0xF0; + } + + n=static_cast(multi)*BCD2I(v); + m=m*0.01+n; + if(k!=7) { + if ((m>0)||(k>5)) + value=QString("%1").arg(n,0)+value; + } + else + value=QString("%1.").arg(n,0)+value; + + } + ret=sign*m*qPow(base,exp); + + if(sign<0) { + value=QString("-")+value; + } + + if(exp!=0) + value=value+"E"+QString("%1").arg(exp,0); + + listvalue.dReal=ret; + listvalue.sValue=value; + + return listvalue; +} + +bool BCD(QDataStream &ds, double real) { + +qint16 out; + +double exp; +double base; +double mant; +exp = real; +int i; + +qDebug()<<"BCD from "<>c; + a1.append(c); + } + data = a1; + parseData(); +} + +AbstractData::~AbstractData() { + qDebug()<<"~AbstractData"; +} + +//REAL +// +Application::Application(QString name_in, hp_DataType type_in): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_FUNCTIONS); +} + +void Application::parseData() { + +} + +//REAL +// +Real::Real(QString name_in, hp_DataType type_in): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_SETTINGS); +} + +//Find the vars in the calc.hpsettings file. Marker b4 01 00 +void Real::parseData() { + + QByteArray a1; + int ind=0; + int len; + int j; + int start; + QByteArray searchstr=QByteArrayLiteral("\x0c\x00\xc0\x05"); + QByteArrayMatcher matcher(searchstr); + + QByteArray item; + itemData value1,value2; + itemData listvalue; + + QString name; + errlog("Real: Parsing Vars"); + + name=getName(); + errlog(name); + a1.clear(); + a1=getData(); + + main_err->dump((uint8_t *)searchstr.constData(),4); + + // ind=a1.indexOf(searchstr,0); + ind=matcher.indexIn(a1,0); + if (ind>0) + len=((((a1[ind-3])&0x0F)<<8)+((a1[ind-4])&0xFF)-4)/16; + else + len=0; + + errlog(QString("Real: %1 %2 %3").arg(ind,0,10) + .arg(searchstr.size()) + .arg(len,2,10)); + // ind=a1.indexOf(searchstr,0); + ind=matcher.indexIn(a1,0); + if (ind>0) + len=((((a1[ind-3])&0x0F)<<8)+((a1[ind-4])&0xFF)-4)/16; + else + len=0; + + start=ind+4; + qDebug()<(item[2])==0x13) { + main_err->dump((uint8_t *)item.constData(),16); + value1=extract16(item); + j++; + start=start+16; + item=a1.mid(start,16); + main_err->dump((uint8_t *)item.constData(),16); + value2=extract16(item); + listvalue.dReal=value1.dReal; + listvalue.sValue=value1.sValue; + listvalue.dImaginary=value2.dReal; + listvalue.sValue=complex2Str(value1.sValue,value2.sValue); + start=start+16; + } + else { + main_err->dump((uint8_t *)item.constData(),16); + listvalue=extract16(item); + start=start+16; + } + + setListItem(getListSize(),listvalue); + } +// errlog("Real Dump"); +// main_err->dump((uint8_t *)a1.constData(),a1.size()); +} + +//Gets a list item from the list +itemData Real::getListItem(int row) { + + itemData null; + + if (row0) + len=((((a1[ind-3])&0x0F)<<8)+((a1[ind-4])&0xFF)-4)/16; + else + len=0; + + errlog(QString("Real: %1 %2 %3").arg(ind,0,10) + .arg(searchstr.size()) + .arg(len,2,10)); + // ind=a1.indexOf(searchstr,0); + ind=matcher.indexIn(a1,0); + if (ind>0) + len=((((a1[ind-3])&0x0F)<<8)+((a1[ind-4])&0xFF)-4)/16; + else + len=0; + + start=ind+4; + qDebug()<(item[2])==0x13) { + main_err->dump((uint8_t *)item.constData(),16); + value1=extract16(item); + j++; + start=start+16; + item=a1.mid(start,16); + main_err->dump((uint8_t *)item.constData(),16); + value2=extract16(item); + listvalue.dReal=value1.dReal; + listvalue.sValue=value1.sValue; + listvalue.dImaginary=value2.dReal; + listvalue.sValue=complex2Str(value1.sValue,value2.sValue); + start=start+16; + } + else { + main_err->dump((uint8_t *)item.constData(),16); + listvalue=extract16(item); + start=start+16; + } + + setListItem(getListSize(),listvalue); + } +// main_err->dump((uint8_t *)a1.constData(),a1.size()); +} + +//Gets a list item from the list +itemData Complex::getListItem(int row) { + + itemData null; + + if (row(searchstr),0); + + //look for FF 16 00 + + len=a1[ind+3]; + + for(j=0;j(item[2])==0x13) { + main_err->dump((uint8_t *)(item.constData()),16); + value1=extract16(item); + j++; + start=start+16; + item=a1.mid(start,16); + main_err->dump((uint8_t *)item.constData(),16); + value2=extract16(item); + listvalue.dReal=value1.dReal; + listvalue.sValue=value1.sValue; + listvalue.dImaginary=value2.dReal; + listvalue.sValue=complex2Str(value1.sValue,value2.sValue); + start=start+16; + } + else { + main_err->dump((uint8_t *)item.constData(),16); + listvalue=extract16(item); + start=start+16; + } + + setListItem(-1,listvalue); + + } + main_err->dump((uint8_t *)a1.constData(),a1.size()); +} + +//Gets a list item from the list +itemData List::getListItem(int row) { + + itemData null; + + if (row>c; + a1.append(c); + } + data = a1; + parseData(); +} + + +void Matrix::parseData() { + + QByteArray a1; + QByteArray item; + itemData listvalue,value1,value2; + QString name; + QString msg; + QString value=QStringLiteral("");; + int mrows; + int mcolumns; + int start; + int k,j; + int ind; + int flag =0; + qint8 vtype; + + QString ds; +// QByteArray searchstr((char *)std::begin({0x01,0x00}),2); + //Start keeps changing 01 or 02 + //0x14 real 0x94 Complex + + qDebug()<<"Matrix: Parsing a Matrix"; + + name=getName(); + errlog(name); + a1=data; +// ind=a1.indexOf(searchstr,0); + ind=0; + vtype=a1[ind+2]; + + errlog(QString("vtype=%1").arg(vtype,1,16)); + if ((vtype&0x7F)==0x14) { + errlog("matrix found"); + flag =1; + } + errlog(QString("vtype=%1").arg(vtype&0x7F,1,16)); + if ((vtype&0x80)==0x80) { + errlog("complex found"); + flag =2; + } + errlog(QString("vtype=%1").arg(vtype&0x80,1,16)); + + //look for 00 14 + errlog(QString("Found string at %1").arg(ind)); + + mcolumns=a1[ind+12]; + mrows=a1[ind+8]; + qDebug()<dump((uint8_t *)a1.constData(),a1.size()); +} + +//Gets a item from the matrix +itemData Matrix::getListItem(int row, int column) { + + itemData data; + data=mdata.at(row,column); + return data; +} + +//Gets a list item in the matrix at position row,column +void Matrix::setListItem(int row, int column, itemData item) { + + mdata.insert(row,column,item); +} + +//Gets a string representation of the list item in the matrix at position row,column +QString Matrix::getItem(int row, int column) { + + itemData data; + QString item; + + data=mdata.at(row,column); + item=data.sValue; +// item=QString("%1").arg(data.dReal,5); + return item; +} + +//Passes a string representation of the item in the matrix at position position row,column +void Matrix::setItem(int row, int column, QString string) { + + setItem(row,column,string,string.toDouble()); +} + +//Passes a string representation of the list item in the matrix at position row,column +void Matrix::setItem(int row, int column, QString string, double value) { + + itemData item; + item.dReal=value; + item.sValue=string; + setListItem(row,column,item); +} + +bool Matrix::getData(QDataStream &ds) { + qDebug()<<"Matrix::getData(ds)"; +// QByteArray out; +// out.clear(); + mdata.dataOut(ds); + return true; +} + +//Passes the number of entries in the list +m_Size Matrix::getMatrixSize() { + + m_Size size; + size.row=mdata.rows(); + size.column=mdata.columns(); + + return size; +} + +//Passes the number of entries in the list +int Matrix::getMatrixRows() { + + return mdata.rows(); +} + +//Passes the number of entries in the list +int Matrix::getMatrixColumns() { + + return mdata.columns(); +} + +//Program +Program::Program(QString name_in, hp_DataType type_in, QString data): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_PROG); + setProg(data); +} + +QString Program::getProg() { + return text; +} + +void Program::setProg(QString data_in) { + QByteArray ba_data=data_in.toUtf8(); + setData(ba_data); + text=data_in; + qDebug()<toUnicode(a1); + + return; +} + +void Program::parseData(QDataStream& in) { + + QTextCodec * codec = QTextCodec::codecForName("ISO 8859-1"); + QByteArrayMatcher matcher; + QByteArray search; + QByteArray phrase; + int ind; + int pos; + QString str; + in.setByteOrder(QDataStream::LittleEndian); + qint8 c; + QByteArray a1; + uint length; + length=16; + + qDebug()<<"Parsing Program"; + in.startTransaction(); + while(!in.atEnd()) { + in>>c; + a1.append(c); + } + + main_err->dump((uint8_t *)a1.constData(),a1.size()); + + 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); + errlog(QString("TD...%1 %2").arg(pos,0,16).arg(ind)); + main_err->dump((uint8_t *)phrase.data(),3*16); + errlog(str); + } + } + } + else { + errlog("Data is not a program file"); + } + + + // char cstr[20]; +// in.readRawData(cstr,20); +// str=QString(cstr); +// qDebug()<toUnicode(a1); + setProg(codec->toUnicode(a1)); + + return; +} + + +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()<toUnicode(a1); + format = codec->toUnicode(a3); + +} + +void Notes::setNote(QString data_in) { + text=data_in; +} + +//Variables +Variables::Variables(QString name_in, hp_DataType type_in): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_SETTINGS); + +} + +void Variables::parseData() { + +// quint16 len1,len2; + + QByteArray a1,a3; + + a1=getData(); + +} + +//CAS Variables +CASVariables::CASVariables(QString name_in, hp_DataType type_in): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_SETTINGS); + +} + +void CASVariables::parseData() { + +// quint16 len1,len2; + + QByteArray a1,a3; + + a1=getData(); + +} + +//Settings +Settings::Settings(QString name_in, hp_DataType type_in): + AbstractData(name_in, type_in) { + + setFileCode(HP_TP_SETTINGS); + +} + +void Settings::parseData() { + +// quint16 len1,len2; + + QByteArray a1,a3; + + a1=getData(); + +} + +void Settings::setData(QByteArray datain) { + + qDebug()<<"Settings Compare:"; + + int len1=data.size(); + int len2=datain.size(); + errlog(QString("Settings Compare %1 %2").arg(len1).arg(len2)); + int i=0; + while ((i. + */ + +#include +#include "cntfilesystemmodel.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#define FILE_NUM 9 + + +//list of file types and associated icons +//Todo fix for all file types +const QString contentFileSystemModel::filetype_list[FILE_NUM][2]={{"hpprgm",":/icons/apps_16x16.png"}, + {"CAS Vars",":/icons/casFolder_16x16.png"}, + {"Complex",":/icons/complex_16x16.png"}, + {"hplist",":/icons/list_16x16.png"}, + {"Matrices",":/icons/table_16x16.png"}, + {"Notes",":/icons/note_16x16.png"}, + {"hpprgm",":/icons/program_16x16.png"}, + {"Real",":/icons/real_16x16.png"}, + {"Variables",":/icons/varFolder_16x16.png"} + }; + + +//list of data object types used by contentFileSystemModel +const hp_DataType contentFileSystemModel::func_type[FILE_TYPE]={ + HP_PROG, + HP_LIST, + HP_MATRIX, + HP_NOTE, + HP_MAIN}; + +/* +const std::array,FILE_TYPE> contentFileSystemModel::file_type{ {0,"hpprgm"}, + {1,"hplist"}, + {2,"hpmat"}, + {3,"hpnote"}, + {4,""}}; +*/ + +//list of file type suffixes +const QString contentFileSystemModel::file_type[FILE_TYPE]{ "hpprgm", + "hplist", + "hpmat", + "hpnote", + ""}; + + +//condstrutor +contentFileSystemModel::contentFileSystemModel(QObject * parent) + :QFileSystemModel(parent) +{ + +} + +//Get and pass on the data to be dragged +QMimeData* contentFileSystemModel::mimeData(const QModelIndexList &indexes) const +{ + + QMimeData *mimeDataPtr = new QMimeData(); + QByteArray mydata; + QModelIndex index; + hp_DataStruct filedata; + + qDebug()<<"contentFileSystemModel::mimeData"; + + foreach(index,indexes) { + + index=indexes.first(); + // qDebug()<>c; + mydata.append(c); + } + mimeDataPtr->setText(info.baseName()); + + + switch (filedata.type) { + + case HP_PROG: + case HP_APP: + case HP_MATRIX: + case HP_NOTE: + case HP_LIST: + case HP_VAR: { + mimeDataPtr->setData(mimetypes[filedata.type][1],mydata); + break; + } + case HP_CAS: + case HP_MAIN: + case HP_COMPLEX: + case HP_SCREEN: + case HP_REAL: { + // no action + } + } + } + + file.close(); + } + + //Allow copy to external file managers + QList urls; + QFileInfo info; + QUrl url; + foreach(index,indexes) { + info = contentFileSystemModel::fileInfo(index); + + url = QUrl::fromLocalFile(info.absoluteFilePath()); + + urls.append(url); + } + mimeDataPtr->setUrls(urls); + + return mimeDataPtr; +} + +//Set drop actions supported +Qt::DropActions contentFileSystemModel::supportedDropActions() const +{ + return Qt::CopyAction | Qt::MoveAction| Qt::TargetMoveAction; +} + +//Not sure that this is neccesary. Item should control this +Qt::ItemFlags contentFileSystemModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QFileSystemModel::flags(index); + + if (index.isValid()) + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + else + return Qt::ItemIsDropEnabled | defaultFlags; +} + +//Allow drop in location +bool contentFileSystemModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + + qDebug()<formats(); + + if (data->hasUrls()) { + return true; + } + + if (data->hasText()) { + return true; + } + + return false; +} + +//Process the drop action +bool contentFileSystemModel::dropMimeData(const QMimeData* md_data, Qt::DropAction action, int row, + int column, const QModelIndex &parent) +{ + + qDebug()<<"contentFileSystemModel::DropMineData"; + + QSettings appSettings("IRGP","QtHPconnect"); + QString path=appSettings.value("contentPath").toString(); + + QDir dir; + dir= rootDirectory(); + + if (!dir.exists()) { + qWarning()<hasUrls()) { + + QString name = md_data->text(); + QList urls = md_data->urls(); + QUrl url; + QString filefrom; + QString fileto; + + foreach(url,urls) { + filefrom=url.toLocalFile(); + QFileInfo fileinfo(filefrom); + fileto=path+"/"+url.fileName(); + if(isFileType(fileinfo)) { + //consider check to limit unusual file types + QFile::copy(filefrom,fileto); + } + } + + return true; + } + + //rework + QByteArray data_in; + QByteArray typeary; + QString name = md_data->text(); + typeary=md_data->data("application/x-type"); + int type_i=typeary[0]; + hp_DataType type=static_cast(type_i); + QString type_str=getFileType(type); + name=name+"_2"+"."+type_str; + data_in=md_data->data("application/x-qabstractmodeldatalist"); + QFileInfo fileinfo(path,name); + + qDebug()<-1) + { + return true; + } + else + return true; +} + +//override to return a file object +QVariant contentFileSystemModel::data( const QModelIndex &index, int role ) const { + + if( role == Qt::DecorationRole ) + { + QString name = index.data().toString(); + QFileInfo info = contentFileSystemModel::fileInfo(index); + //QFileInfo info(name); + + if((info.isFile()&&(name==info.fileName()))) + { + int i; + for (i=0;igetType(); + switch (type) { + case HP_NOTE: + case HP_PROG: { + if (hptextedit==nullptr) + hptextedit = new hp_mdiTextEdit(mdiwin,info, data); + if (hptextedit!=nullptr) + hptextedit ->show(); + } + break; + case HP_CAS: + case HP_REAL: + case HP_COMPLEX: + case HP_LIST: + case HP_MATRIX: { + if (hpvaredit==nullptr) { + if (data!=nullptr) { + qDebug()<<"Opening Varedit"; + hpvaredit = new hp_mdiVariableEdit(mdiwin,info,data); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + } + break; + } + } + else { + qWarning()<<"Read file return null data"; + } + return false; + qDebug()<<"ClickAction "<parseData(in); + } + break; + case HP_NOTE: { + qDebug()<<"HP_NOTE"; + data = new Notes(filedata.filename, HP_NOTE, QStringLiteral("")); + data->parseData(in); + } + break; + case HP_LIST: { + qDebug()<<"HP_LIST"; + data = new List(filedata.filename, HP_LIST); + data->parseData(in); + } + break; + case HP_MATRIX: { + qDebug()<<"HP_MATRIX"; + data = new Matrix(filedata.filename, HP_MATRIX); + data->parseData(in); + } + break; + default: ; + } + + file.close(); + } + + return data; +} + +//write a file to the directory store +int contentFileSystemModel::writeFile(QFileInfo fileinfo, QByteArray data_in) const { + + QFile file(fileinfo.absoluteFilePath()); + + if (file.open(QIODevice::ReadWrite)) { + QDataStream out(&file); +// QTextCodec *codec = QTextCodec::codecForName("UTF-8"); +// out.setCodec(codec); + out.setByteOrder(QDataStream::LittleEndian); + +// quint8 c; +// for (int i =0 ;i< data_in.length();i++) +// { +// c= data_in[i]; +// out<<(quint8)c; +// } + // out.writeRawData(data_in,data_in.length()); + qDebug()<<"Wriiting"; + qDebug()<-1) { + suffix=file_type[i]; + } + + return suffix; +} + +//destructor +contentFileSystemModel::~contentFileSystemModel() { + qDebug()<<"contentFileSystemModel::delete"; +} diff --git a/source/datamodel.cpp b/source/datamodel.cpp new file mode 100644 index 0000000..4905fcf --- /dev/null +++ b/source/datamodel.cpp @@ -0,0 +1,91 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "datamodel.h" + +#include +#include + +dataModel::dataModel(QObject *parent) + :QAbstractTableModel(parent) +{ +} + +int dataModel::rowCount(const QModelIndex & /*parent*/) const +{ +return 2; +} + +int dataModel::columnCount(const QModelIndex & /*parent*/) const +{ +return 3; +} + +QVariant dataModel::data(const QModelIndex &index, int role) const +{ + int row = index.row(); + int col = index.column(); + // // generate a log message when this method gets called + // qDebug() << QString("row %1, col%2, role %3") + // .arg(row).arg(col).arg(role); + + switch(role){ + case Qt::DisplayRole: + if (row == 0 && col == 1) return QString("<--left"); + if (row == 1 && col == 1) return QString("right-->"); + + return QString("Row%1, Column%2") + .arg(row + 1) + .arg(col +1); + break; + case Qt::FontRole: + if (row == 0 && col == 0) //change font only for cell(0,0) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + break; + case Qt::BackgroundRole: + + if (row == 1 && col == 2) //change background only for cell(1,2) + { + QBrush redBackground(Qt::red); + return redBackground; + } + break; + case Qt::TextAlignmentRole: + + if (row == 1 && col == 1) //change text alignment only for cell(1,1) + { + return Qt::AlignRight + Qt::AlignVCenter; + } + break; + case Qt::CheckStateRole: + + if (row == 1 && col == 0) //add a checkbox to cell(1,0) + { + return Qt::Checked; + } + } + return QVariant(); +} + +dataModel::~dataModel() { + + qDebug()<<"dataModel::close"; +} diff --git a/source/errorhandler.cpp b/source/errorhandler.cpp new file mode 100644 index 0000000..a5241d7 --- /dev/null +++ b/source/errorhandler.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "errorhandler.h" +#include "mainwindow.h" + +errorHandler::errorHandler() +{ +} + +errorHandler::errorHandler(QObject * parent) +{ + pParent = parent; +} + +QString errorHandler::getLogFileName() +{ + return QString("hpinterface.log"); +} + +int errorHandler::writeLog(QString lineToBeLogged) +{ + + QMutexLocker locker(&m_lineLoggerMutex); + QFile fileLog(getLogFileName()); + + //doRollLogsIfNeeded(static_cast(fileLog.size() + lineToBeLogged.length())); + + // Do not open in append mode but seek() to avoid warning for unseekable + // devices, note that if open is made with WriteOnly without Append, the + // file gets truncated + if (!fileLog.open(QIODevice::ReadWrite | QIODevice::Text)) + { + QTextStream out(stdout); + out << "CANNOT OPEN LOG FILE: " << getLogFileName(); + return -1; + } + // seek() does nothing on sequential devices, this is in essence what QFile + // does when Append flag is set in open() + if (!fileLog.isSequential()) + { + fileLog.seek(fileLog.size()); + } + QDateTime time(QDateTime::currentDateTime()); + + QTextStream out(&fileLog); + out << time.toString("yyyy/MM/dd hh:mm:ss") << " "<< lineToBeLogged << endl; + + fileLog.close(); + + return 0; +} + +int errorHandler::writeStatus(QString msg) +{ + if (MainWindow *pb = qobject_cast (pParent)) + { + pb->writeStatus( msg); + } + return 0; +} + +int errorHandler::writeChatter(QString msg) +{ + if (MainWindow *pb = qobject_cast (pParent)) + { + pb->writeChatter( msg); + } + return 0; +} + +int errorHandler::error(ErrLevel el, int num, QString msg, QString Data=QString()) +{ + switch (el) { + case L0: + writeLog("Abort: "+msg); + writeStatus("Abort: "+msg); + exit(num); + break; + default: + writeLog(" "+msg+Data); + writeStatus(" "+msg); + if (Data=="") + writeChatter(" "+msg); + else + writeChatter(" "+msg+Data); + break; + } + return 0; +} + +int errorHandler::dump(uint8_t * data, int size) +{ + int i,j; + QString text = QString("Dump:\n"); + QString texta = QString("ASCII:\n"); + j=0; + text = text + QString().sprintf("%04d | ",0); + for (i=0; i< size; i++) + { + text = text + QString(" %1 ").arg(QChar(data[i]).unicode(),2,16,QChar('0')); + j++; + if (j>15) { + j=0; + text=text+"\n"; + text = text + QString().sprintf("%04d | ",i+1); + } + texta = texta +" "+QChar(data[i]).unicode(); + + } + text = text + "\n"; + texta = texta + "\n"; + + writeLog(text); + writeChatter(text); + writeLog(texta); + writeChatter(texta); + + return 0; +} + +errorHandler::~errorHandler() { + qDebug()<<"errorHandler:: close"; +} diff --git a/source/eventthread.cpp b/source/eventthread.cpp new file mode 100644 index 0000000..09b337b --- /dev/null +++ b/source/eventthread.cpp @@ -0,0 +1,42 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "eventthread.h" +#include +#include + +EventThread::EventThread(MainWindow * parent):QThread (parent) +{ + + main=parent; + if (main) + hpapi=main->getAPI(); + + if (hpapi==nullptr) + qDebug()<<"hpusb not started"; +} + +void EventThread::run() { + + qDebug()<<"Event run"; +// emit startTimer(); + hpapi->eventHandler(); + qDebug()<<"Event end"; + //exec(); +} + + diff --git a/source/eventtimer.cpp b/source/eventtimer.cpp new file mode 100644 index 0000000..58ffdc0 --- /dev/null +++ b/source/eventtimer.cpp @@ -0,0 +1,82 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "eventtimer.h" +#include "mainwindow.h" + +EventTimer::EventTimer(MainWindow * main):QObject() +{ + + if (main) + hpapi=main->getAPI(); + + if (hpapi==nullptr) + qDebug()<<"hpusb not started"; + +} + +void EventTimer::timerAction() +{ + QMutexLocker locker(&mutex); + + // qDebug()<<"In Eventhandler"; + // QThread::msleep(1); + + if(hpapi!=nullptr) { + hpapi->eventHandler(); + } + emit tick(); +} + +void EventTimer::start() { + timer = new QTimer(this); + timer->setInterval(100); + // timer->callOnTimeout(SLOT(timerEvent()),Qt::AutoConnection); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(timerAction())); + // timer->connect(timer, SIGNAL(timeout()), hpapi, SLOT(eventHandler()),Qt::DirectConnection); + +// timer->connect(this, SIGNAL(tick()), this, SLOT(tickEvent()),Qt::AutoConnection); + + timer->connect(this, SIGNAL(stop()), this, SLOT(stopTimer())); + timer->start(); + qDebug()<<"EventTimer::started Timer"; +} + +void EventTimer::exit() { + emit stop(); + stop(); +} + +void EventTimer::stopTimer() { + qDebug()<<"EventTimer::stop Timer"; + timer->stop(); + emit stopped(); +} + +void EventTimer::tickEvent() { + qDebug()<<"EventTimer::tickEvent"; +} + +EventTimer::~EventTimer() +{ + stopTimer(); + if (timer!=nullptr) { + delete timer; + timer=nullptr; + } + qDebug()<<"delete EventTimer"; +} diff --git a/source/getnumber.cpp b/source/getnumber.cpp new file mode 100644 index 0000000..42c63c1 --- /dev/null +++ b/source/getnumber.cpp @@ -0,0 +1,33 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "getnumber.h" +#include "ui_getnumber.h" +#include + +getNumber::getNumber(QWidget *parent) : + QDialog(parent), + ui(new Ui::getNumber) +{ + ui->setupUi(this); +} + +getNumber::~getNumber() +{ + // qDebug()<<"Entering ~getNumber()"; + delete ui; +} diff --git a/source/getnumber.ui b/source/getnumber.ui new file mode 100644 index 0000000..1dd93a8 --- /dev/null +++ b/source/getnumber.ui @@ -0,0 +1,91 @@ + + + getNumber + + + + 0 + 0 + 427 + 118 + + + + Dialog + + + + + 0 + 70 + 411 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 30 + 20 + 381 + 32 + + + + + + + 30 + 70 + 88 + 34 + + + + Test + + + + + + + buttonBox + accepted() + getNumber + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + getNumber + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/source/hp_infodialog.cpp b/source/hp_infodialog.cpp new file mode 100644 index 0000000..fbbffa0 --- /dev/null +++ b/source/hp_infodialog.cpp @@ -0,0 +1,36 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hp_infodialog.h" +#include "ui_hp_infodialog.h" +#include + +hp_infoDialog::hp_infoDialog(QWidget *parent, hp_Information info) : + QDialog(parent), + ui(new Ui::hp_infoDialog) +{ + ui->setupUi(this); + ui->serialnum->setText(info.serialnum); + ui->appver->setText(info.appver); + ui->oppver->setText(info.osver); +} + +hp_infoDialog::~hp_infoDialog() +{ + // qDebug()<<"Entering ~hp_infoDialog()"; + delete ui; +} diff --git a/source/hp_infodialog.ui b/source/hp_infodialog.ui new file mode 100644 index 0000000..c59df0f --- /dev/null +++ b/source/hp_infodialog.ui @@ -0,0 +1,125 @@ + + + hp_infoDialog + + + + 0 + 0 + 411 + 143 + + + + HP Information + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + Application version: + + + + + + + - + + + + + + + Operational system version: + + + + + + + - + + + + + + + Serial number: + + + + + + + - + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + rejected() + hp_infoDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + buttonBox + accepted() + hp_infoDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/source/hp_mdilogwindow.cpp b/source/hp_mdilogwindow.cpp new file mode 100644 index 0000000..add2276 --- /dev/null +++ b/source/hp_mdilogwindow.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hp_mdilogwindow.h" +#include + +hp_MdiLogWindow::hp_MdiLogWindow(QWidget * parent) + :hp_MdiWindow(parent) +{ + setMinimumSize(200,200); + setMaximumSize(1000,1000); + setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored); + setup(); + resize(500,400); +} + +void hp_MdiLogWindow::setup() { + + textEdit = new QTextEdit(this); + setWidget(textEdit); +} + +QTextEdit * hp_MdiLogWindow::getEditor() { + return textEdit; +} + +void hp_MdiLogWindow::show() { + textEdit->show(); + hp_MdiWindow::show(); +} + +hp_MdiLogWindow::~hp_MdiLogWindow() { + + qDebug()<<"Entering ~hpmdiLogWindow()"; + +} diff --git a/source/hp_mditexteditor.cpp b/source/hp_mditexteditor.cpp new file mode 100644 index 0000000..e58c02d --- /dev/null +++ b/source/hp_mditexteditor.cpp @@ -0,0 +1,202 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//Called by the calculator Window +hp_mdiTextEdit::hp_mdiTextEdit(QWidget * parent,hpTreeItem * treeItem, AbstractData * calcData) + :hp_MdiWindow(parent) +{ + setMinimumSize(200,200); + setMaximumSize(1000,1000); + setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + + qDebug()<<"hp_mdiTextEdit::hp_mdiTextEdit 1"; + hptreeitem=treeItem; + content=false; + data = calcData; + + filename=treeItem->getFileName(); + calculator=treeItem->getCalculatorName(); + type=treeItem->getType(); + + setup(); + setWindowTitle(calculator+": "+filename); +} + +//Called by the content window +hp_mdiTextEdit::hp_mdiTextEdit(QWidget * parent, QFileInfo filedata, AbstractData * calcData) + :hp_MdiWindow (parent) +{ + + qDebug()<<"hp_mdiTextEdit::hp_mdiTextEdit 2"; + setMinimumSize(200,200); + setMaximumSize(1000,1000); + // setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + calculator=QStringLiteral("Content: "); + content=true; + hptreeitem=nullptr; + data = calcData; + filename=filedata.fileName(); + file=filedata; + type=calcData->getType(); + setup(); + setWindowTitle(calculator+filename); + resize(450,350); +} + +void hp_mdiTextEdit::setup() { + + QString text; + textEdit = new textEditor(this); + + if (data) { + + qDebug()<getName(); + qDebug()<getType(); + + if (data->getType()==HP_NOTE) { + Notes *note; + note=static_cast(data); + text=note->getNote(); + } + + if (data->getType()==HP_PROG) { + Program *prog; + prog=static_cast(data); + text=prog->getProg(); + textEdit->setDocumentTitle(prog->getName()); + } + qDebug()<setPlainText(text); + + } + else { + qDebug()<<"hp_mdiTextEdit::setup - Data Null"; + } + + QIcon save(":/icons/save_22x22.png"); + QAction * actionSave= new QAction(save,"Save",this); + + QWidget * top = new QWidget(); + QBoxLayout * layout = new QVBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + top->setLayout(layout); + + QToolBar * toolbar = new QToolBar("Save"); + toolbar->addAction(actionSave); + + QToolButton *saveButton=new QToolButton(); + QMenu * menu = new QMenu(saveButton); + menu->addAction(actionSave); + layout->setMenuBar(menu); +// layout->addWidget(toolbar); +// QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding); +// sizePolicy1.setHorizontalStretch(0); +// sizePolicy1.setVerticalStretch(0); +// sizePolicy1.setHeightForWidth(textEdit->sizePolicy().hasHeightForWidth()); +// textEdit->setSizePolicy(sizePolicy1); +// layout->setSizeConstraint(QLayout::SetNoConstraint); + + layout->addWidget(textEdit); + setWidget(top); + + connect(actionSave,SIGNAL(triggered()),this,SLOT(eventSave())); + + return; +} + +void hp_mdiTextEdit::eventSave(){ + save(); +} + +bool hp_mdiTextEdit::save(){ + + if(content) + return textEdit->save(file); + else { + return textEdit->save(calculator); + } +} + +bool hp_mdiTextEdit::saveAs(){ + + if(content) + return textEdit->saveAs(file); + else { + return textEdit->saveAs(calculator); + } +} + +void hp_mdiTextEdit::closeEvent(QCloseEvent *event) +{ + + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } + + QMdiSubWindow::closeEvent(event); +} + +bool hp_mdiTextEdit::maybeSave() +{ + if (!textEdit->document()->isModified()) + return true; + + const QMessageBox::StandardButton ret + = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(file.fileName()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + switch (ret) { + case QMessageBox::Save: + return textEdit->save(file); + case QMessageBox::Cancel: + return false; + default: + break; + } + return true; +} + +void hp_mdiTextEdit::show() { + + if (textEdit) + textEdit->show(); + QMdiSubWindow::show(); +} + +hp_mdiTextEdit::~hp_mdiTextEdit() { + + qDebug()<<"Entering ~hpmdiTextEdit()"; + if (textEdit!=nullptr) + delete textEdit; + +} diff --git a/source/hp_mdivariableedit.cpp b/source/hp_mdivariableedit.cpp new file mode 100644 index 0000000..640e691 --- /dev/null +++ b/source/hp_mdivariableedit.cpp @@ -0,0 +1,238 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "hp_mdivariableedit.h" +#include "hptreeitem.h" + +hp_mdiVariableEdit::hp_mdiVariableEdit(QWidget *parent, + hpTreeItem * treeItem, + hpCalcData * dataStore) + : hp_MdiWindow(parent) +{ + setMinimumSize(200,200); + setMaximumSize(1000,1000); + setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored); + + hptreeitem=treeItem; + hpcalc = dataStore; + filename = QStringLiteral("NULL"); + + if (hpcalc!=nullptr) { + calculator=hpcalc->getCalculatorName(); + + if (treeItem!=nullptr) { + filename=treeItem->getFileName(); + type=treeItem->getType(); + } + else { + qWarning()<<"hpcalc is null"; + } + data=hpcalc->getData(filename,type); + } + else { + qWarning()<<"hpcalc is null"; + } + content=false; + setup(); + + setWindowTitle(calculator+": "+filename); +} + +hp_mdiVariableEdit::hp_mdiVariableEdit(QWidget *parent, + QFileInfo fileinfo, + AbstractData * data_in) + : hp_MdiWindow(parent) +{ + setMinimumSize(200,200); + setMaximumSize(1000,1000); + setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored); + + calculator=QStringLiteral("Content: "); + content=true; + hptreeitem=nullptr; + hpcalc = nullptr; + file=fileinfo; + filename=fileinfo.fileName(); + + data = data_in; + + if (data!=nullptr) + type=data->getType(); + + setup(); + + setWindowTitle(calculator+filename); +} + +void hp_mdiVariableEdit::setup() { + + if (data!=nullptr) { + varmodel = new varTableModel(this,data,filename,type); + tableView = new QTableView(this); + tableView->setModel(varmodel); + + QIcon save(":/icons/save_22x22.png"); + QAction * actionSave= new QAction(save,"Save",this); + QWidget * top = new QWidget(); + QBoxLayout * layout = new QVBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + top->setLayout(layout); + QToolBar * toolbar = new QToolBar("Save"); + toolbar->addAction(actionSave); + + QToolButton *saveButton=new QToolButton(); + QMenu * menu = new QMenu(saveButton); + menu->addAction(actionSave); + layout->setMenuBar(menu); + layout->addWidget(tableView); + setWidget(top); + + connect(actionSave,SIGNAL(triggered()),this,SLOT(eventSave())); + } +} + +void hp_mdiVariableEdit::show() { + if(tableView!=nullptr) + tableView->show(); + else { + qWarning()<<"hp_mdiVariableEdit::show tableView null"; + } + hp_MdiWindow::show(); +} + +void hp_mdiVariableEdit::eventSave(){ + save(); +} + +bool hp_mdiVariableEdit::save(){ + + if (content==true) { + return saveFile(file); + } + + + + return false; +} + +bool hp_mdiVariableEdit::saveAs(){ + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), + file.absoluteFilePath()); + if (fileName.isEmpty()) + return false; + + if (content==true) { + QFileInfo fileinfo(fileName); + return saveFile(fileinfo); + } + + return false; +} + +bool hp_mdiVariableEdit::saveFile(const QFileInfo fileinfo) +{ + QFile file(fileinfo.absoluteFilePath()); + if (!file.open(QFile::ReadWrite)) { + + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.") + .arg(fileinfo.canonicalPath(), file.errorString())); + return false; + } + + qDebug()<<"Write file"; + + //Show busy cursor + QApplication::setOverrideCursor(Qt::WaitCursor); + + QDataStream ds(&file); + + ds.setByteOrder(QDataStream::LittleEndian); + varmodel->getData(ds); + + + //reset busy cursor + QApplication::restoreOverrideCursor(); + varmodel->resetModified(); + + file.close(); + return true; +} + + +bool hp_mdiVariableEdit::maybeSave() +{ + + if (varmodel==nullptr) + return false; + + if (!varmodel->isModified()) { + qDebug()<<"Var not modified"; + return true; + } + + if (content==false) { + return true; + } + + const QMessageBox::StandardButton ret + = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(file.fileName()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + switch (ret) { + case QMessageBox::Save: + return saveFile(file); + case QMessageBox::Cancel: + return false; + default: + break; + } + + return true; +} + + +void hp_mdiVariableEdit::closeEvent(QCloseEvent *event) +{ + + qDebug()<<"hp_mdiVariableEdit::closeEvent"; + + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } + + QMdiSubWindow::closeEvent(event); +} + +hp_mdiVariableEdit::~hp_mdiVariableEdit() { + + qDebug()<<"Entering ~hpmdiVariableEdit()"; + + if (varmodel!=nullptr) + delete varmodel; +} diff --git a/source/hp_mdiwindow.cpp b/source/hp_mdiwindow.cpp new file mode 100644 index 0000000..ecdb46f --- /dev/null +++ b/source/hp_mdiwindow.cpp @@ -0,0 +1,64 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hp_mdiwindow.h" +#include +#include +#include +#include +#include + +hp_MdiWindow::hp_MdiWindow(QWidget * parent) + :QMdiSubWindow(parent) +{ + // setMinimumSize(500,400); + // setMaximumSize(1000,1000); + setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored); + setup(); +} + +void hp_MdiWindow::setup() { + + +} + +void hp_MdiWindow::eventSave() { + qDebug()<<"Save pressed"; +} + +bool hp_MdiWindow::save() { + + qDebug()<<"hp_MdiWindow::save"; + return false; +} + +bool hp_MdiWindow::saveAs() { + + qDebug()<<"hp_MdiWindow::saveas"; + return false; +} + +void hp_MdiWindow::show() { + + QMdiSubWindow::show(); +} + +hp_MdiWindow::~hp_MdiWindow() { + + qDebug()<<"Entering ~hpmdiWindow()"; + +} diff --git a/source/hp_mdiwindow.ui b/source/hp_mdiwindow.ui new file mode 100644 index 0000000..a3a7916 --- /dev/null +++ b/source/hp_mdiwindow.ui @@ -0,0 +1,58 @@ + + + hp_MdiWindow + + + true + + + + 0 + 0 + 575 + 320 + + + + + 400 + 200 + + + + LogWindow + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + :/icons/save_22x22.png:/icons/save_22x22.png + + + Save + + + + + + + + diff --git a/source/hp_settingsdlg.cpp b/source/hp_settingsdlg.cpp new file mode 100644 index 0000000..c940a06 --- /dev/null +++ b/source/hp_settingsdlg.cpp @@ -0,0 +1,125 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hp_settingsdlg.h" +#include "ui_hp_settingsdlg.h" + +#include +#include + +hp_SettingsDlg::hp_SettingsDlg(QWidget *parent, hp_Settings * hpset) : + QDialog(parent), + ui(new Ui::hp_SettingsDlg) +{ + if (hpset) { + dlgset=*hpset; + retsettings=hpset; + } + ui->setupUi(this); + setupSettings(); + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(on_clicked(QAbstractButton*))); +} + +void hp_SettingsDlg::setupSettings() { + ui->cb_angle->setCurrentIndex(dlgset.angle_measure); + ui->cb_format->setCurrentIndex(dlgset.number_format); + ui->cb_precision->setCurrentIndex(dlgset.precision); + ui->cb_grouping->setCurrentIndex(dlgset.digit_grouping); + ui->cb_entry->setCurrentIndex(dlgset.entry); + ui->cb_integers->setCurrentIndex(dlgset.integers); + ui->cb_complex->setCurrentIndex(dlgset.complex); + ui->cb_language->setCurrentIndex(dlgset.language); + ui->cb_font->setCurrentIndex(dlgset.font_size); + ui->cb_theme->setCurrentIndex(dlgset.theme); + + ui->le_integer->setText(QString().sprintf("%d",dlgset.bits)); + + if (dlgset.textbook) + ui->ch_textbook->setCheckState(Qt::Checked); + else + ui->ch_textbook->setCheckState(Qt::Unchecked); + + if (dlgset.menu) + ui->ch_menu->setCheckState(Qt::Checked); + else + ui->ch_menu->setCheckState(Qt::Unchecked); + + if (dlgset.signed_int) + ui->ch_signed->setCheckState(Qt::Checked); + else + ui->ch_signed->setCheckState(Qt::Unchecked); + +} + +void hp_SettingsDlg::putSettings() { + dlgset.angle_measure=ui->cb_angle->currentIndex(); + dlgset.number_format=ui->cb_format->currentIndex(); + dlgset.precision=ui->cb_precision->currentIndex(); + dlgset.digit_grouping= ui->cb_grouping->currentIndex(); + dlgset.entry=ui->cb_entry->currentIndex(); + dlgset.integers=ui->cb_integers->currentIndex(); + dlgset.complex=ui->cb_complex->currentIndex(); + dlgset.language=ui->cb_language->currentIndex(); + dlgset.font_size=ui->cb_font->currentIndex(); + dlgset.theme=ui->cb_theme->currentIndex(); + + dlgset.bits=ui->le_integer->text().toInt(); + + if (ui->ch_menu->checkState()==Qt::Checked) + dlgset.menu=true; + else + dlgset.menu=false; + + if (ui->ch_textbook->checkState()==Qt::Checked) + dlgset.textbook=true; + else + dlgset.textbook=false; + + if (ui->ch_signed->checkState()==Qt::Checked) + dlgset.signed_int=true; + else + dlgset.signed_int=false; +} + +void hp_SettingsDlg::resetSettings() { + hp_Settings newset; + dlgset = newset; + setupSettings(); +} + +void hp_SettingsDlg::on_clicked(QAbstractButton * button) { + + if(button==(QAbstractButton*) ui->buttonBox->button(QDialogButtonBox::Reset) ){ + resetSettings(); + } + if(button==(QAbstractButton*) ui->buttonBox->button(QDialogButtonBox::Ok) ){ + putSettings(); + if (retsettings) { + *retsettings=dlgset; + } + close(); + } + if(button==(QAbstractButton*) ui->buttonBox->button(QDialogButtonBox::Cancel) ){ + close(); + } +} + +hp_SettingsDlg::~hp_SettingsDlg() +{ + qDebug()<<"delete hp_SettingsDlf"; + delete ui; +} diff --git a/source/hp_settingsdlg.ui b/source/hp_settingsdlg.ui new file mode 100644 index 0000000..f766c44 --- /dev/null +++ b/source/hp_settingsdlg.ui @@ -0,0 +1,720 @@ + + + hp_SettingsDlg + + + true + + + + 0 + 0 + 415 + 455 + + + + Qt::StrongFocus + + + Settings + + + + + + 0 + + + + Home Settings + + + + + 17 + 20 + 101 + 30 + + + + Qt::RightToLeft + + + Angle Measure: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 130 + 20 + 131 + 32 + + + + Radians + + + 0 + + + + Radians + + + + + Degrees + + + + + Gradians + + + + + + + 310 + 150 + 41 + 22 + + + + Qt::RightToLeft + + + ±: + + + + + + 130 + 50 + 131 + 32 + + + + Standard + + + + Standard + + + + + Fixed + + + + + Scientific + + + + + Engineering + + + + + Floating + + + + + Rounded + + + + + + + 130 + 81 + 131 + 32 + + + + 123,456.789 + + + + 123,456.789 + + + + + 123'456.789 + + + + + 123 456.789 + + + + + 123456.789 + + + + + 123.456,789 + + + + + 123'456,789 + + + + + 123 456,789 + + + + + 123"456.789 + + + + + 123456,789 + + + + + 1234,5678.901 + + + + + 1,23,456.789 + + + + + + + 20 + 50 + 101 + 30 + + + + Qt::RightToLeft + + + Number Format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 20 + 80 + 101 + 30 + + + + Qt::RightToLeft + + + Digit Grouping: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 130 + 112 + 131 + 32 + + + + Textbook + + + + Textbook + + + + + Algebraic + + + + + RPN + + + + + + + 20 + 111 + 101 + 30 + + + + Qt::RightToLeft + + + Entry: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 130 + 144 + 131 + 32 + + + + Binary + + + + Binary + + + + + Octal + + + + + Decimal + + + + + Hex + + + + + + + 20 + 143 + 101 + 30 + + + + Qt::RightToLeft + + + Integers: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 20 + 175 + 101 + 30 + + + + Qt::RightToLeft + + + Complex: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 130 + 176 + 131 + 32 + + + + a+b*i + + + + a+b*i + + + + + (a,b) + + + + + + + 130 + 208 + 131 + 32 + + + + Deutsch + + + + Deutsch + + + + + English + + + + + Espanol + + + + + Francais + + + + + Nederlands + + + + + Portugues + + + + + New Item + + + + + New Item + + + + + + + 20 + 207 + 101 + 30 + + + + Qt::RightToLeft + + + Language: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 20 + 239 + 101 + 30 + + + + Qt::RightToLeft + + + Font Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 130 + 240 + 131 + 32 + + + + Small Font + + + + Small Font + + + + + Medium Font + + + + + Large Font + + + + + + + 8 + 277 + 141 + 22 + + + + Qt::RightToLeft + + + Textbook Display: + + + + + + 151 + 277 + 141 + 22 + + + + Qt::RightToLeft + + + Menu Display: + + + + + + 130 + 311 + 131 + 32 + + + + Light + + + + Light + + + + + Dark + + + + + + + 20 + 310 + 101 + 30 + + + + Qt::RightToLeft + + + Color Theme: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 270 + 50 + 51 + 32 + + + + 0 + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 11 + + + + + + + 266 + 144 + 41 + 32 + + + + Qt::ImhDigitsOnly + + + 32 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset + + + + + + + + + buttonBox + accepted() + hp_SettingsDlg + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + hp_SettingsDlg + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/source/hpdata.cpp b/source/hpdata.cpp new file mode 100644 index 0000000..9c77270 --- /dev/null +++ b/source/hpdata.cpp @@ -0,0 +1,438 @@ +// +// +// +// +// This class acts as a data store for the interface and calls for data as required +// +#include "hpdata.h" +#include "global.h" +#include "errorhandler.h" +#include "abstractdata.h" +#include "hp_typedef.h" + +const QString hpCalcData::func_list[FUNC_NUM][2]={{"Application Library",":/icons/apps_32x32.png"}, + {"CAS Vars",":/icons/casFolder_32x32.png"}, + {"Real",":/icons/real_32x32.png"}, + {"Complex",":/icons/complex_32x32.png"}, + {"Lists",":/icons/list_32x32.png"}, + {"Matrices",":/icons/table_32x32.png"}, + {"Notes",":/icons/note_32x32.png"}, + {"Programs",":/icons/program_32x32.png"}, + {"Variables",":/icons/varFolder_32x32.png"} + }; + + +const hp_DataType hpCalcData::func_type[FUNC_NUM]={HP_APP, + HP_CAS, + HP_REAL, + HP_COMPLEX, + HP_LIST, + HP_MATRIX, + HP_NOTE, + HP_PROG, + HP_VAR + }; + + + +//constructor +hpCalcData::hpCalcData(QString name, hpusb * handle) + :QObject() +{ + hp_api = handle; + lData.clear(); + calculatorName=name; + + //open usb port and store the handle + if (hp_api) { + hp_handle.calc=this; + hp_api->hp_open(getHandle()); + } +} + +//return the interface class +hp_Handle * hpCalcData::getHandle() { + hp_handle.calc=this; + return &hp_handle; +} + +//return the interface class +hpusb * hpCalcData::getAPI() { + return hp_api; +} + +//data managment +hp_Information hpCalcData::getInfo() { + + return hp_info; +} + +//get Name +QString hpCalcData::getName() { + + return hp_info.name; +} + +//get Calculator Name +QString hpCalcData::getCalculatorName() { + + return calculatorName; +} + + +//get Settings +hp_Settings hpCalcData::getSettings() { + + return hp_homesettings; +} + +//Add a new object to the list +void hpCalcData::addData(AbstractData * data) { + lData.append(data); +} + +void hpCalcData::deleteData(AbstractData * data) { + // lData.erase(); + if (data!=nullptr) { + QString name=data->getName(); + hp_DataType type=data->getType(); + QList::iterator i; + i=findData(name,type); + + lData.erase(i); + delete data; + qDebug()<<"hpCalcData::deleteData - Object Deleted"; + } + else { + qDebug()<<"hpCalcData::deleteData - Object not deleted"; + } +} + +//returns position of entry in list or returns 0; +QList::iterator hpCalcData::findData(QString name, hp_DataType dataType) { + + QList::iterator i; + AbstractData * ldata; + + i = lData.begin(); + while (i!= lData.end()) { + ldata=*i; + if (ldata->equivalent(name,dataType)) { + return i; + } + + } + + return nullptr; +} + +//returns position of entry in list or returns 0; +AbstractData * hpCalcData::getData(QString name, hp_DataType dataType) { + + + for (int i = 0; i < lData.size(); ++i) { + if (lData.at(i)->equivalent(name,dataType)) { + + qDebug()<<"hpCalcData::Data found"<usbhandle); + if (api) { + api->get_settings(handle); + } + } + else { + errlog("hpCalcData::readSettings Handle null"); + } + } + else { + errlog("hpCalcData::readSettings API null"); + } + // hp_homesettings=hpset; + + // hp_Change change; + // change.dataChange=HP_MAIN; + // emit dataChanged(change); +} + +//read Settings via usb +void hpCalcData::readScreen() { + + hpusb * api; + hp_Handle * handle; + hp_Settings hpset; + + errlog("Reading Screen"); + + api=getAPI(); + handle=getHandle(); + + QByteArray imageData; + + if (api) { + if(handle) { + qDebug()<usbhandle); + if (api) { + api->get_screen_shot(handle); + // if (screenShot!=nullptr) { + // delete screenShot; + // } +// +// screenShot = new QPixmap(); +// screenShot->loadFromData(imageData); + } + } + } +// emit emitChange(HP_SCREEN); +} + +//recieve Screenshot +void hpCalcData::recvScreen(hp_ScreenShot shot) { + + errlog("Recieving Screen"); + + QByteArray imageData; + if (screenShot!=nullptr) { + delete screenShot; + } + screenShot = shot.image; + + emit emitChange(HP_SCREEN); +} + +//recieve Setting +void hpCalcData::recvSettings(hp_Data data) { + + QString filename; + errlog("hpCalcData::recvSettings: Recieving Setting"); + filename = data.name; + qDebug()<setData(data.data); + addData(obj1); + emit emitChange(HP_REAL); + + qDebug()<<"hpCalcData::recvSetting - Complex"; + errlog("hpCalcData::recvSetting - Complex"); + Complex * obj2 = new Complex(data.name,HP_COMPLEX); + obj2->setData(data.data); + addData(obj2); + emit emitChange(HP_COMPLEX); + + } + + if (filename== QStringLiteral("cas.hpsettings")) { + qDebug()<<"cas.chps"; + + qDebug()<<"hpCalcData::recvSetting - CAS"; + CASVariables * obj2 = new CASVariables(data.name,HP_CAS); + obj2->setData(data.data); + addData(obj2); + emit emitChange(HP_CAS); + } + + if (filename==QStringLiteral("calc.hpvars")) { + + qDebug()<<"hpCalcData::recvSetting - Variables"; + Variables * var = new Variables(data.name,HP_VAR); + var->setData(data.data); + addData(var); + } + + if (filename==QStringLiteral("settings")) { + qDebug()<<"set-"; + + qDebug()<<"hpCalcData::recvSetting - Variables"; + Settings * var = new Settings(data.name,HP_SETTINGS); + var->setData(data.data); + addData(var); + } + + emit emitChange(HP_MAIN); +} + + +//recieve Program +void hpCalcData::recvProg(hp_Prog program) { + + errlog("Recieving Program"); + qDebug()<<"hpCalcData::recvProg"; + + qDebug()<setData(program.data); + addData(obj); + + emit emitChange(HP_PROG); +} + +//recieve Program +void hpCalcData::recvNote(hp_Note note) { + + errlog("Recieving Note"); + qDebug()<<"hpCalcData::recvNote"; + + qDebug()<setData(note.data); + addData(obj); + + emit emitChange(HP_NOTE); +} + +//recieve Program +void hpCalcData::recvData(hp_Data data) { + + errlog("Recieving Data"); + + switch (data.type) { + case HP_APP: { + qDebug()<<"hpCalcData::recvData - Application"; + Application * obj = new Application(data.name,data.type); + obj->setData(data.data); + addData(obj); + emit emitChange(HP_APP); + } + break; + case HP_LIST: { + List * obj = new List(data.name,data.type); + obj->setData(data.data); + addData(obj); + emit emitChange(HP_LIST); + } + break; + case HP_MATRIX: { + qDebug()<<"hpCalcData::recvData - Matrix"; + Matrix * obj = new Matrix(data.name,data.type); + obj->setData(data.data); + addData(obj); + emit emitChange(HP_MATRIX); + } + break; + } +} + + +void hpCalcData::emitChange(hp_DataType type) { + + hp_Change change; + change.dataChange=type; + change.calc = this; + + emit dataChanged(change); + +} + +hp_ScreenShot hpCalcData::getScreenShot() { + hp_ScreenShot scn; + + scn.image = screenShot; + scn.format = CALC_SCREENSHOT_FORMAT_PRIME_PNG_320x240x16; + scn.calc = this; + + return scn; +} + +//set Settings +int hpCalcData::setSettings(hp_Settings set) { + + hp_homesettings=set; +} + +void hpCalcData::setInfo(hp_Information dtype) { + hp_info=dtype; + return; +} + +//read information via hp interface +void hpCalcData::readInfo() { + + hpusb * api; + hp_Handle * handle; + hp_Information hpinfo; + + api=getAPI(); + handle=getHandle(); + + if (api) { + if(handle) { + qDebug()<usbhandle); + if (api) + api->load_info(handle); + } + } +} + +void hpCalcData::recvInfo(hp_Information hpinfo) { + + hp_info=hpinfo; + emit emitChange(HP_MAIN); +} + + +void hpCalcData::vpkt_send_experiments(int cmd) { + + hpusb * api; + hp_Handle * handle; + + api=getAPI(); + handle=getHandle(); + + if (api) { + if(handle) { + if (api) { + api->is_ready(handle); + + // api->vpkt_send_experiments(handle,cmd); + + } + } + } + +} + +hpCalcData::~hpCalcData() { + qDebug()<<"Close ~hpCalcData"; +}; diff --git a/source/hptoolbox.cpp b/source/hptoolbox.cpp new file mode 100644 index 0000000..42935d9 --- /dev/null +++ b/source/hptoolbox.cpp @@ -0,0 +1,14 @@ +#include +#include "ui_hptoolbox.h" + +hpToolBox::hpToolBox(QWidget *parent) : + QToolBox(parent), + ui(new Ui::hpToolBox) +{ + ui->setupUi(this); +} + +hpToolBox::~hpToolBox() +{ + delete ui; +} diff --git a/source/hptreeitem.cpp b/source/hptreeitem.cpp new file mode 100644 index 0000000..112443d --- /dev/null +++ b/source/hptreeitem.cpp @@ -0,0 +1,641 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hptreeitem.h" +#include "global.h" +#include "hpdata.h" +#include "hp_mditexteditor.h" +#include "hp_infodialog.h" +#include "hp_settingsdlg.h" + +#include +#include + +const QString hpTreeItem::func_list[FUNC_NUM][2]={ + {"Main",":/icons/apps_32x32.png"}, + {"Application Library",":/icons/apps_32x32.png"}, + {"CAS Vars",":/icons/casFolder_32x32.png"}, + {"Real",":/icons/real_32x32.png"}, + {"Complex",":/icons/complex_32x32.png"}, + {"Lists",":/icons/list_32x32.png"}, + {"Matrices",":/icons/table_32x32.png"}, + {"Notes",":/icons/note_32x32.png"}, + {"Programs",":/icons/program_32x32.png"}, + {"Variables",":/icons/varFolder_32x32.png"} + }; + +const hp_DataType hpTreeItem::func_type[FUNC_NUM]={ + HP_MAIN, + HP_APP, + HP_CAS, + HP_REAL, + HP_COMPLEX, + HP_LIST, + HP_MATRIX, + HP_NOTE, + HP_PROG, + HP_VAR + }; + + + +//QString hpTreeItem::hp_name; + + +hpTreeItem::hpTreeItem() + :QStandardItem() { + setDropEnabled(true); + setEditable(0); +} + + + + +hpTreeItem::hpTreeItem(const QString & name,hpCalcData * hpDataStore,int flag) +:QStandardItem(name) +{ + setEditable(0); + setDataStore(hpDataStore); + + setDragEnabled(true); + setDropEnabled(true); + + // filename=name; + + if (flag==0) + setGraphicTree(); +} + +bool hpTreeItem::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) { + + qDebug()<<"hpTreeItem::dropMimeData"; +} + +QStandardItem * hpTreeItem::clone() const { + //return new hpTreeItem(QStringLiteral("test"),getDataStore(),0); +} + +void hpTreeItem::setGraphicTree() { + + int func_num=FUNC_NUM; + hpTreeItem * newChild; + + int i; + + for (i=1; isetType(func_type[i]); + newChild->setIcon(QIcon(func_list[i][1])); + newChild->setEditable(0); + newChild->setToolTip(QString("Manage Applications")); +// newChild->getDataStore()->getInfo().serialnum="12-3456"; + appendRow(newChild); + } +} + +void hpTreeItem::clickAction(QMdiArea * mdiwin) { + + hp_infoDialog * hpinfodlg; + hp_Information hpinfo; + hpCalcData * calc; + hp_DataStruct hpdata; + calc=getDataStore(); + AbstractData * data=nullptr; + + // QString test; + // test=data(Qt::DisplayRole).toString(); + + qDebug()<<"hpTreeItem::clickAction ... click"; + + switch (getType()) { + case HP_MAIN: { + hpCalcData * dataStore; + dataStore = getDataStore(); + hpinfo=dataStore->getInfo(); + hpinfodlg = new hp_infoDialog(mdiwin,hpinfo); + hpinfodlg->show(); + } + break; + case HP_APP: { + + } + break; + case HP_CAS: + if (hpvaredit==nullptr) { + if (calc) { + data=calc->getData(getFileName(),HP_COMPLEX); + } + if (data!=nullptr) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,this,calc); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + case HP_COMPLEX: + if (hpvaredit==nullptr) { + if (calc) { + data=calc->getData(getFileName(),HP_COMPLEX); + } + if (data!=nullptr) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,this,calc); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + break; + case HP_LIST: + if (hpvaredit==nullptr) { + if (calc) { + data=calc->getData(getFileName(),HP_LIST); + } + if (data) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,this,calc); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + break; + case HP_MATRIX: + if (hpvaredit==nullptr) { + if (calc) { + data=calc->getData(getFileName(),HP_MATRIX); + } + if (data!=nullptr) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,this,calc); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + break; + case HP_NOTE: { + hpCalcData * dataStore; + dataStore = getDataStore(); + + AbstractData * data =nullptr; + dataStore = getDataStore(); + if (dataStore) { + data=dataStore->getData(getFileName(),getType()); + } + + //To fix by having hp_mdi reset + hptextedit=nullptr; + + + if ((hptextedit==nullptr)&&(data!=nullptr)) + hptextedit = new hp_mdiTextEdit(mdiwin,this, data); + if (hptextedit!=nullptr) + hptextedit ->show(); + } + break; + case HP_PROG: { + hpCalcData * dataStore =nullptr; + AbstractData * data =nullptr; + dataStore = getDataStore(); + qDebug()<<"HP_Prog ... click"<getData(getFileName(),getType()); + if(data!=nullptr) { + qDebug()<getName(); + } + } + + //To fix by having hp_mdi reset + hptextedit=nullptr; + + if ((hptextedit==nullptr)&&(data!=nullptr)) { + hptextedit = new hp_mdiTextEdit(mdiwin,this, data); + } + if (hptextedit!=nullptr) + hptextedit ->show(); + } + break; + case HP_REAL: + if (hpvaredit==nullptr) { + if (calc) { + data=calc->getData(getFileName(),HP_REAL); + } + if (data!=nullptr) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,this,calc); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + break; + case HP_VAR: + + break; + default: ; + } +} + +void hpTreeItem::contextAction(QMdiArea * mdiwin, contextActionType cta) { + + hp_SettingsDlg * hpsettingsdlg; + hp_Information hpinfo; + hp_Settings hpset; + int ret=0; + switch (getType()) { + case HP_MAIN: { + switch (cta) { + case CT_PREFERENCE: { + hpCalcData * dataStore; + dataStore = getDataStore(); + dataStore->readSettings(); + hpset=dataStore->getSettings(); + hpsettingsdlg = new hp_SettingsDlg(mdiwin, &hpset); + ret=hpsettingsdlg->exec(); + if (ret) + dataStore->setSettings(hpset); + } + break; + default: ; + } + } + break; + default: ; + } +} + +hp_DataType hpTreeItem::getType() { + return type; +} + +void hpTreeItem::setType(hp_DataType dtype) { + type=dtype; + return; +} + +//manage access to datastore +hpCalcData * hpTreeItem::getDataStore() { + if (hp_data) { + qDebug()<<"Data store found"; + return hp_data; + } + else { + qDebug()<<"Null data store"; + return nullptr; + } +} + +void hpTreeItem::setDataStore(hpCalcData * dtype) { + hp_data=dtype; + return; +} + +int hpTreeItem::dt2int() { + switch (getType()) { + case HP_APP: return 0; + case HP_CAS: return 1; + case HP_COMPLEX: return 2; + case HP_LIST: return 3; + case HP_MATRIX: return 4; + case HP_NOTE: return 5; + case HP_PROG: return 6; + case HP_REAL: return 7; + case HP_VAR: return 8; + default:; + }; + return 0; +} + +QString hpTreeItem::getGroupName() { + return func_list[dt2int()][0]; + } + +QString hpTreeItem::getFileName() { + + return text(); + } + +QString hpTreeItem::getCalculatorName() { + hpCalcData * hpcalc; + QString calcName; + hpcalc=getDataStore(); + + if (hpcalc!=nullptr) + calcName=hpcalc->getCalculatorName(); + + qDebug()<getName(); + setData(name,Qt::DisplayRole); + } + break; + case HP_SCREEN: { + emit dataChanged(hpchange); + } + break; + case HP_REAL: { + refresh(); + } + break; + case HP_APP: { + refresh(); + } + case HP_MATRIX: { + refresh(); + } + break; + case HP_LIST: { + refresh(); + } + break; + case HP_NOTE: { + refresh(); + } + break; + case HP_PROG: { + refresh(); + } + break; + default:; + } +} + +void hpTreeItem::addChild(AbstractData *obj) { + hpTreeItem * subItem=nullptr; + hp_DataType type; + + qDebug()<<"hpTreeItem:Adding Child"; + + if (obj!=nullptr) { + QString name; + //create fixed variable list + + type= obj->getType(); + name=obj->getName(); + + qDebug()<<"hpTreeItem:this is "<setType(type); + subItem->setIcon(QIcon(func_list[HP_APP][1])); + } + break; + case HP_MATRIX: { + subItem= new hpTreeItem(name,getDataStore(),1); + subItem->setType(type); + subItem->setIcon(QIcon(func_list[HP_MATRIX][1])); + } + break; + case HP_LIST: { + subItem= new hpTreeItem(name,getDataStore(),1); + subItem->setType(type); + subItem->setIcon(QIcon(func_list[HP_LIST][1])); + + } + break; + case HP_NOTE: { + subItem= new hpTreeItem(name,getDataStore(),1); + subItem->setType(type); + subItem->setIcon(QIcon(func_list[HP_NOTE][1])); + qDebug()<<"hpTreeItem: Creating Note type:"<setType(type); + subItem->setIcon(QIcon(func_list[HP_PROG][1])); + } + break; + case HP_REAL: { + setType(type); + setFileName(name); + } + break; + case HP_COMPLEX: { + setType(type); + setFileName(name); + } + break; + default: { + subItem= new hpTreeItem(name,getDataStore(),1); + subItem->setType(type); + } + } + if (subItem) + appendRow(subItem); + } + else { + qDebug()<<"hpTreeItem:No Object added"; + } + + } +} + +//Up date the data +void hpTreeItem::refresh() { + int rows,i,j; + int datalen; + hpTreeItem * ti_child; + + QString name; + hp_DataType type; + + rows=rowCount(); + hpCalcData * calc; + + calc=getDataStore(); + + if (calc) { + if (columnCount()==1) { + AbstractData * obj; + datalen=calc->dataCount(); + //get object at from calc + //get number of list items + + //for all data items in list + for (j=0; jdataAt(j); + + if (obj) { + for (i=0; igetFileName(); + type=ti_child->getType(); + + if(obj->getType()==type) { + ti_child->addFile(obj); + } + } + } + else + { + qDebug()<<"hpTreeItem:obj is null!"; + } + } + } + + /* + //delete excess + qDebug()<<"hpTreeItem: Checking for deletes"; + if (columnCount()==1) { + AbstractData * obj; + int ret; + rows=rowCount(); + flag =0; + //for all rows check data exists + for (i=0; igetFileName(); + type=ti_child->getType(); + for (j=0; jdataAt(j); + if (obj) { + qDebug()<<"hpTreeItem::refresh - calling object"; + if(obj->getType()==type) { + ret=ti_child->findFile(obj->getName()); + } + if(ret!=0) { + flag =1; //obj found + } + } + } + } + //If data and no row add row + if (flag==0) { + qDebug()<<"hpTreeItem::refresh - deleting "; + removeRow(i); + } + } + } + */ + } + +} + +//check if file is in the list and add it if not +void hpTreeItem::addFile(AbstractData * obj) { + + int i; + int rows; + int flag; + + hpTreeItem * ti_child; + QString name; + hp_DataType type; + +// qDebug()<<"hpTreeItem::addFile"; + + rows=rowCount(); + flag=0; + + if (obj) { +// qDebug()<<"hpTreeItem::addFile - File Not null"; + for (i=0; igetFileName(); + type=ti_child->getType(); + if(obj->equivalent(name,type)) { + flag =1; //obj found + } + } + //If data and no row add row + if (flag==0) { + qDebug()<<"hpTreeItem::addFile - Adding a child"; + addChild(obj); + } + } + else + { + qDebug()<<"hpTreeItem:obj is null!"; + } +} + +//check if file is in the list of children and add it if not return 0 else return row; +int hpTreeItem::findFile(QString dataname) { + + int i; + int rows; + int flag; + + rows=rowCount(); + hpTreeItem * ti_child; + QString name; + + for (i=0; i(child(i)); + dataname=ti_child->getFileName(); + if(name==dataname) { + return i; + } + } + return 0; +} + + +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; + } +*/ + removeColumn(0); + qDebug()<<"hpTreeItem:: delete"< 0 = error + +#include +#include + +#include "global.h" +#include "hpdata.h" +#include +#include +#include "hpusb.h" + +uint16_t crc16_block(const uint8_t * buffer, uint32_t len) { + static const uint16_t ccitt_crc16_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 + }; + uint16_t crc = 0; + + while (len--) { + crc = ccitt_crc16_table[(crc >> 8) ^ *buffer++] ^ (crc << 8); + } + return crc; +} + +//hot plug call back +int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event, void *hp_usbptr) { + + hpusb * usbptr; + usbptr=(hpusb*)hp_usbptr; + qDebug()<<"hotplug_callback: Hot plugin"; + if (hp_usbptr) { + usbptr->hotplugcallback(ctx,dev,event); + } + return 0; +} + +//Constructor +hpusb::hpusb():QObject() +{ + lb_init=0; +} + +// Initialise libusb +// returns 0 if succesfull +int hpusb::hp_init() +{ + int ret=0; + libusb_hotplug_callback_handle callback_handle; + int rc; + + if(!lb_init) { + errlog("Initialising usb interface"); + + if(!(ret=libusb_init(&ctx))) { + errlog("libusb init ok"); + libusb_set_debug(ctx,LIBUSB_LOG_LEVEL_WARNING); + + rc = libusb_hotplug_register_callback(ctx, (libusb_hotplug_event) (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_NO_FLAGS , USB_VID_HP, USB_PID_PRIME3, + LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, this, + &callback_handle); + + if (LIBUSB_SUCCESS != rc) { + errlog("Error creating a hotplug callback\n"); + libusb_exit(ctx); + return EXIT_FAILURE; + } + errlog("hpusb::hp_init - hotplug registered\n"); + hp_callback_handle=callback_handle; + lb_init=1; + return ret; + } + else + err(L3,ret,QString(QString().sprintf("Could not open libusb: %d",ret))); + } + return ret; +} + +//open usb and claim it +int hpusb::hp_open(hp_Handle * handle) { + + int ret=0; + // discover devices + libusb_device **list; + libusb_device *found = nullptr; + libusb_device_handle * devh; + + if(!lb_init) + hp_init(); + + if ((!handle->dev_open)&&(lb_init)) { + + ssize_t cnt = libusb_get_device_list(nullptr, &list); + ssize_t i = 0; + + if (cnt < 0) + err(L3,0,"Could not get a device list"); + for (i = 0; i < cnt; i++) { + libusb_device *device = list[i]; + if (is_device(device)) { + found = device; + errlog("Device found"); + break; + } + } + + if (found) { + ret= libusb_open(found, &devh); + + if (ret) { + err(L3,ret,"Could not open usb device"); + goto endfunc; + } + qDebug()<<"set handle"; + if (handle!=nullptr) { + handle->usbhandle = devh; + handle->usbdevice = found; + } + else + { + err(L3,0,"handle null"); + } + + errlog("Device opened"); + + //claim interface + ret = libusb_kernel_driver_active ( handle->usbhandle, 0x0) ; + if (ret==1) { + errlog(QString().sprintf("Keneral active")); + ret = libusb_detach_kernel_driver( handle->usbhandle, 0x0) ; + errlog(QString().sprintf("Keneral detach: %s\n", libusb_error_name(ret))); + if (ret!=0) { + errlog(QString().sprintf("Keneral detach error: %s\n", libusb_error_name(ret))); + goto endfunc; + } + } + else + if (ret!=0) { + errlog(QString().sprintf("Kernal error %s\n", libusb_error_name(ret))); + goto endfunc; + } + + //Note: Configuration 0 causes calculator to reboot + // 1 ok + // +// ret=libusb_set_configuration(handle->usbhandle,0x1); +// if (ret!=0) { +// errlog(QString().sprintf("Set Configuration: %s\n", libusb_error_name(ret))); +// goto endfunc; +// } + handle->dev_open=1; + + ret = libusb_claim_interface(handle->usbhandle, 0x0); + if (ret!=0) { + errlog(QString().sprintf("Claim interface Error: %s\n", libusb_error_name(ret))); + return -1; + } + } + else { + ret=-1; + } + + endfunc: + libusb_free_device_list(list, 1); + } + return ret; +} + +// check device handler for idVendor and idProduct +// replace with libusb_open_device_with_vid_pid +int hpusb::is_device(libusb_device * device) { + + libusb_device_descriptor desc; + int rc=0; + rc = libusb_get_device_descriptor(device, &desc); + if (rc!=0) { + err(L3,rc,QString(__FUNCTION__) + QString(" Could not get device descriptor ")); + } + else { +// errlog(QString().sprintf("Vendor:Device = %04x:%04x", desc.idVendor, desc.idProduct)); + if ((desc.idVendor==USB_VID_HP)&&(desc.idProduct==USB_PID_PRIME3)) { + dumpDevice(device); + return 1; + } + } + return 0; +} + +//print the device descriptor +void hpusb::dumpDevice(libusb_device * device) { + + QString dump("Device Descriptor\n"); + libusb_device_descriptor desc; + int rc; + if (device) { + rc = libusb_get_device_descriptor(device, &desc); + if (!rc) { + dump+=QString().sprintf("bLength: %d\n",(int)desc.bLength); + dump+=QString().sprintf("bDescriptor Type: %d\n",(int)desc.bDescriptorType); + dump+=QString().sprintf("bcdUSB: %d\n",(int)desc.bcdUSB); + dump+=QString().sprintf("bDeviceClass: %d\n",(int)desc.bDeviceClass); + dump+=QString().sprintf("bDeviceSubClass: %d\n",(int)desc.bDeviceSubClass); + dump+=QString().sprintf("bDeviceProtocal: %d\n",(int)desc.bDeviceProtocol); + dump+=QString().sprintf("bMaxPacketSize0: %d\n",(int)desc.bMaxPacketSize0); + dump+=QString().sprintf("idVendor: %X\n",(int)desc.idVendor); + dump+=QString().sprintf("idProduct: %d\n",(int)desc.idProduct); + dump+=QString().sprintf("bcdDevicel: %d\n",(int)desc.bcdDevice); + dump+=QString().sprintf("iManufacture: %i\n",desc.iManufacturer); + dump+=QString().sprintf("iProduct: %i\n",desc.iProduct); + dump+=QString().sprintf("iSerialNumber: %i\n",desc.iSerialNumber); + dump+=QString().sprintf("bNumConfigurations: %d\n",desc.bNumConfigurations); + } + } + errlog(dump); + qDebug()<usbhandle; + if (devh!=nullptr) { + memset((void *)&raw, 0, sizeof(raw)); + q = (pktout->size) / (PRIME_RAW_DATA_SIZE); + r = (pktout->size) % (PRIME_RAW_DATA_SIZE); + + qDebug()<1) { + raw.data[0]= 0x01; + raw.data[1] = pkt_id; + memcpy(raw.data + 2, pktout->data + offset, PRIME_RAW_DATA_SIZE-1); + offset += PRIME_RAW_DATA_SIZE - 1; + } + else { + memcpy(raw.data, pktout->data + offset, PRIME_RAW_DATA_SIZE-1); + offset += PRIME_RAW_DATA_SIZE - 1; + } + + errlog("In sync send transfer"); + qDebug()<usbhandle); + + //write + errlog("Send.."); + ret = libusb_interrupt_transfer(devh, ENDPOINT_OUT, raw.data, raw.size, + &trans,10000); + if (ret) { + errlog(QString().sprintf("Write Error: %s\n", libusb_error_name(ret))); + r = 0; + break; + } + else { + errlog(QString().sprintf("Write bytes: %d\n", trans)); + } + // Increment packet ID, which seems to be necessary for computer -> calc packets + pkt_id++; + if (pkt_id == 0xFF) { + pkt_id = 0; // Skip 0xFF, which is used for other purposes. + } + } + + if (r || !pktout->size) { + if (i>1) { + raw.size = r + 2; + raw.data[0] = 0x01; + raw.data[1] = pkt_id; + memcpy(raw.data + 2, pktout->data + offset, PRIME_RAW_DATA_SIZE-1); + } + else + { + raw.size = r; + memcpy(raw.data, pktout->data + offset, PRIME_RAW_DATA_SIZE-1); + } + errlog("Send small packet.."); + + ret = libusb_interrupt_transfer(devh, ENDPOINT_OUT, raw.data, raw.size, + &trans,10000); + + if (ret) { + errlog(QString().sprintf("Write Error: %s\n", libusb_error_name(ret))); + } + else { + errlog(QString().sprintf("Write bytes: %d\n", trans)); + } + } + + } + } + return ret; +} + +//extracts the header from the pkt and returns it in the header structure +// very exprimental +int hpusb::extract_header(uint8_t * raw, usb_header * uh) { + + qDebug()<0x00) { + qDebug()<<"hpusb:Chunck Header"; + uh->type=HP_HDR_CHUNK; + uh->typecode=0; + uh->chunk=raw[0]; + uh->headerlen=1; + QString msg = QString("hpusb:Chunk Number: %1").arg(uh->chunk); + qDebug()<type=HP_HDR_INFO; + uh->typecode=raw[1]; + uh->items =raw[2]; + uh->pkt_size=PRIME_RAW_DATA_SIZE; //assume third byte is header length + uh->num_chunks=(uh->pkt_size-1)/PRIME_RAW_DATA_SIZE; + uh->name_length=0; + uh->headerlen=6; + uh->embedded_crc = 0; + memcpy(uh->header,raw,6); + QString msg = QString("Info Header chunks: %1 size: %2 items: %3") + .arg(uh->num_chunks).arg(uh->pkt_size).arg(uh->items); + qDebug()<type=HP_HDR_PNG; + uh->typecode=raw[1]; + uh->items=raw[2]; + Int32=0; + Int32=(Int32<<8)+raw[3]; + Int32=(Int32<<8)+raw[4]; + Int32=(Int32<<8)+raw[5]; + Int32=(Int32<<8)+raw[6]; + uh->pkt_size=Int32; //assume third byte is header length + uh->num_chunks=uh->pkt_size/PRIME_RAW_DATA_SIZE; + uh->name_length=0; + uh->embedded_crc = (((uint16_t)(raw[8] & 0xFF)) << 8) | ((uint16_t)(raw[7] & 0xFF)); + uh->headerlen=14; + memcpy(uh->header,raw,HEADER_LEN); + QString msg = QString("PNG Header chunks: %1 size: %2 Items: %3") + .arg(uh->num_chunks).arg(uh->pkt_size).arg(uh->items); + qDebug()<type=HP_HDR_FILE; + uh->typecode=raw[1]; + uh->items =raw[2]; + Int32=0; + Int32=(Int32<<8)+raw[3]; + Int32=(Int32<<8)+raw[4]; + Int32=(Int32<<8)+raw[5]; + Int32=(Int32<<8)+raw[6]; + uh->pkt_size=Int32; //assume third byte is data length + uh->pkt_type=raw[7]; //File type being read + uh->num_chunks=uh->pkt_size/PRIME_RAW_DATA_SIZE; + uh->name_length=0; + uh->headerlen=8; + uh->embedded_crc = 0; + memcpy(uh->header,raw,HEADER_LEN); + QString msg = QString("File Header chunks: %1 size: %2 items: %3") + .arg(uh->num_chunks).arg(uh->pkt_size).arg(uh->items); + qDebug()<type=HP_HDR_UNKNOWN; + uh->typecode=raw[1]; + uh->items =raw[2]; + Int32=0; + Int32=(Int32<<8)+raw[3]; + Int32=(Int32<<8)+raw[4]; + Int32=(Int32<<8)+raw[5]; + Int32=(Int32<<8)+raw[6]; + uh->pkt_size=Int32; //assume third byte is data length + uh->num_chunks=uh->pkt_size/PRIME_RAW_DATA_SIZE; + uh->name_length=raw[7]; + uh->headerlen=11; + uh->embedded_crc = (((uint16_t)(raw[7])) << 8) | ((uint16_t)(raw[8])); + memcpy(uh->header,raw,HEADER_LEN); + QString msg = QString("File Header chunks: %1 size: %2 items: %3") + .arg(uh->num_chunks).arg(uh->pkt_size).arg(uh->items); + qDebug()<usbhandle; + + errlog("hpusb::submit_sync_r_transfer: Receive..."); + qDebug()<usbhandle); + + if (!handle) { + errlog("Null handle"); + return -1; + } + + if (!devh) + return -1; + + pkt.cmd=pktin->cmd; + pkt.calc=handle->calc; + + while(exitflag) { + trans_c=0; + + //read + memset(raw,0,PRIME_RAW_DATA_SIZE); + if ((ret = libusb_interrupt_transfer(devh,ENDPOINT_IN,raw,PRIME_RAW_DATA_SIZE,&trans_c,TIME_OUT))!=0) { + qDebug()<0) { + in_buffer.append((const char *)&raw[uh2.headerlen],trans_c-uh2.headerlen); + trans+=trans_c-uh2.headerlen; + qDebug()<=uh1.pkt_size) { + } + +// pkt.array=in_buffer.mid(0,uh1.pkt_size-uh1.headerlen+3); + + //PROBLEM : Needed to -1 to get text file to work? + pkt.array=in_buffer.mid(0,uh1.pkt_size); + + qDebug()<type) { + case HP_HDR_PNG: + send_screen_shot(pktin); + break; + case HP_HDR_INFO: + send_info(pktin); + break; + case HP_HDR_FILE: + send_file(pktin); + break; + } + main_err-> dump((uint8_t *)pktin->array.constData(),pktin->array.size()); + + return 0; +} + +//request to recieve a file transfer +int hpusb::sync_s_recv_file(hp_Handle *) { + + return 0; +} + +//recieve the file transfer +int hpusb::sync_r_recv_file(hp_Handle *) { + + return 0; +} + +int hpusb::send_info(hp_pkt_in * pkt) { + + hp_Information hpinfo; + + qDebug()<<"hpusb:In send info"; + if( pkt->calc!=nullptr) { + + errlog("Unpacking Data"); + int ind=0; + QTextCodec * codec = QTextCodec::codecForName("UTF-16LE"); + QTextCodec * codec8 = QTextCodec::codecForName("UTF-8"); + QByteArray rd= pkt->array; + + //find name + ind=rd.indexOf(QChar(0x6c),0)+1; + QByteArray str1 =rd.mid(ind,64); + + QString name; + name = codec->toUnicode(str1); + hpinfo.name=name; + + //unsigned char searchstr[] = {0x80,0x20,0x80,0x01,0x62}; + //ind+=rd.indexOf((char *) searchstr,ind+64); + ind +=64; + + //find Application Version + //FIX + str1 =rd.mid(ind,12); + + //test + QTime t; + QDataStream ds1(str1); + ds1.setByteOrder(QDataStream::LittleEndian); + ds1>>t; + qDebug()<> listnum[j]; + qDebug()<toUnicode(str1); + hpinfo.appver=QString("v%1").arg(listnum[4]); + errlog(app); + + //find OS Version + ind+=12; + str1 =rd.mid(ind,16); +// qDebug()<toUnicode(str1); + hpinfo.osver=osv; +// qDebug()<toUnicode(str1); + hpinfo.serialnum=serial; + errlog(serial); + pkt->calc->recvInfo(hpinfo); + return 0; + + } + else { + errlog("Passed a null pointer"); + return 1; + } + //Error + return 1; +} + +int hpusb::send_screen_shot(hp_pkt_in * pkt) { + + int endpos; + QByteArray imageData; + QPixmap * screenShot; + hp_ScreenShot shot; + + if( pkt->calc!=nullptr) { + + endpos = pkt->array.indexOf("IEND"); + qDebug()<<"hpusb::send_screen_shot: End pos:"<array.mid(0,endpos+4)); + screenShot = new QPixmap(); + screenShot->loadFromData(imageData); + shot.image=screenShot; +// shot.format=0; + pkt->calc->recvScreen(shot); + return 0; + } + //Error + return 1; +} + +//File Processor +int hpusb::send_file(hp_pkt_in * pkt) { + + qDebug()<<"hpusb::send_file: In File Processor"; + + QString filename; + QTextCodec * codec = QTextCodec::codecForName("UTF-16LE"); + QByteArray rd= pkt->array; + int len; + qint8 crc; + + len = rd[0]; + + //TODO + + //What is byte rd[1],rd[2]? + //Check if CRC + + QByteArray temp((const char *)pkt->array,pkt->array.size()); + temp[1]=0x00; + temp[2]=0x00; + crc=crc16_block((uint8_t *)temp.constData(),temp.size()); +// crc= qChecksum(pkt.array,pkt.array.size()); +// crc=crc16_block((uint8_t *)pkt.array.constData(),pkt.array.size()); + qDebug()<toUnicode(str1); + errlog(QString("File: %1 Type: %2").arg(filename).arg(pkt->pkt_type)); + + qDebug()<<"hpusb:Checking file type"; + qDebug()<pkt_type); + qDebug()<pkt_type) { + + case HP_TP_SETTINGS: { + qDebug()<<"hpusb:File type settings"; + qDebug()<calc->recvSettings(sData); + } + break; + case HP_TP_FUNCTIONS: { + qDebug()<<"hpusb:File functions"; + hp_Data sData; + sData.type=HP_APP; + sData.name=filename; + sData.data=rd.mid(len+3,-1); + pkt->calc->recvData(sData); + } + break; + case HP_TP_LIST: { + qDebug()<<"hpusb:File type list"; + hp_Data sData; + sData.type=HP_LIST; + sData.name=filename; + sData.data=rd.mid(len+3,-1); + pkt->calc->recvData(sData); + } + break; + case HP_TP_MATRIX: { + qDebug()<<"hpusb:File type matrix"; + hp_Data sData; + sData.type=HP_MATRIX; + sData.name=filename; + sData.data=rd.mid(len+3,-1); + pkt->calc->recvData(sData); + } + break; + case HP_TP_NOTE: { + //get a note + int size; + qDebug()<<"hpusb:File type Note"; + hp_Note note; + note.filename=filename; + + qDebug()<toUnicode(str1); + note.data=str1; + pkt->calc->recvNote(note); + } + break; + case HP_TP_PROG: { + //get a grogram + int size; + qDebug()<<"hpusb:File type program"; + hp_Prog prog; + prog.filename=filename; + + qDebug()<toUnicode(str1); + pkt->calc->recvProg(prog); + } + break; + case HP_TP_CUSTOM: + qDebug()<<"hpusb:File type custom"; + break; + default: + qDebug()<<"hpusb:Unknown file type"; + } + + return 0; +} + +//Get a screen shot. HP replies with image starting on byte 14 +//ToDo - make robust +int hpusb::get_screen_shot(hp_Handle * handle) { + + int res; + if (handle != NULL) { + + uint8_t transferbuffer[LEN_IN_BUFFER+8]; + hp_pkt_in pktin; + hp_pkt_out pktout; + + transferbuffer[0]=0x00; + transferbuffer[1]=CMD_PRIME_RECV_SCREEN; + transferbuffer[2]=(uint8_t) CALC_SCREENSHOT_FORMAT_PRIME_PNG_320x240x4; + + pktout.cmd = CMD_PRIME_RECV_SCREEN; + pktout.data = transferbuffer; + pktout.size=1024; + + if (!(res=submit_sync_s_transfer(handle,&pktout))){ + + pktin.cmd= CMD_PRIME_RECV_SCREEN; + + errlog(QString("%1: Waiting for a reply").arg(__FUNCTION__)); + + if (!submit_sync_r_transfer(handle,&pktin)){ + + errlog(QString("%1: Recieved a reply").arg(__FUNCTION__)); + //Trying to understand reply +/* int endpos; + QByteArray rd = pktin.array; + endpos = rd.indexOf("IEND"); + qDebug()<<"End pos:"<>8)&0xFF); +// transferbuffer[1]=((cmd>>0)&0xFF); + + transferbuffer[0]=0x00; + transferbuffer[1]=CMD_PRIME_CHECK_READY; + + pktout.cmd = CMD_PRIME_CHECK_READY; + pktout.data = transferbuffer; + pktout.size=2; + + if (!(res=submit_sync_s_transfer(handle,&pktout))){ + + pktin.cmd= CMD_PRIME_CHECK_READY; +// pktin.data=in_buffer; +// pktin.size=1024; + errlog(QString("%1: Waiting for a reply").arg(__FUNCTION__)); + + if (!submit_sync_r_transfer(handle,&pktin)){ + errlog(QString("%1: Recieved a reply").arg(__FUNCTION__)); + //Trying to understand reply + qDebug()< dump((uint8_t *)pktin.array.constData(),pktin.array.size()); + QByteArray rd= QByteArray(pktin.array, pktin.array.size()); + // lookfordouble(rd,64); + } + } + else { + errlog(QString("%1: Could not send ready request ").arg(__FUNCTION__)); + return res; + } + } + return res; + } + +int hpusb::load_info(hp_Handle * handle) { + + uint8_t transferbuffer[LEN_IN_BUFFER+8]; +// uint8_t in_buffer[LEN_IN_BUFFER+8]; + + hp_pkt_in pktin; + hp_pkt_out pktout; + + memset((void *)&transferbuffer, 0, sizeof(transferbuffer)); + + qDebug()<toUnicode(str1); + errlog(app); + + int i,ind; + ind=start; + + for (i=0; i<300; i++) { + ind+=1; + str1 =rd.mid(ind,sizeof(num)); + num= *(long double*)(str1.constData()); + app = codec->toUnicode(str1); + // qDebug()<>8)&0xFF); +// transferbuffer[1]=((cmd>>0)&0xFF); + + transferbuffer[0]=0x00; + transferbuffer[1]=0xF9; + transferbuffer[2]=0x00; + transferbuffer[3]=0x00; + transferbuffer[4]=0x00; + transferbuffer[5]=0x00; + transferbuffer[6]=0x00; + transferbuffer[7]=0x00; + transferbuffer[8]=0x00; + transferbuffer[9]=0x00; + transferbuffer[10]=0x00; + + //CRC + quint16 crcBytes = qChecksum((char *)&transferbuffer[2],9); + + qDebug()<>8)&0xFF; + transferbuffer[12]=(crcBytes>>0)&0xFF; + + transferbuffer[11]=0x1c; + transferbuffer[12]=0xf5; + + transferbuffer[13]=0x97; + transferbuffer[14]=0x01; + transferbuffer[15]=0x33; + transferbuffer[16]=0x45; + transferbuffer[17]=0xe6; + transferbuffer[18]=0x76; + transferbuffer[19]=0x00; + transferbuffer[20]=0x00; + transferbuffer[21]=0x00; + transferbuffer[22]=0x00; + transferbuffer[23]=0x48; + + transferbuffer[1024]=0x00; + transferbuffer[1025]=0x00; + transferbuffer[1026]=0x07; + transferbuffer[1027]=0x00; + transferbuffer[1028]=0x00; + transferbuffer[1029]=0x00; + transferbuffer[1030]=0xfd; + transferbuffer[1031]=0x01; + +/* + transferbuffer[0]=0x01; + transferbuffer[1]=0x01; + + transferbuffer[2]=0x00; + transferbuffer[3]=0x00; + transferbuffer[4]=0x07; + transferbuffer[5]=0x00; + transferbuffer[6]=0x00; + transferbuffer[7]=0x00; + transferbuffer[8]=0xfd; + transferbuffer[9]=0x01; +*/ + + pktout.data=transferbuffer; + pktout.size=2; + + submit_sync_s_transfer(handle,&pktout); + + submit_sync_r_transfer(handle,&pktin); + { + + transferbuffer[0]=0x01; + transferbuffer[1]=0x01; + transferbuffer[2]=0x00; + transferbuffer[3]=0x00; + transferbuffer[4]=0x00; + transferbuffer[5]=0x07; + transferbuffer[6]=0x00; + transferbuffer[7]=0x00; + transferbuffer[8]=0x00; + transferbuffer[9]=0x00; + + pktout.data=transferbuffer; + pktout.size=1024*2; + + // submit_sync_s_transfer(handle,&pktout); + // submit_sync_r_transfer(handle,&pktin); + + return 0; + } + + return 1; +} + +int hpusb::hp_close(hp_Handle * handle) +{ + if (handle) { + if (handle->dev_open) { + libusb_release_interface(handle->usbhandle, 0); + libusb_close(handle->usbhandle); + handle->dev_open =0; + } + } + return 0; +} + + +// debugging function to display libusb_transfer +void hpusb::print_libusb_transfer(struct libusb_transfer *p_t) +{ int i; + if ( NULL == p_t){ + errlog("No libusb_transfer...\n"); + } + else { + errlog("libusb_transfer structure:\n"); + errlog(QString().sprintf("flags =%x \n", p_t->flags)); + errlog(QString().sprintf("endpoint=%x \n", p_t->endpoint)); + errlog(QString().sprintf("type =%x \n", p_t->type)); + errlog(QString().sprintf("timeout =%d \n", p_t->timeout)); + // length, and buffer are commands sent to the device + errlog(QString().sprintf("length =%d \n", p_t->length)); + errlog(QString().sprintf("actual_length =%d \n", p_t->actual_length)); + errlog(QString().sprintf("buffer =%p \n", p_t->buffer)); + + for (i=0; i < p_t->length; i++){ + errlog(QString().sprintf("%d %x", i, p_t->buffer[i])); + } + } + return; +} + + +//send a submission +int hpusb::submit_async_transfer(hp_Handle * handle, hp_pkt_in * pktin, hp_pkt_out *pktout) { + +// static uint8_t in_buffer[LEN_IN_BUFFER]; + + int buffer_len; + buffer_len=pktin->size; + + struct sigaction sigact; + + int r = 1; // result + + do_exit = 0; + + libusb_device_handle * devh = handle->usbhandle; + + //Allocation + + // allocate transfer of data IN (IN to host PC from USB-device) + transfer_in = libusb_alloc_transfer(0); + + //Filling + //libusb_fill_interrupt_setup(in_buffer,LIBUSB_RECIPIENT_DEVICE ,LIBUSB_REQUEST_TYPE_STANDARD,0,0,16); +// libusb_fill_control_transfer( transfer_in, devh, +// pktin->data, // Note: in_buffer is where input data written. +// cb_in, nullptr, 1000); // no user data + + //take the initial time measurement + clock_gettime(CLOCK_REALTIME, &t1); + + //Submission + + //submit the transfer, all following transfers are initiated from the CB + r = libusb_submit_transfer(transfer_in); + + // Define signal handler to catch system generated signals + // (If user hits CTRL+C, this will deal with it.) + sigact.sa_handler = sighandler; // sighandler is defined below. It just sets do_exit. + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigaction(SIGINT, &sigact, nullptr); + sigaction(SIGTERM, &sigact, nullptr); + sigaction(SIGQUIT, &sigact, nullptr); + + printf("Entering loop to process callbacks...\n"); + + /* The implementation of the following while loop makes a huge difference. + * Since libUSB asynchronous mode doesn't create a background thread, + * libUSB can't create a callback out of nowhere. This loop calls the event handler. + * In real applications you might want to create a background thread or call the event + * handler from your main event hanlder. + * For a proper description see: + * http://libusbx.sourceforge.net/api-1.0/group__asyncio.html#asyncevent + * http://libusbx.sourceforge.net/api-1.0/group__poll.html + * http://libusbx.sourceforge.net/api-1.0/mtasync.html + */ + int c=0; + if(0){ + qDebug()<<"At loop"; + // This implementation uses a blocking call + while (!do_exit) { + c++; + r = libusb_handle_events_completed(ctx, nullptr); + if ((r < 0)||(c>100000)){ // negative values are errors + qDebug()<<"At break"; + exitflag = out_deinit; + break; + } + } + } + else{ + // This implementation uses a blocking call and aquires a lock to the event handler + struct timeval timeout; + timeout.tv_sec = 0; // seconds + timeout.tv_usec = 100000; // ( .1 sec) + libusb_lock_events(ctx); + c=0; + while (!do_exit) { + c++; + r = libusb_handle_events_locked(ctx, &timeout); + if ((r < 0)||(c>10000)){ // negative values are errors + exitflag = out_deinit; + qDebug()<<"At break 2"; + break; + } + } + libusb_unlock_events(ctx); + } + + // If these transfers did not complete then we cancel them. + // Unsure if this is correct... + if (transfer_out) { + r = libusb_cancel_transfer(transfer_out); + if (0 == r){ + printf("transfer_out successfully cancelled\n"); + } + if (r < 0){ + exitflag = out_deinit; + } + + } + if (transfer_in) { + r = libusb_cancel_transfer(transfer_in); + if (0 == r){ + printf("transfer_in successfully cancelled\n"); + } + if (r < 0){ + exitflag = out_deinit; + } + } + + //Completion Handling + + + //Deallocation + + switch(exitflag){ + case out_deinit: + printf("at out_deinit\n"); + libusb_free_transfer(transfer_out); + libusb_free_transfer(transfer_in); + break; + case out_release: + libusb_release_interface(devh, 0); + break; + case out: + qDebug()<<"out"; + break; + } + return 0; +} + +// This will catch user initiated CTRL+C type events and allow the program to exit +void sighandler(int signum) +{ + printf("sighandler\n"); +} + + +//submission callback +// Out Callback +// - This is called after the Out transfer has been received by libusb +void cb_out(struct libusb_transfer *transfer) { + + QString().sprintf("status =%d, actual_length=%d\n", + transfer->status, transfer->actual_length); + +} + +// In Callback +// - This is called after the command for version is processed. +// That is, the data for in_buffer IS AVAILABLE. +void cb_in(struct libusb_transfer *transfer) +{ + qDebug()<<"in cb_in"; + uint32_t benchPackets=1; + uint32_t benchBytes=0; + struct timespec t1, t2; + uint32_t diff=0; + + //measure the time + clock_gettime(CLOCK_REALTIME, &t2); + //submit the next transfer + //libusb_submit_transfer(transfer_in); + + benchBytes += transfer->actual_length; + //this averages the bandwidth over many transfers + if(++benchPackets%100==0){ + //Warning: uint32_t has a max value of 4294967296 so this will overflow over 4secs + diff = (t2.tv_sec-t1.tv_sec)*1000000000L+(t2.tv_nsec-t1.tv_nsec); + t1.tv_sec = t2.tv_sec; + t1.tv_nsec = t2.tv_nsec; + printf("\rreceived %5d transfers and %8d bytes in %8d us, %8.1f B/s", benchPackets, benchBytes, diff/1000, benchBytes*1000000.0/(diff/1000)); + fflush(stdout); + benchPackets=0; + benchBytes=0; + } +} + +int hpusb::hotplugcallback(struct libusb_context *ctx, struct libusb_device *dev, + libusb_hotplug_event event) { + int count=0; + qDebug()<<"hpusb::hotplug_callback - Hotplug";; + + static libusb_device_handle *handle = nullptr; + struct libusb_device_descriptor desc; + + (void)libusb_get_device_descriptor(dev, &desc); + + if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { + + qDebug()<<"Hot plugin event"; + emit hotplug(HP_OPEN_DEVICE); + } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { + if (handle) { + emit hotplug(HP_CLOSE_DEVICE); + } + } else { + qDebug()<. + */ + +#include "mainwindow.h" +#include +#include +#include + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(qthpconnect); + + QApplication a(argc, argv); + + QCoreApplication::setOrganizationName(""); + QCoreApplication::setApplicationName("Linux QtHP Connect"); + QCoreApplication::setApplicationVersion(HP_VERSION_STRING); + QCommandLineParser parser; + MainWindow w; + + parser.setApplicationDescription(QCoreApplication::applicationName()); + //REWORK + parser.addHelpOption(); + parser.addVersionOption(); +// parser.addPositionalArgument("file", "The file to open."); + parser.process(a); + +// a.setQuitLockEnabled(true); +// if (!parser.positionalArguments().isEmpty()) +// w.loadFile(parser.positionalArguments().first()); + w.show(); + a.exec(); + qDebug()<<"Main.cpp:: closing main"; + return 1; +} diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp new file mode 100644 index 0000000..6c6b388 --- /dev/null +++ b/source/mainwindow.cpp @@ -0,0 +1,1083 @@ +/* + * QtHP Connect: hand-helds support interface. (https://github.com/Indy970/QtHPConnect.git). + * Copyright (C) 2019 Ian Gebbie + * Code patterns and snippets borrowed from libhpcalcs : + * Copyright (C) 1999-2009 Romain Li�vin + * Copyright (C) 2009-2013 Lionel Debroux + * Copyright (C) 1999-2013 libti* contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + +#include +#include "ui_mainwindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#include "hpusb.h" +#include "datamodel.h" +#include "treemodel.h" +#include "variableview.h" +#include "texteditor.h" +#include "hp_mdilogwindow.h" +#include "hptreeitem.h" +#include "hpdata.h" +#include "hp_mdivariableedit.h" +#include "hp_mditexteditor.h" +#include "options.h" +#include "eventthread.h" +#include "eventtimer.h" + +errorHandler *main_err; +#define errlog(a) main_err->error(L7,0,QString(a),QString()); + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + //setup + QCoreApplication::setOrganizationName("IRGP"); + QCoreApplication::setOrganizationDomain(""); + QCoreApplication::setApplicationName("Linux QtHPConnect"); + QSettings appSettings("IRGP","QtHPconnect"); + + //Set config file location (default used) + if(!appSettings.contains("contentPath")) { + appSettings.setValue("contentPath",QDir::homePath()+"/.local/share/qthpconnect/contents/"); + } + + //error handler + main_err = new errorHandler(this); + + //data models + myModel= new dataModel(this); + hpTreeModel = new treeModel(this); + + //usbapi + hpapi = new hpusb(); + + //Interface + ui->setupUi(this); + setWindowIcon(QIcon::fromTheme("accessories-calculator", + QIcon(":/icons/monitor_32x32.png"))); + createLogWindow(); + setTreeMenu(); + setContentWindow(); + + //create some sub menus + QToolButton *createNewButton= + dynamic_cast(ui->toolBar->widgetForAction(ui->actionCreateNew)); + createNewButton->setPopupMode(QToolButton::InstantPopup); + QMenu *createMenu=new QMenu(createNewButton); + + QIcon folder(":/icons/new_folder_16x16.png"); + QAction * actionNewFolder= new QAction(folder,"Folder",this); + + QIcon note(":/icons/note_16x16.png"); + QAction * actionNewNote= new QAction(note,"Note",this); + + QIcon program(":/icons/program_16x16.png"); + QAction * actionNewProgram= new QAction(program,"Program",this); + + createMenu->addAction(actionNewFolder); + createMenu->addAction(actionNewNote); + createMenu->addAction(actionNewProgram); + + createNewButton->setMenu(createMenu); + + //Hack to fix QT resizing bug + resizeDocks({ui->dwCalculator,ui->dwContent},{0,0}, Qt::Horizontal); + + //setup trees + ui->tvCalculators->setModel(hpTreeModel); + ui->tvCalculators->setAcceptDrops(true); + ui->tvCalculators->setDragEnabled(true); + ui->tvCalculators->setDragDropMode(QAbstractItemView::DragDrop); + ui->tvCalculators->setDropIndicatorShown(true); + ui->tvCalculators->show(); + + //setup actions + connect(ui->actionOpen,SIGNAL(triggered()),this,SLOT(onOpen())); + connect(ui->actionAbout_HP_Connect,SIGNAL(triggered()),this,SLOT(about())); + // connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(exit())); + connect(ui->actionContent,SIGNAL(triggered()),this,SLOT(showContent())); + connect(ui->actionCalculators,SIGNAL(triggered()),this,SLOT(showCalculator())); + connect(ui->actionMessages,SIGNAL(triggered()),this,SLOT(showMessage())); + connect(ui->actionMonitor,SIGNAL(triggered()),this,SLOT(showMonitor())); + + connect(ui->actionSave,SIGNAL(triggered()),this,SLOT(eventSave())); + connect(ui->actionSave_All,SIGNAL(triggered()),this,SLOT(eventSaveAs())); + connect(actionNewFolder,SIGNAL(triggered()),this,SLOT(eventCreateFolder())); + connect(actionNewNote,SIGNAL(triggered()),this,SLOT(eventCreateNote())); + connect(actionNewProgram,SIGNAL(triggered()),this,SLOT(eventCreateProgram())); + + connect(ui->tvCalculators,SIGNAL(clicked(QModelIndex)),this,SLOT(clickedCalculator(QModelIndex))); + connect(ui->tvContent,SIGNAL(clicked(QModelIndex)),this,SLOT(clickedContent(QModelIndex))); + connect(ui->actionLog,SIGNAL(triggered()),this,SLOT(createLogWindow())); + connect(ui->actionTest,SIGNAL(triggered()),this,SLOT(testFunction())); + connect(ui->actionTestSettings,SIGNAL(triggered()),this,SLOT(onTestSettings())); + connect(ui->actionTestScreen,SIGNAL(triggered()),this,SLOT(onTestScreen())); + connect(ui->actionRefresh,SIGNAL(triggered(bool)),this,SLOT(refresh(bool))); + connect(ui->actionPreferences,SIGNAL(triggered(bool)),this,SLOT(onOptions(bool))); + connect(ui->tvCalculators, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(on_tvCalculators_customContextMenuRequested(const QPoint &))); + connect(ui->tvContent, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(on_tvContent_customContextMenuRequested(const QPoint &))); + connect(hpapi, SIGNAL(hotplug(int)), this, SLOT(hotplug_handler(int))); + + connect(ui->actionTile,SIGNAL(triggered()),this,SLOT(eventTileWindow())); + connect(ui->actionCascade,SIGNAL(triggered()),this,SLOT(eventCascadeWindow())); + connect(ui->actionClose,SIGNAL(triggered()),this,SLOT(eventCloseWindow())); + connect(ui->actionClose_all,SIGNAL(triggered()),this,SLOT(eventCloseAllWindow())); + connect(ui->actionNext,SIGNAL(triggered()),this,SLOT(eventNext())); + connect(ui->actionPrevious,SIGNAL(triggered()),this,SLOT(eventPrevious())); + + connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(eventExit())); + + //default data + errlog("Initialising...."); + + if (hpapi->hp_init()) + err(L1,0,QString().sprintf("%s Failed to open libusb",__FUNCTION__)); + + //setup event handler + eventThread = new EventThread(this); + eventTimer = new EventTimer(this); + // connect(eventTimer,SIGNAL(timeout()),this,SLOT(eventHandler())); + connect(eventThread,SIGNAL(finished()),eventTimer,SLOT(exit()), Qt::DirectConnection); + connect(eventTimer,SIGNAL(stopped()),this,SLOT(setTimerStopped()), Qt::DirectConnection); + connect(this,SIGNAL(stopTimer()),eventTimer,SLOT(exit()), Qt::DirectConnection); + connect(eventThread,SIGNAL(startTimer()),eventTimer,SLOT(start())); + eventTimer->moveToThread(eventThread); + eventThread->start(); + + ui->dwMessenger->hide(); + ui->dwMonitor->hide(); + + // addDummy(); + // openHP(); +} + +void MainWindow::testFunction() { + + hpCalcData * pH; + + int cmd; + qDebug()<<"In Test Function"; + pH=getTreeModel()->getCalculator("IAN"); + if (pH) { + + cmd = QInputDialog::getInt(this,"Get Command","CMD:",0,0,0xFFFF); + errlog("command is "+QString().sprintf("%x",cmd)); + pH->vpkt_send_experiments(cmd); + } + else + errlog("Could not get calculator"); + +} + +treeModel * MainWindow::getTreeModel() { + return hpTreeModel; +} + +void MainWindow::writeStatus(QString msg) +{ + statusBar()->showMessage(msg); + return; +} + +void MainWindow::writeChatter(QString line) +{ + if (logEdit) + { + logEdit->append(line); + } + return; +} + +//eventhandler - for comms events +void MainWindow::eventHandler() { + + if(hpapi) { +// qDebug()<<"In Eventhandler"; +// hpapi->eventHandler(); + } +} + +void MainWindow::onOpen() +{ + qDebug()<<"MainWindow::in on Open"; + +//test to see if data model works + hp_Information hpi; + hpi.serialnum="123-56"; + QString key; + key=hpTreeModel->getLastDataKey(); + hpCalcData * hpdata; + + qDebug()<<"MainWindow:: getKey"; + + hpdata=hpTreeModel->getHpCalcData(key); + if(hpdata) + hpdata->setInfo(hpi); + + openHP(); +} + +void MainWindow::onTestSettings() +{ + qDebug()<<"MainWindow::in test Settings"; + + QString key; + key=hpTreeModel->getLastDataKey(); + qDebug()<getHpCalcData(key); + if(hpdata) + hpdata->readSettings(); +} + +void MainWindow::onTestScreen() +{ + qDebug()<<"MainWindow::in test Screen"; + + QString key; + key=hpTreeModel->getLastDataKey(); + hpCalcData * hpdata; + qDebug()<<"MainWindow:: getKey"; + + hpdata=hpTreeModel->getHpCalcData(key); + if(hpdata) + hpdata->readScreen(); +} + +//Experimental +void MainWindow::loadTextFile() +{ + QFile inputFile(":/input.txt"); + inputFile.open(QIODevice::ReadOnly); + + QTextStream in(&inputFile); + QString line = in.readAll(); + inputFile.close(); +} + +//open the first calculator +//rework, find multiple or allow choice +void MainWindow::openHP() +{ + hpCalcData * data; + + qDebug()<<"openHP"; + QString name1 = QString("IAN"); + data=hpTreeModel->getCalculator(name1); + if(data) { + qDebug()<<"Read Info"; + data->readInfo(); + data->readSettings(); + } + else { + qDebug()<<"In open Func"; + hpTreeModel->addCalculator(name1,hpapi); + //handle lost on second call! + // hpapi->submit_sync_transfer(&handle); + } +} + +//close and delete HP and associated functions. +void MainWindow::closeHP() { + +} + +//testcode to add a dummy calculator to the tree +void MainWindow::addDummy() { + + QString name = QString("DUMMY"); + hpTreeModel->addCalculator(name,nullptr); +} + +//slot to handle tree selection +void MainWindow::selectionChangedSlot(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/) +{ + //get the text of the selected item + const QModelIndex index = ui->tvCalculators->selectionModel()->currentIndex(); + + // hpTreeItem * item = (hpTreeItem *)index.internalPointer(); + +// if(item) { + // if (item->isSelectable()) + // item->hptSelection(5); + // }; + + + // hpTreeItem hpt= ui->tvCalculators->selectionModel()-> + QString selectedText = index.data(Qt::DisplayRole).toString(); + + //find out the hierarchy level of the selected item + int hierarchyLevel=1; + QModelIndex seekRoot = index; + while(seekRoot.parent() != QModelIndex()) + { + seekRoot = seekRoot.parent(); + hierarchyLevel++; + } + QString showString = QString("%1, Level %2").arg(selectedText) + .arg(hierarchyLevel); + setWindowTitle(showString); +} + +void MainWindow::clickedCalculator(QModelIndex index) { + +// QStandardItem * item = hpTreeModel->itemFromIndex(index); + qDebug()<<"MainWindow::clickedCalculator"; + + if (hpTreeModel!=nullptr) { + hpTreeModel->clickAction(getMdi(),index); + } +/* + + hpTreeItem * treeItem = dynamic_cast(hpTreeModel->itemFromIndex(index)); + + if(treeItem) { + + hp_DataType treetype; + treetype=treeItem->getType(); + treeItem->clickAction(getMdi()); + + } + else + { + log(QStringLiteral("treeItem is null")); + } + + //HACK + lastCalc=treeItem->data(Qt::DisplayRole).toString(); + log(treeItem->data(Qt::DisplayRole).toString()); + + */ + +} + +void MainWindow::eventSave() { + + hp_MdiWindow * activechild; + + activechild = activeMdiChild(); + qDebug()<<"Save Pressed"; + + if (activechild!=nullptr) { + if (activechild->save()) { + qDebug()<<"Save Succesfull"; + statusBar()->showMessage(tr("File saved"), 2000); + } + else { + qDebug()<<"Save not successfull"; + statusBar()->showMessage(tr("File not saved!"), 2000); + } + } + else { + qDebug()<<"No active window"; + } +} + +hp_MdiWindow * MainWindow::activeMdiChild() { + QMdiArea * mdi=getMdi(); + + if (QMdiSubWindow *activeSubWindow = mdi->activeSubWindow()) + return qobject_cast(activeSubWindow); + return nullptr; +} + +void MainWindow::eventSaveAs() { + + qDebug()<<"Save As Pressed"; +} + +void MainWindow::eventTileWindow() { + + QMdiArea * mdi=getMdi(); + mdi->tileSubWindows(); +} + +void MainWindow::eventCascadeWindow() { + + QMdiArea * mdi=getMdi(); + mdi->cascadeSubWindows(); +} + +void MainWindow::eventCloseWindow() { + + QMdiArea * mdi=getMdi(); + mdi->closeActiveSubWindow(); +} + +void MainWindow::eventCloseAllWindow() { + + QMdiArea * mdi=getMdi(); + mdi->closeAllSubWindows(); +} + +void MainWindow::eventPrevious() { + + QMdiArea * mdi=getMdi(); + mdi->activatePreviousSubWindow(); +} + +void MainWindow::eventNext() { + + QMdiArea * mdi=getMdi(); + mdi->activateNextSubWindow(); +} + +void MainWindow::eventExit() { + QMdiArea * mdi=getMdi(); + mdi->closeAllSubWindows(); + close(); +} + +void MainWindow::eventCreateFolder() { + + QString newName= QStringLiteral("New Folder"); + bool ok; + newName = QInputDialog::getText(this, tr("Enter new folder name"), + tr("Folder name:"), QLineEdit::Normal, + newName, &ok); + + contentModel.createNewFolder(newName); + + return; +} + +void MainWindow::eventCreateNote() { + + QString newName= QStringLiteral("New Note"); + bool ok; + newName = QInputDialog::getText(this, tr("Enter new Note name"), + tr("Note name:"), QLineEdit::Normal, + newName, &ok); + + contentModel.createNewNote(getMdi(),newName); + + return; +} + +void MainWindow::eventCreateProgram() { + + QString newName= QStringLiteral("New Program"); + bool ok; + newName = QInputDialog::getText(this, tr("Enter new Program name"), + tr("Program name:"), QLineEdit::Normal, + newName, &ok); + + contentModel.createNewProgram(getMdi(),newName); + + return; +} + + +void MainWindow::clickedContent(QModelIndex index) { + + contentModel.clickAction(getMdi(),index); +} + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About QtHP Connect"), + QString("QtHp Connect is an interface for the HP Prime G2 Calculator\n\n")+QString("Version: ")+HP_VERSION_STRING); + +} + +//Show options window +void MainWindow::onOptions(bool clicked) +{ + Options * optiondlg = new Options(this); + optiondlg->show(); +} + +//show or hide content window +void MainWindow::showContent() { + + if (ui->dwContent->isVisible()) { + ui->dwContent->hide(); + } + else + { + ui->dwContent->show(); + } +} + +//Setup the content window to show saved content +void MainWindow::setContentWindow() { + + QSettings appSettings("IRGP","QtHPconnect"); + QString path; + + path=appSettings.value("contentPath").toString(); + qDebug()<<"Content Path:"<setOptions(QFileIconProvider::DontUseCustomDirectoryIcons); + + ui->tvContent->setModel(&contentModel); + + QDir dir(path); + + if (!dir.exists()) { + qDebug()<<"Content Path Does not Exist:"<tvContent->setRootIndex(rootIndex); + ui->tvContent->setAcceptDrops(true); + ui->tvContent->setDragEnabled(true); + ui->tvContent->setDragDropMode(QAbstractItemView::DragDrop); + ui->tvContent->setDropIndicatorShown(true); + + } + } + readSettings(); +} + +//show or hide calculator window +void MainWindow::showCalculator() { + + if (ui->dwCalculator->isVisible()) { + ui->dwCalculator->hide(); + } + else + { + ui->dwCalculator->show(); + } +} + +//show or hide message window +void MainWindow::showMessage() { + + if (ui->dwMessenger->isVisible()) { + ui->dwMessenger->hide(); + } + else + { + ui->dwMessenger->show(); + } +} + +//show or hide message window +void MainWindow::showMonitor() { + + if (ui->dwMonitor->isVisible()) { + ui->dwMonitor->hide(); + } + else + { + ui->dwMonitor->show(); + } +} + +// slot to process low level changes that affect the main Window +void MainWindow::dataChange(hp_Change hpchange) { + + hpCalcData * ptr=nullptr; + qDebug()<<"MainWindow Datachange"; + switch (hpchange.dataChange) { + case HP_MAIN: + + break; + case HP_SCREEN: { + if (hpchange.calc!=nullptr) { + hp_ScreenShot scrn; + scrn = hpchange.calc->getScreenShot(); + monitorAddImage(scrn); + } + } + break; + default:; + } +} + +//Add screen shots to the message window +void MainWindow::monitorAddImage(hp_ScreenShot scrnshot) { + + QPixmap * pic; + int col; + int row; + int count; + int maxcol=2; //number of images in a column + + if (scrnshot.image!=nullptr) { + + //Todo fix default image + pic=new QPixmap(*scrnshot.image); +// pic->scaled(200, 200, Qt::KeepAspectRatio,Qt::SmoothTransformation); + + QLabel * label = new QLabel("Screenshot"); + label->setPixmap(*pic); + row = ui->wMonitorGrid->rowCount(); + col = ui->wMonitorGrid->columnCount(); + count = ui->wMonitorGrid->count(); + + col=count%maxcol; + row=count/maxcol; + +// qDebug()<<"Row set"<wMonitorGrid->addWidget(label,row,col,Qt::AlignTop); + } + else + { + errlog("Could not load image"); + } + ui->dwMonitor->show(); +} + +void MainWindow::setTimerStopped() { + + qDebug()<<"MainWindow:: set timerStopped Flag"; + timerStopped=1; + eventThread->exit(); + 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; +} + +//opens a new test window +//todo - link to hpdata +void MainWindow::createTextWindow() { + + msgWindow = new QMdiSubWindow(ui->mdiArea); + QTextEdit * textWindow = new QTextEdit("hell",msgWindow); +} + +//opens the log window +void MainWindow::createLogWindow() { + + if (!logWindow) + logWindow = new hp_MdiLogWindow(ui->mdiArea); + else + logWindow->show(); + if (!logEdit) + logEdit = logWindow->getEditor(); +} + +//returns the multi document area +QMdiArea * MainWindow::getMdi() { + return ui->mdiArea; +} + +//action on refresh button +void MainWindow::refresh(bool clicked) { + qDebug()<<"MainWindow:: Refresh"; + + QString key; + key=hpTreeModel->getLastDataKey(); + hpCalcData * hpdata; + hpdata=hpTreeModel->getHpCalcData(key); + if(hpdata) + hpdata->refresh(); +} + +//handle hotplug actions +void MainWindow::hotplug_handler(int status) { + qDebug()<<"MainWindow::hotplugin_handler"; + + if (status==HP_OPEN_DEVICE) { + openHP(); + } + + if (status==HP_CLOSE_DEVICE) { + + //TODO + } +} + +void MainWindow::setTreeMenu() { + + treeMenu = new QMenu(ui->tvCalculators); // add menu items + treeMenu->addAction(ui->actionSettings); + treeMenu->addAction(ui->actionRefresh); + ui->tvCalculators->setContextMenuPolicy(Qt::CustomContextMenu); + ui->tvContent->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->actionSettings, SIGNAL(triggered(bool)), + this, SLOT(treeMenuAction(bool))); + connect(ui->actionRefresh, SIGNAL(triggered(bool)), + this, SLOT(refresh(bool))); + + + treeMenu1 = new QMenu(ui->tvCalculators); + treeMenu1->addAction(ui->actionCalcOpen); + treeMenu1->addAction(ui->actionCalcDelete); + treeMenu1->addAction(ui->actionCalcRename); + + treeMenu2 = new QMenu(ui->tvCalculators); + treeMenu2->addAction(ui->actionCalcOpen); + treeMenu2->addAction(ui->actionCalcDelete); + + connect(ui->actionCalcOpen, SIGNAL(triggered(bool)), + this, SLOT(treeOpenAction(bool))); + connect(ui->actionCalcDelete, SIGNAL(triggered(bool)), + this, SLOT(treeDeleteAction(bool))); + connect(ui->actionCalcRename, SIGNAL(triggered(bool)), + this, SLOT(treeRenameAction(bool))); + + + fileMenu1 = new QMenu(ui->tvContent); + fileMenu1->addAction(ui->actionFileOpen); + fileMenu1->addAction(ui->actionFileDelete); + fileMenu1->addAction(ui->actionFileRename); + + fileMenu2 = new QMenu(ui->tvContent); + fileMenu2->addAction(ui->actionFileOpen); + fileMenu2->addAction(ui->actionFileDelete); + + connect(ui->actionFileOpen, SIGNAL(triggered(bool)), + this, SLOT(contentOpenAction(bool))); + connect(ui->actionFileRename, SIGNAL(triggered(bool)), + this, SLOT(contentRenameAction(bool))); + connect(ui->actionFileDelete, SIGNAL(triggered(bool)), + this, SLOT(contentDeleteAction(bool))); + +} + +void MainWindow::treeMenuAction(bool clicked) { + + qDebug()<<"MainWindow::treeMenuAction"; + + QPoint pos; + pos=ui->actionSettings->data().toPoint(); + + QModelIndex index = ui->tvCalculators->indexAt(pos); + if (index.isValid()) { + hpTreeItem * treeItem = dynamic_cast(hpTreeModel->itemFromIndex(index)); + if(treeItem) { + hp_DataType treetype; + treetype=treeItem->getType(); + switch (treetype) { + case HP_MAIN: + treeItem->contextAction(getMdi(),CT_PREFERENCE); + break; + default:; + } + } + else + { + errlog(QStringLiteral("treeItem is null")); + } + } +} + + +void MainWindow::treeOpenAction(bool clicked) { + qDebug()<<"MainWindow::treeOpenAction"; + + QPoint pos; + pos=ui->actionCalcOpen->data().toPoint(); + QModelIndex index = ui->tvCalculators->indexAt(pos); + + if (index.isValid()) { + hpTreeModel->openFile(getMdi(),index); + } + else { + } + return; + +} + +void MainWindow::treeRenameAction(bool clicked) { + qDebug()<<"MainWindow::treeRenameAction"; + + QPoint pos; + pos=ui->actionCalcRename->data().toPoint(); + QModelIndex index = ui->tvCalculators->indexAt(pos); + + if (index.isValid()) { + + QString newName= hpTreeModel->getName(index); + bool ok; + newName = QInputDialog::getText(this, tr("QInputDialog::getText()"), + tr("File name:"), QLineEdit::Normal, + newName, &ok); + + if (ok && !newName.isEmpty()) { + hpTreeModel->renameFile(index,newName); + } + } + else { + } + return; + +} + +void MainWindow::treeDeleteAction(bool clicked) { + qDebug()<<"MainWindow::treeDeleteAction"; + + QPoint pos; + pos=ui->actionCalcDelete->data().toPoint(); + QModelIndex index = ui->tvCalculators->indexAt(pos); + QMessageBox::StandardButton reply; + + if (index.isValid()) { + + QString fileName= hpTreeModel->getName(index); + QString msg("Are you sure you want to delete file "); + msg=msg+fileName; + + reply = QMessageBox::question(this, "Delete File", msg, + QMessageBox::Yes|QMessageBox::No); + if (reply == QMessageBox::Yes) { + hpTreeModel->deleteFile(index); + } + } + else { + } + return; + +} + +void MainWindow::contentMenuAction(bool clicked) { + qDebug()<<"MainWindow::contentMenuAction"; + +} + +void MainWindow::contentOpenAction(bool clicked) { + qDebug()<<"MainWindow::contentOpenAction"; + + QPoint pos; + pos=ui->actionFileOpen->data().toPoint(); + QModelIndex index = ui->tvContent->indexAt(pos); + + if (index.isValid()) { + contentModel.clickAction(getMdi(),index); + } + else { + } + return; +} + +void MainWindow::contentRenameAction(bool clicked) { + qDebug()<<"MainWindow::contentRenameAction"; + + QPoint pos; + pos=ui->actionFileRename->data().toPoint(); + QModelIndex index = ui->tvContent->indexAt(pos); + + QString newName; + + if (index.isValid()) { + QFileInfo fileinfo = contentModel.fileInfo(index); + + newName=fileinfo.fileName(); + + bool ok; + newName = QInputDialog::getText(this, tr("QInputDialog::getText()"), + tr("File name:"), QLineEdit::Normal, + newName, &ok); + if (ok && !newName.isEmpty()) { + contentModel.renameFile(index,newName); + } + } + else { + } + + return; + +} + +void MainWindow::contentDeleteAction(bool clicked) { + qDebug()<<"MainWindow::contentDeleteAction"; + + QPoint pos; + pos=ui->actionFileDelete->data().toPoint(); + QModelIndex index = ui->tvContent->indexAt(pos); + + QMessageBox::StandardButton reply; + + if (index.isValid()) { + QFileInfo fileinfo = contentModel.fileInfo(index); + QString msg("Are you sure you want to delete file "); + + msg=msg+fileinfo.fileName()+"."; + + reply = QMessageBox::question(this, "Delete File", msg, + QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) { + contentModel.deleteFile(index); + } + } + else { + } + + return; +} + +void MainWindow::on_tvCalculators_customContextMenuRequested(const QPoint &pos) +{ + QModelIndex index = ui->tvCalculators->indexAt(pos); + if (index.isValid()) { + + ui->actionCalcOpen->setData(QVariant(pos)); + ui->actionCalcDelete->setData(QVariant(pos)); + ui->actionCalcRename->setData(QVariant(pos)); + + hpTreeItem * treeItem = dynamic_cast(hpTreeModel->itemFromIndex(index)); + if(treeItem) { + hp_DataType treetype; + treetype=treeItem->getType(); + switch (treetype) { + //only show menu on main + case HP_MAIN: { + if(treeMenu) { + ui->actionPreferences->setData(QVariant(pos)); + treeMenu->exec(ui->tvCalculators->viewport()->mapToGlobal(pos)); + } + } + break; + case HP_PROG: + case HP_NOTE:{ + if(treeMenu1) { + ui->actionPreferences->setData(QVariant(pos)); + treeMenu1->exec(ui->tvCalculators->viewport()->mapToGlobal(pos)); + treeMenu1->hide(); + } + } + break; + case HP_MATRIX: + case HP_LIST:{ + if(treeMenu2) { + ui->actionPreferences->setData(QVariant(pos)); + treeMenu2->exec(ui->tvCalculators->viewport()->mapToGlobal(pos)); + } + } + break; + default:; + } + } + } +} + +void MainWindow::on_tvContent_customContextMenuRequested(const QPoint &pos) +{ + QModelIndex index = ui->tvContent->indexAt(pos); + + hp_DataStruct filedata; + if (index.isValid()) { + + QFileInfo info = contentModel.fileInfo(index); + ui->actionFileOpen->setData(QVariant(pos)); + ui->actionFileDelete->setData(QVariant(pos)); + ui->actionFileRename->setData(QVariant(pos)); +// qDebug()<<"MainWindow::on_tvContent_customContextMenuRequested"; + filedata=contentModel.getFileType(info); + switch (filedata.type) { + case HP_PROG: + case HP_APP: + case HP_NOTE: + case HP_VAR: { + fileMenu1->exec(ui->tvContent->viewport()->mapToGlobal(pos)); + fileMenu1->hide(); + break; + } + case HP_CAS: + case HP_MAIN: + case HP_MATRIX: + case HP_LIST: + case HP_COMPLEX: + case HP_SCREEN: + case HP_REAL: { + fileMenu2->exec(ui->tvContent->viewport()->mapToGlobal(pos)); + } + } + + } +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + + qDebug()<<"MainWindow:: closeEvent Step 1"; + writeSettings(); + + //stop the timer pulse + emit stopTimer(); + + eventThread->quit(); + eventThread->terminate(); + eventThread->wait(); + + event->accept(); + + qDebug()<<"MainWindow:: closeEvent Step 2"; +} + + +//destructor +MainWindow::~MainWindow() +{ + + // qDebug()<<"MainWindow:: closeEvent Step 4"; + + if (myModel!=nullptr) { + delete myModel; + myModel=nullptr; + } + + // qDebug()<<"MainWindow:: closeEvent Step 3"; + + ui->tvCalculators->close(); + ui->tvContent->close(); + ui->dwContent->close(); + ui->dwMonitor->close(); + ui->dwMessenger->close(); + ui->dwCalculator->close(); + + // qDebug()<<"MainWindow:: closeEvent Step 5"; + if (main_err!=nullptr) { + delete main_err; + main_err=nullptr; + } + + qDebug()<<"MainWindow:: closing"; +} diff --git a/source/mainwindow.ui b/source/mainwindow.ui new file mode 100644 index 0000000..d8272b7 --- /dev/null +++ b/source/mainwindow.ui @@ -0,0 +1,698 @@ + + + Ian Gebbie + MainWindow + + + + 0 + 0 + 919 + 584 + + + + Linux HP Connect + + + + + + + + 0 + 0 + + + + + 500 + 0 + + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAsNeeded + + + + + + + + + 0 + 0 + 919 + 23 + + + + + 10 + + + + + Fi&le + + + + + + Edit + + + + + + + Wi&ndow + + + + + + + + + + + + + + + + + + + Help + + + + + + + + + + + + 0 + 0 + + + + + 200 + 184 + + + + + 524287 + 524287 + + + + + 300 + 200 + + + + 1 + + + + + 0 + 0 + + + + + 100 + 150 + + + + + + + true + + + + 0 + 0 + + + + Qt::ActionsContextMenu + + + <html><head/><body><p>Calculator View</p></body></html> + + + 2 + + + 1 + + + false + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 300 + 130 + + + + + 524287 + 524287 + + + + 1 + + + + + 0 + 0 + + + + + + + <html><head/><body><p>File View</p></body></html> + + + QAbstractItemView::SelectItems + + + 15 + + + true + + + 47 + + + 150 + + + true + + + false + + + + + + + + + + 0 + 0 + + + + + 150 + 524287 + + + + 2 + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + + + + 2 + + + + + 0 + 0 + + + + + + + + + + + + + 100 + 20 + + + + + 100 + 20 + + + + + + + true + + + + + + :/icons/cut_32x32.png:/icons/cut_32x32.png + + + &Cut + + + + + + + + + :/icons/copy_32x32.png:/icons/copy_32x32.png + + + C&opy + + + + + + + + + :/icons/paste_32x32.png:/icons/paste_32x32.png + + + &Paste + + + + + &Close + + + + + C&lose all + + + + + &Tile + + + + + Ca&scade + + + + + &Next + + + + + + :/icons/chat_32x32.png:/icons/chat_32x32.png + + + &Messages + + + + + + :/icons/monitor_32x32.png:/icons/monitor_32x32.png + + + M&onitor + + + + + + :/icons/calc_tree_32x32.png:/icons/calc_tree_32x32.png + + + Calc&ulators + + + + + + :/icons/about_32x32.png:/icons/about_32x32.png + + + &About HP Connect + + + + + + + + + :/icons/preferences_32x32.png:/icons/preferences_32x32.png + + + P&references + + + + + + + + &Previous + + + + + + :/icons/content_32x32.png:/icons/content_32x32.png + + + Cont&ent + + + + + + :/icons/save_32x32.png:/icons/save_32x32.png + + + Save + + + + + + :/icons/save_all_32x32.png:/icons/save_all_32x32.png + + + Save All + + + + + + :/icons/add_new_32x32.png:/icons/add_new_32x32.png + + + CreateNew + + + Create New + + + + + + :/icons/delete_32x32.png:/icons/delete_32x32.png + + + &Exit + + + + + + :/icons/add_icon_32x32.png:/icons/add_icon_32x32.png + + + Open + + + + + + :/icons/note_32x32.png:/icons/note_32x32.png + + + Lo&g + + + + + + :/icons/clone_to_32x32.png:/icons/clone_to_32x32.png + + + Test + + + Test Button + + + + + + :/icons/preferences_32x32.png:/icons/preferences_32x32.png + + + TreePreference + + + + + + :/icons/preferences_32x32.png:/icons/preferences_32x32.png + + + TestSettings + + + + + + :/icons/add_background_32x32.png:/icons/add_background_32x32.png + + + TestScreen + + + Test get Screen Function + + + + + + :/icons/refresh_32x32.png:/icons/refresh_32x32.png + + + Refresh + + + + + + :/icons/preferences_32x32.png:/icons/preferences_32x32.png + + + Settings + + + + + + :/icons/open_16x16.png + + + + &Open + + + Open a file + + + Alt+O + + + + + + :/icons/delete_16x16.png + + + + &Delete + + + Delete a file + + + Alt+D + + + + + + :/icons/rename_16x16.png + + + + &Rename + + + Rename a file + + + Alt+R + + + + + + :/icons/open_16x16.png + + + + &Open + + + Open a file + + + Alt+O + + + + + + :/icons/delete_16x16.png + + + + &Delete + + + Delete a file + + + Alt+D + + + + + + :/icons/rename_16x16.png + + + + &Rename + + + Rename a file + + + Alt+R + + + + + + :/icons/new_folder_16x16.png:/icons/new_folder_16x16.png + + + Folder + + + Create a New Folder + + + + + New Note + + + + + New Program + + + + + + + + + diff --git a/source/matrixdata.cpp b/source/matrixdata.cpp new file mode 100644 index 0000000..39ba45b --- /dev/null +++ b/source/matrixdata.cpp @@ -0,0 +1,310 @@ +/* + * QtHP Connect: hand-helds support interface. + * Copyright (C) 2019 Ian Gebbie + * Code patterns and snippets borrowed from libhpcalcs : + * Copyright (C) 1999-2009 Romain Li�vin + * Copyright (C) 2009-2013 Lionel Debroux + * Copyright (C) 1999-2013 libti* contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include "matrixdata.h" + +extern bool BCD(QDataStream &ds, double real) ; + +MatrixData::MatrixData() +{ +// clear(); + qDebug()<<"MatrixData Construct"; +} + +//Return the item or a zero item +itemData MatrixData::at(int row, int column) +{ + QList * rowlist; + itemData item; + + if (rowsize()) { + item=rowlist->at(column); + } + } + } + return item; +} + +//Insert a new item and resize the list if larger +void MatrixData::insert(int row, int column, itemData data) +{ + QList * rowlist=nullptr; + + upsize(row+1,column+1); + + if(rowreplace(column,data); + } +} + +//Add a new row +void MatrixData::addRow(int row) +{ + int rows; + int i; + QList * rowlist; + + +// qDebug()<<"MatrixData::addRow" << row; + rows=matrix.size(); + if (rows<=row) + { + for (i=rows; i<=row;i++) { + // qDebug()<<"MatrixData::addRow "<; + matrix.insert(i,rowlist); + } + } +} + +bool MatrixData::dataOut(QDataStream & ds) { + + int row; + int column; + int i,j=0; + + qDebug()<<"MatrixData::dataOut(ds)"; + + row=rows(); + column=columns(); + + itemData item; + QString str; + //header + + static const quint8 mydata[] = {0x02, 0x01, 0x04,0x03,0x06,0x05,0x08,0x07}; + + QByteArray test= QByteArray::fromRawData((char *)mydata,sizeof (mydata)); + + ds<(0x0001); + ds<(0x8014); + ds<(0x0002); + ds<(0x0000); + + ds<(row); + ds<(column); +// ds<(0x30); +// ds<(0x31); + + // qDebug()< * row; + int rows=0; + int maxrows=0; + int columns=0; + int maxcolumns=0; + int i; + int j; + + qDebug()<<"MatrixData::resize"; + + itemData item; + rows = matrix.size(); + qDebug()<<"MatrixData::resize - maxcolumns "<newrow) { + matrix.removeAt(i); + } + } + + //increase rows to match + if(newrow>rows) { + + for(i=rows;isize(); + if (columnsinsert(j,item); + } + } + if (columns>newcol) { + row=matrix.at(i); + if (row) { + for(j=columns;jremoveAt(j); + } + } + } + } +} + +//get all columns to same size by padding it zero items +void MatrixData::upsize(int newrow,int newcol) { + + QList * row; + int rows=0; + + int columns=0; + + int i; + int j; + + qDebug()<<"MatrixData::upsize"; + + itemData item; + item.sValue=QStringLiteral("0"); + + rows = matrix.size(); +// qDebug()<<"MatrixData::upsize - rows:"<size(); + for(j=columns;jinsert(j,item); + } + } + } + else { + qDebug()<<"MatrixData::upsize - Null row!"; + } + } +} + +//get all columns to same size by padding it zero items +void MatrixData::matchsize() { + + QList * row; + int rows=0; + int maxrows=0; + int columns=0; + int maxcolumns=0; + int i; + int j; + + qDebug()<<"MatrixData::matchsize"; + + itemData item; + rows = matrix.size(); + + for(i=0;isize(); + if (maxcolumnssize(); + if (columnsinsert(j,item); + } + } + } +} + +void MatrixData::clear() +{ + int i; + int r; + QList * row; + + r=rows(); + + for(i=0; iclear(); + delete row; + } + } + matrix.clear(); +} + +int MatrixData::columns() +{ + QList * row; + + if (matrix.size()>0) { + row=matrix.at(0); + if (row) { + qDebug()<<"MatrixData: column "<size(); + return row->size(); + } + } + return 0; +} + +int MatrixData::rows() +{ + qDebug()<<"MatrixData: row"< + + +Options::Options(QWidget *parent) : + QDialog(parent), + ui(new Ui::Options) +{ + ui->setupUi(this); + QString path; + + QSettings appSettings("IRGP","QtHPconnect"); + path=appSettings.value("contentPath").toString(); + ui->filePath->setText(path); +} + +void Options::accept() { + + QString path; + path=ui->filePath->text(); + QSettings appSettings("IRGP","QtHPconnect"); + appSettings.setValue("contentPath",path); + QDialog::accept(); +} + +void Options::reject() { + QDialog::reject(); +} + +Options::~Options() +{ + qDebug()<<"~Options()"; + delete ui; +} diff --git a/source/options.ui b/source/options.ui new file mode 100644 index 0000000..595111b --- /dev/null +++ b/source/options.ui @@ -0,0 +1,135 @@ + + + Options + + + + 0 + 0 + 640 + 480 + + + + Dialog + + + + + 10 + 440 + 621 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 10 + 20 + 621 + 91 + + + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 80 + 40 + 521 + 32 + + + + + + + 10 + 30 + 58 + 51 + + + + File Path: + + + + + + 10 + 10 + 141 + 18 + + + + Environment + + + + + + + + buttonBox + accepted() + Options + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Options + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/source/texteditor.cpp b/source/texteditor.cpp new file mode 100644 index 0000000..a18dddb --- /dev/null +++ b/source/texteditor.cpp @@ -0,0 +1,165 @@ +/* + * This file is part of the QtHPConnect distribution (https://github.com/Indy970/QtHPConnect.git). + * Copyright (c) 2020 Ian Gebbie. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 or later. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "texteditor.h" +#include +#include +#include + +textEditor::textEditor(QWidget *parent) : + QTextEdit(parent) +{ + QSettings appSettings("IRGP","QtHPconnect"); + wParent = parent; + setAttribute(Qt::WA_DeleteOnClose); +// setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + isUntitled = true; + + defaultPath=QDir(appSettings.value("contentPath").toString()); + qDebug()<isModified()); +} + +void textEditor::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString textEditor::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + +textEditor::~textEditor() { + qDebug()<<"textEditor:: delete"; +} diff --git a/source/treemodel.cpp b/source/treemodel.cpp new file mode 100644 index 0000000..e090df6 --- /dev/null +++ b/source/treemodel.cpp @@ -0,0 +1,607 @@ +/* + * QtHP Connect: hand-helds support interface. + * Copyright (C) 2019 Ian Gebbie + * Code patterns and snippets borrowed from libhpcalcs : + * Copyright (C) 1999-2009 Romain Li�vin + * Copyright (C) 2009-2013 Lionel Debroux + * Copyright (C) 1999-2013 libti* contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + + +// +// Model to contain the calculator data structure +// + +#include "treemodel.h" +#include "hptreeitem.h" +#include +#include +#include +#include +#include + + +//Constructor +treeModel::treeModel(QObject *parent) + :QStandardItemModel(parent) +{ + setItemPrototype(new hpTreeItem()); + createRoot(); + setParent(parent); + } + +//Create the start of the tree +int treeModel::createRoot() +{ + rootNode = invisibleRootItem(); + return 0; +} + +//Create Item +AbstractData * treeModel::createData(hp_Data data_in) { + + AbstractData * obj=nullptr; + errlog("TreeModel::Creating Data Stucture"); + + switch (data_in.type) { + case HP_APP: { + qDebug()<<"hpCalcData::recvData - Application"; + Application * obj = new Application(data_in.name,data_in.type); + return obj; + } + break; + case HP_LIST: { + List * obj = new List(data_in.name,data_in.type); + return obj; + } + break; + case HP_MATRIX: { + qDebug()<<"hpCalcData::recvData - Matrix"; + Matrix * obj = new Matrix(data_in.name,data_in.type); + return obj; + } + break; + } + + return obj; +} + +//Rework - name should be calc name +int treeModel::addCalculator(QString name, hpusb * handle){ + + hpCalcData * hpData = new hpCalcData(name, handle); + hpTreeItem * hpCalc = new hpTreeItem(name,hpData,0); + hpCalc->setType(HP_MAIN); + hpCalc->setIcon(QIcon(":/icons/monitor_32x32.png")); + hpCalc->setToolTip(QString("Calculator contents")); + QObject::connect(hpData, SIGNAL(dataChanged(hp_Change)),hpCalc, SLOT(dataChange(hp_Change))); + if (parent()!=nullptr) + QObject::connect(hpData, SIGNAL(dataChanged(hp_Change)),parent(), SLOT(dataChange(hp_Change))); + setHpCalcData(name,hpData,hpCalc); + rootNode->appendRow(hpCalc); + hpData->readInfo(); + + return 0; +} + +//return the calculator data within the model +hpCalcData * treeModel::getCalculator(QString name){ + + hpDataLink hplink; + hpCalcData * hpdata = nullptr; + + if (!hpCalcList.isEmpty()) { + QMap::const_iterator i = hpCalcList.find(name); + + if (i!=hpCalcList.end()) { + hplink = i.value(); + hpdata= hplink.dataItem; + } + } + return hpdata; +} + +void treeModel::clickAction(QMdiArea * mdiwin,QModelIndex &index) { + + qDebug()<<"row "<(itemFromIndex(index)); + data=getData(index); + + if ((data!=nullptr)&&(item!=nullptr)) { + calc=item->getCalculatorName(); + name=item->getFileName(); + type=data->getType(); + hpdata=getHpCalcData(calc); + switch (type) { + case HP_MAIN: { + hpinfo=hpdata->getInfo(); + hpinfodlg = new hp_infoDialog(mdiwin,hpinfo); + hpinfodlg->show(); + } + break; + case HP_NOTE: + case HP_PROG: { + if (hptextedit==nullptr) + hptextedit = new hp_mdiTextEdit(mdiwin,item, data); + if (hptextedit!=nullptr) + hptextedit ->show(); + } + break; + case HP_CAS: + case HP_REAL: + case HP_COMPLEX: + case HP_LIST: + case HP_MATRIX: { + if (hpvaredit==nullptr) { + if (data!=nullptr) { + hpvaredit = new hp_mdiVariableEdit(mdiwin,item,hpdata); + } + } + if (hpvaredit!=nullptr) + hpvaredit ->show(); + } + break; + } + } + else { + qDebug()<<"Null data"; + } + + return; +} + +void treeModel::renameFile(QModelIndex &index,QString newName) { + + qDebug()<<"treeModel::renameFile"; + + AbstractData * adata=nullptr; + hpTreeItem * item=nullptr; + QString calc; + QString name; + hp_DataType type; + hpCalcData * hpdata=nullptr; + + qDebug()<<"row "<(itemFromIndex(index)); + + if (item!=nullptr) { + + calc=item->getCalculatorName(); + name=item->getFileName(); + qDebug()<getType(); + hpdata=getHpCalcData(calc); + if (hpdata!=nullptr) { + adata=hpdata->getData(name,type); + } + else { + qDebug()<<"treeModel::renameFile hpdata is null"; + } + + // + item->setFileName(newName); + adata->setName(newName); + + // + } + else { + qDebug()<<"Null data"; + } + } + else { + qDebug()<<"treeModel::renameFile invalid index"; + } +} + +void treeModel::deleteFile( QModelIndex &index) { + + qDebug()<<"treeModel::deleteFile"; + AbstractData * adata=nullptr; + hpTreeItem * item=nullptr; + QString calc; + QString name; + hp_DataType type; + hpCalcData * hpdata=nullptr; + + if (index.isValid()) { + item = static_cast(itemFromIndex(index)); + + if (item!=nullptr) { + + calc=item->getCalculatorName(); + name=item->getFileName(); + qDebug()<getType(); + hpdata=getHpCalcData(calc); + if (hpdata!=nullptr) { + adata=hpdata->getData(name,type); + } + else { + qDebug()<<"treeMoel::deletFile hpdata is null"; + } + + // + //delete hpTreeItem + // qDebug()<<"row "<deleteData(adata); + + } + else { + qDebug()<<"Null data"; + } + } + else { + qDebug()<<"treeMoel::deleteFile invalid index"; + } +} + +//return the calculator data within the model +hpTreeItem * treeModel::getCalculatorItem(QString name){ + + hpDataLink hplink; + hpTreeItem * hpitem = nullptr; + + if (!hpCalcList.isEmpty()) { + QMap::const_iterator i = hpCalcList.find(name); + + if (i!=hpCalcList.end()) { + hplink = i.value(); + hpitem= hplink.treeItem; + } + } + return hpitem; +} + +//index system for data retrieval +//review QStandardItemModel should already have one in place +QString treeModel::getLastDataKey() { + if (hpCalcList.isEmpty()) + return QStringLiteral(""); + else + return hpCalcList.lastKey(); +} + +//manage link between tree and data +//A map stores the treeItem, dataItem and in future perhaps the handle in a list +// retrievable by a string key +hpCalcData * treeModel::getHpCalcData(QString name) const { + + hpDataLink hplink; + hpCalcData * hpdata=nullptr; + + if (!hpCalcList.isEmpty()) { + QMap::const_iterator i = hpCalcList.find(name); + + if (i!=hpCalcList.end()) { + hplink = i.value(); + hpdata= hplink.dataItem; + } + } + return hpdata; +} + +//manage link between tree and data +void treeModel::setHpCalcData(QString name, hpCalcData * data, hpTreeItem * tree ){ + + hpDataLink hplink; + hplink.dataItem=data; + hplink.treeItem=tree; + hpCalcList.insert(name,hplink); + + return; +} + +//Part the the drag and drop system +Qt::DropActions treeModel::supportedDropActions() const +{ + return Qt::CopyAction | Qt::MoveAction | Qt::TargetMoveAction; +} + +QString treeModel::getName(QModelIndex index) const { + + QString calc; + QString name=QStringLiteral("None"); + hpTreeItem * item=nullptr; + if (index.isValid()) { + item = static_cast(itemFromIndex(index)); + if (item!=nullptr) { + calc=item->getCalculatorName(); + name=item->getFileName(); + } + } + return name; +} + + + +//Return the data object belonging to an item +AbstractData * treeModel::getData(QModelIndex index) const { + + AbstractData * adata=nullptr; + QString calc; + QString name; + hp_DataType type; + hpTreeItem * item=nullptr; + hpCalcData * hpdata=nullptr; + if (index.isValid()) { + item = static_cast(itemFromIndex(index)); + if (item!=nullptr) { + calc=item->getCalculatorName(); + name=item->getFileName(); + qDebug()<getType(); + hpdata=getHpCalcData(calc); + if (hpdata!=nullptr) { + adata=hpdata->getData(name,type); + } + else { + qDebug()<<"treeMoel::getData hpdata is null"; + } + } + else { + qDebug()<<"treeMoel::getData item is null"; + } + } + else { + qDebug()<<"treeMoel::getData invalid index"; + } + return adata; +} + + +//Get and pass on the data to be dragged +QMimeData* treeModel::mimeData(const QModelIndexList &indexes) const +{ + + QMimeData *mimeDataPtr = new QMimeData(); + AbstractData * adata = nullptr; + QByteArray mydata; + QByteArray datatype; + QModelIndex index; + + qDebug()<<"treeModel::mimeData"; + + for(int i =0; igetType(); + mydata = adata->getData(); + mimeDataPtr->setText(adata->getName()); + datatype[0] = adata->getType(); + mimeDataPtr->setData("application/x-type",datatype); + mimeDataPtr->setData("application/x-qabstractmodeldatalist",mydata); + } + else { + qDebug()<<"treeModel::mimeData No Data"; + } + + } + + return mimeDataPtr; +} + +//Allow drop in location +bool treeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + return true; +} + +//Process the drop action +bool treeModel::dropMimeData(const QMimeData* md_data, Qt::DropAction action, int row, + int column, const QModelIndex &index) +{ + QByteArray data_in; + AbstractData * absitem; + + qDebug()<<"treemodel::DropMineData "<(itemFromIndex(index)); + if (item!=nullptr) { + hp_DataType type=HP_MAIN; + QStringList formatList; + QString mimeType; + formatList=md_data->formats(); + + foreach(const QString& format, formatList) { + qDebug()<(i); + break; + } + } + } + + if ( type!=HP_MAIN) { + QString name=md_data->text(); + data_in=md_data->data(mimetypes[type][1]); + + QDataStream in(&data_in,QIODevice::ReadOnly); + + qDebug()<<"Type="<parseData(in); + break; + } + case HP_LIST: { + absitem = new List(name, HP_LIST); + absitem->parseData(in); + break; + } + case HP_MATRIX: { + absitem = new Matrix(name, HP_MATRIX); + absitem->parseData(in); + break; + } + case HP_PROG: { + absitem = new Program(name, HP_PROG, QStringLiteral("")); + absitem->parseData(in); + break; + } + case HP_VAR: { + absitem = new Variables(name, HP_VAR); + absitem->parseData(in); + break; + } + } + + QString calc = item->getCalculatorName(); + addItem(calc,absitem); + + // qDebug()<<"treemodel::dropMimeData End"; + } + else { + qDebug()<<"treemodel::sropMimeData type not found "<getGroupName(); + + QModelIndex in = calc->index(); + + for (int e = 0; erowCount(); e++) { + QModelIndex si=index(e,0,in); + item = static_cast(itemFromIndex(si)); + if(item->getType()==type) { + return item; + } + } + + return nullptr; + +} + +//add an object to the correct place in the tree of a calaculator +int treeModel::addItem(QString calc, AbstractData * obj) { + + hp_DataType type; + hpCalcData * hpdata; + + if (obj!=nullptr) { + type = obj->getType(); + } + else { + return -1; + } + + hpTreeItem * rootitem = findTypeRoot(calc,type); + + if(rootitem!=nullptr) { + hpdata=rootitem->getDataStore(); + } + else { + return -1; + } + rootitem->addChild(obj); + hpdata->addData(obj); + + return 0; +} + + +int treeModel::deleteItem(hpCalcData* hpcalc, AbstractData * obj) { + +} + + +Qt::ItemFlags treeModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index); + + if (index.isValid()) + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + else + return Qt::ItemIsDropEnabled | defaultFlags; +} + +int deletCalculator(QString name, hpusb * handle) { + +} + +int treeModel::deleteAllCalculators() { + + hpDataLink hplink; + hpCalcData * hpdata = nullptr; + + foreach(QString key, hpCalcList.keys()) { + + QMap::const_iterator i = hpCalcList.find(key); + hplink=i.value(); + delete(hplink.dataItem); + hpCalcList.remove(key); + } + hpCalcList.clear(); + return 0; + +} + + +treeModel::~treeModel() { + + deleteAllCalculators(); + + qDebug()<<"treeModel:: delete"; +} + + diff --git a/source/variableview.cpp b/source/variableview.cpp new file mode 100644 index 0000000..3f91c63 --- /dev/null +++ b/source/variableview.cpp @@ -0,0 +1,37 @@ +/* + * QtHP Connect: hand-helds support interface. + * Copyright (C) 2019 Ian Gebbie + * Code patterns and snippets borrowed from libhpcalcs : + * Copyright (C) 1999-2009 Romain Li�vin + * Copyright (C) 2009-2013 Lionel Debroux + * Copyright (C) 1999-2013 libti* contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + +#include "variableview.h" +#include "ui_variableview.h" +#include + +variableView::variableView(QWidget *) + +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); +} + +variableView::~variableView() +{ + qDebug()<<"delete variableView"; + delete ui; +} diff --git a/source/variableview.ui b/source/variableview.ui new file mode 100644 index 0000000..67edb45 --- /dev/null +++ b/source/variableview.ui @@ -0,0 +1,28 @@ + + + variableView + + + + 0 + 0 + 347 + 358 + + + + Form + + + + + + true + + + + + + + + diff --git a/source/vartablemodel.cpp b/source/vartablemodel.cpp new file mode 100644 index 0000000..069f016 --- /dev/null +++ b/source/vartablemodel.cpp @@ -0,0 +1,308 @@ +/* + * QtHP Connect: hand-helds support interface. + * Copyright (C) 2019 Ian Gebbie + * Code patterns and snippets borrowed from libhpcalcs : + * Copyright (C) 1999-2009 Romain Li�vin + * Copyright (C) 2009-2013 Lionel Debroux + * Copyright (C) 1999-2013 libti* contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + +#include +#include +#include +#include +#include +#include + +#include "global.h" +#include "vartablemodel.h" + +const QStringList varTableModel::real_header={ "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "o", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "THETA" + }; + +const QStringList varTableModel::complex_header={ "Z0", + "Z1", + "Z2", + "Z3", + "Z4", + "Z5", + "Z6", + "Z7", + "Z8", + "Z9" + }; + +varTableModel::varTableModel(QObject *parent, + AbstractData * data, + QString file, + hp_DataType dtype) + :QAbstractTableModel(parent) +{ + q_parent=parent; + dataobj = data; + filename=file; + type=dtype; + setup(); +} + +//REWORK! +QModelIndex varTableModel::parent(const QModelIndex &index) const { + + return QModelIndex(); +} + +Qt::ItemFlags varTableModel::flags(const QModelIndex &index) const { + + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +} + +//rework! +QModelIndex varTableModel::index(int row, int column, const QModelIndex &parent) const { + + return createIndex(row,column); +} + +//alter the data table if data is edited +bool varTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { + + qDebug()<<"Data Changed"; + + if (type==HP_LIST) { + List * list; + list = static_cast(dataobj); + list->setItem(index.row(),value.toString(),value.toReal()); + ismodified=true; + return true; + } + if (type==HP_MATRIX) { + Matrix * matrix; + matrix = static_cast(dataobj); + matrix->setItem(index.row(),index.column(),value.toString(),value.toReal()); + ismodified=true; + return true; + } + if (type==HP_REAL) { + Real * real; + real = static_cast(dataobj); + // item = real->getItem(index.row()); + // return item; + } + if (type==HP_COMPLEX) { + Complex * complex; + complex = static_cast(dataobj); + // item = complex->getItem(index.row()); + // return item; + } + + return false; +} + +void varTableModel::setup() +{ + ismodified=false; +// if (hpcalc) { + +// dataobj=hpcalc->getData(filename,type); + + // qDebug()<<"varTableModel: type"<getType(); +// } + + return; +} + +int varTableModel::rowCount(const QModelIndex & parent) const +{ + int size=16; //should be zero + if (type==HP_LIST) { + List * list; + list = static_cast(dataobj); + size= list->getListSize()+1; + } + if (type==HP_REAL) { + Real * real; + real = static_cast(dataobj); + size= real->getListSize(); + } + if (type==HP_COMPLEX) { + Complex * complex; + complex = static_cast(dataobj); + size= complex->getListSize(); + } + if (type==HP_MATRIX) { + Matrix * matrix; + matrix = static_cast(dataobj); + size= matrix->getMatrixRows()+1; +// qDebug()<getName()<<" row"<(dataobj); + size= matrix->getMatrixColumns()+1; + // qDebug()<getName()<<" column"<(dataobj); + // size= matrix->getMatrixColumns(); + // qDebug()<getName()<<" column"< &roles) { + + ismodified=true; + qDebug()<<"Data Changed "<(dataobj); + item = list->getItem(index.row()); + return item; + } + if (type==HP_MATRIX) { + Matrix * matrix; + matrix = static_cast(dataobj); + item = matrix->getItem(index.row(),index.column()); + return item; + } + if (type==HP_REAL) { + Real * real; + real = static_cast(dataobj); + item = real->getItem(index.row()); + return item; + } + if (type==HP_COMPLEX) { + Complex * complex; + complex = static_cast(dataobj); + item = complex->getItem(index.row()); + return item; + } + + return QString("Row%1, Column%2") + .arg(index.row() + 1) + .arg(index.column() +1); + } + return QVariant(); +} + +QVariant varTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) { + return QVariant(); + } + + if (orientation == Qt::Horizontal) { + if (type==HP_REAL) { + return QString("%1").arg(section+1); + } + return QString("%1").arg(section+1); + + } + if (orientation == Qt::Vertical) { + if (type==HP_REAL) { + if (section < real_header.size()) { + return real_header.at(section); + } + else { + return QString("%1").arg(section); + } + } + + if (type==HP_COMPLEX) { + if (section < complex_header.size()) { + return complex_header.at(section); + } + else { + return QString("%1").arg(section); + } + } + + return QString("%1").arg(section); + } + + return QVariant(); +} + +bool varTableModel::getData(QDataStream &ds) { + +// QByteArray out; +// out.clear(); + if(dataobj!=nullptr) { + dataobj->getData(ds); + // out=dataobj->fileOut(); + // qDebug()<