diff --git a/qdlt/qdltfile.cpp b/qdlt/qdltfile.cpp index 034f4a63..6123672e 100644 --- a/qdlt/qdltfile.cpp +++ b/qdlt/qdltfile.cpp @@ -130,13 +130,41 @@ int QDltFile::sizeFilter() const return size(); } +int QDltFile::calculateHeaderSize(quint8 htyp) +{ + // Base DLT standard header size (HTYP (1) + MCNT (1) + LEN (2)) + int size = 4; + + // Add standard header extra fields using DLT constants + if (DLT_IS_HTYP_WEID(htyp)) size += DLT_SIZE_WEID; // ECU ID + if (DLT_IS_HTYP_WSID(htyp)) size += DLT_SIZE_WSID; // Session ID + if (DLT_IS_HTYP_WTMS(htyp)) size += DLT_SIZE_WTMS; // Timestamp + + // Add extended header if UEH flag is set + if (DLT_IS_HTYP_UEH(htyp)) { + size += 10; // Extended header: MSIN (1) + NOAR (1) + APID (4) + CTID (4) + } + return size; +} + +quint32 QDltFile::alignedStorageSize(quint32 size) +{ + constexpr int STORAGE_ALIGNMENT = 4; + return ((size + STORAGE_ALIGNMENT - 1) / STORAGE_ALIGNMENT) * STORAGE_ALIGNMENT; +} + bool QDltFile::open(QString _filename, bool append) { qDebug() << "Open file" << _filename << "started"; /* check if file is already opened */ - if(!append) + if(!append) { clear(); + // Reset size counters when opening new file + totalStorageSize = 0; + totalPayloadSize = 0; + totalMessageSize = 0; + } /* create new file item */ QDltFileItem *item = new QDltFileItem(); @@ -156,12 +184,38 @@ bool QDltFile::open(QString _filename, bool append) return true; } +quint64 QDltFile::getTotalStorageSize() { + if (totalStorageSize == 0 && size() > 0) { + calculateTotalSizes(); + } + return totalStorageSize; +} + +quint64 QDltFile::getTotalPayloadSize() { + if (totalPayloadSize == 0 && size() > 0) { + calculateTotalSizes(); + } + return totalPayloadSize; +} + +quint64 QDltFile::getTotalMessageSize() { + if (totalMessageSize == 0 && size() > 0) { + calculateTotalSizes(); + } + return totalMessageSize; +} + void QDltFile::clearIndex() { for(int num=0;numindexAll.clear(); } + + // Reset size counters when clearing index + totalStorageSize = 0; + totalPayloadSize = 0; + totalMessageSize = 0; } bool QDltFile::createIndex() @@ -178,6 +232,7 @@ bool QDltFile::createIndex() ret = updateIndex(); //qDebug() << "Create index finished - " << size() << "messages found"; + calculateTotalSizes(); return ret; } @@ -544,6 +599,10 @@ void QDltFile::close() { /* close file */ clear(); + // Reset size counters when closing + totalPayloadSize = 0; + totalMessageSize = 0; + totalStorageSize = 0; } QByteArray QDltFile::getMsg(int index) const @@ -779,3 +838,102 @@ bool QDltFile::applyRegExStringMsg(QDltMsg &msg) const { return filterList.applyRegExStringMsg(msg); } + +void QDltFile::calculateTotalSizes() +{ + // Structure to hold per-message size info + struct QDltMsgSizeInfo { + quint32 storageSize; + quint32 messageSize; + quint32 payloadSize; + }; + + // Get total number of indexed messages + const int totalMessages = size(); + if (totalMessages == 0) { + totalStorageSize = 0; + totalMessageSize = 0; + totalPayloadSize = 0; + return; + } + + // Create cache for per-message size info + QVector msgSizeCache(totalMessages); + + // Progress reporting interval for large files + const int progressInterval = qMax(1, qMin(totalMessages / 20, 10000)); + for (int msgIndex = 0; msgIndex < totalMessages; msgIndex++) { + // Print progress for large files + if (totalMessages > 10000 && (msgIndex % progressInterval) == 0) { + int percentage = (msgIndex * 100) / totalMessages; + qDebug() << "Caching sizes:" << percentage << "% (" << msgIndex << "/" << totalMessages << ")"; + } + + QByteArray msgData = getMsg(msgIndex); + QDltMsgSizeInfo info = {0, 0, 0}; + if (msgData.isEmpty() || msgData.size() < 20) { + msgSizeCache[msgIndex] = info; + continue; + } + + // Parse storage header + const char *data = msgData.constData(); + const int msgDataSize = msgData.size(); + const quint8 storageHeaderVersion = static_cast(data[3]); + int storageHeaderSize = 16; + if (storageHeaderVersion == 2) { + // DLTv2: storage header size depends on ECU ID length + if (msgDataSize < 14) { + msgSizeCache[msgIndex] = info; + continue; + } + const quint8 ecuIdLength = static_cast(data[13]); + storageHeaderSize = 14 + ecuIdLength; + } + + // Validate enough data for DLT header + if (msgDataSize < storageHeaderSize + 4) { + msgSizeCache[msgIndex] = info; + continue; + } + + // Parse DLT protocol header + const char* dltHeaderData = data + storageHeaderSize; + const quint8 htyp = static_cast(dltHeaderData[0]); + const quint16 dltMessageLength = (static_cast(dltHeaderData[2]) << 8) | + static_cast(dltHeaderData[3]); + + // Validate message length + if (dltMessageLength == 0 || dltMessageLength > 65535 || + dltMessageLength > (msgDataSize - storageHeaderSize)) { + msgSizeCache[msgIndex] = info; + continue; + } + + // Calculate header and payload sizes + const int headerSize = calculateHeaderSize(htyp); + const int payloadSize = dltMessageLength - headerSize; + if (payloadSize < 0) { + msgSizeCache[msgIndex] = info; + continue; + } + + info.storageSize = alignedStorageSize(msgDataSize); + info.messageSize = dltMessageLength; + info.payloadSize = payloadSize; + msgSizeCache[msgIndex] = info; + } + if (totalMessages > 10000) { + qDebug() << "Size caching completed: processed" << totalMessages << "messages"; + } + + // Accumulate totals from cache + totalStorageSize = 0; + totalMessageSize = 0; + totalPayloadSize = 0; + for (int i = 0; i < msgSizeCache.size(); ++i) { + totalStorageSize += msgSizeCache[i].storageSize; + totalMessageSize += msgSizeCache[i].messageSize; + totalPayloadSize += msgSizeCache[i].payloadSize; + } +} diff --git a/qdlt/qdltfile.h b/qdlt/qdltfile.h index 1b508645..32b395dd 100644 --- a/qdlt/qdltfile.h +++ b/qdlt/qdltfile.h @@ -309,9 +309,41 @@ class QDLT_EXPORT QDltFile : public QDlt */ bool applyRegExStringMsg(QDltMsg &msg) const; -protected: + //! Get the total storage size of all indexed DLT messages in bytes. + /*! + * \return Total storage size in bytes (octets), 0 if no messages indexed + **/ + quint64 getTotalStorageSize(); + + //! Get the total payload size of all indexed DLT messages in bytes. + /*! + * \return Total payload size in bytes (octets), 0 if no messages indexed + **/ + quint64 getTotalPayloadSize() ; + + //! Get the total message size of all indexed DLT messages in bytes. + /*! + * \return Total message size in bytes (octets), 0 if no messages indexed + **/ + quint64 getTotalMessageSize(); + + //! Calculate DLT header size based on header type flags. + /*! + * \return Total header size in bytes + **/ + int calculateHeaderSize(quint8 htyp); + + //! Align size to 4-byte boundary for DLT storage format. + /*! + * \return Size rounded up to next 4-byte boundary + **/ + quint32 alignedStorageSize(quint32 size); + private: + // Calculates total storage, message, and payload sizes for all indexed DLT messages. + void calculateTotalSizes(); + //! Mutex to lock critical path for infile mutable QMutex mutexQDlt; @@ -351,6 +383,11 @@ class QDLT_EXPORT QDltFile : public QDlt QCache cache; bool cacheEnable; + // Size calculation variables + quint64 totalStorageSize = 0; + quint64 totalMessageSize = 0; + quint64 totalPayloadSize = 0; + //! DLTv2 Support. /*! true dltv2 support is enabled. diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2230c433..bcf1b676 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2215,6 +2215,7 @@ void MainWindow::reloadLogFile(bool update, bool multithreaded) for(int num=0;numsupportDLTv2Decoding); } +void MainWindow::on_action_menuFile_DLTFilesize_triggered() +{ + quint64 payloadSize = qfile.getTotalPayloadSize(); + quint64 messageSize = qfile.getTotalMessageSize(); + quint64 storageSize = qfile.getTotalStorageSize(); + + if (payloadSize == 0 && messageSize == 0 && storageSize == 0) { + QMessageBox::warning(this, "No Data", "Please open a valid DLT file first."); + return; + } + + QString message = QString( + "Payload Size (octets): %1\n" + "Message Size (octets): %2\n" + "Storage Size (octets): %3" + ).arg(payloadSize).arg(messageSize).arg(storageSize); + + QMessageBox::information(this, "DLT File Size Information", message); +} void MainWindow::on_action_menuFile_Settings_triggered() { diff --git a/src/mainwindow.h b/src/mainwindow.h index 858d227c..22827c5c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -248,7 +248,6 @@ class MainWindow : public QMainWindow void openSupportedFile(const QString& path); void getSelectedItems(EcuItem **ecuitem,ApplicationItem** appitem,ContextItem** conitem); - void reloadLogFile(bool update=false, bool multithreaded = true); void populateEcusTree(EcuTree&& ecuTree); @@ -425,6 +424,7 @@ private slots: void on_action_menuFile_Open_triggered(); void on_actionAppend_triggered(); void on_actionExport_triggered(); + void on_action_menuFile_DLTFilesize_triggered(); public slots: diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 99ded826..bf2e6bd2 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -11,7 +11,7 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus MainWindow @@ -21,7 +21,7 @@ :/icons/png/org.genivi.DLTViewer.png:/icons/png/org.genivi.DLTViewer.png - QTabWidget::Rounded + QTabWidget::TabShape::Rounded @@ -45,10 +45,10 @@ - Qt::CustomContextMenu + Qt::ContextMenuPolicy::CustomContextMenu - QAbstractScrollArea::AdjustToContentsOnFirstShow + QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow false @@ -60,13 +60,13 @@ true - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QAbstractItemView::SelectRows + QAbstractItemView::SelectionBehavior::SelectRows - QAbstractItemView::ScrollPerPixel + QAbstractItemView::ScrollMode::ScrollPerPixel false @@ -118,6 +118,7 @@ + @@ -311,10 +312,10 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus - QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + QDockWidget::DockWidgetFeature::DockWidgetClosable|QDockWidget::DockWidgetFeature::DockWidgetFloatable|QDockWidget::DockWidgetFeature::DockWidgetMovable Project @@ -324,7 +325,7 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus @@ -342,10 +343,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -439,26 +440,26 @@ true - Qt::TabFocus + Qt::FocusPolicy::TabFocus - QTabWidget::South + QTabWidget::TabPosition::South - QTabWidget::Rounded + QTabWidget::TabShape::Rounded 0 - Qt::ElideNone + Qt::TextElideMode::ElideNone false - Qt::NoFocus + Qt::FocusPolicy::NoFocus Explore @@ -476,11 +477,78 @@ 2 + + + + 0 + + + + + + 50 + 16777215 + + + + Sort files: + + + + + + + + By Filename + + + + + By Timestamp + + + + + + + + + 50 + 16777215 + + + + + Asc. + + + + + Desc. + + + + + + + + + + QAbstractItemView::SelectionMode::ExtendedSelection + + + true + + + false + + + - Qt::NoFocus + Qt::FocusPolicy::NoFocus Config @@ -501,19 +569,19 @@ - Qt::TabFocus + Qt::FocusPolicy::TabFocus - Qt::CustomContextMenu + Qt::ContextMenuPolicy::CustomContextMenu true - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QAbstractItemView::SelectRows + QAbstractItemView::SelectionBehavior::SelectRows true @@ -574,7 +642,7 @@ - Qt::CustomContextMenu + Qt::ContextMenuPolicy::CustomContextMenu true @@ -690,7 +758,7 @@ - Qt::CustomContextMenu + Qt::ContextMenuPolicy::CustomContextMenu true @@ -699,13 +767,13 @@ true - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove - Qt::MoveAction + Qt::DropAction::MoveAction - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection false @@ -782,7 +850,7 @@ - Qt::CustomContextMenu + Qt::ContextMenuPolicy::CustomContextMenu false @@ -1601,6 +1669,11 @@ Append... + + + DLT File size + + Shortcuts List