// ************************************************************************** // // (C) Copyright 2009 Swiss SIMTEC AG // // ************************************************************************** // // $HeadURL$ // $LastChangedBy$ // $LastChangedDate$ // $LastChangedRevision$ // // ************************************************************************** #include "LogViewTelegramDialog.hpp" #include "LogViewTelegram.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include "LogViewXdrElement.hpp" #include "LogViewField.hpp" #include "IntegerCalculator.hpp" #include "LogViewBooleanEdit.hpp" #include "LogViewTextEdit.hpp" #include "LogViewValueEdit.hpp" #include "LogViewEnumEdit.hpp" #include "LogViewDateTimeEdit.hpp" #include "LogViewSpinBox.hpp" #include "LogViewTableWidget.hpp" #include "LogViewTabWidget.hpp" namespace N_LogView { // todo: // - feld einfärben wenn geändert, wenn falsch // - mache hartcodierte oder konfigurierbare ranges für spezielle Werte wie GPS-Position: signed 24-bit // --------------------------------------------------------------- LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_readonly) : QDialog(a_parent) , m_ReadOnly(a_readonly) , m_logger(getLogger("LogViewTelegramDialog")) { setAttribute(Qt::WA_DeleteOnClose); } // --------------------------------------------------------------- void LogViewTelegramDialog::showDialog(const QSharedPointer &a_telegram) { delete layout(); hide(); m_Telegram = a_telegram; a_telegram->dump(); m_fieldTree.reset(a_telegram->getFieldTree()); if (m_fieldTree) { QGridLayout *dialogLayout = new QGridLayout; if (!m_ReadOnly) { // edit wait-time QLabel *waitTimeLabel = new QLabel(tr("Wartezeit [ms]"), this); dialogLayout->addWidget(waitTimeLabel, dialogLayout->rowCount(), 0); m_WaitTimeEdit = new QLineEdit(QString::number(a_telegram->getWaitTime()), this); dialogLayout->addWidget(m_WaitTimeEdit, dialogLayout->rowCount() - 1, 1); // edit name QLabel *nameLabel = new QLabel(tr("Name"), this); dialogLayout->addWidget(nameLabel, dialogLayout->rowCount(), 0); m_NameEdit = new QLineEdit(a_telegram->getName(), this); dialogLayout->addWidget(m_NameEdit, dialogLayout->rowCount() - 1, 1); QFrame *f = new QFrame(this); f->setFrameShape(QFrame::HLine); f->setFrameShadow(QFrame::Sunken); dialogLayout->addWidget(f, dialogLayout->rowCount(), 0, 1, 2); } //INFO_LOG(m_logger) << "--------------- create dialog " << fieldTree->getName().toStdString() << "--------------"; //m_fieldTree->dump(); showTree(m_fieldTree.data(), dialogLayout); if (this->findChild() == nullptr) dialogLayout->setRowStretch(dialogLayout->rowCount(), 1); // build the dialog QVBoxLayout *mainLayout = new QVBoxLayout(this); // make dialog scrollable m_contentsWidget = new QWidget; m_contentsWidget->setLayout(dialogLayout); m_ScrollArea = new QScrollArea(this); m_ScrollArea->setWidget(m_contentsWidget); m_ScrollArea->setWidgetResizable(true); mainLayout->addWidget(m_ScrollArea); // buttons QHBoxLayout *btnLayout = new QHBoxLayout; btnLayout->addStretch(); showButtons(btnLayout); mainLayout->addLayout(btnLayout); setWindowTitle(m_fieldTree->cleanName() + QStringLiteral(" (%1)").arg(a_telegram->getTelId())); setModal(true); show(); makePretty(); } else showDataDump(a_telegram, true); } // --------------------------------------------------------------- void LogViewTelegramDialog::showDataDump(const QSharedPointer &a_telegram, bool showErrorMessage) { QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(new QLabel(tr("Telegramm-Dump"))); if (showErrorMessage) // show error-message in dialog layout->addWidget(new QLabel(tr("Konnte Dialog basierend auf Struktur \'%1\' nicht generieren!").arg(a_telegram->getStructName()))); else layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName()))); // generate the telegram-dump QString theDump = QLatin1String(""); const QByteArray &data = a_telegram->getData(); for (int i = 0; i < data.size(); i++) { if (0 == (i % 8)) theDump += QStringLiteral("%1:").arg(i, 4, 16, QLatin1Char('0')); theDump += QStringLiteral(" %1").arg(static_cast(data[i]), 2, 16, QLatin1Char('0')); if (7 == (i % 8)) theDump += QLatin1String("
"); } theDump += QLatin1String("
"); QTextEdit *telegramDump = new QTextEdit(theDump); layout->addWidget(telegramDump); QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen")); QHBoxLayout *btnLayout = new QHBoxLayout; btnLayout->addStretch(); btnLayout->addWidget(btnClose); layout->addLayout(btnLayout); connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject); setLayout(layout); show(); } // --------------------------------------------------------------- void LogViewTelegramDialog::makePretty() { return; // set the size and position of dialog int sbWidth = m_ScrollArea->width() - m_ScrollArea->viewport()->width(); int wDiff = m_contentsWidget->width() - m_ScrollArea->width(); int hDiff = m_contentsWidget->height() - m_ScrollArea->viewport()->height(); const QRect screenSize = QApplication::desktop()->screenGeometry(this); //QRect winGeo = geometry(); int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10); int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10); //setGeometry(winGeo); //QSize size = settings.value(SIZE, sizeHint()).toSize(); resize(QSize(newWidth, newHeight)); //move(settings.value(POS, QPoint(0, 0)).toPoint()); // -------------------------------------------------------------------- } // --------------------------------------------------------------- void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_box) { int i = 0; while (LogViewField *child = a_fieldTree->child(i++)) { if (!a_fieldTree->hasContent()) child->setHasContent(false); switch (child->kind()) { case LogViewField::e_FieldKindBorder: { QGroupBox *groupBox = new QGroupBox(child->cleanName()); QGridLayout *actBox = new QGridLayout(groupBox); a_box->addWidget(groupBox, a_box->rowCount(), 0, 1, 2); showTree(child, actBox); break; } case LogViewField::e_FieldKindTab: showTab(child, a_box); break; case LogViewField::e_FieldKindTabChild: { QWidget *widget = new QWidget; widget->setContentsMargins(QMargins()); QGridLayout *actBox = new QGridLayout(widget); a_box->addWidget(widget, a_box->rowCount(), 0, 1, 2); showTree(child, actBox); break; } case LogViewField::e_FieldKindEdit: case LogViewField::e_FieldKindPodArray: case LogViewField::e_FieldKindPodArrayChild: showEditField(child, a_box); break; } } } // --------------------------------------------------------------- void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram) { INFO_LOG(m_logger) << "******************************************"; // check whether all changed values are valid // ------------------------------------------ for (const auto ptr : qAsConst(m_EditInfoList)) { if (!ptr->isValid()) { INFO_LOG(m_logger) << ptr->field()->name() << " is invalid"; return; // abort when a value is not vaild } } // now save the values // ------------------- a_telegram->resetOffset(); a_telegram->clearJsonData(); for (auto ptr : qAsConst(m_EditInfoList)) { if (!ptr->saveContent(a_telegram)) { QMessageBox::warning(this, tr("Error while saving telegram"), tr("Found an invalid value - the telegram may be not saved correctly")); } } } // --------------------------------------------------------------- void LogViewTelegramDialog::saveTelegram() { fillTelegram(m_Telegram.data()); // save wait-time and name N_SST::IntegerCalculator calculator; N_SST::IntegerCalculator::E_Error error; m_Telegram->setWaitTime(calculator.calc(m_WaitTimeEdit->text().toStdString(), error)); m_Telegram->setName(m_NameEdit->text()); accept(); } // --------------------------------------------------------------- void LogViewTelegramDialog::sendCurrentTelegram() { emit sendTelegram(m_Telegram); } // --------------------------------------------------------------- void LogViewTelegramDialog::showButtons(QLayout *a_layout) { if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol()) { QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send")); btnSend->setEnabled(true); // TODO: Status ob wirklich möglich ggf. überprüfen connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram); a_layout->addWidget(btnSend); } if (m_ReadOnly) { QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen")); connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject); a_layout->addWidget(btnClose); } else { QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Abbrechen")); connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject); a_layout->addWidget(btnClose); QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK")); btnOk->setDefault(true); // fixme: absturz, wenn feld ungültiger wert enthält und ok gedrückt wird connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram); a_layout->addWidget(btnOk); } } // --------------------------------------------------------------- void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box) { // INFO_LOG(m_logger) << a_logViewField->getName() << // << " a_logViewField->getValueListSize()=" << a_logViewField->getValueListSize() // << " a_logViewField->isIsDynamicArray()=" << a_logViewField->isIsDynamicArray() // << " a_logViewField->getValue(0)=" << a_logViewField->getValue(0).toStdString() // << " a_logViewField->getXdrElement())->getValueKind()=" << (int)(static_cast(a_logViewField->getXdrElement())->getValueKind()) // ; switch (a_logViewField->valueListSize()) { case 1: // 1 field (single or multi-line) if (m_ReadOnly || !a_logViewField->isDynamicArray() || (LogViewXdrStandardType::e_Character == static_cast(a_logViewField->xdrElement())->getValueKind())) { QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); LogViewWidget *valueWidget = nullptr; //QString value = a_logViewField->getValue(0); // if (-1 == value.indexOf("
") && value.length() < 80) { // single line // ----------- if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind()) { // enum => combobox // ---------------- valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0); } else { if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField()) { // date-time-field // --------------- valueWidget = new LogViewDateTimeEdit(a_logViewField, this, m_ReadOnly); } else { switch (static_cast(a_logViewField->xdrElement())->getValueKind()) { case LogViewXdrStandardType::e_Boolean: valueWidget = new LogViewBooleanEdit(a_logViewField, this, m_ReadOnly); break; case LogViewXdrStandardType::e_Signed: case LogViewXdrStandardType::e_Unsigned: case LogViewXdrStandardType::e_Float: case LogViewXdrStandardType::e_Data: valueWidget = new LogViewValueEdit(a_logViewField, this, m_ReadOnly); break; case LogViewXdrStandardType::e_Character: // Text valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly); break; } } } if (valueWidget) m_EditInfoList.push_back(valueWidget); } // else // { // // ---------------------------------------------------------------- // // fixme: not used => take away // // multi-line // valueWidget = new QTextEdit(value); // static_cast(valueWidget)->setReadOnly(true); // // make proper width of widget // QFontMetrics fm(valueWidget->font()); // // the 0 (at end) are here, because QFontMetrics does not understand the and tags. // // So not the correct font will be used for calculating the width. // // The solution here is suboptimal, but will hopefully work with a lot of fonts... // valueWidget->setMinimumWidth(fm.width("0000: 00 00 00 00 00 00 00")*1.7); // // ---------------------------------------------------------------- // } QWidget *w = dynamic_cast(valueWidget); if (w) a_box->addWidget(w, a_box->rowCount() - 1, 1); else WARNING_LOG(m_logger) << "Internal error - LogViewWidget is not derived from QWidget... !?"; break; } // fall through for not read-only and dyn. array Q_FALLTHROUGH(); case 0: if (m_ReadOnly) { // no field a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName()))); break; } // fall through for not read-only Q_FALLTHROUGH(); default: { // show the title of table QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); // show the spin-box for changing the dyn. array-size LogViewSpinBox *spinBox = nullptr; if (!m_ReadOnly && a_logViewField->isDynamicArray()) { spinBox = new LogViewSpinBox(a_logViewField, this, a_logViewField->valueListSize()); a_box->addWidget(spinBox, a_box->rowCount() - 1, 1); } // show the table for changing the array-values LogViewTableWidget *tableWidget = new LogViewTableWidget(a_logViewField, this, m_ReadOnly); m_EditInfoList.push_back(tableWidget); a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2); // connect signals if (spinBox) { connect(spinBox, &LogViewSpinBox::valueEditingFinished, tableWidget, &LogViewTableWidget::changeSize); } } break; } } // --------------------------------------------------------------- void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a_box) { LogViewSpinBox *spinBox = nullptr; if (!m_ReadOnly && a_logViewField->isDynamicArray()) { // show the spin-box for changing the dyn. array-size QLabel *label = new QLabel(a_logViewField->cleanName()); a_box->addWidget(label, a_box->rowCount(), 0); spinBox = new LogViewSpinBox(a_logViewField, this, 0); a_box->addWidget(spinBox, a_box->rowCount() - 1, 1); } LogViewTabWidget *a_tabWidget = new LogViewTabWidget(a_logViewField, this, spinBox); m_EditInfoList.push_back(dynamic_cast(a_tabWidget)); a_box->addWidget(a_tabWidget, a_box->rowCount(), 0, 1, 2); // connect signals if (spinBox) { connect(spinBox, &LogViewSpinBox::valueEditingFinished, a_tabWidget, &LogViewTabWidget::changeSize); } // add the tab if (a_logViewField->hasContent()) { for (int i = 0; i < a_logViewField->childCount(); ++i) a_tabWidget->addTab(a_logViewField, false, i); } } // --------------------------------------------------------------- bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonPath) { if (m_EditInfoList.empty()) return false; for (int i = m_EditInfoList.size() - 1; i >= 0; --i) { LogViewWidget *lvw = m_EditInfoList.at(i); const QStringList jsonPathChild = lvw->field()->jsonPath(); if (jsonPathChild.size() < jsonPath.size()) continue; bool bIsChild = true; for (int j = 0; j < jsonPath.size(); ++j) { if (jsonPath.at(j) != jsonPathChild.at(j)) { bIsChild = false; break; } } if (!bIsChild) continue; delete m_EditInfoList.at(i); m_EditInfoList.removeAt(i); } m_EditInfoList.resize(m_EditInfoList.size() - 1); return true; } } // namespace N_LogView