1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QtWidgets>
52#include <QtNetwork>
53
54#include "client.h"
55
56//! [0]
57Client::Client(QWidget *parent)
58 : QDialog(parent)
59 , hostCombo(new QComboBox)
60 , portLineEdit(new QLineEdit)
61 , getFortuneButton(new QPushButton(tr("Get Fortune")))
62 , tcpSocket(new QTcpSocket(this))
63{
64 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
65//! [0]
66 hostCombo->setEditable(true);
67 // find out name of this machine
68 QString name = QHostInfo::localHostName();
69 if (!name.isEmpty()) {
70 hostCombo->addItem(name);
71 QString domain = QHostInfo::localDomainName();
72 if (!domain.isEmpty())
73 hostCombo->addItem(name + QChar('.') + domain);
74 }
75 if (name != QLatin1String("localhost"))
76 hostCombo->addItem(QString("localhost"));
77 // find out IP addresses of this machine
78 QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
79 // add non-localhost addresses
80 for (int i = 0; i < ipAddressesList.size(); ++i) {
81 if (!ipAddressesList.at(i).isLoopback())
82 hostCombo->addItem(ipAddressesList.at(i).toString());
83 }
84 // add localhost addresses
85 for (int i = 0; i < ipAddressesList.size(); ++i) {
86 if (ipAddressesList.at(i).isLoopback())
87 hostCombo->addItem(ipAddressesList.at(i).toString());
88 }
89
90 portLineEdit->setValidator(new QIntValidator(1, 65535, this));
91
92 auto hostLabel = new QLabel(tr("&Server name:"));
93 hostLabel->setBuddy(hostCombo);
94 auto portLabel = new QLabel(tr("S&erver port:"));
95 portLabel->setBuddy(portLineEdit);
96
97 statusLabel = new QLabel(tr("This examples requires that you run the "
98 "Fortune Server example as well."));
99
100 getFortuneButton->setDefault(true);
101 getFortuneButton->setEnabled(false);
102
103 auto quitButton = new QPushButton(tr("Quit"));
104
105 auto buttonBox = new QDialogButtonBox;
106 buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
107 buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
108
109//! [1]
110 in.setDevice(tcpSocket);
111 in.setVersion(QDataStream::Qt_4_0);
112//! [1]
113
114 connect(hostCombo, &QComboBox::editTextChanged,
115 this, &Client::enableGetFortuneButton);
116 connect(portLineEdit, &QLineEdit::textChanged,
117 this, &Client::enableGetFortuneButton);
118 connect(getFortuneButton, &QAbstractButton::clicked,
119 this, &Client::requestNewFortune);
120 connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
121//! [2] //! [3]
122 connect(tcpSocket, &QIODevice::readyRead, this, &Client::readFortune);
123//! [2] //! [4]
124 connect(tcpSocket, &QAbstractSocket::errorOccurred,
125//! [3]
126 this, &Client::displayError);
127//! [4]
128
129 QGridLayout *mainLayout = nullptr;
130 if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
131 auto outerVerticalLayout = new QVBoxLayout(this);
132 outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
133 auto outerHorizontalLayout = new QHBoxLayout;
134 outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
135 auto groupBox = new QGroupBox(QGuiApplication::applicationDisplayName());
136 mainLayout = new QGridLayout(groupBox);
137 outerHorizontalLayout->addWidget(groupBox);
138 outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
139 outerVerticalLayout->addLayout(outerHorizontalLayout);
140 outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
141 } else {
142 mainLayout = new QGridLayout(this);
143 }
144 mainLayout->addWidget(hostLabel, 0, 0);
145 mainLayout->addWidget(hostCombo, 0, 1);
146 mainLayout->addWidget(portLabel, 1, 0);
147 mainLayout->addWidget(portLineEdit, 1, 1);
148 mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
149 mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
150
151 setWindowTitle(QGuiApplication::applicationDisplayName());
152 portLineEdit->setFocus();
153//! [5]
154}
155//! [5]
156
157//! [6]
158void Client::requestNewFortune()
159{
160 getFortuneButton->setEnabled(false);
161 tcpSocket->abort();
162//! [7]
163 tcpSocket->connectToHost(hostCombo->currentText(),
164 portLineEdit->text().toInt());
165//! [7]
166}
167//! [6]
168
169//! [8]
170void Client::readFortune()
171{
172 in.startTransaction();
173
174 QString nextFortune;
175 in >> nextFortune;
176
177 if (!in.commitTransaction())
178 return;
179
180 if (nextFortune == currentFortune) {
181 QTimer::singleShot(0, this, &Client::requestNewFortune);
182 return;
183 }
184
185 currentFortune = nextFortune;
186 statusLabel->setText(currentFortune);
187 getFortuneButton->setEnabled(true);
188}
189//! [8]
190
191//! [13]
192void Client::displayError(QAbstractSocket::SocketError socketError)
193{
194 switch (socketError) {
195 case QAbstractSocket::RemoteHostClosedError:
196 break;
197 case QAbstractSocket::HostNotFoundError:
198 QMessageBox::information(this, tr("Fortune Client"),
199 tr("The host was not found. Please check the "
200 "host name and port settings."));
201 break;
202 case QAbstractSocket::ConnectionRefusedError:
203 QMessageBox::information(this, tr("Fortune Client"),
204 tr("The connection was refused by the peer. "
205 "Make sure the fortune server is running, "
206 "and check that the host name and port "
207 "settings are correct."));
208 break;
209 default:
210 QMessageBox::information(this, tr("Fortune Client"),
211 tr("The following error occurred: %1.")
212 .arg(tcpSocket->errorString()));
213 }
214
215 getFortuneButton->setEnabled(true);
216}
217//! [13]
218
219void Client::enableGetFortuneButton()
220{
221 getFortuneButton->setEnabled(!hostCombo->currentText().isEmpty() &&
222 !portLineEdit->text().isEmpty());
223
224}
225