source: flair-src/trunk/tools/FlairGCS/src/Manager.cpp@ 235

Last change on this file since 235 was 234, checked in by Sanahuja Guillaume, 6 years ago

create file oscket only when necessary

File size: 10.5 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
4// %flair:license}
5#include "Manager.h"
6#include "UdtSocket.h"
7#include "ConnectionLayout.h"
8#include "communication.h"
9#include "file_ui.h"
10#include <QDate>
11#include <QFileDialog>
12#include <QMessageBox>
13#include <QPushButton>
14#include <QTabBar>
15#include <QTimer>
16#include <QThread>
17#include <QTextStream>
18#include <QVBoxLayout>
19#include <QModelIndex>
20#include <QStatusBar>
21#include <qendian.h>
22#include <iostream>
23#include <string>
24#include <fstream>
25#include <stdio.h>
26
27#ifndef WIN32
28#include <arpa/inet.h>
29#else
30#include <winsock2.h>
31#include <ws2tcpip.h>
32#endif
33
34using namespace std;
35
36Manager::Manager(QString name, int port) : QWidget() {
37 qRegisterMetaType<QModelIndex>("QModelIndex"); // pour le file ui??
38 this->name = name;
39//fprintf(stderr,"Manager %x\n",thread());
40 setWindowTitle(name);
41
42 // manager layout
43 managerLayout = new QVBoxLayout;
44 setLayout(managerLayout);
45
46 // tab bar for multiple connections
47 tabBar = new QTabBar();
48 managerLayout->addWidget(tabBar);
49 connect(tabBar, SIGNAL(currentChanged(int)), this,
50 SLOT(tabBarCurrentChanged(int)));
51 currentTab = 0;
52
53 // layout boutons
54 button_layout = new QGridLayout();
55 managerLayout->addLayout(button_layout);
56
57 // boutons du button_Layout
58 send_button = new QPushButton("apply all");
59 reset_button = new QPushButton("reset all");
60 load_button = new QPushButton("load all locally");
61 save_button = new QPushButton("save all locally");
62 button_layout->addWidget(send_button, 0, 0);
63 button_layout->addWidget(reset_button, 0, 1);
64 button_layout->addWidget(load_button, 0, 2);
65 button_layout->addWidget(save_button, 0, 3);
66
67 connect(send_button, SIGNAL(clicked(bool)), this, SLOT(send()));
68 connect(reset_button, SIGNAL(clicked(bool)), this, SLOT(reset()));
69 connect(load_button, SIGNAL(clicked(bool)), this, SLOT(load()));
70 connect(save_button, SIGNAL(clicked(bool)), this, SLOT(save()));
71
72 status=new QStatusBar();
73 status->setSizeGripEnabled(false);
74 button_layout->addWidget(status, 1,0);
75
76 UDT::startup();
77 serv = UDT::socket(AF_INET, SOCK_DGRAM, 0);
78
79 // for non blocking accept
80 bool blocking = false;
81 UDT::setsockopt(serv, 0, UDT_RCVSYN, &blocking, sizeof(bool));
82//UDT::setsockopt(serv, 0, UDT_CC, new CCCFactory<CUDPBlast>, sizeof(CCCFactory<CUDPBlast>));
83 sockaddr_in my_addr;
84 my_addr.sin_family = AF_INET;
85 my_addr.sin_port = htons(port);
86 my_addr.sin_addr.s_addr = INADDR_ANY;
87 memset(&(my_addr.sin_zero), '\0', 8);
88
89 if (UDT::ERROR == UDT::bind(serv, (sockaddr *)&my_addr, sizeof(my_addr))) {
90 printf("bind error, %s\n", UDT::getlasterror().getErrorMessage());
91 }
92
93 if (UDT::ERROR == UDT::listen(serv, 1)) {
94 printf("listen error, %s\n", UDT::getlasterror().getErrorMessage());
95 }
96
97 QTimer *timer = new QTimer(this);
98 connect(timer, SIGNAL(timeout()), this, SLOT(acceptConnections()));
99 timer->start(500);
100}
101
102Manager::~Manager() {
103 printf("%i\n",udtSockets.count());
104 for (int i = 0; i < udtSockets.count(); i++) {
105 udtSockets.at(i)->kill();
106 udtSockets.at(i)->thread()->wait();
107 }
108
109 // delete main_layout;
110 UDT::cleanup();
111 printf("ok\n");
112}
113
114void Manager::acceptConnections(void) {
115 UDTSOCKET socket;
116
117 sockaddr_in their_addr;
118 int namelen = sizeof(their_addr);
119
120 if (UDT::INVALID_SOCK ==(socket = UDT::accept(serv, (sockaddr *)&their_addr, &namelen))) {
121 if (UDT::getlasterror().getErrorCode() != 6002)
122 printf("accept error: %s, code %i\n", UDT::getlasterror().getErrorMessage(),UDT::getlasterror().getErrorCode());
123 return;
124 } else {
125 QString name=QString("%1:%2").arg(inet_ntoa(their_addr.sin_addr)).arg(their_addr.sin_port);
126 printf("connected to %s\n",name.toLocal8Bit().constData());
127
128 QThread *thread = new QThread(this);
129 UdtSocket *udtSocket = new UdtSocket(socket,name);
130 udtSocket->moveToThread(thread);
131 udtSockets.append(udtSocket);
132
133 connect(udtSocket, SIGNAL(newFileUI(UDTSOCKET)), this, SLOT(newFileUI(UDTSOCKET)));
134 connect(udtSocket, SIGNAL(newConnectionLayout(QString)), this, SLOT(newConnectionLayout(QString)),Qt::BlockingQueuedConnection);
135 connect(thread, SIGNAL(started()), udtSocket, SLOT(receiveData()));
136
137 thread->start();
138 }
139}
140
141void Manager::newConnectionLayout(QString name) {
142 UdtSocket* udtSocket=(UdtSocket *)sender();
143
144 ConnectionLayout *newLayout = new ConnectionLayout(udtSocket, name);
145 connectionsLayout.append(newLayout);
146 connect(udtSocket, SIGNAL(UDTStats(QString)), newLayout, SIGNAL(UDTStats(QString)));//connection in 2 steps to get udtsocket as sender
147 connect(newLayout, SIGNAL(UDTStats(QString)), this, SLOT(printUDTStats(QString)));
148 connect(udtSocket, SIGNAL(dataReady(char *, int)), newLayout,SLOT(receive(char *, int)),Qt::BlockingQueuedConnection);
149 connect(newLayout, SIGNAL(destroyed(QObject *)), this, SLOT(layoutDestroyed(QObject *)));
150 connect(udtSocket, SIGNAL(destroyed()), newLayout, SLOT(deleteLater()));
151
152 // widget
153 QWidget *newWidget = new QWidget();
154 connectionsWidget.append(newWidget);
155 newWidget->setLayout(newLayout->getQGridLayout());
156 managerLayout->insertWidget(1, newWidget);
157 newWidget->hide();
158
159 //tab: avoid having only 1 tab (0, 2 or more)
160 if (connectionsLayout.count() == 1) { // first connection
161 connectionsWidget.at(0)->show();
162 hiddenTabName = name;
163 }
164 if (connectionsLayout.count() == 2) {
165 tabBar->addTab(hiddenTabName);
166 currentTab = 0;
167 }
168 if (connectionsLayout.count() > 1) {
169 tabBar->addTab(name);
170 }
171}
172
173void Manager::layoutDestroyed(QObject *obj) {
174 int index = connectionsLayout.indexOf((ConnectionLayout *)obj);
175
176 //tab: avoid having only 1 tab (0, 2 or more)
177 if (tabBar->count() > 1) {
178 tabBar->removeTab(index);
179 }
180
181 delete connectionsWidget.at(index);
182 connectionsWidget.removeAt(index);
183 connectionsLayout.removeOne((ConnectionLayout *)obj);
184
185 if (connectionsLayout.count() == 1) {
186 hiddenTabName = tabBar->tabText(0);
187 tabBar->removeTab(0);
188 }
189
190 if (connectionsLayout.count() == 0) {
191 status->showMessage("");
192 }
193}
194
195void Manager::newFileUI(UDTSOCKET socket) {
196 //remove udtsocket as it will be automatically destroyed
197 udtSockets.removeOne((UdtSocket *)sender());
198
199 QThread *thread = new QThread(this);
200 file_ui* fileUi = new file_ui(socket,name);
201 fileUi->moveToThread(thread);
202 connect(thread, SIGNAL(started()), fileUi, SLOT(receive()));
203 connect(fileUi, SIGNAL(finished()), this, SLOT(deleteFileUI()));
204 thread->start();
205}
206
207void Manager::deleteFileUI(void) {
208 sender()->thread()->quit();
209 delete sender();
210}
211
212void Manager::printUDTStats(QString stats) {
213 int index = connectionsLayout.indexOf((ConnectionLayout *)sender());
214 if(index==-1) return;
215
216 if (tabBar->count() == 0) {
217 status->showMessage(stats);
218 } else if (index==tabBar->currentIndex()) {
219 status->showMessage(QString("%1: %2").arg(tabBar->tabText(index)).arg(stats));
220 }
221}
222
223void Manager::tabBarCurrentChanged(int index) {
224 if (index >= 0) {
225 connectionsWidget.at(currentTab)->hide();
226 connectionsWidget.at(index)->show();
227 currentTab = index;
228 } else {
229 currentTab = 0;
230 connectionsWidget.at(0)->show();
231 }
232
233 if (tabBar->count() == 0) {
234 status->showMessage(connectionsLayout.at(0)->getUDTStats());
235 } else {
236 status->showMessage(QString("%1: %2").arg(tabBar->tabText(index)).arg(connectionsLayout.at(index)->getUDTStats()));
237 }
238}
239
240void Manager::load(void) {
241 QString dir_name =
242 QFileDialog::getExistingDirectory(this, "Select a directory", 0, 0);
243
244 if (dir_name != "") {
245 for (int i = 0; i < connectionsLayout.count(); i++) {
246 QFile *file;
247 file = new QFile(dir_name + "/" +
248 connectionsLayout.at(i)->getName() + ".xml");
249 if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
250 QMessageBox::warning(this, "Warning",
251 "Enable to load " +
252 connectionsLayout.at(i)->getName() +
253 ".xml");
254 continue;
255 }
256
257 QDomDocument doc;
258 QString errorMsg;
259 int errorLine;
260 int errorColumn;
261 if (!doc.setContent(file, &errorMsg, &errorLine, &errorColumn)) {
262 QMessageBox::critical(
263 this, "Error",
264 "unable to read " + connectionsLayout.at(i)->getName() +
265 ".xml" + " (" + errorMsg + " at " + QString::number(errorLine) +
266 "," + QString::number(errorColumn) + ")");
267 } else {
268 connectionsLayout.at(i)->LoadXml(doc);
269 }
270 delete file;
271 }
272 }
273}
274
275void Manager::save(void) {
276 bool isUptodate = true;
277
278 for (int i = 0; i < connectionsLayout.count(); i++) {
279 if (!connectionsLayout.at(i)->IsUptodate()) {
280 isUptodate = false;
281 break;
282 }
283 }
284
285 if (!isUptodate) {
286 QMessageBox msgBox;
287 msgBox.setText("There are pending modifications");
288 msgBox.setInformativeText("Apply and save?");
289 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
290 msgBox.setDefaultButton(QMessageBox::Yes);
291 int ret = msgBox.exec();
292
293 switch (ret) {
294 case QMessageBox::Yes:
295 send();
296 break;
297 case QMessageBox::Cancel:
298 return;
299 break;
300 default:
301 // should never be reached
302 break;
303 }
304 }
305
306 // create dirctory for storage
307 QDateTime dateTime = QDateTime::currentDateTime();
308 QString dir_name =
309 "configs_" + dateTime.toString("yyyyMMdd_hhmm") + "_" + name;
310 if (QDir().exists(dir_name) == true) {
311 dir_name = "configs_" + dateTime.toString("yyyyMMdd_hhmm_ss") + "_" + name;
312 }
313 QDir().mkdir(dir_name);
314
315 for (int i = 0; i < connectionsLayout.count(); i++) {
316 QDomDocument *xml = new QDomDocument("remote_ui_xml");
317
318 connectionsLayout.at(i)->GetFullXml((QDomElement *)xml);
319
320 QFile fichier(dir_name + "/" + connectionsLayout.at(i)->getName() +
321 ".xml");
322 QString write_doc = (xml->ownerDocument()).toString();
323
324 if (!fichier.open(QIODevice::WriteOnly)) {
325 fichier.close();
326 QMessageBox::critical(this, "Error", "Enable to write XML");
327 continue;
328 }
329 QTextStream stream(&fichier);
330 stream << write_doc;
331 fichier.close();
332
333 delete xml;
334 }
335
336 QMessageBox::information(this, "save all", "saved to ./" + dir_name);
337}
338
339void Manager::send(void) {
340 for (int i = 0; i < connectionsLayout.count(); i++) {
341 QDomDocument doc("remote_ui_xml");
342 connectionsLayout.at(i)->GetUpdateXml((QDomElement *)&doc);
343 // printf("merge\n%s\n",doc.toString().toLocal8Bit().constData());
344
345 connectionsLayout.at(i)->XmlToSend(doc);
346 }
347}
348
349void Manager::reset() {
350 for (int i = 0; i < connectionsLayout.count(); i++)
351 connectionsLayout.at(i)->ResetAllChilds();
352}
Note: See TracBrowser for help on using the repository browser.