diff options
author | Itay Grudev <itay@mail.bg> | 2012-12-23 00:12:38 +0200 |
---|---|---|
committer | Itay Grudev <itay@mail.bg> | 2012-12-23 00:12:38 +0200 |
commit | 230b4ebe94400ac7af47731e5c2b965b0c5fb2da (patch) | |
tree | ad0b511cdff2023e0cabe0268986707efcc7b6ff | |
download | singleapplication-230b4ebe94400ac7af47731e5c2b965b0c5fb2da.tar.xz |
Add base files
-rw-r--r-- | .gitattributes | 22 | ||||
-rw-r--r-- | .gitignore | 163 | ||||
-rw-r--r-- | README.md | 0 | ||||
-rw-r--r-- | localserver.cpp | 129 | ||||
-rw-r--r-- | localserver.h | 37 | ||||
-rw-r--r-- | main.cpp | 11 | ||||
-rw-r--r-- | singleapplication.cpp | 61 | ||||
-rw-r--r-- | singleapplication.h | 33 |
8 files changed, 456 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ebd21a --- /dev/null +++ b/.gitignore @@ -0,0 +1,163 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/README.md diff --git a/localserver.cpp b/localserver.cpp new file mode 100644 index 0000000..f3adcb9 --- /dev/null +++ b/localserver.cpp @@ -0,0 +1,129 @@ +#include "localserver.h" + +#include <QFile> +#include <QStringList> + +/** + * @brief LocalServer::LocalServer + * Constructor + */ +LocalServer::LocalServer() +{ + +} + +/** + * @brief LocalServer::~LocalServer + * Destructor + */ +LocalServer::~LocalServer() +{ + server->close(); + for(int i = 0; i < clients.size(); ++i) + { + clients[i]->close(); + } +} + +/** + * ----------------------- + * QThread requred methods + * ----------------------- + */ + +/** + * @brief run + * Initiate the thread. + */ +void LocalServer::run() +{ + server = new QLocalServer(); + + QObject::connect(server, SIGNAL(newConnection()), this, SLOT(slotNewConnection())); + QObject::connect(this, SIGNAL(privateDataReceived(QString)), this, SLOT(slotOnData(QString))); + +#ifdef Q_OS_UNIX + // Make sure the temp address file is deleted + QFile address(QString("/tmp/" LOCAL_SERVER_NAME)); + if(address.exists()){ + address.remove(); + } +#endif + + QString serverName = QString(LOCAL_SERVER_NAME); + server->listen(serverName); + while(server->isListening() == false){ + server->listen(serverName); + msleep(100); + } + exec(); +} + +/** + * @brief LocalServer::exec + * Keeps the thread alive. Waits for incomming connections + */ +void LocalServer::exec() +{ + while(server->isListening()) + { + msleep(100); + server->waitForNewConnection(100); + for(int i = 0; i < clients.size(); ++i) + { + if(clients[i]->waitForReadyRead(100)){ + QByteArray data = clients[i]->readAll(); + emit privateDataReceived(data); + } + } + } +} + +/** + * ------- + * SLOTS + * ------- + */ + +/** + * @brief LocalServer::slotNewConnection + * Executed when a new connection is available + */ +void LocalServer::slotNewConnection() +{ + clients.push_front(server->nextPendingConnection()); +} + +/** + * @brief LocalServer::slotOnData + * Executed when data is received + * @param data + */ +void LocalServer::slotOnData(QString data) +{ + if(data.contains("CMD:", Qt::CaseInsensitive)){ + onSGC(data); + } else { + emit dataReceived(data); + } +} + +/** + * ------- + * Helper methods + * ------- + */ + +void LocalServer::onCMD(QString data) +{ + // Trim the leading part from the command + data.replace(0, 4, ""); + + QStringList commands; + commands << "showUp"; + + switch(commands.indexOf(data)){ + case 0: + emit showUp(); + } +} diff --git a/localserver.h b/localserver.h new file mode 100644 index 0000000..92c9bb1 --- /dev/null +++ b/localserver.h @@ -0,0 +1,37 @@ +#ifndef LOCALSERVER_H +#define LOCALSERVER_H + +#include <QThread> +#include <QVector> +#include <QLocalServer> +#include <QLocalSocket> + +class LocalServer : public QThread +{ + Q_OBJECT +public: + LocalServer(); + ~LocalServer(); + void shut(); + +protected: + void run(); + void exec(); + +signals: + void dataReceived(QString data); + void privateDataReceived(QString data); + void showUp(); + +private slots: + void slotNewConnection(); + void slotOnData(QString data); + +private: + QLocalServer* server; + QVector<QLocalSocket*> clients; + void onCMD(QString data); + +}; + +#endif // LOCALSERVER_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..101534f --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "singleapplication.h" + +int main(int argc, char *argv[]) +{ + SingleApplication app(argc, argv); + + // Is another instance of the program is already running + if(!app.shouldContinue())return 0; + + return app.exec(); +} diff --git a/singleapplication.cpp b/singleapplication.cpp new file mode 100644 index 0000000..7e63371 --- /dev/null +++ b/singleapplication.cpp @@ -0,0 +1,61 @@ +#include "singleapplication.h" + +/** + * @brief SingleApplication::SingleApplication + * Constructor. Checks and fires up LocalServer or closes the program + * if another instance already exists + * @param argc + * @param argv + */ +SingleApplication::SingleApplication(int argc, char *argv[]) : + QGuiApplication(argc, argv) +{ + _shouldContinue = false; // By default this is not the main process + + socket = new QLocalSocket(); + + // Attempt to connect to the LocalServer + socket->connectToServer(LOCAL_SERVER_NAME); + if(socket->waitForConnected(100)){ + socket->write("CMD:showUp"); + socket->flush(); + QThread::msleep(100); + socket->close(); + } else { + // The attempt was insuccessful, so we continue the program + _shouldContinue = true; + server = new LocalServer(); + server->start(); + QObject::connect(server, SIGNAL(showUp()), this, SLOT(slotShowUp())); + } +} + +/** + * @brief SingleApplication::~SingleApplication + * Destructor + */ +Application::~SingleApplication() +{ + if(_shouldContinue){ + server->terminate(); + } +} + +/** + * @brief SingleApplication::shouldContinue + * Weather the program should be terminated + * @return bool + */ +bool SingleApplication::shouldContinue() +{ + return _shouldContinue; +} + +/** + * @brief SingleApplication::slotShowUp + * Executed when the showUp command is sent to LocalServer + */ +void SingleApplication::slotShowUp() +{ + emit showUp(); +} diff --git a/singleapplication.h b/singleapplication.h new file mode 100644 index 0000000..03ac69c --- /dev/null +++ b/singleapplication.h @@ -0,0 +1,33 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include "localserver.h" + +#include <QGuiApplication> +#include <QLocalSocket> + +/** + * @brief The Application class handles trivial application initialization procedures + */ +class SingleApplication : public QGuiApplication +{ + Q_OBJECT +public: + explicit SingleApplication(int, char *[]); + ~SingleApplication(); + bool shouldContinue(); + +signals: + void showUp(); + +private slots: + void slotShowUp(); + +private: + QLocalSocket* socket; + LocalServer* server; + bool _shouldContinue; + +}; + +#endif // APPLICATION_H |