# HG changeset patch # User Chris Cannam # Date 1571059057 -3600 # Node ID 343ef2a866a495c949475f490b2d86dda9c746ad # Parent 6eb3a76c74f7147bd66e1cbc43fd9dd1a35ddaf8 Implement missing TabularModel editing methods. Also made these pure in TabularModel, since almost all subclasses want them and (clearly) forgetting to implement them is a problem! diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/BoxModel.h --- a/data/model/BoxModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/BoxModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -272,6 +272,8 @@ } } + bool isEditable() const override { return true; } + Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override { @@ -298,6 +300,24 @@ return command->finish(); } + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Box")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Box")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } + /** * XmlExportable methods. diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/DenseThreeDimensionalModel.h --- a/data/model/DenseThreeDimensionalModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/DenseThreeDimensionalModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -132,6 +132,11 @@ int getRowCount() const override { return getWidth(); } int getColumnCount() const override { return getHeight() + 2; } + bool isEditable() const override { return false; } + Command *getSetDataCommand(int, int, const QVariant &, int) { return nullptr; } + Command *getInsertRowCommand(int) { return nullptr; } + Command *getRemoveRowCommand(int) { return nullptr; } + QString getHeading(int column) const override { switch (column) { diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/ImageModel.h --- a/data/model/ImageModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/ImageModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -230,6 +230,26 @@ command->add(e1); return command->finish(); } + + bool isEditable() const override { return true; } + + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Image")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Image")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } /** * XmlExportable methods. diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/NoteModel.h --- a/data/model/NoteModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/NoteModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -322,6 +322,26 @@ return SortNumeric; } + bool isEditable() const override { return true; } + + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Note")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Note")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } + /** * NoteExportable methods. */ diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/RegionModel.h --- a/data/model/RegionModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/RegionModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -268,6 +268,8 @@ } } + bool isEditable() const override { return true; } + Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override { if (row < 0 || row >= m_events.count()) return nullptr; @@ -291,6 +293,24 @@ return command->finish(); } + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Region")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Region")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } + /** * XmlExportable methods. diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/SparseOneDimensionalModel.h --- a/data/model/SparseOneDimensionalModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/SparseOneDimensionalModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -243,6 +243,26 @@ return command->finish(); } + bool isEditable() const override { return true; } + + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Point")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Point")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } + /** * NoteExportable methods. */ diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/SparseTimeValueModel.h --- a/data/model/SparseTimeValueModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/SparseTimeValueModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -279,7 +279,10 @@ } } - Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override { + bool isEditable() const override { return true; } + + Command *getSetDataCommand(int row, int column, const QVariant &value, + int role) override { if (row < 0 || row >= m_events.count()) return nullptr; if (role != Qt::EditRole) return nullptr; @@ -299,6 +302,24 @@ command->add(e1); return command->finish(); } + + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Point")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Point")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } /** * XmlExportable methods. diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/TabularModel.h --- a/data/model/TabularModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/TabularModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -32,44 +32,107 @@ * This is very like a cut-down QAbstractItemModel. It assumes a * relationship between row number and frame time. */ - class TabularModel { public: virtual ~TabularModel() { } + /** + * Return the number of rows (items) in the model. + */ virtual int getRowCount() const = 0; + + /** + * Return the number of columns (values/labels/etc per item). + */ virtual int getColumnCount() const = 0; + /** + * Return the heading for a given column, e.g. "Time" or "Value". + * These are shown directly to the user, so must be translated + * already. + */ virtual QString getHeading(int column) const = 0; enum { SortRole = Qt::UserRole }; enum SortType { SortNumeric, SortAlphabetical }; + /** + * Get the value in the given cell, for the given role. The role + * is actually a Qt::ItemDataRole. + */ virtual QVariant getData(int row, int column, int role) const = 0; + + /** + * Return true if the column is the frame time of the item, or an + * alternative representation of it (i.e. anything that has the + * same sort order). Duration is not a time value by this meaning. + */ virtual bool isColumnTimeValue(int col) const = 0; + + /** + * Return the sort type (numeric or alphabetical) for the column. + */ virtual SortType getSortType(int col) const = 0; + /** + * Return the frame time for the given row. + */ virtual sv_frame_t getFrameForRow(int row) const = 0; + + /** + * Return the number of the first row whose frame time is not less + * than the given one. If there is none, return getRowCount(). + */ virtual int getRowForFrame(sv_frame_t frame) const = 0; - virtual bool isEditable() const { return false; } - virtual Command *getSetDataCommand(int /* row */, int /* column */, const QVariant &, int /* role */) { return 0; } - virtual Command *getInsertRowCommand(int /* beforeRow */) { return 0; } - virtual Command *getRemoveRowCommand(int /* row */) { return 0; } + /** + * Return true if the model is user-editable, false otherwise. + */ + virtual bool isEditable() const = 0; - QVariant adaptFrameForRole(sv_frame_t frame, - sv_samplerate_t rate, - int role) const { + /** + * Return a command to set the value in the given cell, for the + * given role, to the contents of the supplied variant. + * + * If the model is not editable or the cell or value is out of + * range, return nullptr. + */ + virtual Command *getSetDataCommand(int row, int column, + const QVariant &, int role) = 0; + + /** + * Return a command to insert a new row before the row with the + * given index. + * + * If the model is not editable or the index is out of range, + * return nullptr. + */ + virtual Command *getInsertRowCommand(int beforeRow) = 0; + + /** + * Return a command to delete the row with the given index. + * + * If the model is not editable or the index is out of range, + * return nullptr. + */ + virtual Command *getRemoveRowCommand(int row) = 0; + +protected: + // Helpers + + static QVariant adaptFrameForRole(sv_frame_t frame, + sv_samplerate_t rate, + int role) { if (role == SortRole) return int(frame); RealTime rt = RealTime::frame2RealTime(frame, rate); if (role == Qt::EditRole) return rt.toString().c_str(); else return rt.toText().c_str(); } - QVariant adaptValueForRole(float value, - QString unit, - int role) const { + static QVariant adaptValueForRole(float value, + QString unit, + int role) { if (role == SortRole || role == Qt::EditRole) return value; else return QString("%1 %2").arg(value).arg(unit); } diff -r 6eb3a76c74f7 -r 343ef2a866a4 data/model/TextModel.h --- a/data/model/TextModel.h Thu Oct 10 10:03:31 2019 +0100 +++ b/data/model/TextModel.h Mon Oct 14 14:17:37 2019 +0100 @@ -233,6 +233,26 @@ command->add(e1); return command->finish(); } + + bool isEditable() const override { return true; } + + Command *getInsertRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Add Label")); + Event e = m_events.getEventByIndex(row); + command->add(e); + return command->finish(); + } + + Command *getRemoveRowCommand(int row) override { + if (row < 0 || row >= m_events.count()) return nullptr; + auto command = new ChangeEventsCommand(getId().untyped, + tr("Delete Label")); + Event e = m_events.getEventByIndex(row); + command->remove(e); + return command->finish(); + } /** * XmlExportable methods.