diff --git a/canframemodel.cpp b/canframemodel.cpp index 5865268..645b70b 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -6,19 +6,6 @@ #include #include "utility.h" -enum class Column { - TimeStamp = 0, ///< The timestamp when the frame was transmitted or received - FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit) - Extended = 2, ///< True if the frames CAN identifier is 29 bit - Remote = 3, ///< True if the frames is a remote frame - Direction = 4, ///< Whether the frame was transmitted or received - Bus = 5, ///< The bus where the frame was transmitted or received - Length = 6, ///< The frames payload data length - ASCII = 7, ///< The payload interpreted as ASCII characters - Data = 8, ///< The frames payload data - NUM_COLUMN -}; - CANFrameModel::~CANFrameModel() { frames.clear(); @@ -26,7 +13,6 @@ CANFrameModel::~CANFrameModel() filters.clear(); } - int CANFrameModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); @@ -82,6 +68,7 @@ CANFrameModel::CANFrameModel(QObject *parent) needFilterRefresh = false; lastUpdateNumFrames = 0; timeFormat = "MMM-dd HH:mm:ss.zzz"; + sortDirAsc = false; } void CANFrameModel::setHexMode(bool mode) @@ -189,6 +176,110 @@ void CANFrameModel::setAllFilters(bool state) sendRefresh(); } +uint64_t CANFrameModel::getCANFrameVal(int row, Column col) +{ + uint64_t temp = 0; + if (row >= frames.count()) return 0; + CANFrame frame = frames[row]; + switch (col) + { + case Column::TimeStamp: + return frame.timestamp; + case Column::FrameId: + return frame.ID; + case Column::Extended: + if (frame.extended) return 1; + return 0; + case Column::Remote: + if (frame.remote) return 1; + return 0; + case Column::Direction: + if (frame.isReceived) return 1; + return 0; + case Column::Bus: + return frame.bus; + case Column::Length: + return frame.len; + case Column::ASCII: //sort both the same for now + case Column::Data: + for (int i = 0; i < frame.len; i++) temp += ((uint64_t)frame.data[i] << (56 - (8 * i))); + //qDebug() << temp; + return temp; + } +} + +void CANFrameModel::qSortCANFrameAsc(QVector *frames, Column column, int lowerBound, int upperBound) +{ + int p, i, j; + qDebug() << "Lower " << lowerBound << " Upper" << upperBound; + if (lowerBound < upperBound) + { + uint64_t piv = getCANFrameVal(lowerBound + (upperBound - lowerBound) / 2, column); + i = lowerBound - 1; + j = upperBound + 1; + for (;;){ + do { + i++; + } while ((i < upperBound) && getCANFrameVal(i, column) < piv); + + do + { + j--; + } while ((j > lowerBound) && getCANFrameVal(j, column) > piv); + if (i < j) { + CANFrame temp = frames->at(i); + frames->replace(i, frames->at(j)); + frames->replace(j, temp); + } + else {p = j; break;} + } + + qSortCANFrameAsc(frames, column, lowerBound, p); + qSortCANFrameAsc(frames, column, p+1, upperBound); + } +} + +void CANFrameModel::qSortCANFrameDesc(QVector *frames, Column column, int lowerBound, int upperBound) +{ + int p, i, j; + qDebug() << "Lower " << lowerBound << " Upper" << upperBound; + if (lowerBound < upperBound) + { + uint64_t piv = getCANFrameVal(lowerBound + (upperBound - lowerBound) / 2, column); + i = lowerBound - 1; + j = upperBound + 1; + for (;;){ + do { + i++; + } while ((i < upperBound) && getCANFrameVal(i, column) > piv); + + do + { + j--; + } while ((j > lowerBound) && getCANFrameVal(j, column) < piv); + if (i < j) { + CANFrame temp = frames->at(i); + frames->replace(i, frames->at(j)); + frames->replace(j, temp); + } + else {p = j; break;} + } + + qSortCANFrameDesc(frames, column, lowerBound, p); + qSortCANFrameDesc(frames, column, p+1, upperBound); + } +} + +void CANFrameModel::sortByColumn(int column) +{ + sortDirAsc = !sortDirAsc; + //beginResetModel(); + if (sortDirAsc) qSortCANFrameAsc(&frames, Column(column), 0, frames.count()-1); + else qSortCANFrameDesc(&frames, Column(column), 0, frames.count()-1); + //endResetModel(); + sendRefresh(); +} + void CANFrameModel::recalcOverwrite() { if (!overwriteDups) return; //no need to do a thing if mode is disabled @@ -283,6 +374,11 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const switch (Column(index.column())) { case Column::TimeStamp: + //Reformatting the output a bit with custom code + ts = Utility::formatTimestamp(thisFrame.timestamp); + if (ts.type() == QVariant::Double) return QString::number(ts.toDouble(), 'f', 5); //never scientific notation, 5 decimal places + if (ts.type() == QVariant::LongLong) return QString::number(ts.toLongLong()); //never scientific notion, all digits shown + if (ts.type() == QVariant::DateTime) return ts.toDateTime().toString(timeFormat); //custom set format for dates and times return Utility::formatTimestamp(thisFrame.timestamp); case Column::FrameId: return Utility::formatCANID(thisFrame.ID, thisFrame.extended); diff --git a/canframemodel.h b/canframemodel.h index 42fd66b..cc3c1d7 100644 --- a/canframemodel.h +++ b/canframemodel.h @@ -10,6 +10,19 @@ #include "dbc/dbchandler.h" #include "connections/canconnection.h" +enum class Column { + TimeStamp = 0, ///< The timestamp when the frame was transmitted or received + FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit) + Extended = 2, ///< True if the frames CAN identifier is 29 bit + Remote = 3, ///< True if the frames is a remote frame + Direction = 4, ///< Whether the frame was transmitted or received + Bus = 5, ///< The bus where the frame was transmitted or received + Length = 6, ///< The frames payload data length + ASCII = 7, ///< The payload interpreted as ASCII characters + Data = 8, ///< The frames payload data + NUM_COLUMN +}; + class CANFrameModel: public QAbstractTableModel { Q_OBJECT @@ -43,6 +56,7 @@ public: void recalcOverwrite(); bool needsFilterRefresh(); void insertFrames(const QVector &newFrames); + void sortByColumn(int column); int getIndexFromTimeID(unsigned int ID, double timestamp); const QVector *getListReference() const; //thou shalt not modify these frames externally! const QVector *getFilteredListReference() const; //Thus saith the Lord, NO. @@ -56,6 +70,10 @@ signals: void updatedFiltersList(); private: + void qSortCANFrameAsc(QVector* frames, Column column, int lowerBound, int upperBound); + void qSortCANFrameDesc(QVector* frames, Column column, int lowerBound, int upperBound); + uint64_t getCANFrameVal(int row, Column col); + QVector frames; QVector filteredFrames; QMap filters; @@ -71,6 +89,7 @@ private: uint64_t timeOffset; int lastUpdateNumFrames; uint32_t preallocSize; + bool sortDirAsc; }; diff --git a/config.h b/config.h index c9a1b1c..cc815a5 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #ifndef CONFIG #define CONFIG -#define VERSION 197 +#define VERSION 198 //try to keep this in sync. //SavvyCAN will complain if you connect a GVRET board with a revision