#include <QStringList>
#include <QTranslator>
#include <QUrl>
+#include <QtGlobal>
#include <TimeStamp>
#include <TZFile>
#include "hmac.h"
#include "keygen.h"
#include "mapplication.h"
-// #include "login.h"
#include "msinterface.h"
#include <ELAM/Engine>
#include "misc.h"
QDesktopServices::openUrl(u);
}
+#define ENV_DATADIR "MAGICSMOKE_DATADIR"
+#define ENV_CONFIGDIR "MAGICSMOKE_CONFIGDIR"
+
MApplication::MApplication(int&ac,char**av)
:QApplication(ac,av)
{
return new MProgressWrapperGui(label,button);
});
+ //check environment
+ if(qEnvironmentVariableIsSet(ENV_DATADIR))
+ setDataDir(QString::fromLocal8Bit(qgetenv(ENV_DATADIR)));
+ if(qEnvironmentVariableIsSet(ENV_CONFIGDIR))
+ setConfigDir(QString::fromLocal8Bit(qgetenv(ENV_CONFIGDIR)));
+
//check parameters
// qDebug()<<"arguments"<<arguments();
for(const QString& param:arguments()){
setDataDir(param.mid(9));
}
}
-
- //data directory
+
+ //data directory fallback
if(dataDir().isEmpty())
setDataDir("$BASE/.magicSmoke2");
}
const QString cdir=MSInterface::resolveDir(d);
QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,cdir);
qDebug()<<"Setting the config directory to"<<cdir<<"from"<<d;
+ qputenv(ENV_CONFIGDIR,d.toLocal8Bit());
}
void MApplication::setDataDir(QString d)
{
MSInterface::setAppDataDir(d);
+ qDebug()<<"Setting Data Directory to"<<d;
+ qputenv(ENV_DATADIR,d.toLocal8Bit());
}
initProfile();
//init help menu layout
initHelpUrl();
- //init updater
- initUpdater();
- //init plugins
- MBarcodeHub::instance()->initialize();
}
void MApplication::initUpdater()
void versionDlg();
///start a browser with the help page
void help();
+
+ ///initialize the updater
+ void initUpdater();
+
private slots:
///jump to a specific help page
void help(int);
///initialize the help menu from config files
void initHelpUrl();
- ///initialize the updater
- void initUpdater();
-
///updater is ready for download
void updateReadyDownload(const QString&);
///updater is ready for install
static QFile*mylogFile=0;
+
static void mymsghandler(QtMsgType,const QMessageLogContext&, const QString&msg)
{
if(mylogFile){
- mylogFile->write(msg.toLatin1());
- mylogFile->write("\n",1);
+ QByteArray data=
+ QDateTime::currentDateTime().toString("yyyy-MM-dd hh.mm.ss.zzz").toLatin1() +" "+
+ msg.toLatin1()+"\n";
+ mylogFile->write(data);
mylogFile->flush();
}
#ifdef Q_OS_UNIX
qDebug()<<"-nolog argument was given, will not create a log file";
}
//create new log file
+ QFileInfo appfi(qApp->applicationFilePath());
QDir(dataDir).mkpath("debuglog");
- mylogFile=new QFile(dataDir+"/debuglog/log-"+QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss.zzz")+".txt");
+ mylogFile=new QFile(dataDir+"/debuglog/"+appfi.baseName()+"-"+QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss.zzz")+".log");
//...open it
if(mylogFile->open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)){
//install as default log
mylogFile=0;
qDebug("Failed to install debuglog.");
}
+ qDebug()<<"Log file opened by"<<appfi.absoluteFilePath();
//delete old logs (older than 30 days)
QStringList fll=QDir(dataDir+"/debuglog").entryList(QDir::Files);
QDateTime old=QDateTime::currentDateTime().addDays(-30);
#include "login.h"
#include "msinterface.h"
#include "configdialog.h"
+#include "sman.h"
#include <QApplication>
#include <QByteArray>
#include <QSizeGrip>
#include <QProgressDialog>
-MLogin::MLogin()
+MLogin::MLogin(MSessionManager*sm)
{
setWindowTitle(tr("Magic Smoke Login"));
setWindowFlags(windowFlags()|Qt::Window|Qt::Dialog);
lab->setAlignment(Qt::AlignRight);
gl->addWidget(profiles=new QComboBox,lctr,1);
connect(profiles,SIGNAL(currentIndexChanged(int)),this,SLOT(loadProfile()));
+ gl->addWidget(lab=new QLabel(tr("Client:")),++lctr,0);
+ lab->setAlignment(Qt::AlignRight);
+ gl->addWidget(clients=new QComboBox,lctr,1);
gl->addWidget(lab=new QLabel(tr("Username:")),++lctr,0);
lab->setAlignment(Qt::AlignRight);
gl->addWidget(username=new QLineEdit,lctr,1);
resizer=new QSizeGrip(this);
connect(p,SIGNAL(clicked()),this,SLOT(startLogin()));
initProfiles();
+ initClients(sm);
loadProfile();
//react to Escape button
password->setFocus();
}
+#define LASTCLIENTSETTING "SessionManager/LastClient"
+void MLogin::initClients(MSessionManager*sm)
+{
+ QString last=QSettings().value(LASTCLIENTSETTING).toString().trimmed();
+ int pos=-1;
+ for(auto entry:sm->menuItems()){
+ if(!entry.first.startsWith('@'))continue;
+ if(last==entry.first)pos=clients->count();
+ clients->addItem(entry.second.replace("&",""),entry.first);
+ }
+ if(pos>=0)
+ clients->setCurrentIndex(pos);
+ connect(clients,static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, [this]{QSettings().setValue(LASTCLIENTSETTING,clients->currentData());} );
+}
+
+QString MLogin::getCurrentClient() const
+{
+ return clients->currentData().toString();
+}
+
void MLogin::startLogin()
{
qDebug()<<"Logging in...";
class QLineEdit;
class QSizeGrip;
+class MSessionManager;
+
/**login and profile configuration window*/
class MLogin:public QWidget
{
Q_OBJECT
public:
- MLogin();
+ explicit MLogin(MSessionManager*);
+ QString getCurrentClient()const;
private:
QString sessionid;
QLineEdit*username,*password;
- QComboBox*profiles;
+ QComboBox*profiles,*clients;
QSizeGrip*resizer;
protected:
void initProfiles();
void loadProfile();
void startLogin();
- void configwin();
+ void initClients(MSessionManager*);
public slots:
+ void configwin();
void relogin();
signals:
//
+#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>
+#include <QMenu>
#include <QMessageBox>
-#include <QSystemTrayIcon>
#include <QProcess>
+#include <QSignalMapper>
+#include <QSystemTrayIcon>
+#include <QTimer>
#include "sman.h"
#include "login.h"
#include "../sesscli/scrand.h"
#include <msinterface.h>
+#include <mapplication.h>
#include <WTransaction>
+static QPointer<MLogin> loginwindow;
+
MSessionManager::MSessionManager ( QObject* parent ) : QObject ( parent )
{
// create socket
//create systray icon
micon=new QSystemTrayIcon(QIcon(":/icon.png"),this);
micon->setToolTip(tr("MagicSmoke Session Manager, waiting for login..."));
+ QMenu*m=new QMenu;
+ QSignalMapper*sm=new QSignalMapper(m);
+ for(auto entry:menuItems()){
+ QAction*a=m->addAction(entry.second);
+ sm->setMapping(a,entry.first);
+ connect(a,SIGNAL(triggered()),sm,SLOT(map()));
+ }
+ connect(sm,SIGNAL(mapped(QString)),this,SLOT(execCmd(QString)));
+ micon->setContextMenu(m);
micon->show();
}
}else if(cmd=="getmenu")
sendMenu(s);
else if(cmd=="exec")
- execCmd(par);
+ execCmd(par.trimmed());
else
qDebug()<<"Warning: unknown client command"<<cmd;
}
void MSessionManager::sendMenu(QLocalSocket*s)
{
s->write("newmenu\n");
- //TODO: send "menu command entry-text" for each entry
+ //send "menu command entry-text" for each entry
+ for(auto entry:menuItems())
+ s->write(QString("menu %1 %2\n").arg(entry.first).arg(entry.second).toUtf8());
s->write("endmenu\n");
}
-void MSessionManager::execCmd ( QString cmd)
+void MSessionManager::execCmd (const QString &cmd)
{
- qDebug()<<"I wish I knew how to execute"<<cmd;
- QProcess *p=new QProcess;
+ qDebug()<<"Received command"<<cmd;
+ if(cmd=="config"){
+ emit openConfig();
+ }else if(cmd=="quit"){
+ qDebug()<<"Sending QUIT command to all clients and exiting!";
+ for(auto c:mconnections){
+ c->write("quit\n");
+ c->flush();
+ }
+ QTimer::singleShot(1000,qApp,SLOT(quit()));
+ }else if(cmd.startsWith("@")){
+ QString bin=(cmd=="@@main")?QString():"-"+cmd.mid(1);
+ startBinary(bin);
+ }else
+ qDebug()<<"I wish I knew how to execute"<<cmd<<"but it does not seem to exist.";
+}
+
+void MSessionManager::startBinary ( QString bin )
+{
+ if(!hasSession()){
+ QMessageBox::warning(nullptr,tr("Warning"),tr("Cannot start a client while not logged in!"));
+ return;
+ }
+ QProcess *p=new QProcess(this);
p->setProcessChannelMode(QProcess::ForwardedChannels);
- p->start(qApp->applicationDirPath()+"/magicsmoke",QStringList()<<"-sms:"+mkey);
+ connect(p,SIGNAL(finished(int,QProcess::ExitStatus)), this,SLOT(processLost(int,QProcess::ExitStatus)));
+ QString binname=qApp->applicationDirPath()+"/magicsmoke"+bin;
+ p->start(binname,QStringList()<<"-sms:"+mkey);
+ qDebug()<<"starting MagicSmoke client binary"<<binname;
+ if(!p->waitForStarted(5000)){
+ qDebug()<<"Error: binary does not start!"<<p->errorString();
+ delete p;
+ return;
+ }
+ qDebug()<<"Started"<<binname<<"as PID"<<p->processId();
+}
+
+void MSessionManager::processLost ( int exitCode, QProcess::ExitStatus exitStatus)
+{
+ QProcess *p=qobject_cast<QProcess*>(sender());
+ qDebug()<<"Process exited with status"<<exitCode<<"and status" <<(exitStatus==QProcess::NormalExit?"normal exit":"crash!");
+ if(p){
+ qDebug()<<" ...process was a"<<p->program();
+ qDebug()<<" ...Last Error reads"<<p->errorString();
+ p->deleteLater();
+ }
}
+
void MSessionManager::loginSucceeded()
{
micon->setToolTip(tr("MagicSmoke Session Manager, logged in as %1 at %2.").arg(username()).arg(profileName()));
if(mconnections.count()>0)
sendNewSessionId();
else
- execCmd("msmoke");
+ execCmd(loginwindow->getCurrentClient());
}
void MSessionManager::sendNewSessionId()
s->write("closed\n");
}
-
-int main(int ac,char**av)
+QList<QPair< QString, QString >> MSessionManager::menuItems() const
{
- QApplication app(ac,av);
- //locate settings
- app.setOrganizationName("MagicSmoke");
- app.setApplicationName("MagicSmoke2");
-
- //set icon
- app.setWindowIcon(QIcon(":/icon.png"));
+ static QList<QPair<QString,QString>> items;
+ if(items.isEmpty()){
+ auto _ = [&](QString c,QString t){items.append(QPair<QString,QString>(c,t));};
+ _("config",tr("&Configuration..."));
+ _("@@main",tr("Start &Expert Client"));
+ _("@wizard",tr("Start &Wizard"));
+ _("@statistic",tr("Start &Statistics Client"));
+ _("@print",tr("Start &Print@Home Daemon"));
+ _("quit",tr("&Quit Session"));
+ }
+ return items;
+}
- MSInterface::setAppDataDir("$BASE/.magicSmoke2");
- WTransaction::setLogPrefix("SM-T");
- MBoxWrapper::setWarning([](QString title,QString text){QMessageBox::warning(nullptr,title,text);});
+int main(int ac,char**av)
+{
+ MApplication app(ac,av);
+ WTransaction::setLogPrefix("SM-T");
+ app.initialize();
+ //init updater
+ app.initUpdater();
MSessionManager *sm=new MSessionManager(&app);
- MLogin lw;
+ MLogin lw(sm);
+ loginwindow=&lw;
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.show();
return app.exec();
#include <QObject>
#include <QList>
+#include <QPair>
+#include <QProcess>
class QLocalServer;
class QLocalSocket;
virtual QString profile()const;
virtual QString profileName()const;
+ virtual QList<QPair<QString,QString>> menuItems()const;
+
private slots:
void newConnection();
void readyRead();
void socketClosed();
void socketLost(QObject*);
+ void execCmd(const QString&);
+
void loginSucceeded();
void sendNewSessionId();
void loginLost();
+ void processLost(int,QProcess::ExitStatus);
+
+signals:
+ void openConfig();
+
private:
QLocalServer*mserver=nullptr;
QList<QLocalSocket*>mconnections;
QSystemTrayIcon*micon;
void sendMenu(QLocalSocket*);
- void execCmd(QString);
void sendSessionInfo(QLocalSocket*);
+ void startBinary(QString);
};
#include "main.h"
#include <WTransaction>
+#include "barcode-plugin.h"
int MagicSmokeMain::realmain(int argc,char**argv)
//init
app.initialize();
+ //init plugins
+ MBarcodeHub::instance()->initialize();
+
+ //get session
MSessionClient sc;
sc.connect(&sc,SIGNAL(sessionLost()),&app,SLOT(quit()));
sc.connect(&sc,SIGNAL(managerLost()),&app,SLOT(quit()));