diff --git a/src/recordpanel.cpp b/src/recordpanel.cpp new file mode 100644 --- /dev/null +++ b/src/recordpanel.cpp @@ -0,0 +1,286 @@ +/* + Copyright © 2017 Hasan Yavuz Özderya + + This file is part of serialplot. + + serialplot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + serialplot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with serialplot. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "recordpanel.h" +#include "ui_recordpanel.h" +#include "setting_defines.h" + +RecordPanel::RecordPanel(DataRecorder* recorder, ChannelManager* channelMan, QWidget *parent) : + QWidget(parent), + ui(new Ui::RecordPanel), + recordToolBar(tr("Record Toolbar")), + recordAction(QIcon::fromTheme("media-record"), tr("Record"), this) +{ + overwriteSelected = false; + _recorder = recorder; + _channelMan = channelMan; + + ui->setupUi(this); + + recordToolBar.setObjectName("tbRecord"); + + recordAction.setCheckable(true); + recordToolBar.addAction(&recordAction); + ui->pbRecord->setDefaultAction(&recordAction); + + connect(ui->pbBrowse, &QPushButton::clicked, + this, &RecordPanel::selectFile); + connect(&recordAction, &QAction::triggered, + this, &RecordPanel::onRecord); + + connect(ui->cbRecordPaused, SIGNAL(toggled(bool)), + this, SIGNAL(recordPausedChanged(bool))); + + connect(ui->cbDisableBuffering, &QCheckBox::toggled, + [this](bool enabled) + { + _recorder->disableBuffering = enabled; + }); +} + +RecordPanel::~RecordPanel() +{ + delete ui; +} + +QToolBar* RecordPanel::toolbar() +{ + return &recordToolBar; +} + +bool RecordPanel::isRecording() +{ + return recordAction.isChecked(); +} + +bool RecordPanel::recordPaused() +{ + return ui->cbRecordPaused->isChecked(); +} + +bool RecordPanel::selectFile() +{ + QString fileName = QFileDialog::getSaveFileName( + parentWidget(), tr("Select recording file")); + + if (fileName.isEmpty()) + { + return false; + } + else + { + selectedFile = fileName; + ui->lbFileName->setText(selectedFile); + overwriteSelected = QFile::exists(fileName); + return true; + } +} + +void RecordPanel::onRecord(bool start) +{ + if (!start) + { + stopRecording(); + return; + } + + bool canceled = false; + if (ui->leSeparator->text().isEmpty()) + { + QMessageBox::critical(this, "Error", + "Column separator cannot be empty! Please select a separator."); + ui->leSeparator->setFocus(Qt::OtherFocusReason); + canceled = true; + } + + // check file name + if (!canceled && selectedFile.isEmpty() && !selectFile()) + { + canceled = true; + } + + if (!canceled && !overwriteSelected && QFile::exists(selectedFile)) + { + if (ui->cbAutoIncrement->isChecked()) + { + // TODO: should we increment even if user selected to replace? + canceled = !incrementFileName(); + } + else + { + canceled = !confirmOverwrite(selectedFile); + } + } + + if (canceled) + { + recordAction.setChecked(false); + } + else + { + overwriteSelected = false; + startRecording(); + } +} + +bool RecordPanel::incrementFileName(void) +{ + QFileInfo fileInfo(selectedFile); + + QString base = fileInfo.completeBaseName(); + QRegularExpression regex("(.*?)(\\d+)(?!.*\\d)(.*)"); + auto match = regex.match(base); + + if (match.hasMatch()) + { + bool ok; + int fileNum = match.captured(2).toInt(&ok); + base = match.captured(1) + QString::number(fileNum + 1) + match.captured(3); + } + else + { + base += "_1"; + } + + QString suffix = fileInfo.suffix();; + if (!suffix.isEmpty()) + { + suffix = "." + suffix; + } + + QString autoFileName = fileInfo.path() + "/" + base + suffix; + + // check if auto generated file name exists, ask user another name + if (QFile::exists(autoFileName)) + { + if (!confirmOverwrite(autoFileName)) + { + return false; + } + } + else + { + selectedFile = autoFileName; + } + + ui->lbFileName->setText(selectedFile); + return true; +} + +bool RecordPanel::confirmOverwrite(QString fileName) +{ + // prepare message box + QMessageBox mb(parentWidget()); + mb.setWindowTitle(tr("File Already Exists")); + mb.setIcon(QMessageBox::Warning); + mb.setText(tr("File (%1) already exists. How to continue?").arg(fileName)); + + auto bCancel = mb.addButton(QMessageBox::Cancel); + auto bOverwrite = mb.addButton(tr("Overwrite"), QMessageBox::DestructiveRole); + mb.addButton(tr("Select Another File"), QMessageBox::YesRole); + + mb.setEscapeButton(bCancel); + + // show message box + mb.exec(); + + if (mb.clickedButton() == bCancel) + { + return false; + } + else if (mb.clickedButton() == bOverwrite) + { + selectedFile = fileName; + return true; + } + else // select button + { + return selectFile(); + } +} + +void RecordPanel::startRecording(void) +{ + QStringList channelNames; + if (ui->cbHeader->isChecked()) + { + channelNames = _channelMan->infoModel()->channelNames(); + } + _recorder->startRecording(selectedFile, getSeparator(), channelNames); + emit recordStarted(); +} + +void RecordPanel::stopRecording(void) +{ + emit recordStopped(); + _recorder->stopRecording(); +} + +void RecordPanel::onPortClose() +{ + if (recordAction.isChecked() && ui->cbStopOnClose->isChecked()) + { + stopRecording(); + recordAction.setChecked(false); + } +} + +QString RecordPanel::getSeparator() const +{ + QString sep = ui->leSeparator->text(); + sep.replace("\\t", "\t"); + return sep; +} + +void RecordPanel::saveSettings(QSettings* settings) +{ + settings->beginGroup(SettingGroup_Record); + settings->setValue(SG_Record_AutoIncrement, ui->cbAutoIncrement->isChecked()); + settings->setValue(SG_Record_RecordPaused, ui->cbRecordPaused->isChecked()); + settings->setValue(SG_Record_StopOnClose, ui->cbStopOnClose->isChecked()); + settings->setValue(SG_Record_Header, ui->cbHeader->isChecked()); + settings->setValue(SG_Record_DisableBuffering, ui->cbDisableBuffering->isChecked()); + settings->setValue(SG_Record_Separator, ui->leSeparator->text()); + settings->endGroup(); +} + +void RecordPanel::loadSettings(QSettings* settings) +{ + settings->beginGroup(SettingGroup_Record); + ui->cbAutoIncrement->setChecked( + settings->value(SG_Record_AutoIncrement, ui->cbAutoIncrement->isChecked()).toBool()); + ui->cbRecordPaused->setChecked( + settings->value(SG_Record_RecordPaused, ui->cbRecordPaused->isChecked()).toBool()); + ui->cbStopOnClose->setChecked( + settings->value(SG_Record_StopOnClose, ui->cbStopOnClose->isChecked()).toBool()); + ui->cbHeader->setChecked( + settings->value(SG_Record_Header, ui->cbHeader->isChecked()).toBool()); + ui->cbDisableBuffering->setChecked( + settings->value(SG_Record_DisableBuffering, ui->cbDisableBuffering->isChecked()).toBool()); + ui->leSeparator->setText(settings->value(SG_Record_Separator, ui->leSeparator->text()).toString()); + settings->endGroup(); +}