|
|
#include "QSignleApplication.h"
|
|
|
|
|
|
#include <QMainWindow>
|
|
|
#include <QtNetwork/QLocalServer>
|
|
|
#include <QtNetwork/QLocalSocket>
|
|
|
#include <QFileInfo>
|
|
|
#include <QMessageBox>
|
|
|
#pragma execution_character_set("utf-8")
|
|
|
SingleApplication::SingleApplication(int &args, char **argv, QString strServerName) :
|
|
|
QApplication(args, argv),
|
|
|
instanceRunning(false),
|
|
|
localServer(NULL),
|
|
|
mainWindow(NULL)
|
|
|
{
|
|
|
/**
|
|
|
* 一般来说是取引用程序名作为 localServer 的进程服务名
|
|
|
* 目前程序的进程名是根据文件名来的,但是一旦用于更改了文件名,那么进程名就不准确了,
|
|
|
* 所以通过文件名来判断是进程服务是不可靠的,应该写死在代码里
|
|
|
*/
|
|
|
// serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
|
|
|
m_serverName = strServerName;
|
|
|
QString a = applicationName();
|
|
|
initLocalConnection();
|
|
|
}
|
|
|
|
|
|
void SingleApplication::initLocalConnection()
|
|
|
{
|
|
|
instanceRunning = false;
|
|
|
QLocalSocket socket;
|
|
|
//将套接字连接至进程服务,参数即为进程服务名
|
|
|
socket.connectToServer(m_serverName);
|
|
|
//若在500ms内连接至进程服务,说明进程服务已运行
|
|
|
if (socket.waitForConnected(500)) {
|
|
|
instanceRunning = true;
|
|
|
|
|
|
// 其他处理,如:将启动参数发送到进程服务端
|
|
|
QTextStream stream(&socket);
|
|
|
QStringList args = QCoreApplication::arguments();
|
|
|
if (args.count() > 1)
|
|
|
stream << args.last();
|
|
|
else
|
|
|
stream << QString();
|
|
|
stream.flush();
|
|
|
socket.waitForBytesWritten();
|
|
|
return;
|
|
|
}
|
|
|
newLocalServer();//连接不上进程服务器,就创建一个
|
|
|
}
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
// 说明:
|
|
|
// 创建LocalServer
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
void SingleApplication::newLocalServer()
|
|
|
{
|
|
|
localServer = new QLocalServer(this);
|
|
|
connect(localServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
|
|
|
if (!localServer->listen(m_serverName)) {
|
|
|
// 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除之
|
|
|
if (localServer->serverError() == QAbstractSocket::AddressInUseError) {
|
|
|
QLocalServer::removeServer(m_serverName); //移除进程服务
|
|
|
localServer->listen(m_serverName); //再次监听
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void SingleApplication::newLocalConnection()
|
|
|
{
|
|
|
//监听进程服务,当有数据进来时,可以通过 nextPendingConnection() 获取套接字
|
|
|
QLocalSocket *socket = localServer->nextPendingConnection();
|
|
|
if (!socket)
|
|
|
return;
|
|
|
socket->waitForReadyRead(1000);
|
|
|
//其他处理
|
|
|
QTextStream stream(socket);
|
|
|
delete socket;
|
|
|
if (mainWindow != NULL) {
|
|
|
//当主窗口对象不为空时,说明有可能主窗口被隐藏了,所以需要将其展示在桌面,同时给予用户提示
|
|
|
mainWindow->raise();
|
|
|
mainWindow->activateWindow();
|
|
|
mainWindow->setWindowState((mainWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
|
|
|
mainWindow->show();
|
|
|
//QMessageBox::warning(NULL, "警告", "程序已经启动!");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
// 说明:
|
|
|
// 检查是否已有一个实例在运行, true - 有实例运行, false - 没有实例运行
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
bool SingleApplication::getInstanceRunning() const
|
|
|
{
|
|
|
return instanceRunning;
|
|
|
}
|
|
|
|
|
|
QMainWindow *SingleApplication::getMainWindow() const
|
|
|
{
|
|
|
return mainWindow;
|
|
|
}
|
|
|
|
|
|
void SingleApplication::setMainWindow(QMainWindow *value)
|
|
|
{
|
|
|
mainWindow = value;
|
|
|
}
|
|
|
|