Skip to content
Open
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 @@ -82,6 +82,8 @@ add_executable(dlt-viewer
resources/dlt_viewer.rc
ecutree.h
ecutree.cpp
filespliting.cpp
filespliting.h
fileexplorertab.ui
fileexplorertab.h
fileexplorertab.cpp
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;
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()) {
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()) {
// 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();
}
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
15 changes: 15 additions & 0 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
#include "qdltoptmanager.h"
#include "qdltctrlmsg.h"
#include "ecutree.h"
#include "filespliting.h"


MainWindow::MainWindow(QWidget *parent) :
Expand Down Expand Up @@ -1212,6 +1213,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 @@ -1725,6 +1727,19 @@ void MainWindow::on_actionExport_triggered()
exporterThread->start();
}

//call for spliting the DLT File
void MainWindow::on_actionSplitDLTFile_triggered(){

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 @@ -369,6 +369,9 @@ class MainWindow : public QMainWindow
void writeDLTMessageToFile(const QByteArray& bufferHeader, std::string_view payload,
const EcuItem* ecuitem);

//File Splitting Settings
QStringList outputFilePath;


protected:
void keyPressEvent ( QKeyEvent * event ) override;
Expand Down Expand Up @@ -425,6 +428,7 @@ private slots:
void on_action_menuFile_Open_triggered();
void on_actionAppend_triggered();
void on_actionExport_triggered();
void on_actionSplitDLTFile_triggered(); //Split DLT Files


public slots:
Expand Down
Loading