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"