]> git.cworth.org Git - vogl/blobdiff - src/vogleditor/vogleditor.cpp
UI: Add a settings file
[vogl] / src / vogleditor / vogleditor.cpp
index da9a9747e31568b35cc7009e9c4d24daa3844267..7eb513ef503e4220a3c4c65bbbe4d5c2891ff24c 100644 (file)
@@ -27,6 +27,7 @@
 #include <QHBoxLayout>
 #include <QItemSelection>
 #include <QPalette>
+#include <QProcess>
 #include <QSortFilterProxyModel>
 #include <QSpacerItem>
 #include <QToolButton>
 #include "vogl_trace_file_reader.h"
 #include "vogl_trace_file_writer.h"
 #include "vogleditor_qstatetreemodel.h"
+#include "vogleditor_settings.h"
 #include "vogleditor_statetreetextureitem.h"
 #include "vogleditor_statetreeprogramitem.h"
 #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);
@@ -61,6 +64,8 @@
 //----------------------------------------------------------------------------------------------------------------------
 static void *g_actual_libgl_module_handle;
 static QString g_PROJECT_NAME = "Vogl Editor";
+static vogleditor_settings g_settings;
+static const char* g_SETTINGS_FILE = "./vogleditor_settings.json";
 
 //----------------------------------------------------------------------------------------------------------------------
 // vogl_get_proc_address_helper
@@ -119,10 +124,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),
@@ -135,6 +139,15 @@ VoglEditor::VoglEditor(QWidget *parent) :
       vogl_init_actual_gl_entrypoints(vogl_get_proc_address_helper);
    }
 
+   // load the settings file. This will only succeed if the file already exists
+   g_settings.load(g_SETTINGS_FILE);
+
+   // always save/resave the file wiill either be created or so that new settings will be added
+   g_settings.save(g_SETTINGS_FILE);
+
+   this->move(g_settings.window_position_left(), g_settings.window_position_top());
+   this->resize(g_settings.window_size_width(), g_settings.window_size_height());
+
    m_pStatusLabel = new QLabel(ui->statusBar);
    m_pStatusLabel->setBaseSize(150, 12);
    ui->statusBar->addWidget(m_pStatusLabel, 1);
@@ -180,35 +193,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*)));
 
