From: PeterLValve Date: Fri, 21 Mar 2014 23:24:59 +0000 (-0700) Subject: UI: Add ability to trim files directly from vogleditor X-Git-Url: https://git.cworth.org/git?p=vogl;a=commitdiff_plain;h=da9408c5d28098035931c0261c1b64d60fbcf414 UI: Add ability to trim files directly from vogleditor * When loading a trace that contains over 200 frames, the user will be prompted whether they'd like to trim the file. The trimmed file can then optionally be loaded instead of the originally selected trace. * The new vogleditor_QTrimDialog allows the user to specify the frame index to start the trim at, the number of frames to trim, and the output file name. * Invalid frame index or lengths will make the textbox turn red to indicate the error. Entries are also validated against the number of frames in the trace file, and the trim lengths are currently limited to 200 frames (so that they can be loaded back into the editor without the trim prompt being shown). * voglreplay32/64 is launched in a separate process to generate the trim file. Failed replays display an error; successful replays are saved and can be reloaded into the editor. * Enabled the Trim Trace button to allow trimming of an already open trace. * Completely removed the Stop and Pause buttons --- diff --git a/src/vogleditor/CMakeLists.txt b/src/vogleditor/CMakeLists.txt index 3ff364c..3132f70 100644 --- a/src/vogleditor/CMakeLists.txt +++ b/src/vogleditor/CMakeLists.txt @@ -53,6 +53,7 @@ set(SRC_LIST vogleditor_qtextureexplorer.cpp vogleditor_qtextureviewer.cpp vogleditor_qtimelineview.cpp + vogleditor_qtrimdialog.cpp vogleditor_statetreearbprogramitem.cpp vogleditor_statetreearbprogramenvitem.cpp vogleditor_statetreebufferitem.cpp @@ -91,6 +92,7 @@ set(UI_HEADER_LIST vogleditor_qtextureviewer.h vogleditor_qtextureexplorer.h vogleditor_qtimelineview.h + vogleditor_qtrimdialog.h ) # these are for non-QOBJECT headers @@ -134,6 +136,7 @@ set(FORM_LIST vogleditor_qprogramexplorer.ui vogleditor_qshaderexplorer.ui vogleditor_qtextureexplorer.ui + vogleditor_qtrimdialog.ui ) set(RESOURCE_LIST diff --git a/src/vogleditor/vogleditor.cpp b/src/vogleditor/vogleditor.cpp index da9a974..1b976ca 100644 --- a/src/vogleditor/vogleditor.cpp +++ b/src/vogleditor/vogleditor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ #include "vogleditor_statetreeshaderitem.h" #include "vogleditor_statetreeframebufferitem.h" #include "vogleditor_qtextureexplorer.h" +#include "vogleditor_qtrimdialog.h" #define VOGLEDITOR_DISABLE_TAB(tab) ui->tabWidget->setTabEnabled(ui->tabWidget->indexOf(tab), false); #define VOGLEDITOR_ENABLE_TAB(tab) ui->tabWidget->setTabEnabled(ui->tabWidget->indexOf(tab), true); @@ -119,10 +121,9 @@ VoglEditor::VoglEditor(QWidget *parent) : m_pShaderTab_layout(NULL), m_currentSnapshot(NULL), m_pCurrentCallTreeItem(NULL), + m_pVoglReplayProcess(new QProcess()), m_pPlayButton(NULL), - m_pPauseButton(NULL), m_pTrimButton(NULL), - m_pStopButton(NULL), m_pTraceReader(NULL), m_pTimelineModel(NULL), m_pApiCallTreeModel(NULL), @@ -180,35 +181,18 @@ VoglEditor::VoglEditor(QWidget *parent) : // add buttons to toolbar m_pPlayButton = new QToolButton(ui->mainToolBar); - m_pPlayButton->setText("Play trace"); + m_pPlayButton->setText("Play Trace"); m_pPlayButton->setEnabled(false); - m_pPauseButton = new QToolButton(ui->mainToolBar); - m_pPauseButton->setText("Pause"); - m_pPauseButton->setEnabled(false); - m_pTrimButton = new QToolButton(ui->mainToolBar); - m_pTrimButton->setText("Trim"); + m_pTrimButton->setText("Trim Trace"); m_pTrimButton->setEnabled(false); - m_pStopButton = new QToolButton(ui->mainToolBar); - m_pStopButton->setText("Stop"); - m_pStopButton->setEnabled(false); - - // Temporarily hide the other buttons (until asyncronous playback is supported) - m_pPauseButton->setVisible(false); - m_pTrimButton->setVisible(false); - m_pStopButton->setVisible(false); - ui->mainToolBar->addWidget(m_pPlayButton); - ui->mainToolBar->addWidget(m_pPauseButton); ui->mainToolBar->addWidget(m_pTrimButton); - ui->mainToolBar->addWidget(m_pStopButton); connect(m_pPlayButton, SIGNAL(clicked()), this, SLOT(playCurrentTraceFile())); - connect(m_pPauseButton, SIGNAL(clicked()), this, SLOT(pauseCurrentTraceFile())); connect(m_pTrimButton, SIGNAL(clicked()), this, SLOT(trimCurrentTraceFile())); - connect(m_pStopButton, SIGNAL(clicked()), this, SLOT(stopCurrentTraceFile())); connect(m_pProgramExplorer, SIGNAL(program_edited(vogl_program_state*)), this, SLOT(on_program_edited(vogl_program_state*))); @@ -262,24 +246,12 @@ VoglEditor::~VoglEditor() m_pPlayButton = NULL; } - if (m_pPauseButton != NULL) - { - delete m_pPauseButton; - m_pPauseButton = NULL; - } - if (m_pTrimButton != NULL) { delete m_pTrimButton; m_pTrimButton = NULL; } - if (m_pStopButton != NULL) - { - delete m_pStopButton; - m_pStopButton = NULL; - } - if (m_pFramebufferTab_layout != NULL) { delete m_pFramebufferTab_layout; @@ -315,6 +287,12 @@ VoglEditor::~VoglEditor() delete m_pStateTreeModel; m_pStateTreeModel = NULL; } + + if (m_pVoglReplayProcess != NULL) + { + delete m_pVoglReplayProcess; + m_pVoglReplayProcess = NULL; + } } void VoglEditor::playCurrentTraceFile() @@ -324,18 +302,14 @@ void VoglEditor::playCurrentTraceFile() // update UI m_pPlayButton->setEnabled(false); - m_pPauseButton->setEnabled(true); - m_pTrimButton->setEnabled(true); - m_pStopButton->setEnabled(true); + m_pTrimButton->setEnabled(false); m_pStatusLabel->clear(); if (m_traceReplayer.replay(m_pTraceReader, m_pApiCallTreeModel->root(), NULL, 0, true)) { // replay was successful m_pPlayButton->setEnabled(true); - m_pPauseButton->setEnabled(false); - m_pTrimButton->setEnabled(false); - m_pStopButton->setEnabled(false); + m_pTrimButton->setEnabled(true); } else { @@ -345,50 +319,79 @@ void VoglEditor::playCurrentTraceFile() setCursor(origCursor); } -void VoglEditor::pauseCurrentTraceFile() +void VoglEditor::trimCurrentTraceFile() +{ + trim_trace_file(m_openFilename, static_cast(m_pTraceReader->get_max_frame_index()), 200); +} + +/// \return True if the new trim file is now open in the editor +/// \return False if there was an error, or the user elected NOT to open the new trim file +bool VoglEditor::trim_trace_file(QString filename, uint maxFrameIndex, uint maxAllowedTrimLen) { - if (m_traceReplayer.pause()) + // open a dialog to gather parameters for the replayer + vogleditor_QTrimDialog trimDialog(filename, maxFrameIndex, maxAllowedTrimLen, this); + int code = trimDialog.exec(); + + if (code == QDialog::Rejected) { - // update UI - m_pPlayButton->setEnabled(true); - m_pPauseButton->setEnabled(false); - m_pTrimButton->setEnabled(true); - m_pStopButton->setEnabled(true); - m_pStatusLabel->clear(); + return false; } - else + + QStringList arguments; + arguments << "--trim_frame" << trimDialog.trim_frame() << "--trim_len" << trimDialog.trim_len() << "--trim_file" << trimDialog.trim_file() << filename; + +#ifdef __i386__ + int procRetValue = m_pVoglReplayProcess->execute("./voglreplay32", arguments); +#else + int procRetValue = m_pVoglReplayProcess->execute("./voglreplay64", arguments); +#endif + + bool bCompleted = false; + if (procRetValue == -2) { - m_pStatusLabel->setText("Failed to pause the trace replay."); + // proc failed to starts + m_pStatusLabel->setText("Error: voglreplay could not be executed."); } -} - -void VoglEditor::trimCurrentTraceFile() -{ - if (m_traceReplayer.trim()) + else if (procRetValue == -1) + { + // proc crashed + m_pStatusLabel->setText("Error: voglreplay aborted unexpectedly."); + } + else if (procRetValue == 0) { - m_pStatusLabel->clear(); + // success + bCompleted = true; } else { - m_pStatusLabel->setText("Failed to trim the trace replay."); + // some other return value + bCompleted = false; } -} -void VoglEditor::stopCurrentTraceFile() -{ - if (m_traceReplayer.stop()) + if (bCompleted) { - // update UI - m_pPlayButton->setEnabled(true); - m_pPauseButton->setEnabled(false); - m_pTrimButton->setEnabled(false); - m_pStopButton->setEnabled(false); - m_pStatusLabel->clear(); + int ret = QMessageBox::warning(this, tr(g_PROJECT_NAME.toStdString().c_str()), tr("Would you like to load the new trimmed trace file?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + + if (ret == QMessageBox::Yes) + { + close_trace_file(); + if (open_trace_file(trimDialog.trim_file().toStdString().c_str())) + { + m_pStatusLabel->clear(); + return true; + } + else + { + QMessageBox::critical(this, tr("Error"), tr("Could not open trace file.")); + } + } } else { - m_pStatusLabel->setText("Failed to stop the trace replay."); + QMessageBox::critical(this, tr("Error"), tr("Failed to trim the trace file.")); } + return false; } void VoglEditor::on_actionE_xit_triggered() @@ -406,7 +409,7 @@ void VoglEditor::on_action_Open_triggered() filename.set(fileName.toStdString().c_str()); if (open_trace_file(filename) == false) { - QMessageBox::critical(this, tr("Error"), tr("Could not open file")); + QMessageBox::critical(this, tr("Error"), tr("Could not open trace file.")); return; } } @@ -1024,6 +1027,29 @@ bool VoglEditor::open_trace_file(dynamic_string filename) m_pStatusLabel->clear(); } + if (tmpReader->get_max_frame_index() > 200) + { + int ret = QMessageBox::warning(this, tr(g_PROJECT_NAME.toStdString().c_str()), tr("The loaded trace file has many frames and debugging may be difficult.\nWould you like to trim the trace?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + + if (ret == QMessageBox::Yes) + { + if (trim_trace_file(filename.c_str(), static_cast(tmpReader->get_max_frame_index()), 200)) + { + // user decided to open the new trim file, and the UI should already be updated + // clean up here and return + vogl_delete(tmpReader); + this->setCursor(origCursor); + return true; + } + else + { + // either there was an error, or the user decided NOT to open the trim file, + // so continue to load the original file + } + } + } + // now that we know the new trace file can be opened, // close the old one, and update the trace reader close_trace_file(); @@ -1130,9 +1156,7 @@ bool VoglEditor::open_trace_file(dynamic_string filename) // update toolbar m_pPlayButton->setEnabled(true); - m_pPauseButton->setEnabled(false); - m_pTrimButton->setEnabled(false); - m_pStopButton->setEnabled(false); + m_pTrimButton->setEnabled(true); // timeline m_pTimelineModel = new vogleditor_apiCallTimelineModel(m_pApiCallTreeModel->root()); @@ -1292,9 +1316,7 @@ void VoglEditor::reset_tracefile_ui() m_pStatusLabel->clear(); m_pPlayButton->setEnabled(false); - m_pPauseButton->setEnabled(false); m_pTrimButton->setEnabled(false); - m_pStopButton->setEnabled(false); VOGLEDITOR_DISABLE_TAB(ui->machineInfoTab); diff --git a/src/vogleditor/vogleditor.h b/src/vogleditor/vogleditor.h index 01d5d36..ced6b2d 100644 --- a/src/vogleditor/vogleditor.h +++ b/src/vogleditor/vogleditor.h @@ -51,6 +51,7 @@ class vogleditor_QTextureExplorer; class QItemSelection; class QModelIndex; +class QProcess; class QSortFilterProxyModel; class QToolButton; class vogl_context_snapshot; @@ -91,9 +92,9 @@ private slots: void on_treeView_clicked(const QModelIndex& index); void playCurrentTraceFile(); - void pauseCurrentTraceFile(); void trimCurrentTraceFile(); - void stopCurrentTraceFile(); + + bool trim_trace_file(QString filename, uint maxFrameIndex, uint maxAllowedTrimLen); void on_stateTreeView_clicked(const QModelIndex &index); @@ -162,10 +163,9 @@ private: vogleditor_gl_state_snapshot* m_currentSnapshot; vogleditor_apiCallTreeItem* m_pCurrentCallTreeItem; + QProcess* m_pVoglReplayProcess; QToolButton* m_pPlayButton; - QToolButton* m_pPauseButton; QToolButton* m_pTrimButton; - QToolButton* m_pStopButton; vogleditor_traceReplayer m_traceReplayer; vogl_trace_file_reader* m_pTraceReader; diff --git a/src/vogleditor/vogleditor_qtrimdialog.cpp b/src/vogleditor/vogleditor_qtrimdialog.cpp new file mode 100644 index 0000000..6a4db8d --- /dev/null +++ b/src/vogleditor/vogleditor_qtrimdialog.cpp @@ -0,0 +1,108 @@ +#include "vogleditor_qtrimdialog.h" +#include "ui_vogleditor_qtrimdialog.h" +#include + +vogleditor_QTrimDialog::vogleditor_QTrimDialog(QString parentTraceFile, uint maxFrameIndex, uint maxTrimLength, QWidget *parent) : + QDialog(parent), + ui(new Ui::vogleditor_QTrimDialog), + m_maxFrameIndex(maxFrameIndex), + m_maxTrimLength(maxTrimLength), + m_trim_frame("0"), + m_trim_len("1") +{ + ui->setupUi(this); + ui->trimFrameLineEdit->setText(m_trim_frame); + ui->trimLenLineEdit->setText(m_trim_len); + + QString trimFilename = parentTraceFile; + trimFilename.insert(trimFilename.lastIndexOf("."), "-trim"); + ui->trimFileLineEdit->setText(trimFilename); +} + +vogleditor_QTrimDialog::~vogleditor_QTrimDialog() +{ + delete ui; +} + +void vogleditor_QTrimDialog::on_buttonBox_accepted() +{ + // verify all input + bool bValidFrame = false; + uint tmpFrame = ui->trimFrameLineEdit->text().toUInt(&bValidFrame); + bValidFrame = bValidFrame && (tmpFrame <= m_maxFrameIndex); + + bool bValidLen = false; + uint tmpLen = ui->trimLenLineEdit->text().toUInt(&bValidLen); + bValidLen = bValidLen && (tmpLen > 0 && tmpLen < m_maxTrimLength); + + bool bValidFile = (ui->trimFrameLineEdit->text().isEmpty() == false); + + if (bValidFrame && bValidLen && bValidFile) + { + m_trim_frame = ui->trimFrameLineEdit->text(); + m_trim_len = ui->trimLenLineEdit->text(); + m_trim_file = ui->trimFileLineEdit->text(); + accept(); + } +} + +void vogleditor_QTrimDialog::on_buttonBox_rejected() +{ + reject(); +} + +void vogleditor_QTrimDialog::on_pickTrimFileButton_pressed() +{ + // open file dialog + QString suggestedName = ui->trimFileLineEdit->text(); + QString selectedName = QFileDialog::getSaveFileName(this, tr("Save Trim File"), suggestedName, tr("Trace file (*.bin)")); + + if (!selectedName.isEmpty()) + { + ui->trimFileLineEdit->setText(selectedName); + } +} + +void vogleditor_QTrimDialog::on_trimLenLineEdit_textChanged(const QString &arg1) +{ + bool bConverted = false; + uint trimLen = arg1.toUInt(&bConverted); + + // make sure the length could be converted to a UINT, and that it isn't more than the allowed length + if (bConverted == false || trimLen > m_maxTrimLength) + { + // turn background red + QPalette palette(ui->trimLenLineEdit->palette()); + palette.setColor(QPalette::Base, Qt::red); + ui->trimLenLineEdit->setPalette(palette); + } + else + { + // restore background color + QPalette palette(ui->trimLenLineEdit->palette()); + palette.setColor(QPalette::Base, Qt::white); + ui->trimLenLineEdit->setPalette(palette); + } +} + +void vogleditor_QTrimDialog::on_trimFrameLineEdit_textChanged(const QString &arg1) +{ + bool bConverted = false; + uint trimFrame = arg1.toUInt(&bConverted); + + // make sure frame could be converted to a UINT, and that it isn't greater than the number of frames in the trace + if (bConverted == false || trimFrame > m_maxFrameIndex) + { + // turn background red + QPalette palette(ui->trimFrameLineEdit->palette()); + palette.setColor(QPalette::Base, Qt::red); + ui->trimFrameLineEdit->setPalette(palette); + } + else + { + // restore background color + QPalette palette(ui->trimFrameLineEdit->palette()); + palette.setColor(QPalette::Base, Qt::white); + ui->trimFrameLineEdit->setPalette(palette); + } +} diff --git a/src/vogleditor/vogleditor_qtrimdialog.h b/src/vogleditor/vogleditor_qtrimdialog.h new file mode 100644 index 0000000..a9ec3de --- /dev/null +++ b/src/vogleditor/vogleditor_qtrimdialog.h @@ -0,0 +1,54 @@ +#ifndef VOGLEDITOR_QTRIMDIALOG_H +#define VOGLEDITOR_QTRIMDIALOG_H + +#include +#include + +namespace Ui { +class vogleditor_QTrimDialog; +} + +class vogleditor_QTrimDialog : public QDialog +{ + Q_OBJECT + +public: + explicit vogleditor_QTrimDialog(QString parentTraceFile, uint maxFrameIndex, uint maxTrimLength, QWidget *parent = 0); + ~vogleditor_QTrimDialog(); + + QString trim_frame() + { + return m_trim_frame; + } + + QString trim_len() + { + return m_trim_len; + } + + QString trim_file() + { + return m_trim_file; + } + +private slots: + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + + void on_pickTrimFileButton_pressed(); + + void on_trimLenLineEdit_textChanged(const QString &arg1); + + void on_trimFrameLineEdit_textChanged(const QString &arg1); + +private: + Ui::vogleditor_QTrimDialog *ui; + uint m_maxFrameIndex; + uint m_maxTrimLength; + QString m_trim_frame; + QString m_trim_len; + QString m_trim_file; +}; + +#endif // VOGLEDITOR_QTRIMDIALOG_H diff --git a/src/vogleditor/vogleditor_qtrimdialog.ui b/src/vogleditor/vogleditor_qtrimdialog.ui new file mode 100644 index 0000000..d9cef6c --- /dev/null +++ b/src/vogleditor/vogleditor_qtrimdialog.ui @@ -0,0 +1,197 @@ + + + vogleditor_QTrimDialog + + + + 0 + 0 + 430 + 154 + + + + + 0 + 0 + + + + Dialog + + + + + + What range of frames would you like to trim? + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + trim_frame: + + + + + + + + + + + + + + + + + + + + trim_len: + + + + + + + + + + + + + + + + + + + + + + + + trim_file: + + + + + + + + 1 + 0 + + + + + + + + + 80 + 16777215 + + + + ... + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + buttonBox + accepted() + vogleditor_QTrimDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + vogleditor_QTrimDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +