1 //========================================================= 2 // MusE 3 // Linux Music Editor 4 // 5 // rasterizer.h 6 // Copyright (C) 2020 Tim E. Real (terminator356 on users dot sourceforge dot net) 7 // 8 // This program is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU General Public License 10 // as published by the Free Software Foundation; version 2 of 11 // the License, or (at your option) any later version. 12 // 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 // 22 //========================================================= 23 24 #ifndef __RASTERIZER_H__ 25 #define __RASTERIZER_H__ 26 27 #include <QAbstractTableModel> 28 #include <QModelIndex> 29 #include <QVariant> 30 #include <QString> 31 #include <QObject> 32 #include <QMetaObject> 33 #include <QList> 34 #include <QMap> 35 #include <QSize> 36 37 namespace MusEGui { 38 39 class Rasterizer : public QObject { 40 private: 41 Q_OBJECT 42 43 public: 44 enum Column { 45 InvalidColumn = -1, 46 TripletColumn = 0, 47 NormalColumn = 1, 48 DottedColumn = 2 49 }; 50 51 enum CommonRasters { 52 CommonRasterBar, CommonRasterOff, CommonRaster1, CommonRaster2, CommonRaster4, 53 CommonRaster8, CommonRaster16, CommonRaster32, CommonRaster64 54 }; 55 56 private: 57 int _division; // System midi division (ticks per quarter note) setting. 58 int _rows; // Current number of rows in the raster array. 59 int *_rasterArray; // Two-dimensional array of raster values. -1 = invalid. 0 = Snap to bar. 1 = 'off'. 60 61 void updateColumn(Column col); 62 63 signals: 64 // This signal is emitted just before the data will be rebuilt. 65 void dataAboutToBeReset(); 66 // This signal is emitted just after the data has been rebuilt. 67 void dataReset(); 68 69 public: 70 Rasterizer(int division, QObject *parent = nullptr); 71 ~Rasterizer(); 72 division()73 int division() const { return _division; } 74 void setDivision(int div); 75 rowCount()76 int rowCount() const { return _rows; } 77 78 // Returns the number of columns. 79 int columnCount() const; 80 81 // Rebuilds the raster array. 82 void updateRasterizer(); 83 84 // Returns the given raster, or returns 1 division (1 quarter note) if no suitable raster could be found. 85 int checkRaster(int val) const; 86 87 // Returns the index into the array of the given raster value, or -1 if raster not found. 88 int indexOf(int val) const; 89 // Returns raster value at given row and column, or -1 if no raster 90 // at that location, or row or column are out of range. 91 int rasterAt(int row, int col) const; 92 93 // Returns true if the raster at the given row and column is 0 (snap to bar). 94 bool isBarRaster(int row, int col) const; 95 // Returns true if the raster at the given row and column is 1 ('off'). 96 bool isOffRaster(int row, int col) const; 97 // Returns the row number of the 'bar' row. 98 int barRow() const; 99 // Returns the row number of the 'off' row. 100 int offRow() const; 101 // Returns the raster value of some often-used denominator values. 102 // Returns -1 if the raster is not available. 103 int commonRaster(CommonRasters commonRast) const; 104 // Returns true if the raster at the given row and column is less than 105 // a triple, normal, or dotted version of the given normal raster value. 106 bool isLessThanNormalRaster(int row, int col, int normalRaster) const; 107 // Returns a denominator value for the row, suitable for display (1 2 4 8 16 32 etc.) 108 // Returns zero if the row is a 'bar' row. 109 int rasterDenomAt(int row) const; 110 }; 111 112 class RasterizerModel : public QAbstractTableModel 113 { 114 private: 115 Q_OBJECT 116 117 public: 118 enum Roles { RasterTextRole = Qt::DisplayRole, RasterValueRole = Qt::UserRole}; 119 enum DisplayFormat { FractionFormat, DenominatorFormat }; 120 enum RasterPick { NoPick, 121 ToggleTriple, ToggleDotted, ToggleHigherDotted, 122 GotoBar, GotoOff, Goto1, Goto2, Goto4, Goto8, Goto16, Goto32, Goto64 }; 123 124 private: 125 // The external rasterizer array used in this model. 126 const Rasterizer *_rasterizer; 127 // Maximum number of rows. If set to -1, all rows are included. 128 int _maxRows = 0; 129 // How text is displayed. 130 DisplayFormat _displayFormat; 131 132 // Lookup lists for model <> raster rows and columns. 133 QList<int /*rasterRow*/> _modelToRasterRowList; 134 QMap<int /*rasterRow*/, int /*modelRow*/> _rasterToModelRowMap; 135 QList<Rasterizer::Column> _modelToRasterColumnList; 136 QMap<Rasterizer::Column, int /*modelColumn*/> _rasterToModelColumnMap; 137 138 QMetaObject::Connection _dataAboutToBeResetConnection; 139 QMetaObject::Connection _dataResetConnection; 140 141 void updateRows(); 142 143 // Converts model row to rasterizer row. Returns -1 if row out of bounds. 144 int modelToRasterRow(int row) const; 145 // Converts model column to rasterizer column. 146 // Returns Rasterizer::InvalidColumn if column out of bounds. 147 Rasterizer::Column modelToRasterCol(int col) const; 148 149 // Returns raster text at given row and column, or empty string if no raster 150 // at that location, or row or column are out of range. 151 QString textAt(int row, int col) const; 152 // Returns raster value at given row and column, or -1 if no raster 153 // at that location, or row or column are out of range. 154 int rasterAt(int row, int col) const; 155 156 protected slots: 157 void endResetModelHandler(); 158 159 public: 160 RasterizerModel( 161 Rasterizer *rasterizer, QObject *parent = nullptr, int max_rows = -1, 162 QList<Rasterizer::Column> visible_columns = QList<Rasterizer::Column>(), 163 DisplayFormat displayFormat = DenominatorFormat); 164 virtual ~RasterizerModel(); 165 166 // Required overrides for QAbstractTableModel. 167 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 168 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 169 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 170 171 // Returns the external Rasterizer array used in this model. rasterizer()172 const Rasterizer *rasterizer() { return _rasterizer; } 173 // Sets the external Rasterizer array used in this model. 174 void setRasterizer(const Rasterizer *r); 175 176 // Returns the system midi division that the rasterizer is using. 177 int division() const; 178 // Returns maximum number of rows. If -1, all rows are included. 179 int maxRows() const; 180 // Sets maximum number of rows. If set to -1, all rows are included. 181 void setMaxRows(int rows); 182 // Returns a model-to-raster row list, ie. which raster rows are included in the model. 183 QList<int /*rasterRow*/> visibleRows() const; 184 // Returns the model-to-raster column list, ie. which raster columns are included in the model. 185 QList<Rasterizer::Column> visibleColumns() const; 186 // Sets the model-to-raster column list, ie. which raster columns are included in the model. 187 void setVisibleColumns(const QList<Rasterizer::Column>& cols); 188 // How text is displayed. 189 DisplayFormat displayFormat() const; 190 // Sets how text is displayed. 191 void setDisplayFormat(DisplayFormat format); 192 193 // Returns the model row number of the 'bar' row. 194 int barRow() const; 195 // Returns the model row number of the 'off' row. 196 int offRow() const; 197 // Returns true if the raster at the given row and column is 0 (snap to bar). 198 bool isBarRaster(int row, int col) const; 199 // Returns true if the raster at the given row and column is 1 ('off'). 200 bool isOffRaster(int row, int col) const; 201 // Returns the raster value of some often-used denominator values. 202 // Returns -1 if the raster is not available. 203 int commonRaster(Rasterizer::CommonRasters commonRast) const; 204 // Returns the index into the model of the given raster value, or -1 if raster not found. 205 int indexOfRaster(int val) const; 206 // Returns the model index of the given raster value, or invalid model index if raster not found. 207 QModelIndex modelIndexOfRaster(int val) const; 208 // Returns the given raster, or returns 1 division (1 quarter note) if no suitable raster could be found. 209 int checkRaster(int val) const; 210 // Given a raster, picks another raster based on the RasterPick, for example toggle the triple or dotted 211 // version of raster, or pick a raster from the same column that raster is in. 212 int pickRaster(int raster, RasterPick pick) const; 213 }; 214 215 } // namespace MusEGui 216 217 #endif 218