File indexing completed on 2024-12-08 03:46:50
0001 /* 0002 SPDX-FileCopyrightText: 2007 Paolo Capriotti <p.capriotti@gmail.com> 0003 SPDX-FileCopyrightText: 2007 Riccardo Iaconelli <ruphy@fsfe.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "networkdialog.h" 0009 0010 #include <QLabel> 0011 #include <QTcpSocket> 0012 #include <QTcpServer> 0013 #include <QVBoxLayout> 0014 #include <QHBoxLayout> 0015 #include <QPushButton> 0016 0017 #include <KComboBox> 0018 #include <KPluralHandlingSpinBox> 0019 #include <KLineEdit> 0020 #include <KLocalizedString> 0021 #include <KSeparator> 0022 #include <KDNSSD/ServiceBrowser> 0023 #include <KDNSSD/ServiceModel> 0024 #include <KDNSSD/PublicService> 0025 #include <KConfigGroup> 0026 #include <QDialogButtonBox> 0027 0028 #include "settings.h" 0029 0030 NetworkDialog::NetworkDialog(bool client, QWidget* parent, const QUrl* url) 0031 : QDialog(parent) 0032 , m_publisher(nullptr), m_client(client) 0033 { 0034 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); 0035 QVBoxLayout *topLayout = new QVBoxLayout; 0036 setLayout(topLayout); 0037 m_okButton = buttonBox->button(QDialogButtonBox::Ok); 0038 m_okButton->setDefault(true); 0039 m_okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0040 connect(buttonBox, &QDialogButtonBox::accepted, this, &NetworkDialog::slotOkClicked); 0041 connect(buttonBox, &QDialogButtonBox::rejected, this, &NetworkDialog::reject); 0042 0043 QLabel* tmp; 0044 QWidget* main = new QWidget(this); 0045 0046 QHBoxLayout* tmpLayout; 0047 QVBoxLayout* mainLayout = new QVBoxLayout; 0048 0049 // feedback 0050 m_feedback = new QLabel(QLatin1String(""), this); 0051 m_feedback->setAlignment(Qt::AlignHCenter); 0052 { 0053 QFont font = m_feedback->font(); 0054 font.setStyle(QFont::StyleItalic); 0055 m_feedback->setFont(font); 0056 } 0057 m_feedback->hide(); 0058 mainLayout->addWidget(m_feedback); 0059 0060 // nick 0061 tmp = new QLabel(i18n("&Nickname:"), main); 0062 m_nickname = new KLineEdit(main); 0063 m_nickname->setClearButtonEnabled(true); 0064 m_nickname->setText(Settings::findNick()); 0065 tmp->setBuddy(m_nickname); 0066 tmpLayout = new QHBoxLayout; 0067 tmpLayout->addWidget(tmp); 0068 tmpLayout->addWidget(m_nickname, 1); 0069 mainLayout->addItem(tmpLayout); 0070 0071 // client part 0072 if (m_client) { 0073 tmp = new QLabel(i18n("&Join game:"), main); 0074 m_games=new KComboBox(main); 0075 KDNSSD::ServiceBrowser* browser=new KDNSSD::ServiceBrowser(QStringLiteral("_kbattleship._tcp"), true); 0076 m_games->setModel(new KDNSSD::ServiceModel(browser, this)); 0077 tmp->setBuddy(m_games); 0078 tmpLayout = new QHBoxLayout; 0079 tmpLayout->addWidget(tmp); 0080 tmpLayout->addWidget(m_games, 1); 0081 connect(m_games, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this, &NetworkDialog::serviceSelected); 0082 mainLayout->addItem(tmpLayout); 0083 0084 QWidget* frame=new QWidget(main); 0085 QVBoxLayout* frameLayout = new QVBoxLayout; 0086 0087 const QString hostName = url? url->host() : Settings::hostname(); 0088 tmp = new QLabel(i18n("&Hostname:"), frame); 0089 m_hostname = new KLineEdit(main); 0090 m_hostname->setClearButtonEnabled(true); 0091 m_hostname->setText(hostName); 0092 tmp->setBuddy(m_hostname); 0093 tmpLayout = new QHBoxLayout; 0094 tmpLayout->addWidget(tmp); 0095 tmpLayout->addWidget(m_hostname, 1); 0096 //TODO PORT QT5 tmpLayout->setSpacing(QDialog::spacingHint()); 0097 frameLayout->addItem(tmpLayout); 0098 0099 // port 0100 const int port = ( url && url->port() != -1 )? url->port(): Settings::port(); 0101 tmp = new QLabel(i18n("&Port:"), main); 0102 m_port = new KPluralHandlingSpinBox(main); 0103 m_port->setRange(1, 99999); 0104 m_port->setValue(port); 0105 tmp->setBuddy(m_port); 0106 tmpLayout = new QHBoxLayout; 0107 tmpLayout->addWidget(tmp); 0108 tmpLayout->addStretch(); 0109 tmpLayout->addWidget(m_port); 0110 frameLayout->addItem(tmpLayout); 0111 frame->setLayout(frameLayout); 0112 0113 mainLayout->addWidget(frame); 0114 frame->setVisible(false); 0115 0116 QPushButton* sw=new QPushButton(i18n("&Enter server address manually"), main); 0117 sw->setCheckable(true); 0118 connect(sw, &QPushButton::toggled, frame, &QWidget::setVisible); 0119 connect(sw, &QPushButton::toggled, m_games, &KComboBox::setDisabled); 0120 mainLayout->addWidget(sw); 0121 if(url) { 0122 sw->click(); 0123 } 0124 0125 } 0126 else { 0127 m_hostname = nullptr; 0128 m_games = nullptr; 0129 0130 // port 0131 tmp = new QLabel(i18n("&Port:"), main); 0132 m_port = new KPluralHandlingSpinBox(main); 0133 m_port->setRange(1, 99999); 0134 m_port->setValue(Settings::port()); 0135 tmp->setBuddy(m_port); 0136 tmpLayout = new QHBoxLayout; 0137 tmpLayout->addWidget(tmp); 0138 tmpLayout->addStretch(); 0139 tmpLayout->addWidget(m_port); 0140 mainLayout->addItem(tmpLayout); 0141 } 0142 mainLayout->addStretch(); 0143 0144 main->setLayout(mainLayout); 0145 topLayout->addWidget(main); 0146 topLayout->addWidget(buttonBox); 0147 0148 setWindowTitle(i18n("Network Parameters")); 0149 0150 connect(this, &NetworkDialog::accepted, this, &NetworkDialog::savePreferences); 0151 0152 } 0153 0154 NetworkDialog::~NetworkDialog() 0155 { 0156 delete m_publisher; 0157 } 0158 0159 void NetworkDialog::savePreferences() 0160 { 0161 Settings::setNickname(nickname()); 0162 if (m_hostname) { 0163 Settings::setHostname(hostname()); 0164 } 0165 Settings::setPort(port()); 0166 Settings::self()->save(); 0167 } 0168 0169 void NetworkDialog::serviceSelected(int idx) 0170 { 0171 if (idx==-1) { 0172 return; 0173 } 0174 KDNSSD::RemoteService::Ptr service=m_games->itemData(idx,KDNSSD::ServiceModel::ServicePtrRole ).value<KDNSSD::RemoteService::Ptr>(); 0175 m_hostname->setText(service->hostName()); 0176 m_port->setValue(service->port()); 0177 } 0178 0179 QString NetworkDialog::hostname() const 0180 { 0181 if (m_hostname) { 0182 return m_hostname->text(); 0183 } 0184 else { 0185 return QString(); 0186 } 0187 } 0188 0189 int NetworkDialog::port() const 0190 { 0191 return m_port->value(); 0192 } 0193 0194 QString NetworkDialog::nickname() const 0195 { 0196 return m_nickname->text(); 0197 } 0198 0199 QTcpSocket* NetworkDialog::socket() const 0200 { 0201 return m_socket; 0202 } 0203 0204 void NetworkDialog::slotOkClicked() 0205 { 0206 m_okButton->setEnabled(false); 0207 m_feedback->show(); 0208 0209 if (m_client) { 0210 m_feedback->setText(i18n("Connecting to remote host...")); 0211 m_socket = new QTcpSocket; 0212 connect(m_socket, &QTcpSocket::connected, this, &NetworkDialog::clientOK); 0213 connect(m_socket, &QTcpSocket::errorOccurred, this, &NetworkDialog::clientError); 0214 m_socket->connectToHost(m_hostname->text(), m_port->value()); 0215 } 0216 else { 0217 m_feedback->setText(i18n("Waiting for an incoming connection...")); 0218 QTcpServer* server = new QTcpServer; 0219 connect(server, &QTcpServer::newConnection, this, &NetworkDialog::serverOK); 0220 m_publisher=new KDNSSD::PublicService(nickname(), QStringLiteral("_kbattleship._tcp"), m_port->value()); 0221 m_publisher->publishAsync(); 0222 0223 server->listen(QHostAddress::Any, static_cast<quint16>(m_port->value())); 0224 } 0225 } 0226 0227 void NetworkDialog::clientOK() 0228 { 0229 accept(); 0230 } 0231 0232 void NetworkDialog::clientError() 0233 { 0234 m_socket->deleteLater(); 0235 m_socket = nullptr; 0236 m_feedback->setText(i18n("Could not connect to host")); 0237 m_okButton->setEnabled(true); 0238 } 0239 0240 void NetworkDialog::serverOK() 0241 { 0242 QTcpServer* server = qobject_cast<QTcpServer*>(sender()); 0243 Q_ASSERT(server); 0244 0245 m_socket = server->nextPendingConnection(); 0246 Q_ASSERT(m_socket); 0247 0248 // refuse all other connections 0249 while (server->hasPendingConnections()) { 0250 delete server->nextPendingConnection(); 0251 } 0252 0253 // reparent socket, so that we can safely destroy the server 0254 m_socket->setParent(this); 0255 delete server; 0256 0257 // we're done 0258 accept(); 0259 } 0260 0261 #include "moc_networkdialog.cpp"