Print@Home: extend DB and transactions, prototype app
authorKonrad Rosenbaum <konrad@silmor.de>
Tue, 29 Nov 2016 10:17:15 +0000 (11:17 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Tue, 29 Nov 2016 10:17:15 +0000 (11:17 +0100)
Change-Id: I12a228ecfecae4f5e245e9a630982dc30164c532

14 files changed:
printathome/client.cpp
printathome/client.h
printathome/pah.cpp
printathome/printathome.pro
sesscli/scli.cpp
sesscli/scli.h
sessman/login.cpp
sessman/login.h
sessman/sman.cpp
sessman/sman.h
wob/classes/basics.wolf
wob/db/db.wolf
wob/db/order.wolf
wob/transact/order.wolf

index b00df10..d1f4a38 100644 (file)
 
 #include "client.h"
 
+#include "scli.h"
+
 #include <QFormLayout>
 #include <QBoxLayout>
 #include <QCheckBox>
 #include <QPushButton>
 #include <QComboBox>
+#include <QSpinBox>
+#include <QLineEdit>
+#include <QSettings>
 
 #define GROUP "PrintAtHome/Client"
 #define TIMER GROUP "/timermin"
 
 
 MPClientConfig::MPClientConfig(QWidget* parent)
+:QDialog(parent)
 {
+       setWindowTitle(tr("Print@Home Client Configuration"));
        QVBoxLayout*vl;
        setLayout(vl=new QVBoxLayout);
        QFormLayout*fl;
        vl->addLayout(fl=new QFormLayout);
+       //check Interval
        fl->addRow(tr("Check Interval in Minutes:"),mtimer=new QSpinBox);
        mtimer->setRange(1,10080);
        mtimer->setValue(timerInMinutes());
+       //profile
        fl->addRow("",msetprofile=new QCheckBox(tr("Preselect Profile")));
        fl->addRow(tr("Profile:"),mprofile=new QComboBox);
        connect(msetprofile,SIGNAL(clicked(bool)),mprofile,SLOT(setEnabled(bool)));
        msetprofile->setChecked(preselectProfile());
-       //TODO: get profile names
+       //get profile names
+       auto prfs=MSessionClient::instance()->profiles();
+       const QString cprf=preselectedProfileId();
+       int cprfn=-1;
+       for(auto prf:prfs){
+               if(prf.first==cprf)cprfn=mprofile->count();
+               mprofile->addItem(prf.second,prf.first);
+       }
+       mprofile->setCurrentIndex(cprfn);
+       //user
+       fl->addRow("",msetuser=new QCheckBox(tr("Set User Name")));
+       fl->addRow(tr("User Name:"),musername=new QLineEdit);
+       musername->setText(preselectedUserName());
+       connect(msetuser,SIGNAL(clicked(bool)),musername,SLOT(setEnabled(bool)));
+       msetuser->setChecked(preselectUser());
+       //password
+       fl->addRow("",mautologin=new QCheckBox(tr("Auto-Login")));
+       fl->addRow(tr("Password:"),mpassword=new QLineEdit);
+       connect(mautologin,SIGNAL(clicked(bool)),mpassword,SLOT(setEnabled(bool)));
+       mautologin->setChecked(autoLogin());
+       mpassword->setEchoMode(QLineEdit::Password);
+       mpassword->setText(password());
+       
+       vl->addSpacing(15);
+       QHBoxLayout*hl;
+       vl->addLayout(hl=new QHBoxLayout);
+       hl->addStretch(1);
+       QPushButton*p;
+       hl->addWidget(p=new QPushButton(tr("&OK")));
+       connect(p,SIGNAL(clicked()),this,SLOT(save()),Qt::DirectConnection);
+       connect(p,SIGNAL(clicked()),this,SLOT(accept()),Qt::QueuedConnection);
+       hl->addWidget(p=new QPushButton(tr("&Cancel")));
+       connect(p,SIGNAL(clicked()),this,SLOT(reject()));
        
 }
 
+//note: this is NOT an encryption algorithm - it merely masks against accidental reading, it is trivial to reverse
+static inline QByteArray maskPwd(QString pwd)
+{
+       QByteArray r=pwd.toUtf8();
+       int m=0x58;
+       for(int i=0;i<r.size();i++){
+               r[i]=r[i]^(char)m;
+               m++;
+       }
+       return r.toBase64();
+}
+
+//note 2: this is how trivial it is...
+// maybe we should use TRIPLE-rot13? ;-)
+static inline QString unmaskPwd(QByteArray ms)
+{
+       ms=QByteArray::fromBase64(ms);
+       int m=0x58;
+       for(int i=0;i<ms.size();i++){
+               ms[i]=ms[i]^(char)m;
+               m++;
+       }
+       return QString::fromUtf8(ms);
+}
+
 void MPClientConfig::save()
 {
+       QSettings set;
+       set.setValue(SETPROFILE,msetprofile->isChecked());
+       set.setValue(TIMER,mtimer->value());
+       set.setValue(PROFILE,mprofile->currentData());
+       set.setValue(SETUSER,msetuser->isChecked());
+       set.setValue(USERNAME,musername->text());
+       set.setValue(AUTOLOGIN,mautologin->isChecked());
+       set.setValue(PASSWD,maskPwd(mpassword->text()));
+}
+
+bool MPClientConfig::preselectProfile()
+{
+       return QSettings().value(SETPROFILE,false).toBool();
+}
 
+int MPClientConfig::timerInMinutes()
+{
+       return QSettings().value(TIMER,60).toInt();
+}
+
+QString MPClientConfig::preselectedProfileId()
+{
+       return QSettings().value(PROFILE).toString();
+}
+
+bool MPClientConfig::preselectUser()
+{
+       return QSettings().value(SETUSER,false).toBool();
+}
+
+QString MPClientConfig::preselectedUserName()
+{
+       return QSettings().value(USERNAME).toString();
+}
+
+bool MPClientConfig::autoLogin()
+{
+       return QSettings().value(AUTOLOGIN,false).toBool();
+}
+
+QString MPClientConfig::password()
+{
+       return unmaskPwd(QSettings().value(PASSWD).toByteArray());
+}
+
+void MPClientConfig::performAutoLogin(MSessionClient&sc)
+{
+       sc.waitForReady();
+       if(preselectProfile())
+               sc.setProfile(preselectedProfileId());
+       if(preselectUser())
+               sc.login(preselectedUserName(),password(),autoLogin());
 }
index 993186b..4ab0a92 100644 (file)
 
 #include <QDialog>
 
+class QCheckBox;
+class QLineEdit;
+class QComboBox;
+class QSpinBox;
+class MSessionClient;
+
 class MPClientConfig:public QDialog
 {
        Q_OBJECT
@@ -23,18 +29,20 @@ public:
        
        static int timerInMinutes();
        static bool preselectProfile();
-       static QString preselectedProfileName();
+       static QString preselectedProfileId();
        static bool preselectUser();
        static QString preselectedUserName();
        static bool autoLogin();
        static QString password();
        
+       static void performAutoLogin(MSessionClient&);
+       
 public slots:
        void save();
        
 private:
        QSpinBox*mtimer;
-       QCheckBox*msetprofile,msetuser,mautologin;
+       QCheckBox*msetprofile,*msetuser,*mautologin;
        QLineEdit*musername,*mpassword;
        QComboBox*mprofile;
        
index 539b674..0874a3b 100644 (file)
@@ -16,6 +16,7 @@
 #include <WTransaction>
 
 #include "pah.h"
+#include "client.h"
 
 #include <QIcon>
 #include <QMenu>
@@ -64,7 +65,8 @@ void PrintIcon::setPrintMode(PrintMode m)
 
 void PrintIcon::clientConfig()
 {
-       
+       MPClientConfig cc;
+       cc.exec();
 }
 
 
@@ -79,11 +81,13 @@ int main(int argc,char**argv)
        
        //init
        app.initialize();
+       app.setQuitOnLastWindowClosed(false);
 
        //get session
        MSessionClient sc;
        sc.connect(&sc,SIGNAL(sessionLost()),&app,SLOT(quit()));
        sc.connect(&sc,SIGNAL(managerLost()),&app,SLOT(quit()));
+       MPClientConfig::performAutoLogin(sc);
        if(sc.waitForSessionAvailable()){
                WTransaction::setLogPrefix("P@H-T");
                MSInterface*ms=new MSInterface(sc.currentProfileId());
index d657e80..68806e3 100644 (file)
@@ -7,8 +7,8 @@ include(../iface/iface.pri)
 include(../commonlib/commonlib.pri)
 
 #sources
-SOURCES += pah.cpp
-HEADERS += pah.h
+SOURCES += pah.cpp client.cpp
+HEADERS += pah.h client.h
 
 RESOURCES += files.qrc
 
index ee0422c..6905450 100644 (file)
@@ -141,6 +141,18 @@ bool MSessionClient::waitForSessionAvailable()
        return !msid.isEmpty();
 }
 
+bool MSessionClient::waitForReady()
+{
+       if(!isConnected())return false;
+       if(misready)return true;
+       //wait for signal
+       QEventLoop loop;
+       connect(this,SIGNAL(readyReceived()),&loop,SLOT(quit()));
+       connect(this,SIGNAL(managerLost()),&loop,SLOT(quit()));
+       loop.exec();
+       return misready;
+}
+
 QList< QPair< QString, QString > > MSessionClient::menuEntries(bool force) const
 {
        if(!isConnected())return QList<QPair<QString,QString>>();
@@ -226,13 +238,13 @@ void MSessionClient::readSocket()
                        mdefaultprofile.clear();
                }else if(cmd=="haveprofile"){
                        const int pos=par.indexOf(' ');
-                       if(pos<2){
-                               qDebug()<<"Warning: received invalid haveprofile command. Ignoring it.";
+                       if(pos<1){
+                               qDebug()<<"Warning: received invalid haveprofile command. Ignoring it. Info Parameter: "<<par;
                                continue;
                        }
                        mprofiles.append(QPair<QString,QString>(par.left(pos),par.mid(pos+1)));
                }else if(cmd=="defaultprofile"){
-                       mdefaultprofile=par;
+                       mdefaultprofile=par.trimmed();
                }else if(cmd=="endprofiles"){
                        qDebug()<<"Received new list of profiles.";
                        emit profilesChanged();
@@ -242,6 +254,9 @@ void MSessionClient::readSocket()
                        emit sessionLost();
                }else if(cmd=="quit"){
                        socketLost();
+               }else if(cmd=="ready"){
+                       misready=true;
+                       emit readyReceived();
                }else
                        qDebug()<<"Warning: unknown session manager signal"<<cmd<<"encountered. Ignoring it.";
        }
@@ -259,11 +274,12 @@ void MSessionClient::setProfile(QString pn)
                msocket->write(QString("setprofile %1\n").arg(pn).toUtf8());
 }
 
-void MSessionClient::login(QString user,QString password)
+void MSessionClient::login(QString user,QString password,bool attemptLogin)
 {
        if(msocket && msocket->isOpen())
-               msocket->write(QString("setuser %1\nsetpasswd %2\nlogin\n")
+               msocket->write(QString("setuser %1\nsetpasswd %2\n%3")
                        .arg(user)
                        .arg(QString::fromLatin1(password.toUtf8().toBase64()))
+                       .arg(attemptLogin?"login\n":"")
                        .toUtf8());
 }
index f8e5e26..05846d7 100644 (file)
@@ -41,6 +41,9 @@ public:
        ///Wait until a session is available or the Session Manager quits.
        ///\returns true if a session is available, false on error
        virtual bool waitForSessionAvailable();
+       
+       ///Wait until the session manager is ready to receive commands.
+       virtual bool waitForReady();
 
        ///Returns true if there currently is a session available.
        virtual bool sessionIsAvailable()const;
@@ -67,7 +70,7 @@ public:
 public slots:
        void execServerCommand(QString);
        void setProfile(QString);
-       void login(QString user,QString password);
+       void login(QString user,QString password,bool attemptLogin=true);
 
 signals:
        void sessionIdChanged(QString sessionId);
@@ -75,6 +78,7 @@ signals:
        void managerLost();
        void menuChanged();
        void profilesChanged();
+       void readyReceived();
 
 private slots:
        void socketLost();
@@ -84,6 +88,7 @@ private:
        QLocalSocket*msocket=nullptr;
        QString msid,mprofile,muser,mdefaultprofile;
        QList<QPair<QString,QString>> mmenu,mprofiles;
+       bool misready=false;
 };
 
 
index 6c22591..958107a 100644 (file)
@@ -229,6 +229,24 @@ void MLogin::relogin()
                emit lostSession();
 }
 
