1 /*
2  * Stellarium Remote Sync plugin
3  * Copyright (C) 2015 Florian Schaukowitsch
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #ifndef REMOTESYNC_HPP
21 #define REMOTESYNC_HPP
22 
23 #include "StelModule.hpp"
24 #include "SyncClient.hpp"
25 #include "SyncServer.hpp"
26 
27 #include <QFont>
28 #include <QKeyEvent>
29 #include <QLoggingCategory>
30 #include <QTimer>
31 
32 class RemoteSyncDialog;
33 
34 Q_DECLARE_LOGGING_CATEGORY(remoteSync)
35 
36 /*! @defgroup remoteSync RemoteSync plug-in
37 @{
38 Provides state synchronization for multiple Stellarium instances
39 running in a network. See manual for detailed description.
40 
41 @}
42 */
43 
44 //! @ingroup remoteSync
45 //! Main class of the %RemoteSync plug-in.
46 //! Provides a synchronization mechanism for multiple Stellarium instances in a network.
47 //! This plugin has been developed during ESA SoCiS 2015/2016.
48 //! @author Florian Schaukowitsch
49 //! @author Georg Zotti
50 class RemoteSync : public StelModule
51 {
52 	Q_OBJECT
53 
54 public:
55 	enum SyncState
56 	{
57 		IDLE, //Plugin is disabled
58 		SERVER, //Plugin is running as server
59 		CLIENT, //Plugin is connected as a client to a server
60 		CLIENT_CONNECTING, //Plugin is currently trying to connect to a server
61 		CLIENT_CLOSING, //Plugin is disconnecting from the server
62 		CLIENT_WAIT_RECONNECT //Plugin is waiting to try reconnecting again
63 	};
64 	Q_ENUM(SyncState)
65 
66 	//! Defines behavior when client connection is lost/server quits
67 	enum ClientBehavior
68 	{
69 		NONE, //do nothing
70 		RECONNECT, //automatically try to reconnect
71 		QUIT //quit the client
72 	};
73 	Q_ENUM(ClientBehavior)
74 
75 	RemoteSync();
76 	virtual ~RemoteSync() Q_DECL_OVERRIDE;
77 
78 	///////////////////////////////////////////////////////////////////////////
79 	// Methods defined in the StelModule class
80 	virtual void init() Q_DECL_OVERRIDE;
81 	virtual void update(double deltaTime) Q_DECL_OVERRIDE;
82 
83 	virtual double getCallOrder(StelModuleActionName actionName) const Q_DECL_OVERRIDE;
84 
85 	virtual bool configureGui(bool show=true) Q_DECL_OVERRIDE;
86 	///////////////////////////////////////////////////////////////////////////
87 
getClientServerHost() const88 	QString getClientServerHost() const { return clientServerHost; }
getClientServerPort() const89 	quint16 getClientServerPort() const { return clientServerPort; }
getServerPort() const90 	quint16 getServerPort() const { return serverPort; }
getClientSyncOptions() const91 	SyncClient::SyncOptions getClientSyncOptions() const { return syncOptions; }
getStelPropFilter() const92 	QStringList getStelPropFilter() const { return stelPropFilter; }
getConnectionLostBehavior() const93 	ClientBehavior getConnectionLostBehavior() const { return connectionLostBehavior; }
getQuitBehavior() const94 	ClientBehavior getQuitBehavior() const { return quitBehavior; }
95 
getState() const96 	SyncState getState() const { return state; }
97 	//! Very few propertries cannot be synchronized for technical reasons.
98 	static bool isPropertyBlacklisted(const QString &name);
99 
100 public slots:
101 	void setClientServerHost(const QString& clientServerHost);
102 	void setClientServerPort(const int port);
103 	void setServerPort(const int port);
104 	void setClientSyncOptions(SyncClient::SyncOptions options);
105 	void setStelPropFilter(const QStringList& stelPropFilter);
106 	void setConnectionLostBehavior(const ClientBehavior bh);
107 	void setQuitBehavior(const ClientBehavior bh);
108 
109 	//! Starts the plugin in server mode, on the port specified by the serverPort property.
110 	//! If currently in a state other than IDLE, this call has no effect.
111 	void startServer();
112 
113 	//! Tries to disconnect all current clients and stops the server, returning to the IDLE state.
114 	//! Only has an effect in the SERVER state.
115 	void stopServer();
116 
117 	//! Connects the plugin to the server specified by the clientServerHost and clientServerPort properties.
118 	//! If currently in a state other than IDLE or CLIENT_WAIT_RECONNECT, this call has no effect.
119 	void connectToServer();
120 
121 	//! Disconnects from the server and returns to the IDLE state.
122 	//! Only has an effect in the CLIENT state.
123 	void disconnectFromServer();
124 
125 	//! Load the plug-in's settings from the configuration file.
126 	//! Settings are kept in the "RemoteSync" section in Stellarium's
127 	//! configuration file. If no such section exists, it will load default
128 	//! values.
129 	//! @see saveSettings(), restoreSettings()
130 	void loadSettings();
131 
132 	//! Save the plug-in's settings to the configuration file.
133 	//! @see loadSettings(), restoreSettings()
134 	void saveSettings();
135 
136 	//! Restore the plug-in's settings to the default state.
137 	//! Replace the plug-in's settings in Stellarium's configuration file
138 	//! with the default values and re-load them.
139 	//! Uses internally loadSettings() and saveSettings().
140 	void restoreDefaultSettings();
141 
142 signals:
143 	void errorOccurred(const QString& errorString);
144 	void clientServerHostChanged(const QString& clientServerHost);
145 	void clientServerPortChanged(const int port);
146 	void serverPortChanged(const int port);
147 	void clientSyncOptionsChanged(const SyncClient::SyncOptions options);
148 	void stelPropFilterChanged(const QStringList& stelPropFilter);
149 	void connectionLostBehaviorChanged(const ClientBehavior bh);
150 	void quitBehaviorChanged(const ClientBehavior bh);
151 
152 	void stateChanged(RemoteSync::SyncState state);
153 
154 private slots:
155 	void clientDisconnected(bool clean);
156 	void clientConnected();
157 private:
158 	void setState(RemoteSync::SyncState state);
159 	void setError(const QString& errorString);
160 	QVariant argsGetOptionWithArg(const QStringList &args, QString shortOpt, QString longOpt, QVariant defaultValue);
161 
162 	SyncState applyClientBehavior(ClientBehavior bh);
163 
164 	static QString packStringList(const QStringList props);
165 	static QStringList unpackStringList(const QString packedProps);
166 
167 	//The host string/IP addr to connect to
168 	QString clientServerHost;
169 	//The host port to connect to
170 	quint16 clientServerPort;
171 	//the port used in server mode
172 	quint16 serverPort;
173 	SyncClient::SyncOptions syncOptions;
174 	QStringList stelPropFilter;
175 	ClientBehavior connectionLostBehavior;
176 	ClientBehavior quitBehavior;
177 
178 	QTimer reconnectTimer;
179 
180 	SyncState state;
181 	SyncServer* server;
182 	SyncClient* client;
183 
184 	// the last error that occurred
185 	QString errorString;
186 
187 	QSettings* conf;
188 	bool allowVersionMismatch; // set true to sync even different versions of Stellarium
189 
190 	// GUI
191 	RemoteSyncDialog* configDialog;
192 	// A stringlist which contains property names which cannot be synchronized.
193 	// The list currently is fixed.
194 	static QStringList propertyBlacklist;
195 };
196 
197 Q_DECLARE_METATYPE(RemoteSync::SyncState)
198 
199 //! Stream overload for debugging
200 QDebug operator<<(QDebug, RemoteSync::SyncState);
201 
202 #include "StelPluginInterface.hpp"
203 
204 //! This class is used by Qt to manage a plug-in interface
205 class RemoteSyncStelPluginInterface : public QObject, public StelPluginInterface
206 {
207 	Q_OBJECT
208 	Q_PLUGIN_METADATA(IID StelPluginInterface_iid)
209 	Q_INTERFACES(StelPluginInterface)
210 public:
211 	virtual StelModule* getStelModule() const Q_DECL_OVERRIDE;
212 	virtual StelPluginInfo getPluginInfo() const Q_DECL_OVERRIDE;
getExtensionList() const213 	virtual QObjectList getExtensionList() const Q_DECL_OVERRIDE { return QObjectList(); }
214 };
215 
216 #endif /*REMOTESYNC_HPP*/
217 
218