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

Last change on this file since 468 was 436, checked in by Sanahuja Guillaume, 3 years ago

gcs:sync graphs

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