Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ add_executable(dlt-viewer
searchdialog.ui
updatechecker.h
updatechecker.cpp
filespliting.cpp
filespliting.h
)

target_link_libraries(dlt-viewer
Expand Down
203 changes: 203 additions & 0 deletions src/filespliting.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#include <mainwindow.h>
#include <filespliting.h>

#include "qmessagebox.h"
#include <QDialog>
#include <QFileDialog>
#include <qboxlayout.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qpushbutton.h>

FileSpliting::FileSpliting(QWidget *parent)
: QWidget(parent){

}

void FileSpliting::setFile(QFile *file)
{
m_file = file;
}


//The function is triggered when Split DLT File is clicked which is under File Menu.
//A dialog box asking for the splitting size is opened where the user can specify the size in KB,MB or GB.
//The size is casted toqint64 and them parsed to splitOutputFile function.
//The destination path can also be selected by user which will also be parsend to splitOutFile function.

void FileSpliting::splitDLTFile_triggered(QFile &file,QStringList path){
qDebug() << "Split File Triggered";

QDialog dialog(this);
dialog.setWindowTitle("Enter Split Size");

QLabel *sizeLabel = new QLabel("Size (number):");
QLineEdit *sizeEdit = new QLineEdit();
sizeEdit->setValidator(new QDoubleValidator(0, 999999, 2, this)); // Accepts decimal input

QLabel *unitLabel = new QLabel("Unit:");
QComboBox *unitCombo = new QComboBox();
unitCombo->addItem("KB");
unitCombo->addItem("MB");
unitCombo->addItem("GB");

QPushButton *okButton = new QPushButton("OK");
QPushButton *cancelButton = new QPushButton("Cancel");

QHBoxLayout *inputLayout = new QHBoxLayout();
inputLayout->addWidget(sizeLabel);
inputLayout->addWidget(sizeEdit);
inputLayout->addWidget(unitLabel);
inputLayout->addWidget(unitCombo);

QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);

QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addLayout(inputLayout);
mainLayout->addLayout(buttonLayout);
dialog.setLayout(mainLayout);

connect(okButton, &QPushButton::clicked, &dialog, &QDialog::accept);
connect(cancelButton, &QPushButton::clicked, &dialog, &QDialog::reject);

if (dialog.exec() == QDialog::Accepted) {
double sizeValue = sizeEdit->text().toDouble();
QString sizeUnit = unitCombo->currentText();

qint64 multiplier = 1;
if (sizeUnit == "KB") multiplier = 1024LL;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think KB split is really needed.
@mfukar what do you think?

else if (sizeUnit == "MB") multiplier = 1024LL * 1024;
else if (sizeUnit == "GB") multiplier = 1024LL * 1024 * 1024;

qint64 maxChunkSizeBytes = static_cast<qint64>(sizeValue * multiplier);

//FileSaveDialog Implementation
QString folderPath = QFileDialog::getExistingDirectory(
this,
"Select Folder to Save Split Files",
QDir::homePath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
);

if (folderPath.isEmpty()) {
QMessageBox::warning(this, "No Folder Selected", "Split operation canceled.");
return;
}


if (folderPath.isEmpty()) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant empty checks.

QMessageBox::warning(this, "No Folder Selected", "Split operation canceled.");
return;
}

splitOutputFile(path,maxChunkSizeBytes, folderPath);
}
}

//The outputfile (i.e) DLT File is opened in ReadOnly mode and splitted on basis of requirement given by the user.
//If the same files are splitted twice the olde files will be deleted.
//chunk carry is done to avoid data loss
void FileSpliting::splitOutputFile(QStringList filePath,qint64 maxChunkSizeBytes, const QString &destinationFolder){

if (!m_file->isOpen()) {
qWarning() << "Failed to open Output File for File Splitting";
return;
}

QString fullPath = filePath[0];

QFileInfo fileInfo(fullPath);
QString baseName = fileInfo.completeBaseName();
QString extension = fileInfo.completeSuffix();

QDir dir(destinationFolder);
QString pattern = QString("%1_%2.%3").arg(baseName).arg("*").arg(extension);
QStringList oldFiles = dir.entryList(QStringList() << pattern, QDir::Files);
for (const QString &file : oldFiles) {
QString fullFilePath = dir.filePath(file);
if (QFile::remove(fullFilePath)) {
qDebug() << "Deleted old split:" << QDir::toNativeSeparators(fullFilePath);
} else {
qWarning() << "Failed to delete:" << fullFilePath;
}
}

int fileIndex = 1;
qint64 accumulatedSize = 0;
QByteArray buffer;

// Reset to start
m_file->seek(0);

while (!m_file->atEnd()) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this while look blocks UI thread, so if we try to split big file, the whole DLT-Viewer application is stuck and does not respond till the export is done. (which might take ~30-40 sec. in some cases.)
may be having thread safe implementation for this might help. if not, we can create a pop-up which show's the progress while export is going on.

// Read DLT standard header (first 4 bytes)
QByteArray header = m_file->read(4);
if (header.size() < 4) {
qDebug() << "Reached EOF while reading header.";
break;
}

// Extract payload length from bytes 2 and 3
quint16 payloadLen = ((quint8)header[2] << 8) | (quint8)header[3];
quint32 msgLen = payloadLen + 4; // total = header + payload

// Check if enough bytes remain in file
if (m_file->bytesAvailable() < (msgLen - 4)) {
qWarning() << "Unexpected EOF: file ends before message fully read.";
break;
}

// Read payload
QByteArray payload = m_file->read(msgLen - 4);
QByteArray completeMessage = header + payload;

// Check if adding this message exceeds current chunk size
if (accumulatedSize + completeMessage.size() > maxChunkSizeBytes && !buffer.isEmpty()) {
// Write buffer to new file
QString outputFileName = QString("%1/%2_%3.%4")
.arg(destinationFolder)
.arg(baseName)
.arg(fileIndex++)
.arg(extension);

QFile output(outputFileName);
if (output.open(QIODevice::WriteOnly)) {
output.write(buffer);
output.close();
qDebug() << "Written split:" << QDir::toNativeSeparators(outputFileName);
} else {
qWarning() << "Failed to create" << outputFileName;
break;
}

// Reset buffer
buffer.clear();
accumulatedSize = 0;
}

// Append message to buffer
buffer.append(completeMessage);
accumulatedSize += completeMessage.size();
}

