diff --git a/DRAMSys/analyzer/data/tracedb.cpp b/DRAMSys/analyzer/data/tracedb.cpp index 06f35f9b..89cd17cb 100644 --- a/DRAMSys/analyzer/data/tracedb.cpp +++ b/DRAMSys/analyzer/data/tracedb.cpp @@ -52,10 +52,18 @@ using namespace std; -TraceDB::TraceDB(QString path,bool openExisting) +TraceDB::TraceDB(QString path, bool openExisting) { this->pathToDB = path; - database = QSqlDatabase::addDatabase("QSQLITE",path); + + database = QSqlDatabase::database(path); + if (database.isValid() && database.isOpen()) { + // Close the database connection if it exists and was not closed yet. + database.removeDatabase(path); + database.close(); + } + + database = QSqlDatabase::addDatabase("QSQLITE", path); database.setDatabaseName(path); database.open(); if(!openExisting) diff --git a/DRAMSys/analyzer/traceanalyzer.cpp b/DRAMSys/analyzer/traceanalyzer.cpp index 11b96392..c3e9e3e2 100644 --- a/DRAMSys/analyzer/traceanalyzer.cpp +++ b/DRAMSys/analyzer/traceanalyzer.cpp @@ -63,9 +63,14 @@ TraceAnalyzer::TraceAnalyzer(QWidget *parent) : ui(new Ui::TraceAnalyzer) { setUpGui(); + // Disable actions except for "Open" until some file is open. + ui->actionReload_all->setEnabled(false); + ui->actionSaveChangesToDB->setEnabled(false); + ui->actionClose_all->setEnabled(false); + ui->actionTest->setEnabled(false); + ui->actionMetrics->setEnabled(false); } - TraceAnalyzer::TraceAnalyzer(QSet paths, StartupOption option, QWidget *parent): QMainWindow(parent), ui(new Ui::TraceAnalyzer) @@ -104,9 +109,18 @@ void TraceAnalyzer::openTracefile(const QString &path) return; TraceFileTab* tab = new TraceFileTab(this, path); - connect(tab, SIGNAL(statusChanged(QString)), this, SLOT(statusChanged(QString))); + connect(tab, SIGNAL(statusChanged(QString, bool)), this, SLOT(statusChanged(QString, bool))); ui->traceFileTabs->addTab(tab,QFileInfo(path).baseName()); openedTraceFiles.insert(path); + + // Enable actions + ui->actionReload_all->setEnabled(true); + ui->actionSaveChangesToDB->setEnabled(true); + ui->actionClose_all->setEnabled(true); + ui->actionTest->setEnabled(true); + ui->actionMetrics->setEnabled(true); + + statusLabel->clear(); } void TraceAnalyzer::on_traceFileTabs_tabCloseRequested(int index) @@ -121,13 +135,65 @@ void TraceAnalyzer::on_actionClose_all_triggered() { while(ui->traceFileTabs->count()) on_traceFileTabs_tabCloseRequested(0); + + // All files closed. Disable actions except for "Open". + ui->actionReload_all->setEnabled(false); + ui->actionSaveChangesToDB->setEnabled(false); + ui->actionClose_all->setEnabled(false); + ui->actionTest->setEnabled(false); + ui->actionMetrics->setEnabled(false); + + statusLabel->clear(); } - - -void TraceAnalyzer::statusChanged(QString message) +void TraceAnalyzer::on_actionReload_all_triggered() { - statusLabel->setText(message + " - (" + QTime::currentTime().toString() + ")"); + TraceFileTab *traceFileTab; + + // Remove all tabs + int tabIndex = 0; + while (ui->traceFileTabs->count() != 0) { + traceFileTab = static_cast(ui->traceFileTabs->widget(0)); + std::cout << "Closing tab #" << tabIndex << " \"" << traceFileTab->getPathToTraceFile().toStdString() << "\"" << std::endl; + + ui->traceFileTabs->removeTab(0); + delete traceFileTab; + + tabIndex++; + } + + QList list = openedTraceFiles.toList(); + qSort(list); + + // Recreate all tabs + tabIndex = 0; + for (auto path : list) { + std::cout << "Reopening tab# " << tabIndex << " \"" << path.toStdString() << "\"" << std::endl; + + traceFileTab = new TraceFileTab(this, path); + connect(traceFileTab, SIGNAL(statusChanged(QString, bool)), this, SLOT(statusChanged(QString, bool))); + ui->traceFileTabs->addTab(traceFileTab, QFileInfo(path).baseName()); + + tabIndex++; + } + + this->statusChanged(QString("All databases reloaded "), true); +} + +void TraceAnalyzer::on_actionSaveChangesToDB_triggered() +{ + for (int index = 0; index < ui->traceFileTabs->count(); index++) { + // Changes in the database files will trigger the file watchers from + // the TraceFileTab class. They generate signals connected to TraceAnalyzer::statusChanged(). + TraceFileTab *traceFileTab = static_cast(ui->traceFileTabs->widget(index)); + traceFileTab->commitChangesToDB(); + } +} + +void TraceAnalyzer::statusChanged(QString message, bool saveChangesEnable) +{ + statusLabel->setText(message + QTime::currentTime().toString()); + ui->actionSaveChangesToDB->setEnabled(saveChangesEnable); } void TraceAnalyzer::on_actionTest_triggered() @@ -142,5 +208,5 @@ void TraceAnalyzer::on_actionMetrics_triggered() evaluationTool.raise(); evaluationTool.activateWindow(); evaluationTool.showAndEvaluateMetrics(openedTraceFiles.toList()); - } + diff --git a/DRAMSys/analyzer/traceanalyzer.h b/DRAMSys/analyzer/traceanalyzer.h index e0b16a0f..f1c04887 100644 --- a/DRAMSys/analyzer/traceanalyzer.h +++ b/DRAMSys/analyzer/traceanalyzer.h @@ -73,6 +73,8 @@ private: private Q_SLOTS: void on_actionOpen_triggered(); + void on_actionReload_all_triggered(); + void on_actionSaveChangesToDB_triggered(); void on_traceFileTabs_tabCloseRequested(int index); void on_actionClose_all_triggered(); void on_actionTest_triggered(); @@ -80,10 +82,11 @@ private Q_SLOTS: void on_actionMetrics_triggered(); public Q_SLOTS: - void statusChanged(QString message); + void statusChanged(QString message, bool saveChangesEnable = false); private: Ui::TraceAnalyzer *ui; }; #endif // TRACEANALYZER_H + diff --git a/DRAMSys/analyzer/traceanalyzer.ui b/DRAMSys/analyzer/traceanalyzer.ui index d99934c7..9dec9288 100644 --- a/DRAMSys/analyzer/traceanalyzer.ui +++ b/DRAMSys/analyzer/traceanalyzer.ui @@ -57,6 +57,8 @@ File + + @@ -81,10 +83,29 @@ Ctrl+O + + + Reload databases + + + CTRL+R + + + + + Save changes to DB + + + CTRL+S + + Close all + + CTRL+Q + diff --git a/DRAMSys/analyzer/tracefiletab.cpp b/DRAMSys/analyzer/tracefiletab.cpp index eb7353da..e2132d84 100644 --- a/DRAMSys/analyzer/tracefiletab.cpp +++ b/DRAMSys/analyzer/tracefiletab.cpp @@ -41,14 +41,15 @@ #include "QFileInfo" #include "qmessagebox.h" #include -#include TraceFileTab::TraceFileTab(QWidget *parent,const QString& path) : - QWidget(parent), - ui(new Ui::TraceFileTab) + QWidget(parent), ui(new Ui::TraceFileTab), savingChangesToDB(false) { ui->setupUi(this); this->path = path; + + std::cout << "Opening new tab for \"" << path.toStdString() << "\"" << std::endl; + initNavigatorAndItsDependentWidgets(path); setUpFileWatcher(path); ui->fileDescriptionEdit->setPlainText(navigator->GeneralTraceInfo().description); @@ -57,10 +58,15 @@ TraceFileTab::TraceFileTab(QWidget *parent,const QString& path) : TraceFileTab::~TraceFileTab() { - navigator->commitChangesToDB(); delete ui; } +void TraceFileTab::commitChangesToDB() +{ + savingChangesToDB = true; + navigator->commitChangesToDB(); +} + void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path) { navigator = new TraceNavigator(path,this); @@ -82,15 +88,20 @@ void TraceFileTab::setUpFileWatcher(QString path) QObject::connect(fileWatcher,SIGNAL(fileChanged(QString)),this,SLOT(tracefileChanged())); } - - void TraceFileTab::tracefileChanged() { - Q_EMIT statusChanged(QString("Last Database Refresh")); + if (savingChangesToDB == true) { + // Database has changed due to user action (e.g., saving comments). + // No need to disable the "Save changes to DB" menu. + savingChangesToDB = false; + Q_EMIT statusChanged(QString("Changes saved "), true); + } else { + // External event changed the database file (e.g., the database file + // was overwritten when running a new test). + // The "Save changes to DB" menu must be disabled to avoid saving + // changes to a corrupted or inconsistent file. + Q_EMIT statusChanged(QString("At least one database has changed on disk "), false); + } navigator->refreshData(); } - - - - diff --git a/DRAMSys/analyzer/tracefiletab.h b/DRAMSys/analyzer/tracefiletab.h index bf57bd88..5acaa96a 100644 --- a/DRAMSys/analyzer/tracefiletab.h +++ b/DRAMSys/analyzer/tracefiletab.h @@ -60,6 +60,7 @@ public: void setUpFileWatcher(QString filename); void initNavigatorAndItsDependentWidgets(QString path); QString getPathToTraceFile(){return path;} + void commitChangesToDB(void); private: QString path; @@ -67,14 +68,15 @@ private: TraceNavigator *navigator; QFileSystemWatcher *fileWatcher; void setUpQueryEditor(QString path); + bool savingChangesToDB; public Q_SLOTS: void tracefileChanged(); Q_SIGNALS: - void statusChanged(QString); + void statusChanged(QString message, bool saveChangesEnable = false); void colorGroupingChanged(ColorGrouping colorgrouping); - }; #endif // TRACEFILETAB_H +