+void MLogin::setProfile(QString p)
+{
+       bool ok;
+       int n=p.toInt(&ok);
+       if(!ok)return;
+       profiles->setCurrentIndex(n);
+}
+
+void MLogin::setUsername(QString u)
+{
+       username->setText(u);
+}
+
+void MLogin::setPassword(QString pw)
+{
+       password->setText(pw);
+}
+
 void MLogin::clientConfig()
 {
        MClientConfig cc(this);
index 5527ea9..eb2b9b3 100644 (file)
@@ -45,13 +45,16 @@ class MLogin:public QWidget
        private slots:
                void initProfiles();
                void loadProfile();
-               void startLogin();
                void initClients(MSessionManager*);
 
        public slots:
                void configwin();
                void relogin();
                void clientConfig();
+               void setProfile(QString);
+               void setUsername(QString);
+               void setPassword(QString);
+               void startLogin();
 
        signals:
                void loginSucceeded();
index 40bf458..e930908 100644 (file)
@@ -171,6 +171,7 @@ void MSessionManager::newConnection()
                connect(s,SIGNAL(error(QLocalSocket::LocalSocketError)),this,SLOT(socketClosed()));
                connect(s,SIGNAL(destroyed(QObject*)),this,SLOT(socketLost(QObject*)));
                mconnections.append(s);
+               if(misready)s->write("ready\n");
        }
 }
 