// Write remaining buffer if not empty
if (!buffer.isEmpty()) {
QString outputFileName = QString("%1/%2_%3.%4")
.arg(destinationFolder)
.arg(baseName)
.arg(fileIndex++)
.arg(extension);

QFile output(outputFileName);
if (output.open(QIODevice::WriteOnly)) {
output.write(buffer);
output.close();
qDebug() << "Written last split:" << QDir::toNativeSeparators(outputFileName);
}
}

m_file->close();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when trying the feature, getting error "Unexpected EOF: file ends before message fully read." in application output.

Also, last few logs (20-100 lines) are missed. Data loss is seen when splitting the files.
Please test and correct the behaviour.

}
28 changes: 28 additions & 0 deletions src/filespliting.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef FILESPLITING_H
#define FILESPLITING_H

#include <qmainwindow.h>
#include <QFile>

class FileSpliting : public QWidget
{
Q_OBJECT

public:

explicit FileSpliting(QWidget *parent = nullptr);

void splitDLTFile_triggered(QFile &file,QStringList path); //Split DLT Files
void splitOutputFile(QStringList filePath,qint64 maxChunkSizeBytes, const QString &destinationFolder);

void setFile(QFile *file);



private:

QFile *m_file = nullptr;

};

#endif // FILESPLITING_H
16 changes: 16 additions & 0 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
#include <qdltmsgwrapper.h>
#include "ecutree.h"
#include "updatechecker.h"
#include "filespliting.h"


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
Expand Down Expand Up @@ -1334,6 +1336,7 @@ bool MainWindow::openDltFile(QStringList fileNames)
qDebug() << "Open filename error in " << __FILE__ << __LINE__;
return false;
}
outputFilePath = fileNames;
/* Color of the scrollbar when dark mode is enabled */
if (QDltSettingsManager::UI_Colour::UI_Dark == QDltSettingsManager::getInstance()->uiColour)
{
Expand Down Expand Up @@ -2015,6 +2018,19 @@ void MainWindow::on_actionExport_triggered()
exporterThread->start();
}

//call for spliting the DLT File
void MainWindow::on_actionSplitDLTFile_triggered(){
Copy link
Copy Markdown
Collaborator

@shubhamshahaBMW shubhamshahaBMW Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please handle below cases

  1. After running DLT-Viewer first time if we trigger file split W/O opening any file, it causes a crash. We can give error popup saying no open file.
  2. start DLT -> connect to hw for live logs -> try to split the file (while connected/disconnected). -> split pop-up does not appear. We can give error popup saying save the file first.


if (!outputfile.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open Output File for File Splitting";
return;
}
FileSpliting *splitFile = new FileSpliting(this);
splitFile->setFile(&outputfile);
splitFile->splitDLTFile_triggered(outputfile,outputFilePath);

}

void MainWindow::on_action_menuFile_SaveAs_triggered()
{

Expand Down
4 changes: 4 additions & 0 deletions src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ class MainWindow : public QMainWindow
void writeDLTMessageToFile(const QByteArray& bufferHeader, std::string_view payload,
const EcuItem* ecuitem);

//File Splitting Settings
QStringList outputFilePath;



void findFilteredLines();
Expand Down Expand Up @@ -459,6 +462,7 @@ private slots:
void on_actionAppend_triggered();
void on_actionExport_triggered();
void on_action_menuFile_DLTFilesize_triggered();
void on_actionSplitDLTFile_triggered(); //Split DLT Files


public slots:
Expand Down
74 changes: 73 additions & 1 deletion src/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@
<y>0</y>
<width>1001</width>
<height>23</height>

</rect>
</property>
<widget class="QMenu" name="menuFile">
Expand All @@ -118,6 +117,7 @@
<addaction name="action_menuFile_Import_DLT_Stream_with_Serial_Header"/>
<addaction name="separator"/>
<addaction name="action_menuConfig_Copy_to_clipboard"/>
<addaction name="actionSplitDLTFile"/>
<addaction name="actionExport"/>
<addaction name="action_menuFile_DLTFilesize"/>
<addaction name="separator"/>
Expand Down Expand Up @@ -480,6 +480,73 @@
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelExplorerSort">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Sort files:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxExplorerSortType">
<item>
<property name="text">
<string>By Filename</string>
</property>
</item>
<item>
<property name="text">
<string>By Timestamp</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxExplorerSortOrder">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Asc.</string>
</property>
</item>
<item>
<property name="text">
<string>Desc.</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="exploreView">
<property name="selectionMode">
<enum>QAbstractItemView::SelectionMode::ExtendedSelection</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabConfig">
Expand Down Expand Up @@ -1625,6 +1692,11 @@
<string>Check For Latest Updates</string>
</property>
</action>
<action name="actionSplitDLTFile">
<property name="text">
<string>Split DLT File</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
Expand Down
Loading