1 // Copyright 2005-2019 The Mumble Developers. All rights reserved. 2 // Use of this source code is governed by a BSD-style license 3 // that can be found in the LICENSE file at the root of the 4 // Mumble source tree or at <https://www.mumble.info/LICENSE>. 5 6 #ifndef MUMBLE_MUMBLE_CONNECTDIALOG_H_ 7 #define MUMBLE_MUMBLE_CONNECTDIALOG_H_ 8 9 #ifndef Q_MOC_RUN 10 # include <boost/accumulators/accumulators.hpp> 11 # include <boost/accumulators/statistics/stats.hpp> 12 #endif 13 14 #include <QtCore/QtGlobal> 15 #include <QtCore/QString> 16 #include <QtCore/QUrl> 17 #if QT_VERSION >= 0x050000 18 # include <QtWidgets/QStyledItemDelegate> 19 # include <QtWidgets/QTreeView> 20 # include <QtWidgets/QTreeWidgetItem> 21 #else 22 # include <QtGui/QStyledItemDelegate> 23 # include <QtGui/QTreeView> 24 # include <QtGui/QTreeWidgetItem> 25 #endif 26 27 #include <QtNetwork/QHostInfo> 28 29 #ifdef USE_BONJOUR 30 #include <dns_sd.h> 31 #endif 32 33 #include "BonjourRecord.h" 34 #include "Net.h" 35 #include "HostAddress.h" 36 #include "Timer.h" 37 #include "UnresolvedServerAddress.h" 38 #include "ServerAddress.h" 39 40 struct FavoriteServer; 41 class QUdpSocket; 42 43 struct PublicInfo { 44 QString qsName; 45 QUrl quUrl; 46 QString qsIp; 47 QString qsCountry; 48 QString qsCountryCode; 49 QString qsContinentCode; 50 unsigned short usPort; 51 bool bCA; 52 }; 53 54 struct PingStats { 55 private: 56 Q_DISABLE_COPY(PingStats) 57 protected: 58 void init(); 59 public: 60 quint32 uiVersion; 61 quint32 uiPing; 62 quint32 uiPingSort; 63 quint32 uiUsers; 64 quint32 uiMaxUsers; 65 quint32 uiBandwidth; 66 quint32 uiSent; 67 quint32 uiRecv; 68 69 double dPing; 70 71 typedef boost::accumulators::accumulator_set<double, boost::accumulators::stats<boost::accumulators::tag::count, boost::accumulators::tag::extended_p_square> > asQuantileType; 72 asQuantileType *asQuantile; 73 74 void reset(); 75 76 PingStats(); 77 ~PingStats(); 78 }; 79 80 class ServerItem; 81 82 class ServerViewDelegate : public QStyledItemDelegate { 83 Q_OBJECT 84 Q_DISABLE_COPY(ServerViewDelegate) 85 public: 86 ServerViewDelegate(QObject *p = NULL); 87 ~ServerViewDelegate(); 88 89 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; 90 }; 91 92 class ServerView : public QTreeWidget { 93 Q_OBJECT 94 Q_DISABLE_COPY(ServerView) 95 public: 96 ServerItem *siFavorite, *siLAN, *siPublic; 97 QMap<QString, QString> qmContinentNames; 98 QMap<QString, ServerItem *> qmCountry; 99 QMap<QString, ServerItem *> qmContinent; 100 101 ServerView(QWidget *); 102 ~ServerView() Q_DECL_OVERRIDE; 103 104 void fixupName(ServerItem *si); 105 106 ServerItem *getParent(const QString &continent, const QString &countrycode, const QString &countryname, const QString &usercontinentcode, const QString &usercountrycode); 107 protected: 108 QMimeData *mimeData(const QList<QTreeWidgetItem *>) const Q_DECL_OVERRIDE; 109 QStringList mimeTypes() const Q_DECL_OVERRIDE; 110 Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE; 111 bool dropMimeData(QTreeWidgetItem *, int, const QMimeData *, Qt::DropAction) Q_DECL_OVERRIDE; 112 }; 113 114 #include "ui_ConnectDialog.h" 115 #include "ui_ConnectDialogEdit.h" 116 117 class ServerItem : public QTreeWidgetItem, public PingStats { 118 Q_DISABLE_COPY(ServerItem) 119 protected: 120 void init(); 121 public: 122 enum ItemType { FavoriteType, LANType, PublicType }; 123 124 static QMap<QString, QIcon> qmIcons; 125 126 bool bParent; 127 ServerItem *siParent; 128 QList<ServerItem *> qlChildren; 129 130 QString qsName; 131 132 QString qsHostname; 133 unsigned short usPort; 134 bool bCA; 135 136 QString qsUsername; 137 QString qsPassword; 138 139 QString qsCountry; 140 QString qsCountryCode; 141 QString qsContinentCode; 142 143 QString qsUrl; 144 145 QString qsBonjourHost; 146 BonjourRecord brRecord; 147 148 /// Contains the resolved addresses for 149 /// this ServerItem. 150 QList<ServerAddress> qlAddresses; 151 152 ItemType itType; 153 154 ServerItem(const FavoriteServer &fs); 155 ServerItem(const PublicInfo &pi); 156 ServerItem(const QString &name, const QString &host, unsigned short port, const QString &uname, const QString &password = QString()); 157 ServerItem(const BonjourRecord &br); 158 ServerItem(const QString &name, ItemType itype, const QString &continent = QString(), const QString &country = QString()); 159 ServerItem(const ServerItem *si); 160 ~ServerItem(); 161 162 /// Converts given mime data into a ServerItem object 163 /// 164 /// This function checks the clipboard for a valid mumble:// style 165 /// URL and converts it into a ServerItem ready to add to the connect 166 /// dialog. It also parses .lnk files of InternetShortcut/URL type 167 /// to enable those to be dropped onto the clipboard. 168 /// 169 /// @note If needed can query the user for a user name using a modal dialog. 170 /// @note If a server item is returned it's the callers reponsibility to delete it. 171 /// 172 /// @param mime Mime data to analyze 173 /// @param default_name If true the hostname is set as item name if none is given 174 /// @param p Parent widget to use in case the user has to be queried 175 /// @return Server item or NULL if mime data invalid. 176 /// 177 static ServerItem *fromMimeData(const QMimeData *mime, bool default_name = true, QWidget *p = NULL, bool convertHttpUrls=false); 178 /// Create a ServerItem from a mumble:// URL 179 static ServerItem *fromUrl(QUrl url, QWidget *p); 180 181 void addServerItem(ServerItem *child); 182 183 FavoriteServer toFavoriteServer() const; 184 QMimeData *toMimeData() const; 185 static QMimeData *toMimeData(const QString &name, const QString &host, unsigned short port, const QString &channel = QString()); 186 187 static QIcon loadIcon(const QString &name); 188 189 void setDatas(double ping = 0.0, quint32 users = 0, quint32 maxusers = 0); 190 bool operator< (const QTreeWidgetItem &) const Q_DECL_OVERRIDE; 191 192 QVariant data(int column, int role) const Q_DECL_OVERRIDE; 193 194 void hideCheck(); 195 }; 196 197 class ConnectDialogEdit : public QDialog, protected Ui::ConnectDialogEdit { 198 private: 199 Q_OBJECT 200 Q_DISABLE_COPY(ConnectDialogEdit) 201 202 void init(); 203 protected: 204 bool bOk; 205 bool bCustomLabel; 206 ServerItem *m_si; 207 208 public slots: 209 void validate(); 210 void accept(); 211 212 void on_qbFill_clicked(); 213 void on_qbDiscard_clicked(); 214 void on_qcbShowPassword_toggled(bool); 215 void on_qleName_textEdited(const QString&); 216 void on_qleServer_textEdited(const QString&); 217 void showNotice(const QString &text); 218 bool updateFromClipboard(); 219 public: 220 QString qsName, qsHostname, qsUsername, qsPassword; 221 unsigned short usPort; 222 ConnectDialogEdit(QWidget *parent, 223 const QString &name, 224 const QString &host, 225 const QString &user, 226 unsigned short port, 227 const QString &password); 228 /// Add a new Server 229 /// Prefills from clipboard content or the connected to server if available 230 ConnectDialogEdit(QWidget *parent); 231 virtual ~ConnectDialogEdit(); 232 }; 233 234 class ConnectDialog : public QDialog, public Ui::ConnectDialog { 235 friend class ServerView; 236 private: 237 Q_OBJECT 238 Q_DISABLE_COPY(ConnectDialog) 239 protected: 240 static QList<PublicInfo> qlPublicServers; 241 static QString qsUserCountry, qsUserCountryCode, qsUserContinentCode; 242 static Timer tPublicServers; 243 244 QMenu *qmPopup, *qmFilters; 245 QActionGroup *qagFilters; 246 QPushButton *qpbEdit; 247 248 bool bPublicInit; 249 bool bAutoConnect; 250 251 Timer tPing; 252 Timer tCurrent, tHover, tRestart; 253 QUdpSocket *qusSocket4; 254 QUdpSocket *qusSocket6; 255 QTimer *qtPingTick; 256 QList<ServerItem *> qlItems; 257 258 ServerItem *siAutoConnect; 259 260 QList<UnresolvedServerAddress> qlDNSLookup; 261 QSet<UnresolvedServerAddress> qsDNSActive; 262 QHash<UnresolvedServerAddress, QSet<ServerItem *> > qhDNSWait; 263 QHash<UnresolvedServerAddress, QList<ServerAddress> > qhDNSCache; 264 265 QHash<ServerAddress, quint64> qhPingRand; 266 QHash<ServerAddress, QSet<ServerItem *> > qhPings; 267 268 QMap<UnresolvedServerAddress, unsigned int> qmPingCache; 269 270 bool bIPv4; 271 bool bIPv6; 272 int iPingIndex; 273 274 bool bLastFound; 275 276 /// bAllowPing determines whether ConnectDialog can use 277 /// UDP packets to ping remote hosts to be able to show a 278 /// ping latency and user count. 279 bool bAllowPing; 280 /// bAllowHostLookup determines whether ConnectDialog can 281 /// resolve hosts via DNS, Bonjour, and so on. 282 bool bAllowHostLookup; 283 /// bAllowBonjour determines whether ConfigDialog can use 284 /// Bonjour to find nearby servers on the local network. 285 bool bAllowBonjour; 286 /// bAllowFilters determines whether filters are available 287 /// in the ConfigDialog. If this option is diabled, the 288 /// 'Show All' filter is forced, and no other filter can 289 /// be chosen. 290 bool bAllowFilters; 291 292 QMap<QString, QIcon> qmIcons; 293 294 void sendPing(const QHostAddress &, unsigned short port); 295 296 void initList(); 297 void fillList(); 298 299 void startDns(ServerItem *); 300 void stopDns(ServerItem *); 301 public slots: 302 void accept(); 303 void fetched(QByteArray xmlData, QUrl, QMap<QString, QString>); 304 305 void udpReply(); 306 void lookedUp(); 307 void timeTick(); 308 309 void on_qaFavoriteAdd_triggered(); 310 void on_qaFavoriteAddNew_triggered(); 311 void on_qaFavoriteEdit_triggered(); 312 void on_qaFavoriteRemove_triggered(); 313 void on_qaFavoriteCopy_triggered(); 314 void on_qaFavoritePaste_triggered(); 315 void on_qaUrl_triggered(); 316 void onFiltersTriggered(QAction *); 317 void on_qtwServers_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *); 318 void on_qtwServers_itemDoubleClicked(QTreeWidgetItem *, int); 319 void on_qtwServers_customContextMenuRequested(const QPoint &); 320 void on_qtwServers_itemExpanded(QTreeWidgetItem *); 321 void OnSortChanged(int, Qt::SortOrder); 322 public: 323 QString qsServer, qsUsername, qsPassword; 324 unsigned short usPort; 325 ConnectDialog(QWidget *parent, bool autoconnect); 326 ~ConnectDialog(); 327 328 #ifdef USE_BONJOUR 329 protected: 330 QList<BonjourRecord> qlBonjourActive; 331 public slots: 332 void onUpdateLanList(const QList<BonjourRecord> &); 333 void onLanBrowseError(DNSServiceErrorType); 334 335 void onResolved(BonjourRecord, QString, int); 336 void onLanResolveError(BonjourRecord, DNSServiceErrorType); 337 #endif 338 }; 339 340 #endif 341