@@ -351,6 +352,14 @@ void MSessionManager::loginLost()
                s->write("closed\n");
 }
 
+void MSessionManager::setReady()
+{
+       if(misready)return;
+       misready=true;
+       for(QLocalSocket*s:mconnections)
+               s->write("ready\n");
+}
+
 QList<QPair< QString, QString >> MSessionManager::menuItems() const
 {
        static QList<QPair<QString,QString>> items;
@@ -383,7 +392,13 @@ int main(int ac,char**av)
        lw.connect(&lw,SIGNAL(loginSucceeded()),sm,SLOT(loginSucceeded()));
        lw.connect(&lw,SIGNAL(lostSession()),sm,SLOT(loginLost()));
        lw.connect(sm,SIGNAL(openConfig()),&lw,SLOT(configwin()));
+       lw.connect(sm,SIGNAL(setProfile(QString)),&lw,SLOT(setProfile(QString)));
+       lw.connect(sm,SIGNAL(setUsername(QString)),&lw,SLOT(setUsername(QString)));
+       lw.connect(sm,SIGNAL(setPassword(QString)),&lw,SLOT(setPassword(QString)));
+       lw.connect(sm,SIGNAL(startLogin()),&lw,SLOT(startLogin()));
        lw.show();
+       
+       sm->setReady();
 
        return app.exec();
 }
