Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYResultatWidget.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
21 #include <cstdlib>
22 #include <qradiobutton.h>
23 #include <qbuttongroup.h>
24 #include <qtablewidget.h>
25 #include <qcombobox.h>
26 #include <qmenu.h>
27 #include <qfiledialog.h>
28 #include <qpainter.h>
29 
30 // Added by qt3to4:
31 #include <QHBoxLayout>
32 #include <QBoxLayout>
33 #include <QGridLayout>
34 #include <QFrame>
35 #include <QPixmap>
36 #include <QHeaderView>
37 
38 #include <QtPrintSupport/QPrinter>
39 #include <QtPrintSupport/QPrintDialog>
40 
41 #include "Tympan/core/logging.h"
51 #include "TYResultatTreeDialog.h"
52 #include "TYResultatWidget.h"
53 
54 #define TR(id) OLocalizator::getString("TYResultatWidget", (id))
55 
56 // Declaration de la fonction utilisee par qsort pour le tri des valeurs numerique
57 static int compareRes(const void* elem1, const void* elem2);
58 
59 // Declaration de la fonction utilisee par qsort pour le tri par nom des sources
60 static int compareName(const void* elem1, const void* elem2);
61 
62 TYResultatWidget::TYResultatWidget(TYResultat* pElement, QWidget* _pParent /*=NULL*/)
63  : TYWidget(pElement, _pParent)
64 {
65  _freq = 100;
66  _choixOperation = 0;
67  _max = NULL; // Tableau des maxima par colonne (initialise plus tard)
68  _nbSources = 0;
69  _nbRecepteurs = 0;
70  _nbLignes = 0;
71  _nbColonnes = 0;
72 
73  resize(300, 50);
74  setWindowTitle(TR("id_caption"));
75  _resultatLayout = new QGridLayout();
76  setLayout(_resultatLayout);
77 
78  // Placement de l'element (evite de renumeroter les lignes chaque fois qu'on deplace un widget)
79  int iln = 0;
80 
81  QGroupBox* groupBoxFlag = new QGroupBox(this);
82  groupBoxFlag->setTitle(TR(""));
83  QGridLayout* groupBoxFlagLayout = new QGridLayout();
84  groupBoxFlag->setLayout(groupBoxFlagLayout);
85 
86  // Bouton radio dB(A)/dB(Lin)/dB(freq)
87  QButtonGroup* buttonGroupALIN = new QButtonGroup();
88  _radioButtonDBA = new QRadioButton(TR("id_radiobutton_db_a"));
89  buttonGroupALIN->addButton(_radioButtonDBA, 0);
90  _radioButtonDBLIN = new QRadioButton(TR("id_radiobutton_db_lin"));
91  buttonGroupALIN->addButton(_radioButtonDBLIN, 1);
92  _radioButtonDBFRQ = new QRadioButton(TR("id_radiobutton_db_freq"));
93  buttonGroupALIN->addButton(_radioButtonDBFRQ, 2);
94 
95  _choixAffichage = DBA; // Affichage par defaut dBA
96  _radioButtonDBA->setChecked(true);
97  _radioButtonDBLIN->setChecked(false);
98  _radioButtonDBFRQ->setChecked(false);
99 
100  // ComboBox de choix des frequences
101  _comboBoxFreq = new QComboBox();
102  updateFreqList();
103  _comboBoxFreq->setEnabled(false);
104 
105  // Gestion des seuils de contribution (affichage colore)
106  QLabel* pLabelContribution = new QLabel(this);
107  pLabelContribution->setText(TR("id_label_contribution"));
108 
110  _pContributionLineEdit->setFixedSize(50, 20);
111  _pContributionLineEdit->setText("20");
112 
113  // Ajout au layout
114  QGridLayout* groupBoALINLayout = new QGridLayout();
115  groupBoALINLayout->addWidget(pLabelContribution, 0, 0, Qt::AlignRight);
116  groupBoALINLayout->addWidget(_pContributionLineEdit, 0, 1, Qt::AlignLeft);
117 
118  groupBoALINLayout->addWidget(_radioButtonDBA, 1, 0);
119  groupBoALINLayout->addWidget(_radioButtonDBLIN, 1, 1);
120  groupBoALINLayout->addWidget(_radioButtonDBFRQ, 1, 2);
121 
122  groupBoALINLayout->addWidget(_comboBoxFreq, 1, 3);
123 
124  QGroupBox* groupBoxALIN = new QGroupBox();
125  groupBoxALIN->setTitle(TR(""));
126  groupBoxALIN->setLayout(groupBoALINLayout);
127 
128  groupBoxFlagLayout->addWidget(groupBoxALIN, 0, 0);
129 
130  // Disambiguate the overloaded signals
131  void (QComboBox::*_qComboBox_activated)(int) = &QComboBox::activated;
132  void (QButtonGroup::*_qButtonGroup_clicked)(int) = &QButtonGroup::idClicked;
133 
134  // Choix du type d'operation a effectuer (Aucun / Difference / Emergence / Bruit ambiant)
135  _buttonGroupOperation = new QButtonGroup();
136  _radioButtonNoOp = new QRadioButton((TR("id_radiobutton_noop")));
138  _radioButtonDelta = new QRadioButton(TR("id_radiobutton_delta"));
140  _radioButtonEmergence = new QRadioButton(TR("id_radiobutton_emergence"));
142  _radioButtonAmbiant = new QRadioButton(TR("id_radiobutton_ambiant"));
144 
145  _radioButtonNoOp->setChecked(true);
146  _radioButtonDelta->setChecked(false);
147  _radioButtonEmergence->setChecked(false);
148  _radioButtonAmbiant->setChecked(false);
149 
150  // Choix du calcul associe au resultat
151  QLabel* labelSubstCalcul = new QLabel(this);
152  labelSubstCalcul->setText(TR("id_subst_calcul"));
153  _comboBoxSubstCalcul = new QComboBox(this);
154  connect(_comboBoxSubstCalcul, _qComboBox_activated, this, &TYResultatWidget::changeSubstCalcul);
155 
156  QGridLayout* groupBoxCalculLayout = new QGridLayout();
157  groupBoxCalculLayout->addWidget(_radioButtonNoOp, 0, 0, Qt::AlignLeft);
158  groupBoxCalculLayout->addWidget(_radioButtonDelta, 1, 0, Qt::AlignLeft);
159  groupBoxCalculLayout->addWidget(_radioButtonEmergence, 2, 0, Qt::AlignLeft);
160  groupBoxCalculLayout->addWidget(_radioButtonAmbiant, 3, 0, Qt::AlignLeft);
161  groupBoxCalculLayout->addWidget(labelSubstCalcul, 0, 1, Qt::AlignRight);
162  groupBoxCalculLayout->addWidget(_comboBoxSubstCalcul, 0, 2, Qt::AlignLeft);
163 
164  QGroupBox* groupBoxCalcul = new QGroupBox();
165  groupBoxCalcul->setTitle(TR(""));
166  groupBoxCalcul->setLayout(groupBoxCalculLayout);
167 
168  groupBoxFlagLayout->addWidget(groupBoxCalcul, 0, 1);
169 
170  _resultatLayout->addWidget(groupBoxFlag, iln, 0);
171 
172  // Table des resultats
173  _pTable = new QTableWidget();
174  _pTable->setSelectionMode(QAbstractItemView::NoSelection);
175  _pTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
176  _resultatLayout->addWidget(_pTable, ++iln, 0);
177 
178  QGroupBox* pGroupBox = new QGroupBox(this);
179  QHBoxLayout* pGroupBoxLayout = new QHBoxLayout();
180  pGroupBox->setLayout(pGroupBoxLayout);
181 
182  _pButtonExport = new QPushButton(TR("id_export_global"));
183  pGroupBoxLayout->addWidget(_pButtonExport);
184  _pButtonExport->setEnabled(true);
185 
186  _pButtonExportSpectre = new QPushButton(TR("id_export_spectres"));
187  pGroupBoxLayout->addWidget(_pButtonExportSpectre);
188  _pButtonExportSpectre->setEnabled(true);
189 
190  QPushButton* pButtonPrint = new QPushButton(TR("id_print"));
191  pGroupBoxLayout->addWidget(pButtonPrint);
192 
193  _resultatLayout->addWidget(pGroupBox, ++iln, 0);
194 
195  // Permettre le tri en cliquant sur le haut d'une colonne
196  QHeaderView* entetesRecepteurs =
197  _pTable->horizontalHeader(); // On recupere un pointeur sur les entetes horizontales
198  entetesRecepteurs->resizeSections(QHeaderView::ResizeToContents);
199  QObject::connect(entetesRecepteurs, &QHeaderView::sectionClicked, this, &TYResultatWidget::sortCol);
200 
201  QObject::connect(_pContributionLineEdit, &QLineEdit::textChanged, this,
203  QObject::connect(buttonGroupALIN, _qButtonGroup_clicked, this, &TYResultatWidget::changeAffichage);
204  QObject::connect(_comboBoxFreq, _qComboBox_activated, this, &TYResultatWidget::setFrequency);
205  QObject::connect(_buttonGroupOperation, _qButtonGroup_clicked, this, &TYResultatWidget::changeOperation);
206  QObject::connect(_pButtonExport, &QPushButton::clicked, this, &TYResultatWidget::exportExcel);
207  QObject::connect(_pButtonExportSpectre, &QPushButton::clicked, this, &TYResultatWidget::exportSpectre);
208  QObject::connect(pButtonPrint, &QPushButton::clicked, this, &TYResultatWidget::print);
209 
210  // Tableau pour le tri des resultats
211  _tabSortedRes = new TYStructIndiceResultat[getElement()->getNbOfSources()];
212 
213  _seuilContribution = 20;
214 
215  updateContent();
216 
217  _printer = new QPrinter();
218 }
219 
221 {
222  if (_max)
223  {
224  delete[] _max;
225  }
226 
227  if (_tabSortedRes)
228  {
229  delete[] _tabSortedRes;
230  }
231 
232  if (_printer)
233  {
234  delete _printer;
235  }
236 
237  _max = NULL;
238  _tabSortedRes = NULL;
239  _printer = NULL;
240 }
241 
243 {
244  // ACtualisation du combo des calculs
246 
247  // Par defaut le combo des frequences est positionne a 100 Hz
248  int indFreq = TYSpectre::getIndice(100);
249  _comboBoxFreq->setCurrentIndex(indFreq);
250 
251  _nbSources = static_cast<int>(getElement()->getNbOfSources());
252  _nbRecepteurs = static_cast<int>(getElement()->getNbOfRecepteurs());
253  _nbLignes = _nbSources + 1; // Ajouter la ligne "synthese"
254  _nbColonnes = _nbRecepteurs + 2; // Ajouter les colonnes "Nom sources", et "Puissance source"
255 
256  // Nb lignes = Nb sources + 1 car on ajoute la synthese ligne 1
257  _pTable->setRowCount(_nbLignes);
258 
259  // Nb colonnes = Nb recepteurs + 2 car : nom des sources en colonne 1 et puissance sources en colonne 2
260  _pTable->setColumnCount(_nbColonnes);
261 
262  // une boucle pour mettre les entetes horizontales (numeros des lignes)
263  for (unsigned int row = 0; row < _nbLignes; row++)
264  {
265  _pTable->setVerticalHeaderItem(row, new QTableWidgetItem(QString().setNum(row)));
266  }
267 
269 
270  // L'entete de la colonne 1 indique que cette colonne donne acces a la puissance
271  _pTable->setHorizontalHeaderItem(1, new QTableWidgetItem(QString("LW")));
272 
273  // une boucle pour mettre les nom des recepteurs
274  for (unsigned int col = 0; col < _nbRecepteurs; col++)
275  {
276  if (getElement()->getRecepteur(col) == NULL)
277  {
278  continue;
279  }
280 
281  QString titre = getElement()->getRecepteur(col)->getName();
282  _pTable->setHorizontalHeaderItem(col + 2, new QTableWidgetItem(titre));
283  }
284 
285  // On trie par ordre decroissant des niveaux du premier point
286  sortCol(1);
287 
288  _pTable->setColumnHidden(1, getElement()->isLWHidden());
289 }
290 
292 {
293  QString strVal; // Cree ici car pb avec switch/case
294  // L'entete de la colonne 0 rappelle le choix d'affichage
295  switch (_choixAffichage)
296  {
297  case DBLIN:
298  _pTable->setHorizontalHeaderItem(0, new QTableWidgetItem(QString("dBZ")));
299  break;
300  case DBFREQ:
301  strVal = QString("dB(") + QString("%1").arg(_freq) + QString(" Hz)");
302  _pTable->setHorizontalHeaderItem(0, new QTableWidgetItem(strVal));
303  break;
304  case DBA:
305  default:
306  _pTable->setHorizontalHeaderItem(0, new QTableWidgetItem(QString("dBA")));
307  break;
308  }
309 }
310 
312 
314 {
315  updateTable();
316 }
318 {
319  _comboBoxSubstCalcul->clear();
320 
321  // Remplissage du comboBox des calculs
322  if (_pElement->getParent()->getParent()->isA("TYProjet"))
323  {
324  TYProjet* pProjet = TYProjet::safeDownCast(getElement()->getParent()->getParent());
325 
326  TYTabLPCalcul listCalcul = pProjet->getListCalcul();
327  for (int i = 0; i < listCalcul.size(); i++)
328  {
329  _comboBoxSubstCalcul->insertItem(i, listCalcul[i]->getName());
330  }
331  }
332 
333  // On affiche la forme d'objet courante
334  _comboBoxSubstCalcul->setCurrentIndex(0);
335 
336  // Si mode de calcul = none alors le combo est bloque
337  if (_choixOperation == 0)
338  {
339  _comboBoxSubstCalcul->setEnabled(false);
340  }
341  else
342  {
343  _comboBoxSubstCalcul->setEnabled(true);
344  }
345 }
346 
348 {
349  if (_pElement->getParent()->getParent()->isA("TYProjet"))
350  {
351  if (!_radioButtonNoOp->isChecked())
352  {
353  int calcul = _comboBoxSubstCalcul->currentIndex();
354  TYProjet* pProjet = TYProjet::safeDownCast(getElement()->getParent()->getParent());
355  return pProjet->getListCalcul()[calcul];
356  }
357  }
358  return NULL;
359 }
360 
362 {
363  TYResultat* pResultat = TYResultat::safeDownCast(getElement());
364  if (!pResultat)
365  {
366  return;
367  } // Securite
368 
369  QString qFileName = QFileDialog::getSaveFileName(this, "Choose a file", "", "CSVFile (*.csv)");
370 
371  if (!qFileName.isNull())
372  {
373  if (qFileName.right(3) != "csv")
374  {
375  qFileName += ".csv";
376  }
377 
378  pResultat->saveSpectre(qFileName, getSelectedSubstCalcul());
379  }
380 }
381 
383 {
384  TYResultat* pResultat = TYResultat::safeDownCast(getElement());
385 
386  if (!pResultat)
387  {
388  return;
389  } // Securite
390 
391  QString qFileName = QFileDialog::getSaveFileName(this, "Choose a file", "", "CSVFile (*.csv)");
392 
393  if (!qFileName.isNull())
394  {
395  if (qFileName.right(3) != "csv")
396  {
397  qFileName += ".csv";
398  }
399 
400  pResultat->saveValue(qFileName, _choixAffichage, _freq);
401  }
402 }
403 
404 void TYResultatWidget::contextMenuEvent(QContextMenuEvent* e)
405 {
406  TYCalcul* pCalcul = TYCalcul::safeDownCast(getElement()->getParent());
407  TYCalcul* pSubstCalcul = getSelectedSubstCalcul();
408 
409  QPoint point = _pTable->mapFrom(this, e->pos());
410  if ((point.x() >= 0) && (point.y() >= 0) && (point.x() <= _pTable->width()) &&
411  (point.y() <= _pTable->height()))
412  {
413  QPoint resPoint = QPoint(point.x(), point.y() - _pTable->horizontalHeader()->height());
414  QTableWidgetItem* item = _pTable->itemAt(resPoint);
415  if (item)
416  {
417  int row = _pTable->indexAt(resPoint).row();
418  row = row >= 0 ? row : 0; // Securite
419  int col = _pTable->indexAt(resPoint).column();
420  col = col >= 0 ? col : 0; // Securite
421  int ligne = row > 0 ? _tabSortedRes[row - 1].indice : 0;
422 
423  OSpectre spectre1 = getSpectre(row, col, pCalcul);
424  OSpectre spectre2 = getSpectre(row, col, pSubstCalcul);
425 
426  TYSpectre spectre = resuSpectre(spectre1, spectre2, 1);
427 
428  spectre.setType(SPECTRE_TYPE_LP);
429  spectre = spectre.toDB();
430 
431  QAction *editSource = NULL, *editRecepteur = NULL, *editSpectre = NULL, *editContrib = NULL;
432 
433  QMenu* pPopup = new QMenu(this);
434  if ((row == 0) && (col > 1)) // Ligne de synthese
435  {
436  if (_choixOperation == 0) // pas d'operation
437  {
438  editRecepteur = pPopup->addAction(TR("id_popup_see_recepteur"));
439  pPopup->addSeparator();
440  }
441  else
442  {
443  editSpectre = pPopup->addAction(TR("id_popup_see_spectre"));
444  }
445 
446  // Si on a conserve la matrice des resultats bruts
447  if (getElement()->getPartialState())
448  {
449  editContrib = pPopup->addAction(TR("id_popup_see_contrib"));
450  }
451  }
452  else if ((row > 0) && (col > 1)) // Si on selectionne une contribution par source (!= synthese)
453  {
454  editSpectre = pPopup->addAction(TR("id_popup_see_spectre"));
455  pPopup->addSeparator();
456  editSource = pPopup->addAction(TR("id_popup_see_source"));
457  pPopup->addSeparator();
458  editRecepteur = pPopup->addAction(TR("id_popup_see_recepteur"));
459  }
460  else if ((row > 0) && (col == 0))
461  {
462  editSource = pPopup->addAction(TR("id_popup_see_source"));
463  }
464  else if ((row > 0) && (col == 1))
465  {
466  editSource = pPopup->addAction(TR("id_popup_see_source"));
467  }
468 
469  QAction* ret = pPopup->exec(_pTable->mapToGlobal(point));
470 
471  if (ret)
472  {
473  if (ret == editSource)
474  {
475  getElement()->getSource(ligne)->edit(this);
476  }
477  else if (ret == editRecepteur)
478  {
479  TYCalcul* pCalcul = static_cast<TYCalcul*>(getElement()->getParent());
480  TYPointCalcul* pPoint = getElement()->getRecepteur(col - 2);
481  LPTYSpectre pSpectre = nullptr;
482 
483  if (pPoint)
484  {
485  pSpectre = pCalcul->getSpectre(pPoint->getID());
486  }
487  if (pSpectre == nullptr)
488  {
489  return;
490  }
491 
492  // Si c'est un resultat calcule, on ne peut pas changer les valeurs
493  if (pCalcul && (pCalcul->getState() == TYCalcul::Actif))
494  {
495  pSpectre->setIsReadOnly(true);
496  }
497  else
498  {
499  pSpectre->setIsReadOnly(false);
500  }
501 
502  pSpectre->edit(this);
503 
504  // Si c'est une mesure, on actualise le tableau resultat
505  if (pCalcul && (pCalcul->getState() == TYCalcul::Locked))
506  {
507  updateTable();
508  }
509  }
510  else if (ret == editSpectre)
511  {
512  spectre.setIsReadOnly(true);
513  spectre.edit(this);
514  spectre.setIsReadOnly(false);
515  }
516  else if (ret == editContrib)
517  {
519  }
520  }
521  }
522  }
523 }
524 
526 {
527  TYPrintDialog* pDialog = new TYPrintDialog(this);
528  pDialog->_groupBoxProjet->setEnabled(false);
529  pDialog->_groupBoxCalcul->setEnabled(false);
530  if (pDialog->exec() == QDialog::Accepted)
531  {
532  QPrintDialog dialog(_printer, this);
533  if (dialog.exec())
534  {
535  QPainter paint(_printer);
536 
537  QPixmap tmpPix;
538 
539  int mid = int(_printer->width() / 2) -
540  int(paint.fontMetrics().horizontalAdvance(pDialog->_lineEditTete->text()) / 2);
541  paint.drawText(mid, 20, pDialog->_lineEditTete->text());
542  mid = int(_printer->width() / 2) -
543  int(paint.fontMetrics().horizontalAdvance(pDialog->_lineEditPied->text()) / 2);
544  paint.drawText(mid, _printer->height() - 20, pDialog->_lineEditPied->text());
545  paint.setFont(QFont("Helvetica", 15, QFont::Bold));
546  mid = int(_printer->width() / 2) -
547  int(paint.fontMetrics().horizontalAdvance(pDialog->_lineEditTitre->text()) / 2);
548  paint.drawText(mid, 45, pDialog->_lineEditTitre->text());
549  paint.setFont(QFont());
550 
551  int sizeX = 120, sizeY = 25;
552  int ymax = int(double(_printer->height()) * 4 / 5 / (_pTable->rowCount() + 1));
553  if (ymax < sizeY)
554  {
555  sizeY = ymax;
556  }
557  int x = int(double(_printer->width() - sizeX * (_pTable->columnCount())) / 2);
558  int y = int((double(_printer->height()) - sizeY * (_pTable->rowCount() + 3)));
559 
560  int i = 0;
561  for (i = 0; i < _pTable->horizontalHeader()->count(); i++)
562  {
563  paint.drawText(x, y, _pTable->horizontalHeaderItem(i)->text());
564  paint.translate(sizeX, 0);
565  }
566 
567  paint.translate(-_pTable->columnCount() * sizeX, 0);
568  paint.translate(0, sizeY);
569 
570  for (i = 0; i < _pTable->rowCount(); i++)
571  {
572  for (int j = 0; j < _pTable->columnCount(); j++)
573  {
574  if (_pTable->item(i, j))
575  {
576  paint.drawText(x, y, _pTable->item(i, j)->text()); // paintCell(&paint, i, j, QRect(0,
577  // 0, sizeX, sizeY), false);
578  }
579  paint.translate(sizeX, 0);
580  }
581  paint.translate(0, sizeY);
582  paint.translate(-_pTable->columnCount() * sizeX, 0);
583  }
584  }
585  }
586 }
587 
589 {
590  switch (select)
591  {
592  case 1:
593  _choixAffichage = DBLIN; // Affichage dBLin
594  _comboBoxFreq->setEnabled(false);
595  break;
596  case 2:
597  _choixAffichage = DBFREQ; // Affichage par frequence
598  _comboBoxFreq->setEnabled(true);
599  break;
600  case 0:
601  default:
602  _choixAffichage = DBA; // Affichage dBA
603  _comboBoxFreq->setEnabled(false);
604  break;
605  }
606 
607  // Mets a jour le widget
609  updateTable();
610 }
611 
613 {
614  _choixOperation = select;
615 
616  if (_choixOperation == 0)
617  {
618  _comboBoxSubstCalcul->setEnabled(false);
619  _pButtonExport->setEnabled(true);
620  _pButtonExportSpectre->setEnabled(true);
621  }
622  else
623  {
624  _comboBoxSubstCalcul->setEnabled(true);
625  _pButtonExport->setEnabled(false);
626  _pButtonExportSpectre->setEnabled(false);
627  }
628 
629  // Mets a jour le widget
630  updateTable();
631 }
632 
634 {
635  // On commence par remplir la premiere colonne avec les noms des sources
636  QString titre = TR("id_entete_synthese");
637  _pTable->setItem(0, 0, new QTableWidgetItem(titre));
638  _pTable->setRowHeight(0, 30);
639  _pTable->setColumnWidth(0, 140);
640 
641  for (unsigned int row = 1; row < _nbLignes; row++) // On commence apres la ligne synthese
642  {
643  TYElement* pSource = getElement()->getSource(_tabSortedRes[row - 1].indice);
644  if (pSource == NULL)
645  {
646  continue;
647  }
648 
649  QString titre = pSource->getName();
650  _pTable->setItem(row, 0, new QTableWidgetItem(titre));
651  _pTable->setRowHeight(row, 30);
652  }
653 
654  // Recherche des maxima de contribution pour chaque recepteur
655  findMaxima();
656 
657  // Boucle sur les lignes et les colonnes pour afficher le tableau
658  TYCalcul* pCalcOp = getSelectedSubstCalcul();
659  for (unsigned int row = 0; row < _nbLignes; row++)
660  {
661  for (unsigned int col = 1; col < _nbColonnes; col++)
662  {
663  affichageCellule(row, col, pCalcOp);
664  }
665  }
666 }
667 
668 OSpectre TYResultatWidget::getSpectre(const int& row, const int& col, TYCalcul* pCalcul)
669 {
670  OSpectre spectre;
671  spectre.setValid(false);
672 
673  if ((!pCalcul) || (col == 0))
674  {
675  return spectre;
676  } // Cas de la colonne des noms de source
677 
678  if (col == 1) // Spectre de puissance d'une source
679  {
680  if (row > 0)
681  {
682  spectre = getPuissanceElem(_tabSortedRes[row - 1].indice);
683  }
684  else
685  {
686  spectre.setValid(false);
687  }
688  }
689  else
690  {
691  if (row == 0) // Ligne synthese
692  {
693  TYPointCalcul* pPoint = getElement()->getRecepteur(col - 2);
694  if (pPoint)
695  {
696  spectre = *pCalcul->getSpectre(pPoint->getID());
697  }
698  }
699  else // Contribution d'une source en un point
700  {
701  // Recuperation du resultat courant
702  TYResultat* pThisRes = getElement();
703  // Recuperation de pointeurs sur la source et du recepteur
704  TYElement* pSource = pThisRes->getSource(_tabSortedRes[row - 1].indice);
705  TYPointCalcul* pRecepteur = pThisRes->getRecepteur(col - 2);
706 
707  // Puis on recupere le spectre correspondant dans le calcul passe en parametre
708  TYResultat* pResultat = pCalcul->getResultat();
709  spectre = pResultat->getSpectre(pRecepteur, pSource);
710  spectre = spectre.toDB();
711  }
712  }
713 
714  return spectre;
715 }
716 
718 {
719  int row = 1; // Numero de 1ere ligne (ligne 0 = synthese)
720 
721  TYCalcul* pCalcul = TYCalcul::safeDownCast(getElement()->getParent());
722  TYCalcul* pSubstCalcul = getSelectedSubstCalcul();
723 
724  OSpectre spectre1;
725  OSpectre spectre2;
726 
727  bool valid = true;
728 
729  for (unsigned int i = 0; i < getElement()->getNbOfSources(); i++)
730  {
731  _tabSortedRes[i].indice = i;
732  row = i + 1;
733 
734  if (getElement() && getElement()->getSource(i))
735  {
736  _tabSortedRes[i].name = getElement()->getSource(i)->getName().toStdString();
737  }
738 
739  spectre1 = getSpectre(row, col, pCalcul);
740  spectre2 = getSpectre(row, col, pSubstCalcul);
741 
742  _tabSortedRes[i].resultat = resuAffichage(spectre1, spectre2, valid, 1);
743  }
744 }
745 
747 {
748  if (col < 0)
749  {
750  return;
751  }
752  else if (col == 0)
753  {
754  sortName();
755  }
756  else
757  {
758  sortRes(col);
759  // Dans ce cas, on reaffiche car on a reorganise les resultats
760  }
761 
762  updateTable();
763 }
764 
766 {
767  // On commence par remplir le tableau des resultats
768  // (la synthese est supposee etre toujours la plus forte valeur et "surnager" en haut du tableau)
769  initTabSort(col);
770 
771  // Tri
772  qsort(_tabSortedRes, getElement()->getNbOfSources(), sizeof(TYStructIndiceResultat), compareRes);
773 }
774 
776 {
777  // On commence par remplir le tableau des resultats
778  // (la synthese est supposee etre toujours la plus forte valeur et "surnager" en haut du tableau)
779  initTabSort(1);
780 
781  // Tri
782  qsort(_tabSortedRes, getElement()->getNbOfSources(), sizeof(TYStructIndiceResultat), compareName);
783 }
784 
786 {
787  TYElement* pElement = getElement()->getSource(i);
788 
789  return getPuissanceElem(pElement);
790 }
791 
793 {
794  assert(pElement);
795  TYSpectre spectre;
796 
797  std::map<TYElement*, LPTYSpectre>& mapElementSpectre = getElement()->getMapElementSpectre();
798  TYSpectre* puissance = mapElementSpectre[pElement];
799 
800  if (puissance)
801  {
802  spectre = *puissance;
803  }
804 
805  return spectre;
806 }
807 
809 {
810  TYResultatTreeDialog* pDlg = new TYResultatTreeDialog(this);
811 
812  // Recuperation du point de contrOle
813  LPTYPointCalcul pPoint = getElement()->getRecepteur(col - 2);
814  pDlg->set(getElement(), pPoint);
815  pDlg->exec();
816 }
817 
819 {
820  return spectre.isTonalite();
821 }
822 
824 {
825  _seuilContribution = _pContributionLineEdit->text().toDouble();
826  updateTable();
827 }
828 
829 void TYResultatWidget::affichageCellule(const int& row, const int& col, TYCalcul* pCalcOp)
830 {
831  TYCalcul* pCalcul = TYCalcul::safeDownCast(getElement()->getParent());
832 
833  OSpectre spectre1 = getSpectre(row, col, pCalcul);
834  OSpectre spectre2 = getSpectre(row, col, pCalcOp);
835 
836  QTableWidgetItem* pItem = NULL;
837  QString msg;
838  double valeur = 0.0;
839  bool valid = true;
840 
841  // Cas 1 : ligne de synthese
842  if (row == 0)
843  {
844  if (col > 1) // La case (0,1) est vide
845  {
846  valeur = resuAffichage(spectre1, spectre2, valid, CELL_SYNTH);
847  msg = QString("%1").arg(valeur, 7, 'f', 1);
848  pItem = new QTableWidgetItem(msg);
849  decorsSynthese(pItem, row, col, valid, spectre1, spectre2);
850  _pTable->setItem(row, col, pItem);
851  _pTable->setRowHeight(row, 30);
852  }
853  }
854  else if (col > 1) // Tout sauf ligne de synthese ou puissance de source
855  {
856  valeur = resuAffichage(spectre1, spectre2, valid, CELL_CONTRIB);
857  msg = QString("%1").arg(valeur, 7, 'f', 1);
858  pItem = new QTableWidgetItem(msg);
859  decorsContributions(pItem, row, col, valid, spectre1, spectre2);
860  _pTable->setItem(row, col, pItem);
861  _pTable->setRowHeight(row, 30);
862  }
863  else // A priori, il ne reste que la puissance de la source
864  {
865  spectre2 =
866  OSpectre(); // La puissance affichee correspond a la puissance de la source du calcul courant
867  valeur = resuAffichage(spectre1, spectre2, valid, CELL_LW);
868  msg = QString("%1").arg(valeur, 7, 'f', 1);
869  pItem = new QTableWidgetItem(msg);
870  decorsContributions(pItem, row, col, valid, spectre1, spectre2);
871  _pTable->setItem(row, col, pItem);
872  _pTable->setRowHeight(row, 30);
873  }
874 }
875 
876 double TYResultatWidget::resuAffichage(OSpectre& spectre1, OSpectre& spectre2, bool& valid,
877  const int& typeCase)
878 {
879  double val1 = 0.0, val2 = 0.0;
880 
881  switch (_choixAffichage)
882  {
883  case DBLIN:
884  val1 = spectre1.valGlobDBLin();
885  val2 = spectre2.valGlobDBLin();
886  break;
887  case DBFREQ:
888  val1 = spectre1.getValueReal(_freq);
889  val2 = spectre2.getValueReal(_freq);
890  break;
891  case DBA:
892  default:
893  val1 = spectre1.valGlobDBA();
894  val2 = spectre2.valGlobDBA();
895  break;
896  }
897 
898  if (_choixOperation != 0)
899  {
900  if ((!spectre2.isValid()) || (typeCase == CELL_LW))
901  {
902  val2 = 0.0;
903  }
904  if ((!spectre2.isValid()) && ((typeCase == CELL_SYNTH) || (typeCase == CELL_CONTRIB)))
905  {
906  valid = false;
907  }
908  }
909 
910  switch (_choixOperation)
911  {
912  case 0: // Pas d'operation
913  return val1;
914  case 1: // difference entre deux resultats
915  return val1 - val2;
916  case 2: // emergence (uniquement pour la ligne synthese)
917  if (typeCase == CELL_SYNTH)
918  {
919  return (TYResultat::safeDownCast(_pElement))->getEmergence(val1, val2);
920  }
921  else
922  {
923  return val1;
924  }
925  case 3: // bruit ambiant (uniquement pour la ligne synthese)
926  default:
927  if (typeCase == CELL_SYNTH)
928  {
929  return (TYResultat::safeDownCast(_pElement))->getAmbiant(val1, val2);
930  }
931  else
932  {
933  return val1;
934  }
935  }
936 }
937 
938 OSpectre TYResultatWidget::resuSpectre(OSpectre& spectre1, OSpectre& spectre2, const int& typeCase)
939 {
940  switch (_choixOperation)
941  {
942  case 0: // Pas d'operation
943  return spectre1;
944  break;
945  case 1: // difference entre deux resultats
946  return spectre1.subst(spectre2);
947  break;
948  case 2: // emergence
949  return (TYResultat::safeDownCast(_pElement))->getEmergence(spectre1, spectre2);
950  break;
951  case 3: // bruit ambiant
952  default:
953  return (TYResultat::safeDownCast(_pElement))->getAmbiant(spectre1, spectre2);
954  break;
955  }
956 
957  return OSpectre();
958 }
959 
960 void TYResultatWidget::decorsSynthese(QTableWidgetItem* pItem, const int& row, const int& col,
961  const bool& valid, OSpectre& spectre1, OSpectre& spectre2)
962 {
963  if (!valid)
964  {
965  pItem->setBackground(QBrush(QColor(127, 127, 127))); // Gris uni
966  return;
967  }
968 
969  if ((_choixAffichage == DBFREQ) || (_choixOperation == 1) || (_choixOperation == 2))
970  {
971  pItem->setBackground(QBrush(QColor(255, 255, 255))); // Blanc uni ?
972  return; // Rien si affichage sur une frequence ou difference ou emergence
973  }
974 
975  OSpectre spectre;
977 
978  if (_choixOperation == 3) // Bruit ambiant
979  {
980  spectre = getElement()->getAmbiant(spectre1, spectre2);
981  }
982  else if (_choixOperation == 0) // Pas d'operation
983  {
984  spectre = getSpectre(row, col, pCalcul);
985  }
986 
987  if (isPresenceTonaliteMarquee(spectre)) // Coloration en jaune
988  {
989  pItem->setBackground(QBrush(QColor(255, 255, 0)));
990  }
991 }
992 
993 void TYResultatWidget::decorsContributions(QTableWidgetItem* pItem, const int& row, const int& col,
994  const bool& valid, OSpectre& spectre1, OSpectre& spectre2)
995 {
996  // Les cellules sont decorees sauf dans le cas ou on affiche l'ecart entre deux resultats
997  if (!valid)
998  {
999  pItem->setBackground(QBrush(QColor(127, 127, 127))); // Gris uni
1000  return;
1001  }
1002 
1003  if ((_choixOperation == 1) || (col == 1))
1004  {
1005  pItem->setBackground(QBrush(QColor(255, 255, 255))); // Blanc uni ?
1006  }
1007  else
1008  {
1009  double valeur = pItem->text().toDouble();
1010  double global = _pTable->item(0, col)->text().toDouble();
1011  // Affichage orange pour les cellules qui contribuent a plus que valeur globale - seuil
1012  // Uniquement dansle cas ou aucune operation n'a ete faite sur le resultat.
1013  if ((_choixOperation == 0) && (valeur >= (global - _seuilContribution)))
1014  {
1015  pItem->setBackground(QBrush(QColor(255, 204, 0)));
1016  }
1017 
1018  // Affichage rouge de la cellule correspondant a la contribution la plus forte
1019  int imaxi = static_cast<int>(_max[col - 2] * 10);
1020  int ivaleur = static_cast<int>(valeur * 10);
1021  if (ivaleur >= (imaxi - 1))
1022  {
1023  pItem->setBackground(QBrush(QColor(255, 0, 0)));
1024  }
1025  }
1026 }
1027 
1029 {
1031  for (unsigned int i = 0; i < tabFreq.size(); i++)
1032  {
1033  QString str;
1034  str.setNum(tabFreq[i], 'f', 1);
1035  _comboBoxFreq->insertItem(i, str);
1036  }
1037 }
1038 
1040 {
1041  _freq = _comboBoxFreq->currentText().toFloat();
1043  updateTable();
1044 }
1045 
1047 {
1048  // Initialisation du tableau
1049  if (_max)
1050  {
1051  delete[] _max;
1052  _max = NULL;
1053  }
1054 
1055  _max = new double[_nbRecepteurs];
1056 
1058  TYCalcul* pSubstCalcul = getSelectedSubstCalcul();
1059 
1060  double tmpMax = -10000, valeur = 0.0;
1061  bool valid = true;
1062 
1063  for (unsigned int col = 2; col < _nbColonnes; col++)
1064  {
1065  tmpMax = -10000;
1066 
1067  for (unsigned int row = 1; row < _nbLignes; row++)
1068  {
1069  OSpectre spectre1 = getSpectre(row, col, pCalcul);
1070  OSpectre spectre2 = getSpectre(row, col, pSubstCalcul);
1071  valeur = resuAffichage(spectre1, spectre2, valid, 1);
1072  tmpMax = valeur > tmpMax ? valeur : tmpMax;
1073  }
1074 
1075  _max[col - 2] = tmpMax;
1076  }
1077 }
1078 
1079 int compareRes(const void* elem1, const void* elem2)
1080 {
1083 
1084  double res = Res2->resultat - Res1->resultat;
1085  int sgn = int(res / fabs(res));
1086  return (sgn);
1087 }
1088 
1089 int compareName(const void* elem1, const void* elem2)
1090 {
1093 
1094  if (Res1->name > Res2->name)
1095  {
1096  return 1;
1097  }
1098 
1099  return (-1);
1100 }
std::vector< LPTYCalcul > TYTabLPCalcul
Collection de pointeurs de TYCalcul.
Definition: TYDefines.h:394
outil IHM pour une entrée utilisateur (fichier header)
Boite de dialogue des parametres d'impression (fichier header)
Boite de dialogue pour la representation par une arborescence des elements contribuant au resultat d'...
#define TR(id)
outil IHM pour un resultat (fichier header)
const std::vector< double > tabFreq
OTabFreq TYTabFreq
Collection des frequences.
Definition: TYSpectre.h:27
static OPrototype * safeDownCast(OPrototype *pObject)
Definition: TYElement.cpp:71
bool isA(const char *className) const
Definition: TYElement.cpp:65
OSpectreAbstract & subst(const OSpectreAbstract &spectre) const
Arithmetic subtraction of two spectrums in one-third Octave.
Definition: spectre.cpp:316
double valGlobDBA() const
Compute the global value dB[A] of a one-third Octave spectrum.
Definition: spectre.cpp:683
double valGlobDBLin() const
Compute the global value dB[Lin] of a one-third Octave spectrum.
Definition: spectre.cpp:671
void setType(TYSpectreType type)
Set the spectrum type.
Definition: spectre.h:152
void setValid(const bool &valid=true)
Definition: spectre.h:141
OSpectreAbstract & toDB() const
Converts to dB.
Definition: spectre.cpp:590
bool isValid() const
Check the spectrum validity. Invalidity is caused by: corrupted data, impossible calculation.
Definition: spectre.h:133
bool isTonalite() const
Existence d'une tonalite marquee.
Definition: spectre.cpp:1076
double getValueReal(double freq)
Definition: spectre.cpp:959
static int getIndice(const double &freq)
Return the index associated to a frequency.
Definition: spectre.h:397
Calculation program.
Definition: TYCalcul.h:50
int getState()
Get calculation state.
Definition: TYCalcul.h:416
@ Locked
Definition: TYCalcul.h:62
@ Actif
Definition: TYCalcul.h:63
LPTYSpectre getSpectre(const TYUUID &id_pt)
Definition: TYCalcul.cpp:1223
const LPTYResultat getResultat() const
Get result.
Definition: TYCalcul.h:367
TYElement * getParent() const
Definition: TYElement.h:699
const TYUUID & getID() const
Definition: TYElement.cpp:176
virtual QString getName() const
Definition: TYElement.h:684
Classe de definition d'un point de calcul.C'est une classe derivee a TYPoint avec en plus un spectrep...
Definition: TYPointCalcul.h:33
classe pour une boite de dialogue des parametres d'impression.
Definition: TYPrintDialog.h:52
QGroupBox * _groupBoxCalcul
Definition: TYPrintDialog.h:67
QLineEdit * _lineEditPied
Definition: TYPrintDialog.h:84
QLineEdit * _lineEditTete
Definition: TYPrintDialog.h:85
QGroupBox * _groupBoxProjet
Definition: TYPrintDialog.h:62
QLineEdit * _lineEditTitre
Definition: TYPrintDialog.h:87
classe de definition d'un projet.
Definition: TYProjet.h:45
TYTabLPCalcul & getListCalcul()
Set/Get de la liste des Calcul.
Definition: TYProjet.h:366
Boite de dialogue pour la representation par une arborescence des elements contribuant au resultat d'...
void set(LPTYResultat pResultat, LPTYPointCalcul pPtCalcul)
void slotContributionLineEditChanged()
void findMaxima()
Recherche des maxima de contribution pour chaque recepteur.
OSpectre resuSpectre(OSpectre &spectre1, OSpectre &spectre2, const int &typeCase)
Calcul du spectre en fonction du contexte (option de calcul)
QRadioButton * _radioButtonDelta
unsigned int _nbLignes
Nombre de ligne, de colonnes.
virtual void updateContent()
QRadioButton * _radioButtonDBLIN
QGridLayout * _resultatLayout
int _choixOperation
Type d'operation choisie.
virtual void setFrequency(int freq)
CHangement de la frequence de travail.
double _freq
Frequence de travail.
void sortCol(int col)
unsigned int _nbColonnes
double resuAffichage(OSpectre &spectre1, OSpectre &spectre2, bool &valid, const int &typeCase)
Calcul du contenu de la cellule en fonction du contexte (option de calcul)
QRadioButton * _radioButtonAmbiant
void updateFreqList()
Remplissage du combo des frequences.
void sortRes(int col)
void changeAffichage(int select)
QTableWidget * _pTable
QRadioButton * _radioButtonNoOp
TYCalcul * getSelectedSubstCalcul()
void changeSubstCalcul(int calcul)
QPushButton * _pButtonExportSpectre
QRadioButton * _radioButtonEmergence
QPushButton * _pButtonExport
void decorsSynthese(QTableWidgetItem *pItem, const int &row, const int &col, const bool &valid, OSpectre &spectre1, OSpectre &spectre2)
Coloration de la cellule en fonction du contexte pour la synthese, pour le reste du tableau.
void initTabSort(int col=1)
void decorsContributions(QTableWidgetItem *pItem, const int &row, const int &col, const bool &valid, OSpectre &spectre1, OSpectre &spectre2)
TYSpectre getPuissanceElem(const unsigned int &i)
int _choixAffichage
Mode d'affichage (dBA, dBLin, dB(f))
OSpectre getSpectre(const int &row, const int &col, TYCalcul *pCalcul)
Recherche du spectre associe a une ligne et une colonne pour un calcul.
virtual void contextMenuEvent(QContextMenuEvent *e)
void showContribTreeDialog(int col)
TYStructIndiceResultat * _tabSortedRes
unsigned int _nbRecepteurs
bool isPresenceTonaliteMarquee(const OSpectre &spectre)
QRadioButton * _radioButtonDBFRQ
TYLineEdit * _pContributionLineEdit
void affichageCellule(const int &row, const int &col, TYCalcul *pCalcOp=NULL)
Affichage du contenu de la cellule.
unsigned int _nbSources
Nombre de sources, de recepteurs.
QComboBox * _comboBoxFreq
Combo pour le choix de la frequence de travail.
QComboBox * _comboBoxSubstCalcul
double * _max
Tableau des maxima par colonne.
QRadioButton * _radioButtonDBA
virtual void apply()
QButtonGroup * _buttonGroupOperation
Choix du type de calcul.
void changeOperation(int select)
Changement du type d'operation.
TYResultatWidget(TYResultat *pElement, QWidget *_pParent=NULL)
Classe qui Permet de centraliser les resultats d'un calcul acoustique.
Definition: TYResultat.h:48
LPTYPointCalcul getRecepteur(const int &indexRecepteur)
Retourne le recepteur corresponadnt a l'indice passe.
Definition: TYResultat.cpp:546
void saveValue(const QString &filename, const int &affichage, double freq=100)
Sauvegarde des valeurs dans un fichier affichage : false -> dBA et true -> dBLin.
Definition: TYResultat.cpp:699
LPTYElement getSource(const int &indexSource)
Retourne la source correspondant a l'indice passe.
Definition: TYResultat.cpp:504
void saveSpectre(const QString &filename, TYCalcul *pSubstCalcul=NULL)
Sauvegarde des spectres dans un fichier.
Definition: TYResultat.cpp:567
OSpectre getSpectre(TYElement *pRecepteur, TYElement *pSource)
Retourne un spectre pour un couple S-R.
Definition: TYResultat.cpp:458
virtual void setIsReadOnly(bool flag)
Set/Get du flag _isReadOnly.
Definition: TYSpectre.h:141
static const TYTabFreq getTabFreqNorm(TYSpectreForm form=SPECTRE_FORM_TIERS)
Definition: TYSpectre.cpp:419
classe de l'objet IHM pour un objet metier de type TYElement
Definition: TYWidget.h:43
TYElement * _pElement
Definition: TYWidget.h:114
@ SPECTRE_TYPE_LP
Definition: spectre.h:31