Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ConnectDialog.h « mumble « src - github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 29c562c85a3a2605fba6065a2645a04c1e02b779 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
// Copyright 2007-2022 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.

#ifndef MUMBLE_MUMBLE_CONNECTDIALOG_H_
#define MUMBLE_MUMBLE_CONNECTDIALOG_H_

#ifndef Q_MOC_RUN
#	include <boost/accumulators/accumulators.hpp>
#	include <boost/accumulators/statistics/stats.hpp>
#endif

#include <QtCore/QString>
#include <QtCore/QUrl>
#include <QtCore/QtGlobal>
#include <QtWidgets/QStyledItemDelegate>
#include <QtWidgets/QTreeView>
#include <QtWidgets/QTreeWidgetItem>

#include <QtNetwork/QHostInfo>

#ifdef USE_ZEROCONF
#	include "BonjourRecord.h"
#	include <dns_sd.h>
#endif

#include "HostAddress.h"
#include "Net.h"
#include "ServerAddress.h"
#include "Timer.h"
#include "UnresolvedServerAddress.h"

struct FavoriteServer;
class QUdpSocket;

struct PublicInfo {
	QString qsName;
	QUrl quUrl;
	QString qsIp;
	QString qsCountry;
	QString qsCountryCode;
	QString qsContinentCode;
	unsigned short usPort;
	bool bCA;
};

struct PingStats {
private:
	Q_DISABLE_COPY(PingStats)
protected:
	void init();

public:
	quint32 uiVersion;
	quint32 uiPing;
	quint32 uiPingSort;
	quint32 uiUsers;
	quint32 uiMaxUsers;
	quint32 uiBandwidth;
	quint32 uiSent;
	quint32 uiRecv;

	double dPing;

	typedef boost::accumulators::accumulator_set<
		double,
		boost::accumulators::stats< boost::accumulators::tag::count, boost::accumulators::tag::extended_p_square > >
		asQuantileType;
	asQuantileType *asQuantile;

	void reset();

	PingStats();
	~PingStats();
};

class ServerItem;

class ServerViewDelegate : public QStyledItemDelegate {
	Q_OBJECT
	Q_DISABLE_COPY(ServerViewDelegate)
public:
	ServerViewDelegate(QObject *p = nullptr);
	~ServerViewDelegate();

	void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
};

class ServerView : public QTreeWidget {
	Q_OBJECT
	Q_DISABLE_COPY(ServerView)
public:
	ServerItem *siFavorite, *siLAN, *siPublic;

	ServerView(QWidget *);
	~ServerView() Q_DECL_OVERRIDE;

	void fixupName(ServerItem *si);

protected:
	QMimeData *mimeData(const QList< QTreeWidgetItem * >) const Q_DECL_OVERRIDE;
	QStringList mimeTypes() const Q_DECL_OVERRIDE;
	Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
	bool dropMimeData(QTreeWidgetItem *, int, const QMimeData *, Qt::DropAction) Q_DECL_OVERRIDE;
};

#include "ui_ConnectDialog.h"
#include "ui_ConnectDialogEdit.h"

class ServerItem : public QTreeWidgetItem, public PingStats {
	Q_DISABLE_COPY(ServerItem)
protected:
	void init();

public:
	enum ItemType { FavoriteType, LANType, PublicType };

	static QMap< QString, QIcon > qmIcons;

	bool bParent;
	ServerItem *siParent;
	QList< ServerItem * > qlChildren;

	QString qsName;

	QString qsHostname;
	unsigned short usPort;
	bool bCA;

	QString qsUsername;
	QString qsPassword;

	QString qsCountry;
	QString qsCountryCode;
	QString qsContinentCode;

	QString qsUrl;
#ifdef USE_ZEROCONF
	QString zeroconfHost;
	BonjourRecord zeroconfRecord;
#endif
	/// Contains the resolved addresses for
	/// this ServerItem.
	QList< ServerAddress > qlAddresses;

	ItemType itType;

