File indexing completed on 2023-10-01 08:01:44
0001 // Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com> 0002 // 0003 // This program is free software; you can redistribute it and/or 0004 // modify it under the terms of the GNU General Public License 0005 // version 2 as published by the Free Software Foundation. 0006 // 0007 // This program is distributed in the hope that it will be useful, 0008 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0010 // General Public License for more details. 0011 // 0012 // You should have received a copy of the GNU General Public License 0013 // along with this program; see the file COPYING. If not, write to 0014 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0015 // Boston, MA 02110-1301, USA. 0016 0017 #include <QTcpSocket> 0018 #include <QHeaderView> 0019 #include <QIntValidator> 0020 0021 #include <klocalizedstring.h> 0022 #include <kiconloader.h> 0023 #include <kguiitem.h> 0024 #include <kstandardguiitem.h> 0025 0026 #include <monopd.h> 0027 0028 #include "metatlantic.h" 0029 0030 #include "selectserver_widget.h" 0031 0032 #include <atlantik_debug.h> 0033 0034 MetaserverEntry::MetaserverEntry(const QString &host, int port, const QString &version, int users) 0035 : QObject() 0036 , QTreeWidgetItem(MetaserverType) 0037 , m_latency(9999) 0038 , m_users(users) 0039 , m_port(port) 0040 , m_isDev(version.indexOf(QLatin1String("CVS")) != -1 || version.indexOf(QLatin1String("-dev")) != -1) 0041 { 0042 setText(0, host); 0043 setText(1, QString::number(m_latency)); 0044 setText(2, version); 0045 setText(3, users == -1 ? i18n("unknown") : QString::number(m_users)); 0046 setIcon(0, KDE::icon(QStringLiteral("atlantik"))); 0047 setDisabled(true); 0048 0049 m_latencySocket = new QTcpSocket(); 0050 m_latencySocket->setSocketOption(QAbstractSocket::LowDelayOption, true); 0051 connect(m_latencySocket, SIGNAL(hostFound()), this, SLOT(resolved())); 0052 connect(m_latencySocket, SIGNAL(connected()), this, SLOT(connected())); 0053 0054 m_latencySocket->connectToHost(host, m_port); 0055 } 0056 0057 bool MetaserverEntry::isDev() const 0058 { 0059 return m_isDev; 0060 } 0061 0062 QString MetaserverEntry::host() const 0063 { 0064 return text(0); 0065 } 0066 0067 int MetaserverEntry::port() const 0068 { 0069 return m_port; 0070 } 0071 0072 bool MetaserverEntry::operator<(const QTreeWidgetItem &other) const 0073 { 0074 if (other.type() != MetaserverType) 0075 return QTreeWidgetItem::operator<(other); 0076 0077 // sort by (less) latency first, then (most) users, then by host 0078 const MetaserverEntry *e = static_cast<const MetaserverEntry *>(&other); 0079 if (m_latency < e->m_latency) 0080 return true; 0081 if (m_users > e->m_users) 0082 return true; 0083 return QString::compare(host(), e->host()) > 0; 0084 } 0085 0086 void MetaserverEntry::resolved() 0087 { 0088 m_timer.start(); 0089 qCDebug(ATLANTIK_LOG) << host() << "resolved; timer starts"; 0090 } 0091 0092 void MetaserverEntry::connected() 0093 { 0094 m_latency = m_timer.elapsed(); 0095 m_latencySocket->abort(); 0096 qCDebug(ATLANTIK_LOG) << "connected to" << host() << "- latency =" << m_latency; 0097 setDisabled(false); 0098 setText(1, QString::number(m_latency)); 0099 disconnect(m_latencySocket, nullptr, this, nullptr); 0100 m_latencySocket->deleteLater(); 0101 m_latencySocket = nullptr; 0102 } 0103 0104 SelectServer::SelectServer(bool hideDevelopmentServers, QWidget *parent) 0105 : QWidget(parent) 0106 , m_metatlantic(nullptr) 0107 , m_hideDevelopmentServers(hideDevelopmentServers) 0108 { 0109 setupUi(this); 0110 layout()->setContentsMargins(0, 0, 0, 0); 0111 0112 connect(m_hostEdit, SIGNAL(returnPressed()), this, SLOT(customConnect())); 0113 connect(m_hostEdit, SIGNAL(textChanged(QString)), this, SLOT(validateCustomConnectButton())); 0114 0115 m_portEdit->setText(QString::number(MONOPD_PORT)); 0116 m_portEdit->setValidator(new QIntValidator(1, 65535, m_portEdit)); 0117 connect(m_portEdit, SIGNAL(returnPressed()), this, SLOT(customConnect())); 0118 connect(m_portEdit, SIGNAL(textChanged(QString)), this, SLOT(validateCustomConnectButton())); 0119 0120 m_customConnectButton->setIcon(KDE::icon(QStringLiteral("network-wired"))); 0121 connect(m_customConnectButton, SIGNAL(clicked()), this, SLOT(customConnect())); 0122 0123 // List of servers 0124 m_serverList->sortItems(1, Qt::AscendingOrder); 0125 m_serverList->header()->setSectionsClickable(false); 0126 m_serverList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); 0127 m_serverList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); 0128 m_serverList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents); 0129 0130 connect(m_serverList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(validateConnectButton())); 0131 connect(m_serverList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotConnect())); 0132 connect(m_serverList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(validateConnectButton())); 0133 0134 // Server List / Refresh 0135 KGuiItem::assign(m_refreshButton, KGuiItem(i18n("Get Server List"), QStringLiteral("network-wired"))); 0136 connect(m_refreshButton, SIGNAL(clicked()), this, SLOT(reloadServerList())); 0137 0138 // Connect 0139 m_connectButton->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon()); 0140 0141 connect(m_connectButton, SIGNAL(clicked()), this, SLOT(slotConnect())); 0142 0143 validateConnectButton(); 0144 validateCustomConnectButton(); 0145 } 0146 0147 SelectServer::~SelectServer() 0148 { 0149 if (m_metatlantic) 0150 m_metatlantic->kill(); 0151 delete m_metatlantic; 0152 } 0153 0154 void SelectServer::setHideDevelopmentServers(bool hideDevelopmentServers) 0155 { 0156 if ( m_hideDevelopmentServers != hideDevelopmentServers ) 0157 { 0158 m_hideDevelopmentServers = hideDevelopmentServers; 0159 foreach (MetaserverEntry *e, m_developmentServers) 0160 e->setHidden(m_hideDevelopmentServers); 0161 } 0162 } 0163 0164 void SelectServer::initMetaserver() 0165 { 0166 // Hardcoded, but there aren't any other Metatlantic root servers at the moment 0167 Q_EMIT msgStatus(i18n("Retrieving server list...")); 0168 0169 KGuiItem::assign(m_refreshButton, KGuiItem(i18n("Reload Server List"), QStringLiteral("view-refresh"))); 0170 m_metatlantic = new Metatlantic(QString::fromLatin1(METATLANTIC_HOST), METATLANTIC_PORT); 0171 0172 connect(m_metatlantic, SIGNAL(metatlanticAdd(QString,int,QString,int)), this, SLOT(slotMetatlanticAdd(QString,int,QString,int))); 0173 connect(m_metatlantic, SIGNAL(result(KJob*)), SLOT(metatlanticFinished())); 0174 0175 m_metatlantic->start(); 0176 } 0177 0178 void SelectServer::slotMetatlanticAdd(const QString &host, int port, const QString &version, int users) 0179 { 0180 MetaserverEntry *item = new MetaserverEntry(host, port, version, users); 0181 m_serverList->addTopLevelItem(item); 0182 m_serverList->resizeColumnToContents(0); 0183 0184 if ( item->isDev() ) 0185 { 0186 m_developmentServers.append(item); 0187 item->setHidden(m_hideDevelopmentServers); 0188 } 0189 0190 validateConnectButton(); 0191 } 0192 0193 void SelectServer::metatlanticFinished() 0194 { 0195 if (m_metatlantic->error()) 0196 Q_EMIT msgStatus(i18n("Error while retrieving the server list.")); 0197 else 0198 Q_EMIT msgStatus(i18n("Retrieved server list.")); 0199 m_metatlantic = nullptr; 0200 m_refreshButton->setEnabled(true); 0201 } 0202 0203 void SelectServer::validateConnectButton() 0204 { 0205 if (!m_serverList->selectedItems().isEmpty()) 0206 m_connectButton->setEnabled(true); 0207 else 0208 m_connectButton->setEnabled(false); 0209 } 0210 0211 void SelectServer::validateCustomConnectButton() 0212 { 0213 m_customConnectButton->setEnabled(!m_hostEdit->text().isEmpty() && !m_portEdit->text().isEmpty()); 0214 } 0215 0216 void SelectServer::reloadServerList() 0217 { 0218 m_developmentServers.resize(0); // Keep the capacity allocated 0219 m_serverList->clear(); 0220 validateConnectButton(); 0221 0222 m_refreshButton->setEnabled(false); 0223 initMetaserver(); 0224 } 0225 0226 void SelectServer::slotConnect() 0227 { 0228 const QList<QTreeWidgetItem *> items = m_serverList->selectedItems(); 0229 if (!items.isEmpty()) 0230 { 0231 const QTreeWidgetItem *item = items.first(); 0232 Q_ASSERT(item->type() == MetaserverEntry::MetaserverType); 0233 const MetaserverEntry *e = static_cast<const MetaserverEntry *>(item); 0234 Q_EMIT serverConnect(e->host(), e->port()); 0235 } 0236 } 0237 0238 void SelectServer::customConnect() 0239 { 0240 if (!m_hostEdit->text().isEmpty() && !m_portEdit->text().isEmpty()) 0241 Q_EMIT serverConnect(m_hostEdit->text(), m_portEdit->text().toInt()); 0242 } 0243 0244 #include "moc_selectserver_widget.cpp"