Engauge Digitizer 2
Loading...
Searching...
No Matches
CurveNameList.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
7#include "CurveNameList.h"
8#include "DocumentSerialize.h"
9#include "EngaugeAssert.h"
10#include "Logger.h"
11#include <qdebug.h>
12#include <QHash>
13#include <QTextStream>
14#include "QtToString.h"
15#include <QVariant>
16#include <QXmlStreamWriter>
17
19 QStandardItemModel()
20{
21}
22
23int CurveNameList::columnCount (const QModelIndex & /* parent */) const
24{
26}
27
28bool CurveNameList::containsCurveNameCurrent (const QString &curveName) const
29{
30 LOG4CPP_INFO_S ((*mainCat)) << "CurveNameList::containsCurveNameCurrent";
31
32 // Search for curve with matching name
33 CurrentCurveToOriginalCurve::const_iterator itr;
34 for (itr = m_currentCurveToOriginalCurve.begin (); itr != m_currentCurveToOriginalCurve.end (); ++itr) {
35
36 if (itr.key () == curveName) {
37 return true;
38 }
39 }
40
41 return false;
42}
43
45{
46 LOG4CPP_INFO_S ((*mainCat)) << "CurveNameList::currentCurvesAsString";
47
48 QString out;
49 QTextStream str (&out);
50
51 for (int row = 0; row < rowCount (); row++) {
52
53 QString curveCurrent = data (index (row, CURVE_NAME_LIST_COLUMN_CURRENT)).toString ();
54 QString curveOriginal;
55 unsigned int points = 0;
56 if (m_currentCurveToOriginalCurve.contains (curveCurrent)) {
57 curveOriginal = m_currentCurveToOriginalCurve [curveCurrent];
58 if (m_originalCurveToPointCount.contains (curveOriginal)) {
59
60 points = m_originalCurveToPointCount [curveOriginal];
61 }
62 }
63
64 str << "\n current=" << curveCurrent.toLatin1().data()
65 << " original=" << curveOriginal
66 << " points=" << points;
67 }
68
69 return out;
70}
71
72QString CurveNameList::currentCurveToOriginalCurve (const QString &currentCurve) const
73{
74 return m_currentCurveToOriginalCurve [currentCurve];
75}
76
77unsigned int CurveNameList::currentCurveToPointCount (const QString &currentCurve) const
78{
79 QString originalCurve = m_currentCurveToOriginalCurve [currentCurve];
80
81 return m_originalCurveToPointCount [originalCurve];
82}
83
84bool CurveNameList::curveNameIsAcceptable (const QString &curveNameNew,
85 int row) const
86{
87 // First test is to verify curve name is not empty
88 bool success = (!curveNameNew.isEmpty ());
89
90 if (success) {
91
92 // First test was passed. Second test is to check for duplication
93 for (int row1 = 0; row1 < rowCount(); row1++) {
94
95 // Use table entry except for the one row that gets overridden
96 QModelIndex index1 = index (row1, CURVE_NAME_LIST_COLUMN_CURRENT);
97 QString curveNameCurrent1 = (row1 == row ?
98 curveNameNew :
99 data (index1).toString ());
100
101 for (int row2 = row1 + 1; row2 < rowCount(); row2++) {
102
103 // Use table entry except for the one row that gets overridden
104 QModelIndex index2 = index (row2, CURVE_NAME_LIST_COLUMN_CURRENT);
105 QString curveNameCurrent2 = (row2 == row ?
106 curveNameNew :
107 data (index2).toString ());
108
109 if (curveNameCurrent1 == curveNameCurrent2) {
110
111 // Duplicate!
112 success = false;
113 break;
114 }
115 }
116 }
117 }
118
119 return success;
120}
121
122Qt::ItemFlags CurveNameList::flags (const QModelIndex &index) const
123{
124 if (index.isValid ()) {
125
126 // Not root item. ItemIsDropEnabled is unwanted during dragging since dragged entry would overwrite
127 // another entry if user forgets to drop into the space between successive entries
128 return (QStandardItemModel::flags (index) |
129 Qt::ItemIsDragEnabled |
130 Qt::ItemIsEnabled |
131 Qt::ItemIsSelectable |
132 Qt::ItemIsEditable) & ~Qt::ItemIsDropEnabled;
133
134 } else {
135
136 // Root item
137 return QStandardItemModel::flags (index) |
138 Qt::ItemIsDropEnabled;
139
140 }
141}
142
144 const QString &curveCurrent,
145 const QString &curveOriginal,
146 unsigned int pointCount)
147{
148 LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::insertRow"
149 << " row=" <<row
150 << " curveCurrent=" << curveCurrent.toLatin1().data()
151 << " curveOriginal=" << curveOriginal.toLatin1().data()
152 << " points=" << pointCount;
153
154 QStandardItem *item = new QStandardItem (curveCurrent);
155 QStandardItemModel::insertRow (row, item);
156
157 // Documentation for QAbstractItemModels says beginInsertRows/endInsertRows send off a rowsAboutToBeInserted signal
158 beginInsertRows (QModelIndex (),
159 row,
160 row);
161
162 m_currentCurveToOriginalCurve [curveCurrent] = curveOriginal;
163 m_originalCurveToPointCount [curveOriginal] = pointCount;
164
165 endInsertRows ();
166}
167
168QStandardItem *CurveNameList::item(int row, int column) const
169{
170 LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::item"
171 << " row=" << row;
172
173 ENGAUGE_ASSERT (row < rowCount ());
174
175 return QStandardItemModel::item (row, column);
176}
177
178unsigned int CurveNameList::numPointsForSelectedCurves (const QList<unsigned int> &rowsSelected) const
179{
180 int numPoints = 0;
181 for (int i = 0; i < rowsSelected.count(); i++) {
182 int row = signed (rowsSelected [i]);
183
184 QModelIndex idx = index (row, CURVE_NAME_LIST_COLUMN_CURRENT);
185 QString currentCurve = data (idx).toString ();
186 if (m_currentCurveToOriginalCurve.contains (currentCurve)) {
187
188 QString originalCurve = m_currentCurveToOriginalCurve [currentCurve];
189 if (m_originalCurveToPointCount.contains (originalCurve)) {
190
191 numPoints += m_originalCurveToPointCount [originalCurve];
192 }
193 }
194 }
195
196 return unsigned (numPoints);
197}
198
200 int count,
201 const QModelIndex &parent)
202{
203 // LOG4CPP is below
204
205 bool skip = (count != 1 || row < 0 || row > rowCount () || parent.isValid());
206
207 QString before, after;
208 if (!skip) {
209
210 before = currentCurvesAsString ();
211
212 // As documented for QAbstractItemModel, beginRemoveRows "emits the rowsAboutToBeRemoved() signal which connected views
213 // (or proxies) must handle before the data is removed. Otherwise, the views may end up in an invalid state."
214 beginRemoveRows (QModelIndex (),
215 row,
216 row + count - 1);
217
218 // We do not call QStandardItemModel::removeRow or QAbstractItemModel::removeRow here since that leads to an infinite loop when it calls this method
219 for (int rowRemove = row; rowRemove < row + count; rowRemove++) {
220 QStandardItemModel::removeRows (row,
221 count,
222 parent);
223 }
224
225 endRemoveRows ();
226
227 after = currentCurvesAsString ();
228 }
229
230 LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::removeRows"
231 << " row=" << row
232 << " count=" << count
233 << " isRoot=" << (parent.isValid () ? "no" : "yes")
234 << " skip=" << (skip ? "yes" : "no")
235 << " before=" << before.toLatin1().data()
236 << " after=" << after.toLatin1().data();
237 return true;
238}
239
241{
242 LOG4CPP_INFO_S ((*mainCat)) << "CurveNameList::reset";
243
244 clear();
245 m_currentCurveToOriginalCurve.clear();
246 m_originalCurveToPointCount.clear();
247}
248
249int CurveNameList::rowCount (const QModelIndex & /* parent */) const
250{
251 int count = QStandardItemModel::rowCount ();
252
253// LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::rowCount"
254// << " count=" << count;
255
256 return count;
257}
258
259bool CurveNameList::setData (const QModelIndex &index,
260 const QVariant &value,
261 int role)
262{
263 LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::setData"
264 << " row=" << index.row()
265 << " value=" << value.toString().toLatin1().data()
266 << " role=" << roleAsString (role).toLatin1().data();
267
268 bool success;
269 if (role == Qt::EditRole) {
270
271 // Each curve name must be unique
272 if (curveNameIsAcceptable (value.toString(),
273 index.row())) {
274
275 // Curve name is fine
276 QModelIndex idxOld = QStandardItemModel::index (index.row(), CURVE_NAME_LIST_COLUMN_CURRENT);
277
278 // Old and new curve names
279 QString curveCurrentOld = data (idxOld).toString ();
280 QString curveCurrentNew = value.toString ();
281
282 // Remove old entry after saving original curve name
283 QString curveOriginal;
284 if (m_currentCurveToOriginalCurve.contains (curveCurrentOld)) {
285
286 // Remember old original curve name
287 curveOriginal = m_currentCurveToOriginalCurve [curveCurrentOld];
288
289 // Remove old entry
290 m_currentCurveToOriginalCurve.remove (curveCurrentOld);
291
292 // Add new entry
293 m_currentCurveToOriginalCurve [curveCurrentNew] = curveOriginal;
294 }
295
296 success = QStandardItemModel::setData (index,
297 value,
298 role);
299 } else {
300
301 // Curve name is unacceptable
302 success = false;
303
304 }
305 } else {
306
307 // For non-edits, this method just calls the superclass method
308 success = QStandardItemModel::setData (index,
309 value,
310 role);
311 }
312
313 return success;
314}
315
317 int column,
318 QStandardItem *item)
319{
320 // LOG4CPP is below
321
323
324 QString before = currentCurvesAsString ();
325
326 QStandardItemModel::setItem (row,
327 column,
328 item);
329
330 QString after = currentCurvesAsString ();
331
332 LOG4CPP_DEBUG_S ((*mainCat)) << "CurveNameList::setItem"
333 << " row=" << row
334 << " before=" << before.toLatin1().data()
335 << " after=" << after.toLatin1().data();
336}
337
339{
340 return Qt::MoveAction;
341}
@ NUMBER_CURVE_NAME_LIST_COLUMNS
@ CURVE_NAME_LIST_COLUMN_CURRENT
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
log4cpp::Category * mainCat
Definition Logger.cpp:14
QString roleAsString(int role)
void reset()
Clear all information.
bool containsCurveNameCurrent(const QString &curveName) const
Return true if specified curve name is already in the list.
virtual int columnCount(const QModelIndex &parent) const
One column.
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
One row per curve name.
unsigned int currentCurveToPointCount(const QString &currentCurve) const
Return the point count for the specified current curve.
QString currentCurvesAsString() const
For debugging we dump the curve names.
unsigned int numPointsForSelectedCurves(const QList< unsigned int > &rowsSelected) const
Return the number of points associated with the selected curves, as specified by their row numbers.
virtual QStandardItem * item(int row, int column=0) const
Retrieve data from model.
virtual void setItem(int row, int column, QStandardItem *item)
Store one curve name data.
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Override normal flags with additional editing flags.
virtual bool removeRows(int row, int count, const QModelIndex &parent)
Remove one row.
void insertRow(int row, const QString &curveCurrent, const QString &curveOriginal, unsigned int pointCount)
Create a new entry at the specified row.
CurveNameList()
Default constructor.
QString currentCurveToOriginalCurve(const QString &currentCurve) const
Return the original curve for the specified current curve.
virtual Qt::DropActions supportedDropActions() const
Allow dragging for reordering.
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
Store data for one curve name.
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18
#define LOG4CPP_DEBUG_S(logger)
Definition convenience.h:20