Merge branch 'work/traceanalyzer_comments' into 'develop'
Rewrite of comment system / add functionality to select comments and directly delete/edit them See merge request ems/astdm/dram.sys!308
This commit is contained in:
@@ -75,7 +75,6 @@ add_executable(TraceAnalyzer
|
||||
presentation/tracescroller.cpp
|
||||
traceanalyzer.cpp
|
||||
presentation/transactiontreewidget.cpp
|
||||
presentation/commenttreewidget.cpp
|
||||
presentation/util/clkgrid.cpp
|
||||
queryeditor.cpp
|
||||
presentation/selectedtransactiontreewidget.cpp
|
||||
@@ -97,6 +96,7 @@ add_executable(TraceAnalyzer
|
||||
presentation/util/customlabelscaledraw.cpp
|
||||
presentation/traceselector.cpp
|
||||
businessObjects/configmodels.cpp
|
||||
businessObjects/commentmodel.cpp
|
||||
|
||||
selectmetrics.ui
|
||||
preferences.ui
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef COMMENT_H
|
||||
#define COMMENT_H
|
||||
#include <QString>
|
||||
#include "timespan.h"
|
||||
|
||||
class Comment
|
||||
{
|
||||
traceTime time;
|
||||
QString text;
|
||||
public:
|
||||
Comment(traceTime time, QString text): time(time), text(text) {}
|
||||
traceTime Time() const
|
||||
{
|
||||
return time;
|
||||
}
|
||||
const QString &Text() const
|
||||
{
|
||||
return text;
|
||||
}
|
||||
void changeText(QString newText)
|
||||
{
|
||||
text = newText;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COMMENT_H
|
||||
305
DRAMSys/traceAnalyzer/businessObjects/commentmodel.cpp
Normal file
305
DRAMSys/traceAnalyzer/businessObjects/commentmodel.cpp
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "commentmodel.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QKeyEvent>
|
||||
|
||||
CommentModel::CommentModel(QObject *parent) : QAbstractTableModel(parent),
|
||||
gotoAction(new QAction("Goto comment", this)),
|
||||
editAction(new QAction("Edit comment", this)),
|
||||
deleteAction(new QAction("Delete comment", this)),
|
||||
selectAllAction(new QAction("Select all comments", this)),
|
||||
deselectAllAction(new QAction("Deselect all comments", this)),
|
||||
internalSelectionModel(new QItemSelectionModel(this, this))
|
||||
{
|
||||
setUpActions();
|
||||
}
|
||||
|
||||
void CommentModel::setUpActions()
|
||||
{
|
||||
QObject::connect(gotoAction, &QAction::triggered, this, [=](){
|
||||
const QModelIndexList indexes = internalSelectionModel->selectedRows();
|
||||
for (const QModelIndex ¤tIndex : indexes)
|
||||
{
|
||||
emit gotoCommentTriggered(currentIndex);
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(editAction, &QAction::triggered, this, [=](){
|
||||
const QModelIndexList indexes = internalSelectionModel->selectedRows();
|
||||
for (const QModelIndex ¤tIndex : indexes)
|
||||
emit editTriggered(index(currentIndex.row(), static_cast<int>(Column::Comment)));
|
||||
});
|
||||
|
||||
QObject::connect(deleteAction, &QAction::triggered, this, [=](){
|
||||
const QModelIndexList indexes = internalSelectionModel->selectedRows();
|
||||
for (const QModelIndex ¤tIndex : indexes)
|
||||
removeComment(currentIndex);
|
||||
});
|
||||
|
||||
QObject::connect(selectAllAction, &QAction::triggered, this, [=](){
|
||||
QModelIndex topLeft = index(0, 0);
|
||||
QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
|
||||
internalSelectionModel->select(QItemSelection(topLeft, bottomRight),
|
||||
QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
});
|
||||
|
||||
QObject::connect(deselectAllAction, &QAction::triggered,
|
||||
internalSelectionModel, &QItemSelectionModel::clearSelection);
|
||||
}
|
||||
|
||||
int CommentModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return comments.size();
|
||||
}
|
||||
|
||||
int CommentModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
return static_cast<int>(Column::COLUMNCOUNT);
|
||||
}
|
||||
|
||||
QVariant CommentModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
// Qt::UserRole is used to get the raw time without pretty formatting.
|
||||
if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::UserRole)
|
||||
return QVariant();
|
||||
|
||||
const Comment &comment = comments.at(index.row());
|
||||
|
||||
if (role == Qt::UserRole && static_cast<Column>(index.column()) == Column::Time)
|
||||
return QVariant(comment.time);
|
||||
|
||||
switch (static_cast<Column>(index.column())) {
|
||||
case Column::Time:
|
||||
return QVariant(prettyFormatTime(comment.time));
|
||||
case Column::Comment:
|
||||
return QVariant(comment.text);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool CommentModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
if (static_cast<Column>(index.column()) != Column::Comment)
|
||||
return false;
|
||||
|
||||
QString newText = value.toString();
|
||||
|
||||
Comment &comment = comments.at(index.row());
|
||||
comment.text = newText;
|
||||
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant CommentModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (static_cast<Column>(section)) {
|
||||
case Column::Time:
|
||||
return "Time";
|
||||
case Column::Comment:
|
||||
return "Comment";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags CommentModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
|
||||
|
||||
if (index.isValid() && index.column() == static_cast<int>(Column::Comment))
|
||||
flags |= Qt::ItemIsEditable;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void CommentModel::openContextMenu()
|
||||
{
|
||||
if (!internalSelectionModel->hasSelection())
|
||||
return;
|
||||
|
||||
QMenu *menu = new QMenu();
|
||||
menu->addActions({gotoAction, editAction, deleteAction});
|
||||
menu->addSeparator();
|
||||
menu->addActions({selectAllAction, deselectAllAction});
|
||||
|
||||
QObject::connect(menu, &QMenu::aboutToHide, [=]() {
|
||||
menu->deleteLater();
|
||||
});
|
||||
|
||||
menu->popup(QCursor::pos());
|
||||
}
|
||||
|
||||
QItemSelectionModel *CommentModel::selectionModel() const
|
||||
{
|
||||
return internalSelectionModel;
|
||||
}
|
||||
|
||||
void CommentModel::addComment(traceTime time)
|
||||
{
|
||||
auto commentIt = std::find_if(comments.rbegin(), comments.rend(), [time](const Comment &comment){
|
||||
return comment.time <= time;
|
||||
});
|
||||
|
||||
int insertIndex = std::distance(comments.begin(), commentIt.base());
|
||||
|
||||
beginInsertRows(QModelIndex(), insertIndex, insertIndex);
|
||||
comments.insert(comments.begin() + insertIndex, {time, "Enter comment text..."});
|
||||
endInsertRows();
|
||||
|
||||
internalSelectionModel->setCurrentIndex(index(insertIndex, 0),
|
||||
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
|
||||
emit editTriggered(index(insertIndex, 1));
|
||||
}
|
||||
|
||||
void CommentModel::addComment(traceTime time, QString text)
|
||||
{
|
||||
auto commentIt = std::find_if(comments.rbegin(), comments.rend(), [time](const Comment &comment){
|
||||
return comment.time <= time;
|
||||
});
|
||||
|
||||
int insertIndex = std::distance(comments.begin(), commentIt.base());
|
||||
|
||||
beginInsertRows(QModelIndex(), insertIndex, insertIndex);
|
||||
comments.insert(comments.begin() + insertIndex, {time, text});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CommentModel::removeComment(traceTime time)
|
||||
{
|
||||
auto commentIt = std::find_if(comments.begin(), comments.end(), [time](const Comment &comment){
|
||||
return comment.time == time;
|
||||
});
|
||||
|
||||
if (commentIt == comments.end())
|
||||
return;
|
||||
|
||||
int removeIndex = std::distance(comments.begin(), commentIt);
|
||||
|
||||
beginRemoveRows(QModelIndex(), removeIndex, removeIndex);
|
||||
comments.erase(commentIt);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void CommentModel::removeComment(const QModelIndex &index)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), index.row(), index.row());
|
||||
comments.erase(comments.begin() + index.row());
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
const std::vector<CommentModel::Comment> &CommentModel::getComments() const
|
||||
{
|
||||
return comments;
|
||||
}
|
||||
|
||||
traceTime CommentModel::getTimeFromIndex(const QModelIndex &index) const
|
||||
{
|
||||
Q_ASSERT(comments.size() > index.row());
|
||||
|
||||
return comments[index.row()].time;
|
||||
}
|
||||
|
||||
QModelIndex CommentModel::hoveredComment(Timespan timespan) const
|
||||
{
|
||||
auto commentIt = std::find_if(comments.begin(), comments.end(), [timespan](const Comment &comment){
|
||||
return timespan.Begin() < comment.time && comment.time < timespan.End();
|
||||
});
|
||||
|
||||
if (commentIt == comments.end())
|
||||
return QModelIndex();
|
||||
|
||||
int commentIndex = std::distance(comments.begin(), commentIt);
|
||||
|
||||
return index(commentIndex, 0);
|
||||
}
|
||||
|
||||
bool CommentModel::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object)
|
||||
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Delete)
|
||||
{
|
||||
const QModelIndexList indexes = internalSelectionModel->selectedRows();
|
||||
for (const QModelIndex ¤tIndex : indexes)
|
||||
{
|
||||
removeComment(currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CommentModel::rowDoubleClicked(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (static_cast<Column>(index.column()) == Column::Time)
|
||||
Q_EMIT gotoCommentTriggered(index);
|
||||
}
|
||||
119
DRAMSys/traceAnalyzer/businessObjects/commentmodel.h
Normal file
119
DRAMSys/traceAnalyzer/businessObjects/commentmodel.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef COMMENTMODEL_H
|
||||
#define COMMENTMODEL_H
|
||||
|
||||
#include "tracetime.h"
|
||||
#include "timespan.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <utility>
|
||||
|
||||
class QAction;
|
||||
class QItemSelectionModel;
|
||||
|
||||
class CommentModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CommentModel(QObject *parent = nullptr);
|
||||
|
||||
struct Comment {
|
||||
traceTime time;
|
||||
QString text;
|
||||
};
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
enum class Column {
|
||||
Time = 0,
|
||||
Comment,
|
||||
COLUMNCOUNT
|
||||
};
|
||||
|
||||
void openContextMenu();
|
||||
|
||||
QItemSelectionModel *selectionModel() const;
|
||||
|
||||
void addComment(traceTime time);
|
||||
void addComment(traceTime time, QString text);
|
||||
|
||||
void removeComment(traceTime time);
|
||||
void removeComment(const QModelIndex &index);
|
||||
|
||||
const std::vector<Comment> &getComments() const;
|
||||
|
||||
traceTime getTimeFromIndex(const QModelIndex &index) const;
|
||||
|
||||
QModelIndex hoveredComment(Timespan timespan) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void rowDoubleClicked(const QModelIndex &index);
|
||||
|
||||
protected:
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
/**
|
||||
* The eventFilter is used to delete comments using the delete key.
|
||||
*/
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void editTriggered(const QModelIndex &index);
|
||||
void gotoCommentTriggered(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
void setUpActions();
|
||||
|
||||
std::vector<Comment> comments;
|
||||
|
||||
QAction *gotoAction;
|
||||
QAction *editAction;
|
||||
QAction *deleteAction;
|
||||
QAction *selectAllAction;
|
||||
QAction *deselectAllAction;
|
||||
|
||||
QItemSelectionModel *internalSelectionModel;
|
||||
};
|
||||
|
||||
#endif // COMMENTMODEL_H
|
||||
@@ -44,7 +44,6 @@
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include "data/tracedb.h"
|
||||
#include "businessObjects/comment.h"
|
||||
#include "businessObjects/phases/phasefactory.h"
|
||||
|
||||
|
||||
@@ -87,7 +86,7 @@ void TraceDB::prepareQueries()
|
||||
selectDebugMessagesByTimespanWithLimit.prepare("SELECT time, Message FROM DebugMessages WHERE :begin <= time AND time <= :end LIMIT :limit");
|
||||
}
|
||||
|
||||
void TraceDB::updateComments(vector<Comment> comments)
|
||||
void TraceDB::updateComments(const std::vector<CommentModel::Comment> &comments)
|
||||
{
|
||||
|
||||
QSqlQuery query(database);
|
||||
@@ -95,9 +94,10 @@ void TraceDB::updateComments(vector<Comment> comments)
|
||||
executeQuery(query);
|
||||
query.prepare("insert into Comments values(:time,:text)");
|
||||
|
||||
for (const Comment &comment : comments) {
|
||||
query.bindValue(":time", comment.Time());
|
||||
query.bindValue(":text", comment.Text());
|
||||
for (const auto &comment : comments)
|
||||
{
|
||||
query.bindValue(":time", comment.time);
|
||||
query.bindValue(":text", comment.text);
|
||||
executeQuery(query);
|
||||
}
|
||||
}
|
||||
@@ -341,7 +341,7 @@ unsigned int TraceDB::getNumberOfPhases()
|
||||
return query.value(0).toInt();
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::getComments()
|
||||
vector<CommentModel::Comment> TraceDB::getComments()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT Time,Text From Comments");
|
||||
@@ -350,7 +350,7 @@ vector<Comment> TraceDB::getComments()
|
||||
}
|
||||
|
||||
|
||||
vector<Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span)
|
||||
vector<CommentModel::Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span)
|
||||
{
|
||||
selectDebugMessagesByTimespan.bindValue(":begin", span.Begin());
|
||||
selectDebugMessagesByTimespan.bindValue(":end", span.End());
|
||||
@@ -359,7 +359,7 @@ vector<Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span)
|
||||
return parseCommentsFromQuery(selectDebugMessagesByTimespan);
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span,
|
||||
vector<CommentModel::Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span,
|
||||
unsigned int limit = 50)
|
||||
{
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":begin", span.Begin());
|
||||
@@ -432,12 +432,12 @@ vector<shared_ptr<Transaction>> TraceDB::parseTransactionsFromQuery(
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::parseCommentsFromQuery(QSqlQuery &query)
|
||||
vector<CommentModel::Comment> TraceDB::parseCommentsFromQuery(QSqlQuery &query)
|
||||
{
|
||||
vector<Comment> result;
|
||||
vector<CommentModel::Comment> result;
|
||||
while (query.next()) {
|
||||
result.push_back(Comment(query.value(0).toLongLong(),
|
||||
query.value(1).toString()));
|
||||
result.push_back(CommentModel::Comment{query.value(0).toLongLong(),
|
||||
query.value(1).toString()});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#include "businessObjects/generalinfo.h"
|
||||
#include "businessObjects/commandlengths.h"
|
||||
#include "businessObjects/phases/phasefactory.h"
|
||||
#include "businessObjects/comment.h"
|
||||
#include "businessObjects/commentmodel.h"
|
||||
#include "QueryTexts.h"
|
||||
|
||||
/* TraceDB handles the connection to a SQLLite database containing trace data.
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
return pathToDB;
|
||||
}
|
||||
|
||||
void updateComments(std::vector<Comment> comments);
|
||||
void updateComments(const std::vector<CommentModel::Comment> &comments);
|
||||
void updateFileDescription(const QString &description);
|
||||
void refreshData();
|
||||
|
||||
@@ -98,9 +98,9 @@ public:
|
||||
std::shared_ptr<Transaction> getTransactionByID(ID id);
|
||||
ID getTransactionIDFromPhaseID(ID phaseID);
|
||||
|
||||
std::vector<Comment> getComments();
|
||||
std::vector<Comment> getDebugMessagesInTimespan(const Timespan &span);
|
||||
std::vector<Comment> getDebugMessagesInTimespan(const Timespan &span,
|
||||
std::vector<CommentModel::Comment> getComments();
|
||||
std::vector<CommentModel::Comment> getDebugMessagesInTimespan(const Timespan &span);
|
||||
std::vector<CommentModel::Comment> getDebugMessagesInTimespan(const Timespan &span,
|
||||
unsigned int limit);
|
||||
|
||||
QSqlDatabase getDatabase() const;
|
||||
@@ -125,7 +125,7 @@ private:
|
||||
std::shared_ptr<Transaction> parseTransactionFromQuery(QSqlQuery &query);
|
||||
std::vector<std::shared_ptr<Transaction>> parseTransactionsFromQuery(
|
||||
QSqlQuery &query);
|
||||
std::vector<Comment> parseCommentsFromQuery(QSqlQuery &query);
|
||||
std::vector<CommentModel::Comment> parseCommentsFromQuery(QSqlQuery &query);
|
||||
|
||||
void executeScriptFile(QString fileName);
|
||||
void dropAndCreateTables();
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "commenttreewidget.h"
|
||||
#include <QTreeWidgetItem>
|
||||
#include <iostream>
|
||||
#include <QMenu>
|
||||
#include <QKeyEvent>
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
|
||||
CommentTreeWidget::CommentTreeWidget(QWidget *parent) : QTreeWidget(parent),
|
||||
deleteComment(new QAction("Delete comment", this)),
|
||||
changeCommentText(new QAction("Change comment text", this))
|
||||
{
|
||||
connect(deleteComment, &QAction::triggered, this, [this](){
|
||||
for (QTreeWidgetItem *item : selectedItems())
|
||||
{
|
||||
CommentTreeItem *commentItem = static_cast<CommentTreeItem *>(item);
|
||||
navigator->removeCommentAtTime(commentItem->Time());
|
||||
}
|
||||
});
|
||||
|
||||
connect(changeCommentText, &QAction::triggered, this, [this](){
|
||||
for (QTreeWidgetItem *item : selectedItems())
|
||||
{
|
||||
CommentTreeItem *commentItem = static_cast<CommentTreeItem *>(item);
|
||||
|
||||
bool ok;
|
||||
QString newText = QInputDialog::getText(this, QString("Change comment text"),
|
||||
QString("Change comment text"), QLineEdit::Normal,
|
||||
QString(), &ok);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
deleteComment->trigger();
|
||||
navigator->insertComment({commentItem->Time(), newText});
|
||||
}
|
||||
|
||||
commentsChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CommentTreeWidget::init(TraceNavigator *navigator)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
this->navigator = navigator;
|
||||
setColumnCount(2);
|
||||
setHeaderLabels(QStringList({"Time", "Comment"}));
|
||||
QObject::connect(navigator, SIGNAL(commentsChanged()), this,
|
||||
SLOT(commentsChanged()));
|
||||
QObject::connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
|
||||
SLOT(itemDoubleClicked(QTreeWidgetItem *, int)));
|
||||
QObject::connect(this, SIGNAL(customContextMenuRequested(QPoint)), this,
|
||||
SLOT(ContextMenuRequested(QPoint)));
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
printComments();
|
||||
}
|
||||
|
||||
void CommentTreeWidget::commentsChanged()
|
||||
{
|
||||
clear();
|
||||
printComments();
|
||||
}
|
||||
|
||||
void CommentTreeWidget::printComments()
|
||||
{
|
||||
for (const auto &pair : navigator->getComments()) {
|
||||
const Comment &comment = pair.second;
|
||||
QTreeWidgetItem *item = new CommentTreeItem(this, comment);
|
||||
addTopLevelItem(item);
|
||||
}
|
||||
resizeColumnToContents(0);
|
||||
}
|
||||
|
||||
void CommentTreeWidget::itemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
|
||||
{
|
||||
CommentTreeItem *commentItem = static_cast<CommentTreeItem *>(item);
|
||||
navigator->navigateToTime(commentItem->Time());
|
||||
}
|
||||
|
||||
void CommentTreeWidget::ContextMenuRequested(QPoint point)
|
||||
{
|
||||
QMenu contextMenu(this);
|
||||
contextMenu.addActions({deleteComment, changeCommentText});
|
||||
contextMenu.exec(mapToGlobal(point));
|
||||
}
|
||||
|
||||
|
||||
CommentTreeWidget::CommentTreeItem::CommentTreeItem(QTreeWidget *parent,
|
||||
const Comment &comment): QTreeWidgetItem(parent), comment(comment)
|
||||
{
|
||||
this->setText(0, prettyFormatTime(comment.Time()));
|
||||
this->setText(1, comment.Text());
|
||||
}
|
||||
|
||||
void CommentTreeWidget::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Delete)
|
||||
deleteComment->trigger();
|
||||
else if (event->key() == Qt::Key_F2)
|
||||
changeCommentText->trigger();
|
||||
|
||||
QTreeWidget::keyPressEvent(event);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef COMMENTTREEWIDGET_H
|
||||
#define COMMENTTREEWIDGET_H
|
||||
#include <QTreeWidget>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QAction>
|
||||
#include "businessObjects/comment.h"
|
||||
#include "tracenavigator.h"
|
||||
|
||||
class CommentTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CommentTreeWidget(QWidget *parent = nullptr);
|
||||
void init(TraceNavigator *navigator);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void commentsChanged();
|
||||
void ContextMenuRequested(QPoint point);
|
||||
void itemDoubleClicked(QTreeWidgetItem *item, int column);
|
||||
|
||||
private:
|
||||
bool isInitialized = false;
|
||||
TraceNavigator *navigator;
|
||||
void printComments();
|
||||
QAction *deleteComment;
|
||||
QAction *changeCommentText;
|
||||
|
||||
class CommentTreeItem : public QTreeWidgetItem
|
||||
{
|
||||
private:
|
||||
Comment comment;
|
||||
public:
|
||||
CommentTreeItem(QTreeWidget *parent, const Comment &comment);
|
||||
QString Text()
|
||||
{
|
||||
return comment.Text();
|
||||
}
|
||||
traceTime Time()
|
||||
{
|
||||
return comment.Time();
|
||||
}
|
||||
void changeText(QString newText)
|
||||
{
|
||||
comment.changeText(newText);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // COMMENTTREEWIDGET_H
|
||||
@@ -84,19 +84,19 @@ void DebugMessageTreeWidget::currentTraceTimeChanged()
|
||||
traceplot->GetCurrentTimespan()));
|
||||
}
|
||||
|
||||
void DebugMessageTreeWidget::showDebugMessages(const vector<Comment> &comments)
|
||||
void DebugMessageTreeWidget::showDebugMessages(const vector<CommentModel::Comment> &comments)
|
||||
{
|
||||
clear();
|
||||
if (comments.empty())
|
||||
return;
|
||||
|
||||
traceTime currentTime = -1;
|
||||
for (Comment comment : comments) {
|
||||
if (currentTime != comment.Time()) {
|
||||
addTopLevelItem(new QTreeWidgetItem({prettyFormatTime(comment.Time()), formatDebugMessage(comment.Text())}));
|
||||
currentTime = comment.Time();
|
||||
for (const auto &comment : comments) {
|
||||
if (currentTime != comment.time) {
|
||||
addTopLevelItem(new QTreeWidgetItem({prettyFormatTime(comment.time), formatDebugMessage(comment.text)}));
|
||||
currentTime = comment.time;
|
||||
} else {
|
||||
addTopLevelItem(new QTreeWidgetItem({"", formatDebugMessage(comment.Text())}));
|
||||
addTopLevelItem(new QTreeWidgetItem({"", formatDebugMessage(comment.text)}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QMouseEvent>
|
||||
#include "businessObjects/comment.h"
|
||||
#include "businessObjects/commentmodel.h"
|
||||
#include "tracenavigator.h"
|
||||
#include "traceplot.h"
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
hexAdressMatcher(QString("0x[0-9,a-f]+")) {}
|
||||
void init(TraceNavigator *navigator, TracePlot *traceplot);
|
||||
|
||||
void showDebugMessages(const std::vector<Comment> &comments);
|
||||
void showDebugMessages(const std::vector<CommentModel::Comment> &comments);
|
||||
void arrangeUiSettings();
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
@@ -39,14 +39,24 @@
|
||||
#include "tracenavigator.h"
|
||||
#include "util/traceplotlinecache.h"
|
||||
#include "vector"
|
||||
#include "businessObjects/commentmodel.h"
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
|
||||
using namespace std;
|
||||
|
||||
TraceNavigator::TraceNavigator(QString path, QObject *parent)
|
||||
: QObject(parent), traceFile(path, true), changesToCommitExist(false)
|
||||
TraceNavigator::TraceNavigator(QString path, CommentModel *commentModel, QObject *parent)
|
||||
: QObject(parent), traceFile(path, true), commentModel(commentModel), changesToCommitExist(false)
|
||||
{
|
||||
getCommentsFromDB();
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::gotoCommentTriggered, this, [=](const QModelIndex &index){
|
||||
navigateToTime(commentModel->getTimeFromIndex(index));
|
||||
});
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::dataChanged, this, &TraceNavigator::traceFileModified);
|
||||
QObject::connect(commentModel, &CommentModel::rowsRemoved, this, &TraceNavigator::traceFileModified);
|
||||
|
||||
tracePlotLineCache =
|
||||
std::make_shared<TracePlotLineCache>(getTracePlotLines(), GeneralTraceInfo().numberOfRanks,
|
||||
GeneralTraceInfo().groupsPerRank, GeneralTraceInfo().banksPerGroup);
|
||||
@@ -79,49 +89,20 @@ void TraceNavigator::navigateToTransaction(ID id)
|
||||
navigateToTime(traceFile.getTransactionByID(id)->span.Begin());
|
||||
}
|
||||
|
||||
|
||||
/* Comment and debug messages
|
||||
*
|
||||
*/
|
||||
void TraceNavigator::insertComment(const Comment &comment)
|
||||
{
|
||||
comments.emplace(comment.Time(), comment);
|
||||
changesToCommitExist = true;
|
||||
Q_EMIT commentsChanged();
|
||||
}
|
||||
|
||||
void TraceNavigator::removeCommentAtTime(traceTime time)
|
||||
{
|
||||
auto found = comments.find(time);
|
||||
if (found != comments.end()) {
|
||||
comments.erase(found);
|
||||
changesToCommitExist = true;
|
||||
Q_EMIT commentsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DB
|
||||
*
|
||||
*/
|
||||
|
||||
void TraceNavigator::commitChangesToDB()
|
||||
{
|
||||
vector<Comment> commentsToInsert;
|
||||
for (const auto &pair : comments) {
|
||||
commentsToInsert.push_back(pair.second);
|
||||
}
|
||||
|
||||
traceFile.updateComments(commentsToInsert);
|
||||
traceFile.updateComments(commentModel->getComments());
|
||||
changesToCommitExist = false;
|
||||
}
|
||||
|
||||
void TraceNavigator::getCommentsFromDB()
|
||||
{
|
||||
for (const Comment &comment : traceFile.getComments()) {
|
||||
comments.emplace(comment.Time(), comment);
|
||||
}
|
||||
for (const auto &comment : traceFile.getComments())
|
||||
commentModel->addComment(comment.time, comment.text);
|
||||
}
|
||||
|
||||
void TraceNavigator::refreshData()
|
||||
@@ -334,3 +315,18 @@ std::shared_ptr<TracePlotLineCache> TraceNavigator::getTracePlotLineCache()
|
||||
{
|
||||
return tracePlotLineCache;
|
||||
}
|
||||
|
||||
const CommentModel *TraceNavigator::getCommentModel() const
|
||||
{
|
||||
return commentModel;
|
||||
}
|
||||
|
||||
bool TraceNavigator::existChangesToCommit() const
|
||||
{
|
||||
return changesToCommitExist;
|
||||
}
|
||||
|
||||
void TraceNavigator::traceFileModified()
|
||||
{
|
||||
changesToCommitExist = true;
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@
|
||||
#include "data/tracedb.h"
|
||||
#include "businessObjects/generalinfo.h"
|
||||
#include "businessObjects/transaction.h"
|
||||
#include "businessObjects/comment.h"
|
||||
#include "memory"
|
||||
|
||||
class TracePlotLineCache;
|
||||
class CommentModel;
|
||||
|
||||
/* Class to navigate through a tracefile
|
||||
*
|
||||
@@ -56,10 +56,9 @@ class TracePlotLineCache;
|
||||
class TraceNavigator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
using CommentMap = std::map<traceTime, Comment>;
|
||||
|
||||
public:
|
||||
TraceNavigator(QString path, QObject *parent = 0);
|
||||
TraceNavigator(QString path, CommentModel *commentModel, QObject *parent = 0);
|
||||
~TraceNavigator();
|
||||
|
||||
traceTime CurrentTraceTime() const
|
||||
@@ -111,23 +110,22 @@ public:
|
||||
bool transactionIsSelected(const std::shared_ptr<Transaction> &Transaction)
|
||||
const;
|
||||
|
||||
void insertComment(const Comment &comment);
|
||||
const CommentMap &getComments()
|
||||
{
|
||||
return comments;
|
||||
}
|
||||
void removeCommentAtTime(traceTime time);
|
||||
|
||||
void commitChangesToDB();
|
||||
void refreshData();
|
||||
|
||||
std::shared_ptr<TracePlotLineVector> getTracePlotLines();
|
||||
std::shared_ptr<TracePlotLineCache> getTracePlotLineCache();
|
||||
|
||||
const CommentModel *getCommentModel() const;
|
||||
|
||||
bool existChangesToCommit() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentTraceTimeChanged();
|
||||
void selectedTransactionsChanged();
|
||||
void commentsChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void traceFileModified();
|
||||
|
||||
private:
|
||||
TraceDB traceFile;
|
||||
@@ -136,7 +134,9 @@ private:
|
||||
//components drawing the tracefile center around that time
|
||||
traceTime currentTraceTime = 0;
|
||||
std::vector<std::shared_ptr<Transaction>> selectedTransactions;
|
||||
CommentMap comments;
|
||||
|
||||
CommentModel *commentModel;
|
||||
|
||||
void getCommentsFromDB();
|
||||
bool changesToCommitExist;
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "traceplot.h"
|
||||
#include "gototimedialog.h"
|
||||
#include "tracedrawing.h"
|
||||
#include "businessObjects/commentmodel.h"
|
||||
#include "util/engineeringScaleDraw.h"
|
||||
#include "util/clkgrid.h"
|
||||
#include "util/customlabelscaledraw.h"
|
||||
@@ -184,12 +185,24 @@ void TracePlot::setUpContextMenu()
|
||||
contextMenu->addActions({showQueryEditor, insertComment, exportToPdf, toggleCollapsedState});
|
||||
}
|
||||
|
||||
void TracePlot::init(TraceNavigator *navigator, QScrollBar *scrollBar)
|
||||
void TracePlot::init(TraceNavigator *navigator, QScrollBar *scrollBar, CommentModel *commentModel)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
|
||||
this->scrollBar = scrollBar;
|
||||
this->commentModel = commentModel;
|
||||
|
||||
installEventFilter(commentModel);
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::dataChanged,
|
||||
this, &TracePlot::commentsChanged);
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::rowsRemoved,
|
||||
this, &TracePlot::commentsChanged);
|
||||
|
||||
QObject::connect(commentModel->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &TracePlot::commentsChanged);
|
||||
|
||||
this->navigator = navigator;
|
||||
connectNavigatorQ_SIGNALS();
|
||||
@@ -216,8 +229,6 @@ void TracePlot::connectNavigatorQ_SIGNALS()
|
||||
SLOT(currentTraceTimeChanged()));
|
||||
QObject::connect(navigator, SIGNAL(selectedTransactionsChanged()), this,
|
||||
SLOT(selectedTransactionsChanged()));
|
||||
QObject::connect(navigator, SIGNAL(commentsChanged()), this,
|
||||
SLOT(commentsChanged()));
|
||||
}
|
||||
|
||||
void TracePlot::setUpDrawingProperties()
|
||||
@@ -343,16 +354,23 @@ Timespan TracePlot::GetCurrentTimespan()
|
||||
|
||||
void TracePlot::getAndDrawComments()
|
||||
{
|
||||
for (const auto &pair : navigator->getComments()) {
|
||||
const Comment &comment = pair.second;
|
||||
QwtPlotMarker *maker = new QwtPlotMarker();
|
||||
maker->setLabel(comment.Text());
|
||||
maker->setLabelOrientation(Qt::Vertical);
|
||||
maker->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
|
||||
maker->setXValue(static_cast<double>(comment.Time()));
|
||||
maker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
|
||||
maker->setLinePen(QColor(Qt::blue), 2);
|
||||
maker->attach(this);
|
||||
QList<QModelIndex> selectedRows = commentModel->selectionModel()->selectedRows();
|
||||
|
||||
for (int row = 0; row < commentModel->rowCount(); row++)
|
||||
{
|
||||
QModelIndex timeIndex = commentModel->index(row, static_cast<int>(CommentModel::Column::Time));
|
||||
QModelIndex textIndex = commentModel->index(row, static_cast<int>(CommentModel::Column::Comment));
|
||||
|
||||
bool selected = std::find(selectedRows.begin(), selectedRows.end(), commentModel->index(row, 0)) != selectedRows.end();
|
||||
|
||||
QwtPlotMarker *marker = new QwtPlotMarker();
|
||||
marker->setLabel(textIndex.data().toString());
|
||||
marker->setLabelOrientation(Qt::Vertical);
|
||||
marker->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
|
||||
marker->setXValue(static_cast<double>(timeIndex.data(Qt::UserRole).toLongLong()));
|
||||
marker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
|
||||
marker->setLinePen(QColor(selected ? Qt::red : Qt::blue), 2);
|
||||
marker->attach(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,13 +559,7 @@ void TracePlot::on_deselectAll()
|
||||
void TracePlot::on_insertComment()
|
||||
{
|
||||
traceTime time = invTransform(xBottom, contextMenuMouseDown.x());
|
||||
bool ok;
|
||||
QString text = QInputDialog::getText(this, QString("Insert comment"),
|
||||
QString("Insert comment at ") + prettyFormatTime(time), QLineEdit::Normal,
|
||||
QString(), &ok);
|
||||
if (ok) {
|
||||
navigator->insertComment(Comment(time, text));
|
||||
}
|
||||
commentModel->addComment(time);
|
||||
}
|
||||
|
||||
void TracePlot::on_goToTime()
|
||||
@@ -646,9 +658,13 @@ bool TracePlot::eventFilter(QObject *object, QEvent *event)
|
||||
mouseDownData.mouseIsDownForDragging = true;
|
||||
canvas()->setCursor(Qt::ClosedHandCursor);
|
||||
SelectTransaction(mouseEvent->x(), mouseEvent->y());
|
||||
SelectComment(mouseEvent->x());
|
||||
}
|
||||
return true;
|
||||
} else if (mouseEvent->button() == Qt::RightButton) {
|
||||
// Also select comments to make it more obvious.
|
||||
SelectComment(mouseEvent->x());
|
||||
|
||||
openContextMenu(this->canvas()->mapToGlobal(mouseEvent->pos()),
|
||||
mouseEvent->pos());
|
||||
return true;
|
||||
@@ -704,7 +720,7 @@ bool TracePlot::eventFilter(QObject *object, QEvent *event)
|
||||
return false;
|
||||
}
|
||||
|
||||
void TracePlot::SelectTransaction(int x, int y)
|
||||
void TracePlot::SelectTransaction(int x, int y) const
|
||||
{
|
||||
double yVal = invTransform(yLeft, y);
|
||||
traceTime time = invTransform(xBottom, x);
|
||||
@@ -717,10 +733,35 @@ void TracePlot::SelectTransaction(int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::SelectComment(int x) const
|
||||
{
|
||||
Timespan timespan = hoveredTimespan(x);
|
||||
QModelIndex index = commentModel->hoveredComment(timespan);
|
||||
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (keyPressData.ctrlPressed)
|
||||
commentModel->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
|
||||
else
|
||||
commentModel->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
Timespan TracePlot::hoveredTimespan(int x) const
|
||||
{
|
||||
traceTime time = invTransform(xBottom, x);
|
||||
traceTime offset = 0.01 * zoomLevel;
|
||||
|
||||
return Timespan(time - offset, time + offset);
|
||||
}
|
||||
|
||||
void TracePlot::openContextMenu(const QPoint &pos, const QPoint &mouseDown)
|
||||
{
|
||||
contextMenuMouseDown = mouseDown;
|
||||
contextMenu->exec(pos);
|
||||
Timespan timespan = hoveredTimespan(mouseDown.x());
|
||||
|
||||
if (commentModel->hoveredComment(timespan).isValid())
|
||||
commentModel->openContextMenu();
|
||||
else
|
||||
contextMenu->exec(pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
class TracePlotMouseLabel;
|
||||
class CustomLabelScaleDraw;
|
||||
class ToggleCollapsedAction;
|
||||
class CommentModel;
|
||||
|
||||
class TracePlot : public QwtPlot
|
||||
{
|
||||
@@ -71,7 +72,7 @@ class TracePlot : public QwtPlot
|
||||
|
||||
public:
|
||||
TracePlot(QWidget *parent = NULL);
|
||||
void init(TraceNavigator *navigator, QScrollBar *scrollBar);
|
||||
void init(TraceNavigator *navigator, QScrollBar *scrollBar, CommentModel *commentModel);
|
||||
Timespan GetCurrentTimespan();
|
||||
traceTime ZoomLevel() const
|
||||
{
|
||||
@@ -97,6 +98,7 @@ Q_SIGNALS:
|
||||
void tracePlotZoomChanged();
|
||||
void tracePlotLinesChanged();
|
||||
void colorGroupingChanged(ColorGrouping colorgrouping);
|
||||
// void editComment
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_executeQuery();
|
||||
@@ -129,6 +131,7 @@ private:
|
||||
QMenu *contextMenu;
|
||||
QScrollBar *scrollBar;
|
||||
CustomLabelScaleDraw *customLabelScaleDraw;
|
||||
CommentModel *commentModel;
|
||||
|
||||
void setUpTracePlotItem();
|
||||
void setUpDrawingProperties();
|
||||
@@ -186,7 +189,10 @@ private:
|
||||
|
||||
void openContextMenu(const QPoint &pos, const QPoint &mouseDown);
|
||||
QPoint contextMenuMouseDown;
|
||||
void SelectTransaction(int x, int y);
|
||||
void SelectTransaction(int x, int y) const;
|
||||
void SelectComment(int x) const;
|
||||
//const std::vector<std::shared_ptr<Comment>> hoveredComments(traceTime time) const;
|
||||
Timespan hoveredTimespan(int x) const;
|
||||
void keyPressEvent(QKeyEvent *keyPressedEvent);
|
||||
void keyReleaseEvent(QKeyEvent *keyReleasedEvent);
|
||||
|
||||
|
||||
@@ -62,6 +62,17 @@ void TraceScroller::init(TraceNavigator *navigator, TracePlot *tracePlot)
|
||||
this -> navigator = navigator;
|
||||
connectNavigatorQ_SIGNALS();
|
||||
|
||||
const CommentModel *commentModel = navigator->getCommentModel();
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::dataChanged,
|
||||
this, &TraceScroller::commentsChanged);
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::rowsRemoved,
|
||||
this, &TraceScroller::commentsChanged);
|
||||
|
||||
QObject::connect(commentModel->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &TraceScroller::commentsChanged);
|
||||
|
||||
setUpDrawingProperties();
|
||||
setUpAxis();
|
||||
setUpTracePlotItem();
|
||||
@@ -119,8 +130,7 @@ void TraceScroller::connectNavigatorQ_SIGNALS()
|
||||
{
|
||||
QObject::connect(navigator, SIGNAL(currentTraceTimeChanged()), this,
|
||||
SLOT(currentTraceTimeChanged()));
|
||||
QObject::connect(navigator, SIGNAL(commentsChanged()), this,
|
||||
SLOT(commentsChanged()));
|
||||
|
||||
QObject::connect(navigator, SIGNAL(selectedTransactionsChanged()), this,
|
||||
SLOT(selectedTransactionsChanged()));
|
||||
}
|
||||
@@ -147,12 +157,19 @@ Timespan TraceScroller::GetCurrentTimespan()
|
||||
|
||||
void TraceScroller::getAndDrawComments()
|
||||
{
|
||||
for (const auto &pair : navigator->getComments()) {
|
||||
const Comment &comment = pair.second;
|
||||
const CommentModel *commentModel = navigator->getCommentModel();
|
||||
QList<QModelIndex> selectedRows = commentModel->selectionModel()->selectedRows();
|
||||
|
||||
for (int row = 0; row < commentModel->rowCount(); row++)
|
||||
{
|
||||
QModelIndex timeIndex = commentModel->index(row, static_cast<int>(CommentModel::Column::Time));
|
||||
|
||||
bool selected = std::find(selectedRows.begin(), selectedRows.end(), commentModel->index(row, 0)) != selectedRows.end();
|
||||
|
||||
QwtPlotMarker *maker = new QwtPlotMarker();
|
||||
maker->setXValue(static_cast<double>(comment.Time()));
|
||||
maker->setXValue(static_cast<double>(timeIndex.data(Qt::UserRole).toLongLong()));
|
||||
maker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
|
||||
maker->setLinePen(QColor(Qt::blue), 2);
|
||||
maker->setLinePen(QColor(selected ? Qt::red : Qt::blue), 2);
|
||||
maker->attach(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ private:
|
||||
void setUpAxis();
|
||||
void connectNavigatorQ_SIGNALS();
|
||||
|
||||
|
||||
void getAndDrawComments();
|
||||
QwtPlotZoneItem *canvasClip;
|
||||
traceTime zoomLevel;
|
||||
|
||||
@@ -37,12 +37,13 @@
|
||||
*/
|
||||
|
||||
#include "traceanalyzer.h"
|
||||
#include "ui_traceanalyzer.h"
|
||||
#include "QMessageBox"
|
||||
#include "tracefiletab.h"
|
||||
#include "ui_traceanalyzer.h"
|
||||
#include <QCloseEvent>
|
||||
#include <QDateTime>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include "QMessageBox"
|
||||
#include <iostream>
|
||||
|
||||
void TraceAnalyzer::setUpStatusBar()
|
||||
@@ -64,13 +65,6 @@ 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->actionExportAsVCD->setEnabled(false);
|
||||
ui->actionClose_all->setEnabled(false);
|
||||
ui->actionTest->setEnabled(false);
|
||||
ui->actionMetrics->setEnabled(false);
|
||||
}
|
||||
|
||||
TraceAnalyzer::TraceAnalyzer(QSet<QString> paths, StartupOption option,
|
||||
@@ -119,41 +113,43 @@ void TraceAnalyzer::openTracefile(const QString &path)
|
||||
ui->traceFileTabs->addTab(tab, QFileInfo(path).baseName());
|
||||
openedTraceFiles.insert(path);
|
||||
|
||||
// Enable actions
|
||||
ui->actionReload_all->setEnabled(true);
|
||||
ui->actionSaveChangesToDB->setEnabled(true);
|
||||
|
||||
if (PythonCaller::instance().vcdExportDependenciesAvailable())
|
||||
ui->actionExportAsVCD->setEnabled(true);
|
||||
|
||||
ui->actionClose_all->setEnabled(true);
|
||||
ui->actionTest->setEnabled(true);
|
||||
ui->actionMetrics->setEnabled(true);
|
||||
|
||||
statusLabel->clear();
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_menuFile_aboutToShow()
|
||||
{
|
||||
ui->actionOpen->setEnabled(true);
|
||||
|
||||
bool tabsOpen = ui->traceFileTabs->count() > 0;
|
||||
bool exportAsVcdAvailable = PythonCaller::instance().vcdExportDependenciesAvailable();
|
||||
|
||||
ui->actionReload_all->setEnabled(tabsOpen);
|
||||
ui->actionSaveChangesToDB->setEnabled(tabsOpen);
|
||||
ui->actionExportAsVCD->setEnabled(tabsOpen && exportAsVcdAvailable);
|
||||
ui->actionClose_all->setEnabled(tabsOpen);
|
||||
ui->actionTest->setEnabled(tabsOpen);
|
||||
ui->actionMetrics->setEnabled(tabsOpen);
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_traceFileTabs_tabCloseRequested(int index)
|
||||
{
|
||||
TraceFileTab *traceFileTab = static_cast<TraceFileTab *>
|
||||
(ui->traceFileTabs->widget(index));
|
||||
openedTraceFiles.remove(traceFileTab->getPathToTraceFile());
|
||||
ui->traceFileTabs->removeTab(index);
|
||||
delete traceFileTab;
|
||||
|
||||
if (traceFileTab->close())
|
||||
{
|
||||
openedTraceFiles.remove(traceFileTab->getPathToTraceFile());
|
||||
ui->traceFileTabs->removeTab(index);
|
||||
delete traceFileTab;
|
||||
}
|
||||
}
|
||||
|
||||
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->actionExportAsVCD->setEnabled(false);
|
||||
ui->actionClose_all->setEnabled(false);
|
||||
ui->actionTest->setEnabled(false);
|
||||
ui->actionMetrics->setEnabled(false);
|
||||
for (unsigned int i = ui->traceFileTabs->count(); i--;)
|
||||
{
|
||||
on_traceFileTabs_tabCloseRequested(i);
|
||||
}
|
||||
|
||||
statusLabel->clear();
|
||||
}
|
||||
@@ -163,23 +159,24 @@ void TraceAnalyzer::on_actionReload_all_triggered()
|
||||
TraceFileTab *traceFileTab;
|
||||
|
||||
// Remove all tabs
|
||||
int tabIndex = 0;
|
||||
while (ui->traceFileTabs->count() != 0) {
|
||||
for (unsigned int i = ui->traceFileTabs->count(); i--;)
|
||||
{
|
||||
traceFileTab = static_cast<TraceFileTab *>(ui->traceFileTabs->widget(0));
|
||||
std::cout << "Closing tab #" << tabIndex << " \"" <<
|
||||
traceFileTab->getPathToTraceFile().toStdString() << "\"" << std::endl;
|
||||
std::cout << "Closing tab #" << i << " \"" << traceFileTab->getPathToTraceFile().toStdString() << "\""
|
||||
<< std::endl;
|
||||
|
||||
if (!traceFileTab->close())
|
||||
return;
|
||||
|
||||
ui->traceFileTabs->removeTab(0);
|
||||
delete traceFileTab;
|
||||
|
||||
tabIndex++;
|
||||
}
|
||||
|
||||
QList<QString> list = openedTraceFiles.toList();
|
||||
qSort(list);
|
||||
|
||||
// Recreate all tabs
|
||||
tabIndex = 0;
|
||||
int tabIndex = 0;
|
||||
for (auto path : list) {
|
||||
std::cout << "Reopening tab# " << tabIndex << " \"" << path.toStdString() <<
|
||||
"\"" << std::endl;
|
||||
@@ -231,3 +228,18 @@ void TraceAnalyzer::on_actionMetrics_triggered()
|
||||
evaluationTool.activateWindow();
|
||||
evaluationTool.showAndEvaluateMetrics(openedTraceFiles.toList());
|
||||
}
|
||||
|
||||
void TraceAnalyzer::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
for (unsigned int i = 0; i < ui->traceFileTabs->count(); i++)
|
||||
{
|
||||
QWidget *tab = ui->traceFileTabs->widget(i);
|
||||
if (!tab->close())
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
event->accept();
|
||||
}
|
||||
|
||||
@@ -67,20 +67,24 @@ public:
|
||||
void setUpStatusBar();
|
||||
void setUpGui();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private:
|
||||
void openTracefile(const QString &path);
|
||||
QLabel *statusLabel;
|
||||
QSet<QString> openedTraceFiles;
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_menuFile_aboutToShow();
|
||||
void on_traceFileTabs_tabCloseRequested(int index);
|
||||
|
||||
void on_actionOpen_triggered();
|
||||
void on_actionReload_all_triggered();
|
||||
void on_actionSaveChangesToDB_triggered();
|
||||
void on_actionExportAsVCD_triggered();
|
||||
void on_traceFileTabs_tabCloseRequested(int index);
|
||||
void on_actionClose_all_triggered();
|
||||
void on_actionTest_triggered();
|
||||
|
||||
void on_actionMetrics_triggered();
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
@@ -37,37 +37,37 @@
|
||||
*/
|
||||
|
||||
#include "tracefiletab.h"
|
||||
#include "ui_tracefiletab.h"
|
||||
#include "queryeditor.h"
|
||||
#include "QFileInfo"
|
||||
#include "qmessagebox.h"
|
||||
#include "businessObjects/commentmodel.h"
|
||||
#include "businessObjects/configmodels.h"
|
||||
#include "businessObjects/pythoncaller.h"
|
||||
#include <iostream>
|
||||
#include <QStandardItemModel>
|
||||
#include <QString>
|
||||
#include <QItemDelegate>
|
||||
#include <QFileDialog>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
#include "qwt_plot_histogram.h"
|
||||
#include "qwt_plot_curve.h"
|
||||
#include "qwt_plot_layout.h"
|
||||
#include "qwt_scale_draw.h"
|
||||
#include "qwt_scale_widget.h"
|
||||
#include "presentation/traceselector.h"
|
||||
#include "qmessagebox.h"
|
||||
#include "queryeditor.h"
|
||||
#include "qwt_legend.h"
|
||||
#include "qwt_plot_curve.h"
|
||||
#include "qwt_plot_histogram.h"
|
||||
#include "qwt_plot_layout.h"
|
||||
#include "qwt_plot_magnifier.h"
|
||||
#include "qwt_plot_panner.h"
|
||||
#include "presentation/traceselector.h"
|
||||
#include "businessObjects/configmodels.h"
|
||||
#include "qwt_scale_draw.h"
|
||||
#include "qwt_scale_widget.h"
|
||||
#include "ui_tracefiletab.h"
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QItemDelegate>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardItemModel>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <iostream>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) :
|
||||
QWidget(parent), ui(new Ui::TraceFileTab), navigator(new TraceNavigator(path, this)),
|
||||
mcConfigModel(new McConfigModel(navigator->TraceFile(), this)),
|
||||
memSpecModel(new MemSpecModel(navigator->TraceFile(), this)),
|
||||
savingChangesToDB(false)
|
||||
TraceFileTab::TraceFileTab(QWidget *parent, const QString &path)
|
||||
: QWidget(parent), ui(new Ui::TraceFileTab), commentModel(new CommentModel(this)),
|
||||
navigator(new TraceNavigator(path, commentModel, this)),
|
||||
mcConfigModel(new McConfigModel(navigator->TraceFile(), this)),
|
||||
memSpecModel(new MemSpecModel(navigator->TraceFile(), this)), savingChangesToDB(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->path = path;
|
||||
@@ -79,6 +79,7 @@ TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) :
|
||||
setUpFileWatcher(path);
|
||||
setUpTraceplotScrollbar();
|
||||
setUpTraceSelector();
|
||||
setUpCommentView();
|
||||
|
||||
ui->fileDescriptionEdit->setPlainText(
|
||||
navigator->GeneralTraceInfo().description);
|
||||
@@ -132,7 +133,7 @@ void TraceFileTab::setUpTraceplotScrollbar()
|
||||
|
||||
void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path)
|
||||
{
|
||||
ui->traceplot->init(navigator, ui->traceplotScrollbar);
|
||||
ui->traceplot->init(navigator, ui->traceplotScrollbar, commentModel);
|
||||
|
||||
ui->traceScroller->init(navigator, ui->traceplot);
|
||||
connect(this, SIGNAL(colorGroupingChanged(ColorGrouping)),
|
||||
@@ -140,7 +141,6 @@ void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path)
|
||||
|
||||
ui->selectedTransactionTree->init(navigator);
|
||||
//ui->debugMessages->init(navigator,ui->traceplot);
|
||||
ui->commentTree->init(navigator);
|
||||
}
|
||||
|
||||
void TraceFileTab::setUpFileWatcher(QString path)
|
||||
@@ -158,6 +158,26 @@ void TraceFileTab::setUpTraceSelector()
|
||||
selector->init(ui->traceplot);
|
||||
}
|
||||
|
||||
void TraceFileTab::setUpCommentView()
|
||||
{
|
||||
ui->commentView->setModel(commentModel);
|
||||
ui->commentView->setSelectionModel(commentModel->selectionModel());
|
||||
ui->commentView->installEventFilter(commentModel);
|
||||
ui->commentView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
QObject::connect(ui->commentView, &QTableView::customContextMenuRequested,
|
||||
commentModel, &CommentModel::openContextMenu);
|
||||
|
||||
QObject::connect(commentModel, &CommentModel::editTriggered, ui->commentView, [=](const QModelIndex &index){
|
||||
ui->tabWidget->setCurrentWidget(ui->tabSelectedTrans);
|
||||
ui->commentView->edit(index);
|
||||
ui->commentView->scrollTo(index);
|
||||
});
|
||||
|
||||
QObject::connect(ui->commentView, &QTableView::doubleClicked,
|
||||
commentModel, &CommentModel::rowDoubleClicked);
|
||||
}
|
||||
|
||||
void TraceFileTab::tracefileChanged()
|
||||
{
|
||||
if (savingChangesToDB == true) {
|
||||
@@ -176,6 +196,37 @@ void TraceFileTab::tracefileChanged()
|
||||
navigator->refreshData();
|
||||
}
|
||||
|
||||
void TraceFileTab::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (navigator->existChangesToCommit())
|
||||
{
|
||||
QMessageBox saveDialog;
|
||||
saveDialog.setWindowTitle(QFileInfo(path).baseName());
|
||||
saveDialog.setText("The trace file has been modified.");
|
||||
saveDialog.setInformativeText("Do you want to save your changes?<br><b>Unsaved changes will be lost.</b>");
|
||||
saveDialog.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||
saveDialog.setDefaultButton(QMessageBox::Save);
|
||||
saveDialog.setIcon(QMessageBox::Warning);
|
||||
int returnCode = saveDialog.exec();
|
||||
|
||||
switch (returnCode)
|
||||
{
|
||||
case QMessageBox::Cancel:
|
||||
event->ignore();
|
||||
break;
|
||||
case QMessageBox::Discard:
|
||||
event->accept();
|
||||
break;
|
||||
case QMessageBox::Save:
|
||||
commitChangesToDB();
|
||||
event->accept();
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
event->accept();
|
||||
}
|
||||
|
||||
class ItemDelegate: public QItemDelegate
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "presentation/tracescroller.h"
|
||||
#include "businessObjects/configmodels.h"
|
||||
|
||||
class CommentModel;
|
||||
|
||||
namespace Ui {
|
||||
class TraceFileTab;
|
||||
}
|
||||
@@ -62,6 +64,7 @@ public:
|
||||
void setUpFileWatcher(QString filename);
|
||||
void setUpTraceplotScrollbar();
|
||||
void setUpTraceSelector();
|
||||
void setUpCommentView();
|
||||
void initNavigatorAndItsDependentWidgets(QString path);
|
||||
QString getPathToTraceFile()
|
||||
{
|
||||
@@ -70,12 +73,17 @@ public:
|
||||
void commitChangesToDB(void);
|
||||
void exportAsVCD();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private:
|
||||
QString path;
|
||||
Ui::TraceFileTab *ui;
|
||||
TraceNavigator *navigator;
|
||||
QFileSystemWatcher *fileWatcher;
|
||||
|
||||
CommentModel *commentModel;
|
||||
TraceNavigator *navigator;
|
||||
|
||||
QAbstractItemModel *mcConfigModel;
|
||||
QAbstractItemModel *memSpecModel;
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="CommentTreeWidget" name="commentTree">
|
||||
<widget class="QTableView" name="commentView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>2</horstretch>
|
||||
@@ -189,11 +189,27 @@
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::NoPen</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -402,11 +418,6 @@
|
||||
<extends>QListView</extends>
|
||||
<header>presentation/tracescroller.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>CommentTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/commenttreewidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SelectedTransactionTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
|
||||
Reference in New Issue
Block a user