index 1d82180..bbe4ffb 100644 (file)
@@ -43,6 +43,8 @@ public:
        virtual QList<QPair<QString,QString>> menuItems()const;
 
        static MSessionManager*instance();
+       
+       void setReady();
 
 private slots:
        void newConnection();
@@ -70,6 +72,7 @@ private:
        QString mkey;
        QSystemTrayIcon*micon;
        bool mhaveslave=false;
+       bool misready=false;
 
        void sendMenu(QLocalSocket*);
        void sendProfiles(QLocalSocket*);
index ef5e9c2..47ba998 100644 (file)
                <Property name="timezone" type="astring">Olsen database time zone name</Property>
                <!-- <Property name="TZtransitions" type="List:TimeTransition">list of all precalculated transitions in this timezone, how far into the future calculations go depends on the server, usually at the moment till 2037</Property> -->
        </Class>
+       
+       <Class name="KeyValuePair">
+               <Property name="key" type="string"/>
+               <Property name="value" type="string"/>
+               <Property name="isnull" type="bool"/>
+       </Class>
 </Wolf>
index 6cd70be..ce017b5 100644 (file)
@@ -9,7 +9,7 @@
        <DataBase
                instance="db" schema="dbScheme" defaultUpdating="yes"
                configTable="config" configKeyColumn="ckey" configValueColumn="cval"