@@ -217,104 +213,105 @@ VoglEditor::VoglEditor(QWidget *parent) :
 
 VoglEditor::~VoglEditor()
 {
-   close_trace_file();
-   delete ui;
+    // update any settings and save the settings file
+    g_settings.set_window_position_left(this->x());
+    g_settings.set_window_position_top(this->y());
+    g_settings.set_window_size_width(this->width());
+    g_settings.set_window_size_height(this->height());
+    g_settings.save(g_SETTINGS_FILE);
 
-   if (m_pStatusLabel != NULL)
-   {
-       delete m_pStatusLabel;
-       m_pStatusLabel = NULL;
-   }
+    close_trace_file();
+    delete ui;
 
-   if (m_pFramebufferExplorer != NULL)
-   {
-       delete m_pFramebufferExplorer;
-       m_pFramebufferExplorer = NULL;
-   }
+    if (m_pStatusLabel != NULL)
+    {
+        delete m_pStatusLabel;
+        m_pStatusLabel = NULL;
+    }
 
-   if (m_pTextureExplorer != NULL)
-   {
-       delete m_pTextureExplorer;
-       m_pTextureExplorer = NULL;
-   }
+    if (m_pFramebufferExplorer != NULL)
+    {
+        delete m_pFramebufferExplorer;
+        m_pFramebufferExplorer = NULL;
+    }
 
-   if (m_pRenderbufferExplorer != NULL)
-   {
-       delete m_pRenderbufferExplorer;
-       m_pRenderbufferExplorer = NULL;
-   }
+    if (m_pTextureExplorer != NULL)
+    {
+        delete m_pTextureExplorer;
+        m_pTextureExplorer = NULL;
+    }
 
-   if (m_pProgramExplorer != NULL)
-   {
-       delete m_pProgramExplorer;
-       m_pProgramExplorer = NULL;
-   }
+    if (m_pRenderbufferExplorer != NULL)
+    {
+        delete m_pRenderbufferExplorer;
+        m_pRenderbufferExplorer = NULL;
+    }
 
-   if (m_pShaderExplorer != NULL)
-   {
-       delete m_pShaderExplorer;
-       m_pShaderExplorer = NULL;
-   }
+    if (m_pProgramExplorer != NULL)
+    {
+        delete m_pProgramExplorer;
+        m_pProgramExplorer = NULL;
+    }
 
-   if (m_pPlayButton != NULL)
-   {
-       delete m_pPlayButton;
-       m_pPlayButton = NULL;
-   }
+    if (m_pShaderExplorer != NULL)
+    {
+        delete m_pShaderExplorer;
+        m_pShaderExplorer = NULL;
+    }
 
-   if (m_pPauseButton != NULL)
-   {
-       delete m_pPauseButton;
-       m_pPauseButton = NULL;
-   }
+    if (m_pPlayButton != NULL)
+    {
+        delete m_pPlayButton;
+        m_pPlayButton = NULL;
+    }
 
-   if (m_pTrimButton != NULL)
-   {
-       delete m_pTrimButton;
-       m_pTrimButton = 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;
+        m_pFramebufferTab_layout = NULL;
+    }
 
-   if (m_pFramebufferTab_layout != NULL)
-   {
-       delete m_pFramebufferTab_layout;
-       m_pFramebufferTab_layout = NULL;
-   }
+    if (m_pTextureTab_layout != NULL)
+    {
+        delete m_pTextureTab_layout;
+        m_pTextureTab_layout = NULL;
+    }
 
-   if (m_pTextureTab_layout != NULL)
-   {
-       delete m_pTextureTab_layout;
-       m_pTextureTab_layout = NULL;
-   }
+    if (m_pRenderbufferTab_layout != NULL)
+    {
+        delete m_pRenderbufferTab_layout;
+        m_pRenderbufferTab_layout = NULL;
+    }
 
-   if (m_pRenderbufferTab_layout != NULL)
-   {
-       delete m_pRenderbufferTab_layout;
-       m_pRenderbufferTab_layout = NULL;
-   }
+    if (m_pProgramTab_layout != NULL)
+    {
+        delete m_pProgramTab_layout;
+        m_pProgramTab_layout = NULL;
+    }
 
-   if (m_pProgramTab_layout != NULL)
-   {
-       delete m_pProgramTab_layout;
-       m_pProgramTab_layout = NULL;
-   }
+    if (m_pShaderTab_layout != NULL)
+    {
+        delete m_pShaderTab_layout;
+        m_pShaderTab_layout = NULL;
+    }
 
-   if (m_pShaderTab_layout != NULL)
-   {
-       delete m_pShaderTab_layout;
-       m_pShaderTab_layout = NULL;
-   }
+    if (m_pStateTreeModel != NULL)
+    {
+        delete m_pStateTreeModel;
+        m_pStateTreeModel = NULL;
+    }
 
-   if (m_pStateTreeModel != NULL)
-   {
-       delete m_pStateTreeModel;
-       m_pStateTreeModel = NULL;
-   }
+    if (m_pVoglReplayProcess != NULL)
+    {
+        delete m_pVoglReplayProcess;
+        m_pVoglReplayProcess = NULL;
+    }
 }
 
 void VoglEditor::playCurrentTraceFile()
@@ -324,18 +321,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 +338,79 @@ void VoglEditor::playCurrentTraceFile()
     setCursor(origCursor);
 }
 
-void VoglEditor::pauseCurrentTraceFile()
+void VoglEditor::trimCurrentTraceFile()
+{
+    trim_trace_file(m_openFilename, static_cast<uint>(m_pTraceReader->get_max_frame_index()), g_settings.trim_large_trace_prompt_size());
+}
+
+/// \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)
     {
-        m_pStatusLabel->clear();
+        // proc crashed
+        m_pStatusLabel->setText("Error: voglreplay aborted unexpectedly.");
+    }
+    else if (procRetValue == 0)
+    {
+        // 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 +428,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 +1046,29 @@ bool VoglEditor::open_trace_file(dynamic_string filename)
        m_pStatusLabel->clear();
    }
 
+   if (tmpReader->get_max_frame_index() > g_settings.trim_large_trace_prompt_size())
+   {
+       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<uint>(tmpReader->get_max_frame_index()), g_settings.trim_large_trace_prompt_size()))
+           {
+               // 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 +1175,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 +1335,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);