	ServerItem(const FavoriteServer &fs);
	ServerItem(const PublicInfo &pi);
	ServerItem(const QString &name, const QString &host, unsigned short port, const QString &uname,
			   const QString &password = QString());
#ifdef USE_ZEROCONF
	ServerItem(const BonjourRecord &br);
#endif
	ServerItem(const QString &name, ItemType itype);
	ServerItem(const ServerItem *si);
	~ServerItem();

	/// Converts given mime data into a ServerItem object
	///
	/// This function checks the clipboard for a valid mumble:// style
	/// URL and converts it into a ServerItem ready to add to the connect
	/// dialog. It also parses .lnk files of InternetShortcut/URL type
	/// to enable those to be dropped onto the clipboard.
	///
	/// @note If needed can query the user for a user name using a modal dialog.
	/// @note If a server item is returned it's the callers reponsibility to delete it.
	///
	/// @param mime Mime data to analyze
	/// @param default_name If true the hostname is set as item name if none is given
	/// @param p Parent widget to use in case the user has to be queried
	/// @return Server item or nullptr if mime data invalid.
	///
	static ServerItem *fromMimeData(const QMimeData *mime, bool default_name = true, QWidget *p = nullptr,
									bool convertHttpUrls = false);
	/// Create a ServerItem from a mumble:// URL
	static ServerItem *fromUrl(QUrl url, QWidget *p);

	void addServerItem(ServerItem *child);

	FavoriteServer toFavoriteServer() const;
	QMimeData *toMimeData() const;
	static QMimeData *toMimeData(const QString &name, const QString &host, unsigned short port,
								 const QString &channel = QString());

	static QIcon loadIcon(const QString &name);

	void setDatas(double ping = 0.0, quint32 users = 0, quint32 maxusers = 0);
	bool operator<(const QTreeWidgetItem &) const Q_DECL_OVERRIDE;

	QVariant data(int column, int role) const Q_DECL_OVERRIDE;
};

class ConnectDialogEdit : public QDialog, protected Ui::ConnectDialogEdit {
private:
	Q_OBJECT
	Q_DISABLE_COPY(ConnectDialogEdit)

	void init();

protected:
	bool bOk;
	bool bCustomLabel;
	ServerItem *m_si;

public slots:
	void validate();
	void accept();

	void on_qbFill_clicked();
	void on_qbDiscard_clicked();
	void on_qcbShowPassword_toggled(bool);
	void on_qleName_textEdited(const QString &);
	void on_qleServer_textEdited(const QString &);
	void showNotice(const QString &text);
	bool updateFromClipboard();

public:
	QString qsName, qsHostname, qsUsername, qsPassword;
	unsigned short usPort;
	ConnectDialogEdit(QWidget *parent, const QString &name, const QString &host, const QString &user,
					  unsigned short port, const QString &password);
	/// Add a new Server
	/// Prefills from clipboard content or the connected to server if available
	ConnectDialogEdit(QWidget *parent);
	virtual ~ConnectDialogEdit();
};

class ConnectDialog : public QDialog, public Ui::ConnectDialog {
	friend class ServerView;

private:
	Q_OBJECT
	Q_DISABLE_COPY(ConnectDialog)
protected:
	static QList< PublicInfo > qlPublicServers;
	static QString qsUserCountry, qsUserCountryCode, qsUserContinentCode;
	static Timer tPublicServers;

	QMenu *qmPopup;
	QPushButton *qpbEdit;

	bool bPublicInit;
	bool bAutoConnect;

	Timer tPing;
	Timer tCurrent, tHover, tRestart;
	QUdpSocket *qusSocket4;
	QUdpSocket *qusSocket6;
	QTimer *qtPingTick;
	QList< ServerItem * > qlItems;

	ServerItem *siAutoConnect;

	QList< UnresolvedServerAddress > qlDNSLookup;
	QSet< UnresolvedServerAddress > qsDNSActive;
	QHash< UnresolvedServerAddress, QSet< ServerItem * > > qhDNSWait;
	QHash< UnresolvedServerAddress, QList< ServerAddress > > qhDNSCache;

