mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-13 20:23:04 +02:00
L'application se lance desormais une seule fois par utilisateur
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@348 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
parent
f4b828a3cd
commit
429d7e55a2
@ -76,6 +76,7 @@ HEADERS += aboutqet.h \
|
||||
qet.h \
|
||||
qetapp.h \
|
||||
qetdiagrameditor.h \
|
||||
qetsingleapplication.h \
|
||||
qgimanager.h \
|
||||
terminal.h \
|
||||
editor/arceditor.h \
|
||||
@ -142,6 +143,7 @@ SOURCES += aboutqet.cpp \
|
||||
qet.cpp \
|
||||
qetapp.cpp \
|
||||
qetdiagrameditor.cpp \
|
||||
qetsingleapplication.cpp \
|
||||
qgimanager.cpp \
|
||||
terminal.cpp \
|
||||
editor/arceditor.cpp \
|
||||
@ -171,7 +173,7 @@ SOURCES += aboutqet.cpp \
|
||||
RESOURCES += qelectrotech.qrc
|
||||
TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts
|
||||
RC_FILE = ico/windows_icon/application_icon/qelectrotech.rc
|
||||
QT += xml svg
|
||||
QT += xml svg network
|
||||
CONFIG += debug_and_release warn_on
|
||||
TARGET = qelectrotech
|
||||
|
||||
|
141
qetapp.cpp
141
qetapp.cpp
@ -32,13 +32,37 @@ QString QETApp::diagram_texts_font = QString();
|
||||
@param argc Nombre d'arguments passes a l'application
|
||||
@param argv Arguments passes a l'application
|
||||
*/
|
||||
QETApp::QETApp(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
QETApp::QETApp(int &argc, char **argv) :
|
||||
QETSingleApplication(argc, argv, QString("qelectrotech-" + QETApp::userName()))
|
||||
{
|
||||
// selectionne le langage du systeme
|
||||
QString system_language = QLocale::system().name().left(2);
|
||||
setLanguage(system_language);
|
||||
|
||||
// parse les arguments
|
||||
foreach(QString argument, arguments()) {
|
||||
// booleen indiquant si l'application va se terminer immediatement apres un court traitement
|
||||
bool must_exit = false;
|
||||
|
||||
// parse les arguments en
|
||||
QStringList files; // liste des fichiers
|
||||
QStringList options; // liste des options
|
||||
|
||||
// recupere les arguments
|
||||
QStringList arguments_list(arguments());
|
||||
arguments_list.pop_front(); // ignore le premier (= chemin de l'executable)
|
||||
|
||||
// separe les fichiers des options
|
||||
foreach(QString argument, arguments_list) {
|
||||
QFileInfo argument_info(argument);
|
||||
if (argument_info.exists()) {
|
||||
// on exprime les chemins des fichiers en absolu
|
||||
files << argument_info.canonicalFilePath();
|
||||
} else {
|
||||
options << argument;
|
||||
}
|
||||
}
|
||||
|
||||
// parse les options
|
||||
foreach(QString argument, options) {
|
||||
#ifdef QET_ALLOW_OVERRIDE_CED_OPTION
|
||||
QString ced_arg("--common-elements-dir=");
|
||||
if (argument.startsWith(ced_arg)) {
|
||||
@ -53,7 +77,7 @@ QETApp::QETApp(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
overrideConfigDir(cd_value);
|
||||
}
|
||||
#endif
|
||||
bool must_exit = false;
|
||||
|
||||
if (argument == QString("--help")) {
|
||||
printHelp();
|
||||
must_exit = true;
|
||||
@ -64,11 +88,23 @@ QETApp::QETApp(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
printLicense();
|
||||
must_exit = true;
|
||||
}
|
||||
if (must_exit) {
|
||||
std::exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!must_exit && isRunning()) {
|
||||
QStringList abs_arg_list(options);
|
||||
abs_arg_list << files;
|
||||
|
||||
// envoie les arguments a l'instance deja existante
|
||||
must_exit = sendMessage("launched-with-args: " + abs_arg_list.join(" "));
|
||||
}
|
||||
|
||||
if (must_exit) {
|
||||
std::exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// prise en compte des messages des autres instances
|
||||
connect(this, SIGNAL(messageAvailable(QString)), this, SLOT(messageReceived(const QString&)));
|
||||
|
||||
// nettoyage avant de quitter l'application
|
||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
|
||||
|
||||
@ -125,10 +161,6 @@ QETApp::QETApp(int &argc, char **argv) : QApplication(argc, argv) {
|
||||
diagram_texts_font = qet_settings -> value("diagramfont", "Sans Serif").toString();
|
||||
|
||||
// Creation et affichage d'un editeur de schema
|
||||
QStringList files;
|
||||
foreach(QString argument, arguments()) {
|
||||
if (QFileInfo(argument).exists()) files << argument;
|
||||
}
|
||||
new QETDiagramEditor(files);
|
||||
buildSystemTrayMenu();
|
||||
}
|
||||
@ -227,6 +259,17 @@ void QETApp::newElementEditor() {
|
||||
new QETElementEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom de l'utilisateur courant
|
||||
*/
|
||||
QString QETApp::userName() {
|
||||
#ifndef Q_OS_WIN32
|
||||
return(QString(getenv("USER")));
|
||||
#else
|
||||
return(QString(getenv("USERNAME")));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Renvoie le dossier des elements communs, c-a-d le chemin du dossier dans
|
||||
lequel QET doit chercher les definitions XML des elements de la collection QET.
|
||||
@ -471,6 +514,58 @@ void QETApp::checkRemainingWindows() {
|
||||
sleep = !sleep;
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les messages recus
|
||||
@param message Message recu
|
||||
*/
|
||||
void QETApp::messageReceived(const QString &message) {
|
||||
if (message.startsWith("launched-with-args: ")) {
|
||||
QString my_message(message.mid(20));
|
||||
QStringList files_list = my_message.split(' ');
|
||||
openFiles(files_list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Ouvre une liste de fichiers.
|
||||
Les fichiers sont ouverts dans le premier editeur de schemas visible venu.
|
||||
Sinon, le premier editeur de schemas existant venu devient visible et est
|
||||
utilise. S'il n'y a aucun editeur de schemas ouvert, un nouveau est cree et
|
||||
utilise.
|
||||
@param files_list Liste des fichiers a ouvrir
|
||||
*/
|
||||
void QETApp::openFiles(const QStringList &files_list) {
|
||||
if (files_list.isEmpty()) return;
|
||||
|
||||
// liste des editeurs de schema ouverts
|
||||
QList<QETDiagramEditor *> diagrams_editors = diagramEditors();
|
||||
|
||||
// s'il y a des editeur de schemas ouvert, on cherche ceux qui sont visibles
|
||||
if (diagrams_editors.count()) {
|
||||
QList<QETDiagramEditor *> visible_diagrams_editors;
|
||||
foreach(QETDiagramEditor *de, diagrams_editors) {
|
||||
if (de -> isVisible()) visible_diagrams_editors << de;
|
||||
}
|
||||
|
||||
// on choisit soit le premier visible soit le premier tout court
|
||||
QETDiagramEditor *de_open;
|
||||
if (visible_diagrams_editors.count()) {
|
||||
de_open = visible_diagrams_editors.first();
|
||||
} else {
|
||||
de_open = diagrams_editors.first();
|
||||
de_open -> setVisible(true);
|
||||
}
|
||||
|
||||
// ouvre les fichiers dans l'editeur ainsi choisi
|
||||
foreach(QString file, files_list) {
|
||||
de_open -> openAndAddDiagram(file);
|
||||
}
|
||||
} else {
|
||||
// cree un nouvel editeur qui ouvrira les fichiers
|
||||
new QETDiagramEditor(files_list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param window fenetre dont il faut trouver les barres d'outils et dock flottants
|
||||
@return les barres d'outils et dock flottants de la fenetre
|
||||
@ -553,8 +648,9 @@ void QETApp::fetchWindowStats(const QList<QETDiagramEditor *> &diagrams, const Q
|
||||
every_editor_reduced = every_element_reduced && every_diagram_reduced;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
/**
|
||||
Gere les evenement
|
||||
Gere les evenements, en particulier l'evenement FileOpen sous MacOs.
|
||||
@param e Evenement a gerer
|
||||
*/
|
||||
bool QETApp::event(QEvent *e) {
|
||||
@ -562,30 +658,13 @@ bool QETApp::event(QEvent *e) {
|
||||
if (e -> type() == QEvent::FileOpen) {
|
||||
// nom du fichier a ouvrir
|
||||
QString filename = static_cast<QFileOpenEvent *>(e) -> file();
|
||||
// liste des editeurs de schema ouverts
|
||||
QList<QETDiagramEditor *> diagrams_editors = diagramEditors();
|
||||
if (diagrams_editors.count()) {
|
||||
// s'il y a des editeur de schemas ouvert, on cherche ceux qui sont visibles
|
||||
QList<QETDiagramEditor *> visible_diagrams_editors;
|
||||
foreach(QETDiagramEditor *de, diagrams_editors) {
|
||||
if (de -> isVisible()) visible_diagrams_editors << de;
|
||||
}
|
||||
// on choisit soit le premier visible soit le premier tout court
|
||||
QETDiagramEditor *de_open;
|
||||
if (visible_diagrams_editors.count()) {
|
||||
de_open = visible_diagrams_editors.first();
|
||||
} else {
|
||||
de_open = diagrams_editors.first();
|
||||
de_open -> setVisible(true);
|
||||
}
|
||||
} else {
|
||||
new QETDiagramEditor(QStringList() << filename);
|
||||
}
|
||||
openFiles(QStringList() << filename);
|
||||
return(true);
|
||||
} else {
|
||||
return(QApplication::event(e));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Affiche l'aide et l'usage sur la sortie standard
|
||||
|
9
qetapp.h
9
qetapp.h
@ -17,7 +17,7 @@
|
||||
*/
|
||||
#ifndef QET_APP_H
|
||||
#define QET_APP_H
|
||||
#include <QApplication>
|
||||
#include "qetsingleapplication.h"
|
||||
#include <QTranslator>
|
||||
#include <QtGui>
|
||||
class QETDiagramEditor;
|
||||
@ -26,7 +26,7 @@ class QETElementEditor;
|
||||
Cette classe represente l'application QElectroTech.
|
||||
|
||||
*/
|
||||
class QETApp : public QApplication {
|
||||
class QETApp : public QETSingleApplication {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
@ -43,6 +43,7 @@ class QETApp : public QApplication {
|
||||
static void printVersion();
|
||||
static void printLicense();
|
||||
|
||||
static QString userName();
|
||||
static QString commonElementsDir();
|
||||
static QString customElementsDir();
|
||||
static QString configDir();
|
||||
@ -66,7 +67,9 @@ class QETApp : public QApplication {
|
||||
static QString diagramTextsFont();
|
||||
|
||||
protected:
|
||||
#ifdef Q_OS_DARWIN
|
||||
bool event(QEvent *);
|
||||
#endif
|
||||
|
||||
// attributs
|
||||
private:
|
||||
@ -109,6 +112,8 @@ class QETApp : public QApplication {
|
||||
void invertMainWindowVisibility(QWidget *);
|
||||
void quitQET();
|
||||
void checkRemainingWindows();
|
||||
void messageReceived(const QString &);
|
||||
void openFiles(const QStringList &);
|
||||
|
||||
// methodes privees
|
||||
private slots:
|
||||
|
@ -569,6 +569,16 @@ bool QETDiagramEditor::openDiagram() {
|
||||
open_dialog_dir.absolutePath(),
|
||||
tr("Sch\351mas QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*)")
|
||||
);
|
||||
|
||||
return(openAndAddDiagram(nom_fichier));
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode ouvre un fichier.
|
||||
@param nom_fichier Chemin du fichier a ouvrir
|
||||
@return true si l'ouverture a reussi, false sinon
|
||||
*/
|
||||
bool QETDiagramEditor::openAndAddDiagram(const QString &nom_fichier) {
|
||||
if (nom_fichier.isEmpty()) return(false);
|
||||
|
||||
open_dialog_dir = QDir(nom_fichier);
|
||||
|
@ -63,6 +63,7 @@ class QETDiagramEditor : public QMainWindow {
|
||||
bool save();
|
||||
bool newDiagram();
|
||||
bool openDiagram();
|
||||
bool openAndAddDiagram(const QString &);
|
||||
bool closeDiagram();
|
||||
void slot_editInfos();
|
||||
void slot_cut();
|
||||
|
120
qetsingleapplication.cpp
Normal file
120
qetsingleapplication.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTAvBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qetsingleapplication.h"
|
||||
#include <QLocalSocket>
|
||||
|
||||
const int QETSingleApplication::timeout_ = 10000;
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param argc Nombre d'arguments passes au programme par le systeme
|
||||
@param argv Tableau des arguments passes au programme par le systeme
|
||||
@param unique_key Cle unique
|
||||
*/
|
||||
QETSingleApplication::QETSingleApplication(int &argc, char **argv, const QString unique_key) :
|
||||
QApplication(argc, argv),
|
||||
unique_key_(unique_key)
|
||||
{
|
||||
// verifie s'il y a un segment de memoire partage correspondant a la cle unique
|
||||
shared_memory_.setKey(unique_key_);
|
||||
if (shared_memory_.attach()) {
|
||||
// oui : l'application est deja en cours d'execution
|
||||
is_running_ = true;
|
||||
} else {
|
||||
// non : il s'agit du premier demarrage de l'application pour cette cle unique
|
||||
is_running_ = false;
|
||||
|
||||
// initialisation du segment de memoire partage
|
||||
if (!shared_memory_.create(1)) {
|
||||
qDebug() << "Impossible de cr\351er l'instance unique.";
|
||||
qDebug() << "Used key is:" << unique_key_;
|
||||
return;
|
||||
}
|
||||
|
||||
// initialisation d'un serveur local pour recevoir les messages des autres instances
|
||||
local_server_ = new QLocalServer(this);
|
||||
connect(local_server_, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
|
||||
// la cle unique est egalement utilise pour le serveur
|
||||
local_server_ -> listen(unique_key_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
QETSingleApplication::~QETSingleApplication() {
|
||||
}
|
||||
|
||||
/**
|
||||
Slot gerant la reception des messages.
|
||||
Lorsque l'application recoit un message, ce slot emet le signal
|
||||
messageAvailable avec le message recu.
|
||||
*/
|
||||
void QETSingleApplication::receiveMessage() {
|
||||
QLocalSocket *local_socket = local_server_ -> nextPendingConnection();
|
||||
if (!local_socket -> waitForReadyRead(timeout_)) {
|
||||
qDebug() << local_socket -> errorString().toLatin1();
|
||||
qDebug() << "Used key is:" << unique_key_;
|
||||
return;
|
||||
}
|
||||
QByteArray byteArray = local_socket -> readAll();
|
||||
QString message = QString::fromUtf8(byteArray.constData());
|
||||
emit(messageAvailable(message));
|
||||
local_socket -> disconnectFromServer();
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si l'application est deja en cours d'execution
|
||||
*/
|
||||
bool QETSingleApplication::isRunning() {
|
||||
return(is_running_);
|
||||
}
|
||||
|
||||
/**
|
||||
Envoie un message a l'application. Si celle-ci n'est pas en cours
|
||||
d'execution, cette methode ne fait rien.
|
||||
@param message Message a transmettre a l'application
|
||||
@return true si le message a ete tranmis, false sinon
|
||||
*/
|
||||
bool QETSingleApplication::sendMessage(const QString &message) {
|
||||
// l'application doit etre en cours d'execution
|
||||
if (!is_running_) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
// se connecte a l'application, avec gestion du timeout
|
||||
QLocalSocket local_socket(this);
|
||||
local_socket.connectToServer(unique_key_, QIODevice::WriteOnly);
|
||||
if (!local_socket.waitForConnected(timeout_)) {
|
||||
qDebug() << local_socket.errorString().toLatin1();
|
||||
qDebug() << "Used key is:" << unique_key_;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// envoi du message, avec gestion du timeout
|
||||
local_socket.write(message.toUtf8());
|
||||
if (!local_socket.waitForBytesWritten(timeout_)) {
|
||||
qDebug() << local_socket.errorString().toLatin1();
|
||||
qDebug() << "Used key is:" << unique_key_;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// deconnexion
|
||||
local_socket.disconnectFromServer();
|
||||
return(true);
|
||||
}
|
56
qetsingleapplication.h
Normal file
56
qetsingleapplication.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef QET_SINGLE_APPLICATION_H
|
||||
#define QET_SINGLE_APPLICATION_H
|
||||
#include <QApplication>
|
||||
#include <QSharedMemory>
|
||||
#include <QLocalServer>
|
||||
/**
|
||||
Cette classe represente une application Qt ne s'executant qu'en un seul
|
||||
exemplaire en fonction d'une cle unique (de type QString).
|
||||
*/
|
||||
class QETSingleApplication : public QApplication {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
QETSingleApplication(int &, char **, const QString);
|
||||
virtual ~QETSingleApplication();
|
||||
|
||||
private:
|
||||
QETSingleApplication(const QETSingleApplication &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool isRunning();
|
||||
bool sendMessage(const QString &);
|
||||
|
||||
public slots:
|
||||
void receiveMessage();
|
||||
|
||||
signals:
|
||||
void messageAvailable(QString);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
bool is_running_;
|
||||
QString unique_key_;
|
||||
QSharedMemory shared_memory_;
|
||||
QLocalServer *local_server_;
|
||||
static const int timeout_;
|
||||
};
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user