1 #include "server_config_dialog.h"
2 #include <QCoreApplication>
3 #include <QGridLayout>
4 #include <QNetworkInterface>
5 #include <QHostInfo>
6 #include <QHostAddress>
7 #include <QSettings>
8 #include <QPalette>
9 #include <QIntValidator>
10 #include <QFormLayout>
11 #include <QBitmap>
12 #include <QPainter>
13
14 #include "startup.h"
15 #include "yacreader_global_gui.h"
16
17 #include "qnaturalsorting.h"
18
19 #include <algorithm>
20
21 //192.168 (most comon local subnet for ips are always put first)
22 //IPs are sorted using natoral sorting
ipComparator(const QString & ip1,const QString & ip2)23 bool ipComparator(const QString &ip1, const QString &ip2)
24 {
25 if (ip1.startsWith("192.168") && ip2.startsWith("192.168"))
26 return naturalSortLessThanCI(ip1, ip2);
27
28 if (ip1.startsWith("192.168"))
29 return true;
30
31 if (ip2.startsWith("192.168"))
32 return false;
33
34 return naturalSortLessThanCI(ip1, ip2);
35 }
36
37 #ifndef Q_OS_WIN32
38
39 #include <sys/types.h>
40 #include <ifaddrs.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <string.h>
44 #include <arpa/inet.h>
45
addresses()46 QList<QString> addresses()
47 {
48 struct ifaddrs *ifAddrStruct = NULL;
49 struct ifaddrs *ifa = NULL;
50 void *tmpAddrPtr = NULL;
51
52 QList<QString> localAddreses;
53
54 getifaddrs(&ifAddrStruct);
55
56 for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
57 if (ifa->ifa_addr) {
58 if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
59 // is a valid IP4 Address
60 tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
61 char addressBuffer[INET_ADDRSTRLEN];
62 inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
63 localAddreses.push_back(QString(addressBuffer));
64 //printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
65 } else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
66 // is a valid IP6 Address
67 tmpAddrPtr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
68 char addressBuffer[INET6_ADDRSTRLEN];
69 inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
70 //printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
71 }
72 }
73 }
74 if (ifAddrStruct != NULL)
75 freeifaddrs(ifAddrStruct);
76 return localAddreses;
77 }
78
79 #endif
80
81 extern Startup *s;
82
ServerConfigDialog(QWidget * parent)83 ServerConfigDialog::ServerConfigDialog(QWidget *parent)
84 : QDialog(parent)
85 {
86 accept = new QPushButton(tr("set port"), this);
87 qrCode = new QLabel(this);
88 qrCode->move(64, 112);
89 qrCode->setFixedSize(200, 200);
90 qrCode->setScaledContents(true);
91
92 QLabel *title1 = new QLabel(tr("Server connectivity information"), this);
93 title1->move(332, 61);
94 title1->setStyleSheet("QLabel {color:#474747; font-size:30px; font-family: Arial;}");
95
96 QLabel *qrMessage = new QLabel(tr("Scan it!"), this);
97 qrMessage->move(135, 388); //373,627);
98 qrMessage->setStyleSheet("QLabel {color:#A3A3A3; font-size:18px; font-family: Arial;}");
99 qrMessage->setWordWrap(true);
100 qrMessage->setFixedWidth(200);
101
102 QLabel *propaganda = new QLabel(tr("YACReader is available for iOS devices. <a href='http://ios.yacreader.com' style='color:rgb(193, 148, 65)'> Discover it! </a>"), this);
103 propaganda->move(332, 505);
104 propaganda->setStyleSheet("QLabel {color:#4D4D4D; font-size:13px; font-family: Arial; font-style: italic;}");
105 /*propaganda->setWordWrap(true);
106 propaganda->setFixedWidth(590);*/
107 propaganda->setOpenExternalLinks(true);
108
109 //FORM---------------------------------------------------------------------
110
111 QLabel *ipLabel = new QLabel(tr("Choose an IP address"), this);
112 ipLabel->move(332, 117);
113 ipLabel->setStyleSheet("QLabel {color:#575757; font-size:18px; font-family: Arial;}");
114
115 QLabel *portLabel = new QLabel(tr("Port"), this);
116 portLabel->move(332, 211);
117 portLabel->setStyleSheet("QLabel {color:#575757; font-size:18px; font-family: Arial;}");
118
119 ip = new QComboBox(this);
120 connect(ip, SIGNAL(activated(const QString &)), this, SLOT(regenerateQR(const QString &)));
121
122 ip->setFixedWidth(200);
123 ip->move(332, 153);
124
125 port = new QLineEdit("8080", this);
126 port->setReadOnly(false);
127 //port->setFixedWidth(100);
128 //port->move(332, 244);
129
130 //port->move(520,110);
131 QValidator *validator = new QIntValidator(1024, 65535, this);
132 port->setValidator(validator);
133
134 QWidget *portWidget = new QWidget(this);
135 auto portWidgetLayout = new QHBoxLayout(this);
136 portWidgetLayout->addWidget(port);
137 portWidgetLayout->addWidget(accept);
138 portWidgetLayout->setMargin(0);
139 portWidget->setLayout(portWidgetLayout);
140 portWidget->move(332, 244);
141 //accept->move(514,149);
142 connect(accept, SIGNAL(pressed()), this, SLOT(updatePort()));
143 //END FORM-----------------------------------------------------------------
144
145 check = new QCheckBox(this);
146 check->move(332, 314);
147 check->setText(tr("enable the server"));
148 check->setStyleSheet("QCheckBox {color:#262626; font-size:13px; font-family: Arial;}");
149
150 performanceWorkaroundCheck = new QCheckBox(this);
151 performanceWorkaroundCheck->move(332, 354);
152 performanceWorkaroundCheck->setText(tr("display less information about folders in the browser\nto improve the performance"));
153 performanceWorkaroundCheck->setStyleSheet("QCheckBox {color:#262626; font-size:13px; font-family: Arial;}");
154
155 // set black background
156 QPalette palette;
157 QImage image(":/images/serverConfigBackground.png");
158 palette.setBrush(this->backgroundRole(), QBrush(image));
159
160 setPalette(palette);
161
162 this->setFixedSize(image.size());
163
164 QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
165 settings->beginGroup("libraryConfig");
166
167 if (settings->value(SERVER_ON, true).toBool()) {
168 check->setChecked(true);
169 generateQR();
170 } else
171 check->setChecked(false);
172
173 performanceWorkaroundCheck->setChecked(settings->value(REMOTE_BROWSE_PERFORMANCE_WORKAROUND, false).toBool());
174
175 settings->endGroup();
176
177 connect(check, SIGNAL(stateChanged(int)), this, SLOT(enableServer(int)));
178 connect(performanceWorkaroundCheck, SIGNAL(stateChanged(int)), this, SLOT(enableperformanceWorkaround(int)));
179 }
180
enableServer(int status)181 void ServerConfigDialog::enableServer(int status)
182 {
183 QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
184 settings->beginGroup("libraryConfig");
185
186 if (status == Qt::Checked) {
187 s->start();
188 this->generateQR();
189 settings->setValue(SERVER_ON, true);
190 } else {
191 s->stop();
192 qrCode->setPixmap(QPixmap());
193 ip->clear();
194 port->setText("");
195 settings->setValue(SERVER_ON, false);
196 }
197 settings->endGroup();
198 }
199
enableperformanceWorkaround(int status)200 void ServerConfigDialog::enableperformanceWorkaround(int status)
201 {
202 QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
203 settings->beginGroup("libraryConfig");
204
205 if (status == Qt::Checked) {
206 settings->setValue(REMOTE_BROWSE_PERFORMANCE_WORKAROUND, true);
207 } else {
208 settings->setValue(REMOTE_BROWSE_PERFORMANCE_WORKAROUND, false);
209 }
210 settings->endGroup();
211 }
212
generateQR()213 void ServerConfigDialog::generateQR()
214 {
215 ip->clear();
216 QString dir;
217
218 #ifdef Q_OS_WIN32
219 QList<QHostAddress> list = QHostInfo::fromName(QHostInfo::localHostName()).addresses();
220
221 QList<QString> otherAddresses;
222 foreach (QHostAddress add, list) {
223 QString tmp = add.toString();
224 if (tmp.contains(".") && !tmp.startsWith("127")) {
225 otherAddresses.push_back(tmp);
226 }
227 }
228
229 #else
230 QList<QString> list = addresses();
231
232 QList<QString> otherAddresses;
233 foreach (QString add, list) {
234 QString tmp = add;
235 if (tmp.contains(".") && !tmp.startsWith("127")) {
236 otherAddresses.push_back(tmp);
237 }
238 }
239 #endif
240
241 std::sort(otherAddresses.begin(), otherAddresses.end(), ipComparator);
242
243 if (!otherAddresses.isEmpty()) {
244 dir = otherAddresses.first();
245 otherAddresses.pop_front();
246 }
247
248 if (otherAddresses.length() > 0 || !dir.isEmpty()) {
249 if (!dir.isEmpty()) {
250 generateQR(dir + ":" + s->getPort());
251
252 ip->addItem(dir);
253 } else {
254 generateQR(otherAddresses.first() + ":" + s->getPort());
255 }
256 ip->addItems(otherAddresses);
257 port->setText(s->getPort());
258 }
259 }
260
generateQR(const QString & serverAddress)261 void ServerConfigDialog::generateQR(const QString &serverAddress)
262 {
263 qrCode->clear();
264
265 QrEncoder encoder;
266 QBitmap image = encoder.encode(serverAddress);
267 if (image.isNull()) {
268 qrCode->setText(tr("Could not load libqrencode."));
269 } else {
270 image = image.scaled(qrCode->size() * devicePixelRatio());
271
272 QPixmap pMask(image.size());
273 pMask.fill(QColor(66, 66, 66));
274 pMask.setMask(image.createMaskFromColor(Qt::white));
275 pMask.setDevicePixelRatio(devicePixelRatio());
276
277 qrCode->setPixmap(pMask);
278 }
279 }
280
regenerateQR(const QString & ip)281 void ServerConfigDialog::regenerateQR(const QString &ip)
282 {
283 generateQR(ip + ":" + s->getPort());
284 }
285
updatePort()286 void ServerConfigDialog::updatePort()
287 {
288
289 QSettings *settings = new QSettings(YACReader::getSettingsPath() + "/YACReaderLibrary.ini", QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
290 settings->beginGroup("listener");
291 settings->setValue("port", port->text().toInt());
292 settings->endGroup();
293
294 s->stop();
295 s->start();
296
297 generateQR(ip->currentText() + ":" + port->text());
298 }
299
QrEncoder()300 QrEncoder::QrEncoder()
301 {
302 #ifdef Q_OS_MACOS
303 QLibrary encoder(QCoreApplication::applicationDirPath() + "/utils/libqrencode.dylib");
304 #else
305 QLibrary encoder("qrencode");
306 #endif
307 QRcode_encodeString8bit = (_QRcode_encodeString8bit)encoder.resolve("QRcode_encodeString8bit");
308 QRcode_free = (_QRcode_free)encoder.resolve("QRcode_free");
309 }
310
encode(const QString & string)311 QBitmap QrEncoder::encode(const QString &string)
312 {
313 if (!QRcode_encodeString8bit) {
314 return QBitmap();
315 }
316 QRcode *code;
317 code = QRcode_encodeString8bit(string.toUtf8().data(), 0, 0);
318 QBitmap result(code->width, code->width);
319 result.fill();
320 /* convert to QBitmap */
321 QPainter painter;
322 painter.begin(&result);
323 unsigned char *pointer = code->data;
324 for (int x = 0; x < code->width; x++) {
325 for (int y = 0; y < code->width; y++) {
326 if ((*pointer++ & 0x1) == 1) {
327 painter.drawPoint(x, y);
328 }
329 }
330 }
331 painter.end();
332 QRcode_free(code);
333 return result;
334 }
335