#include <QPixmap>
#include <QStringList>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextStream>
#include "SciQApp.h"
#include "SciQMW.h"
#include "SciQSettingsDialog.h"
#include "SciQDockWindow.h"
#include "SciQDockWindowFactory.h"
#include "SciQUtil.h"
#include "SciQX11TrayIcon.h"
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#define LISTENPORT 12343
/*
Ok, wow, this needs to be changed to use a unix socket or something similar, possibly shared mem.
also, flock() could be handy.
*/
SciQApp::SciQApp(int &argc, char **argv) : QApplication(argc, argv), qs(this)
{
QApplication::setOrganizationName("StrangeSoft");
QApplication::setOrganizationDomain("strangesoft.net");
QApplication::setApplicationName("SciQ");
initResourcePath();
qDebug("%s: init", __PRETTY_FUNCTION__);
#if 0
sigset_t set, oset;
switch (fork()) {
case -1:
/* Something bad happened */
exit(1);
case 0:
qDebug("in child!\n");
/* We're in the child */
break;
default:
/* Allow SIGTERM from child to wake us up */
sigdelset(&set, SIGTERM);
sigsuspend(&set);
::exit(0);
}
qDebug("before setsid!\n");
if (setsid() == -1)
::_exit(2);
signal(SIGCHLD,SIG_IGN); /* ignore child */
signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
#endif
qDebug("Create TcpSocket!");
sock = new QTcpSocket(this);
connect(sock, SIGNAL(connected()), this, SLOT(connected()));
sock->connectToHost(QHostAddress::LocalHost, LISTENPORT);
if(sock->waitForConnected(1000))
::exit(0);
qDebug("Create TcpServer!");
sess = new QTcpServer(this);
if(!sess->listen(QHostAddress::LocalHost, LISTENPORT)) {
qDebug("failed to startup session server");
::exit(0);
}
connect(sess, SIGNAL(newConnection()), this, SLOT(newConnection()));
qDebug("%s: continue.", __PRETTY_FUNCTION__);
instance = this; // hack ::)
mw = new SciQMW();
//mw->QObject::setParent(this);
mw->show();
sd = ::SciQSettingsDialog::getInstance();
//tray = new SciQX11TrayIcon(mw);
//tray->show();
}
SciQApp::~SciQApp()
{
//tray->hide();
delete mw;
instance = 0;
}
QIcon SciQApp::getIcon(QString name)
{
return findResource<QPixmap>(QString("images/%1.png").arg(name));
}
void SciQApp::newConnection()
{
QTcpSocket *nsock = sess->nextPendingConnection();
QTextStream txt(nsock);
int avail = nsock->bytesAvailable();
qDebug("%s", __PRETTY_FUNCTION__);
nsock->waitForReadyRead();
//if(avail) {
QString line = txt.readLine();
if(line != "SciQ4") {
qDebug("invalid connection sequence: '%s'", qPrintable(line));
nsock->abort();
return;
}
qDebug("got: '%s'", qPrintable(line));
// }
txt << "SciQ4" << endl;
nsock->waitForBytesWritten();
nsock->waitForReadyRead();
int len = 0;
txt >> len;
for(int i=0; i<len; ++i) {
if(nsock->isValid())
nsock->waitForReadyRead();
QString str = txt.readLine();
printf("got: '%s'/'%s'", qPrintable(str), qPrintable(str.section(QString(1, QChar('\0')), 1, -1)));
}
nsock->close();
}
void SciQApp::connected()
{
qDebug("%s", __PRETTY_FUNCTION__);
QTextStream txt(sock);
txt << "SciQ4" << endl;
sock->waitForBytesWritten();
sock->waitForReadyRead();
QString line = txt.readLine();
if(line != "SciQ4") {
qDebug("invalid connect reply sequence: '%s'", qPrintable(line));
sock->abort();
return;
}
qDebug("got: '%s'", qPrintable(line));
txt << argc()-1;
sock->waitForBytesWritten();
qDebug("writing %i elements", argc()-1);
if(argc() > 1) {
char **av = argv();
for(int i=1; i<argc(); ++i) {
QChar ch[5] = { 'O', 'P', 'E', 'N', '\0' };
txt << QString(ch, 5);
txt << av[i] << endl;
if(sock->isValid())
sock->waitForBytesWritten();
}
}
sock->close();
::exit(0);
}
SciQApp *SciQApp::getInstance(int argc, char **argv)
{
if(!instance) {
if(!argv) {
argv = _argv;
argc = _argc;
} else {
_argv = argv;
_argc = argc;
}
instance = new SciQApp(argc, argv);
qDebug("!instance: %p", instance);
}
return instance;
}
SciQDockWindow *SciQApp::getDockWindowInstance(QString &s, SciQMWBase *mw)
{
SciQDockWindowFactory *dwf = 0;
SciQDockWindow *dw = 0;
if(dockhash.contains(s)) {
dwf = dockhash.value(s);
dw = dwf->createInstance(mw);
}
return dw;
}
QString SciQApp::Sequence(QString o) {
static QHash<QString, int> map;
int num = map[o];
QString seq = o + QString().sprintf("%i", num);
// printf("Creating new unique sequence: '%s'\n", qPrintable(seq));
num++;
map[o] = num;
return seq;
}
void SciQApp::addResourcePath(QString p)
{
qDebug("%s: %s", __PRETTY_FUNCTION__, qPrintable(p));
QDir().mkpath(p);
resourcePath << p;
}
QString SciQApp::getResourcePath(QString p)
{
for(int i = 0; i < resourcePath.count(); ++i) {
QString tmp = catdir(QStringList() + resourcePath.at(i) + p);
if(QFile::exists(tmp)) {
// qDebug("%s: %s", __PRETTY_FUNCTION__, qPrintable(tmp));
return tmp;
}
}
// scan resources last
QString tmp = catdir(QStringList() + QString(":/") + p);
if(QFile::exists(tmp)) {
// qDebug("%s: %s", __PRETTY_FUNCTION__, qPrintable(tmp));
return tmp;
}
return QDir().absoluteFilePath(p);
}
// this sets up the unix and windows default search paths
void SciQApp::initResourcePath() {
QString tmp;
#ifdef Q_OS_UNIX
// add /home/user/.SciQ
tmp = catdir(QStringList() + QDir::homePath() + QString(".%1").arg(applicationName()));
addResourcePath(tmp);
// add /usr/share/SciQ
tmp = catdir(QStringList() + QDir::rootPath() + "usr" + "share" + applicationName());
addResourcePath(tmp);
#elif defined Q_OS_WIN32
// This win32 code hasn't been tested...
char szPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath)))
/*
CSIDL_APPDATA
The file system directory that serves as a common repository for application-specific data.
A typical path is C:\Documents and Settings\username\Application Data.
I chose to try this before the code in the "else" clause,
because who knows if the folder is really "Application Data",
as I assume below.
*/
tmp = catdir(QStringList() + szPath + applicationName());
else
tmp = catdir(QStringList() + QDir::homePath() + "Application Data" + applicationName());
addResourcePath(tmp);
QString def = catdir(QStringList() + QDir::rootPath() + "Program Files" + applicationName());
// if the installer saved a "installpath" var... if not, just assume %ROOT%\Program Files\SciQ
addResourcePath(qs.value("installpath", def).toString());
#endif
// And for good measure, add %TEMP%/SciQ
tmp = catdir(QStringList() + QDir::tempPath() + applicationName());
addResourcePath(tmp);
}
SciQWorkspace *SciQApp::newWorkspace(QString path)
{
}
SciQApp *SciQApp::instance = 0;
QStringList SciQApp::resourcePath;
int SciQApp::_argc = 0;
char **SciQApp::_argv = 0;