	QHash< ServerAddress, quint64 > qhPingRand;
	QHash< ServerAddress, QSet< ServerItem * > > qhPings;

	QMap< UnresolvedServerAddress, unsigned int > qmPingCache;

	QString qsSearchServername;
	QString qsSearchLocation;

	bool bIPv4;
	bool bIPv6;
	int iPingIndex;

	bool bLastFound;

	/// bAllowPing determines whether ConnectDialog can use
	/// UDP packets to ping remote hosts to be able to show a
	/// ping latency and user count.
	bool bAllowPing;
	/// bAllowHostLookup determines whether ConnectDialog can
	/// resolve hosts via DNS, Bonjour, and so on.
	bool bAllowHostLookup;
	/// bAllowZeroconf determines whether ConfigDialog can use
	/// zeroconf to find nearby servers on the local network.
	bool bAllowZeroconf;
	/// bAllowFilters determines whether filters are available
	/// in the ConfigDialog. If this option is diabled, the
	/// 'Show All' filter is forced, and no other filter can
	/// be chosen.
	bool bAllowFilters;


	void sendPing(const QHostAddress &, unsigned short port);

	void initList();
	void fillList();

	void startDns(ServerItem *);
	void stopDns(ServerItem *);

	/// Calls ConnectDialog::filterServer for each server in
	/// the public server list
	void filterPublicServerList() const;
	/// Hides the given ServerItem according to the current
	/// filter settings. It is checked that the name of the
	/// given server matches ConnectDialog#qsSearchServername
	/// and the location is equal to ConnectDialog#qsSearchLocation.
	/// Lastly it is checked that the server is reachable or
	/// populated, should the respective filters be set.
	///
	/// \param si  ServerItem that should be filtered
	void filterServer(ServerItem *const si) const;

	/// Enumerates all countries in ConnectDialog#qlPublicServers
	/// and adds an entry to the location filter Combobox with
	/// with the country name as text, the countrycode as
	/// data and the flag of the country as the icon.
	void addCountriesToSearchLocation() const;
public slots:
	void accept();
	void fetched(QByteArray xmlData, QUrl, QMap< QString, QString >);

	void udpReply();
	void lookedUp();
	void timeTick();

	void on_qaFavoriteAdd_triggered();
	void on_qaFavoriteAddNew_triggered();
	void on_qaFavoriteEdit_triggered();
	void on_qaFavoriteRemove_triggered();
	void on_qaFavoriteCopy_triggered();
	void on_qaFavoritePaste_triggered();
	void on_qaUrl_triggered();
	void on_qtwServers_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *);
	void on_qtwServers_itemDoubleClicked(QTreeWidgetItem *, int);
	void on_qtwServers_customContextMenuRequested(const QPoint &);
	/// If the expanded item is the public server list
	/// the user is asked (only once) for consent to transmit
	/// the IP to all public servers. If the user does not
	/// consent the public server list is disabled. If
	/// the user does consent the public server list is
	/// filled and the search dialog is shown.
	/// Finally name resolution is triggered for all child
	/// items of the expanded item.
	void on_qtwServers_itemExpanded(QTreeWidgetItem *item);
	/// Hides the search dialog if the collapsed item is
	/// the public server list
	void on_qtwServers_itemCollapsed(QTreeWidgetItem *item);
	void OnSortChanged(int, Qt::SortOrder);

public:
	QString qsServer, qsUsername, qsPassword;
	unsigned short usPort;
	ConnectDialog(QWidget *parent, bool autoconnect);
	~ConnectDialog();

#ifdef USE_ZEROCONF
protected:
	QList< BonjourRecord > qlBonjourActive;
public slots:
	void onUpdateLanList(const QList< BonjourRecord > &);

	void onResolved(const BonjourRecord, const QString, const uint16_t);
	void onLanResolveError(const BonjourRecord);
#endif
private slots:
	void on_qleSearchServername_textChanged(const QString &searchServername);
	void on_qcbSearchLocation_currentIndexChanged(int searchLocationIndex);
	void on_qcbFilter_currentIndexChanged(int filterIndex);
};

#endif