-               version="01.07" versionRow="MagicSmokeVersion">
+               version="01.08" versionRow="MagicSmokeVersion">
                <AuditTables>
                        <Column name="audittime" type="int64">Time at which the change was made.
                                <Call lang="php" method="time()"/>
index d07e5df..a79aebd 100644 (file)
                <Doc>Documents that refer to a specific order. E.g. invoices, Print@Home tickets, etc.</Doc>
                <Column name="fileid" type="seq64" primarykey="yes"/>
                <Column name="orderid" type="int32" foreignkey="order:orderid" notnull="yes"/>
-               <Column name="filename" type="string" notnull="yes"/>
+               <Column name="filename" type="string" notnull="yes">
+                       The file name shown to the customer, not necessarily related to the template.
+               </Column>
                <Column name="mtime" type="int64" notnull="yes">The time when the file was last modified.</Column>
+               <Column name="rtime" type="int64" notnull="no">The time when the file was last retrieved by the customer.</Column>
                <Column name="content" type="blob"/>
+               <Column name="visible" type="bool" notnull="yes">
+                       Flag whether the document is internal to the theater (false) or visible to the customer (true).
+               </Column>
                <Unique>orderid,filename</Unique>
        </Table>
 </Wolf>
index 52dff6d..d55d46d 100644 (file)
                <Call lang="php" method="WOOrder::getOrderDocument($this);"/>
                <Output>
                        <Var name="content" type="blob"/>
+                       <Var name="visible" type="bool"/>
+                       <Var name="mtime" type="int64"/>
+                       <Var name="rtime" type="int64"/>
                </Output>
        </Transaction>
        <Transaction name="SetOrderDocument" update="yes">
                        <Var name="orderid" type="int"/>
                        <Var name="filename" type="string"/>
                        <Var name="content" type="blob"/>
+                       <Var name="visible" type="bool"/>
                </Input>
                <Call lang="php" method="WOOrder::getOrderDocument($this);"/>
                <Output/>
                </Input>
                <Call lang="php" method=";"/><!-- TODO -->
                <Output/>
+       </Transaction>  
+       
+       <Transaction name="GetPrintAtHomeSettings" update="no">
+               <Doc>Gets all settings pertaining to Print@Home</Doc>
+               <Input/>
+               <Call lang="php" method=";"/><!-- TODO -->
+               <Output>
+                       <Var name="settings" type="List:KeyValuePair"/>
+               </Output>
+       </Transaction>
+       <Transaction name="SetPrintAtHomeSettings" update="yes">
+               <Doc>Overrides settings for Print@Home, use isnull=true to delete entries.</Doc>
+               <Input>
+                       <Var name="settings" type="List:KeyValuePair"/>
+               </Input>
+               <Call lang="php" method=";"/><!-- TODO -->
+               <Output/>
        </Transaction>
 </Wolf>