WARNING: USE THIS SOFTWARE AT YOUR OWN RISK! THIS IS EXPERIMENTAL SOFTWARE NOT INTENDED FOR PRODUCTION USE! Zuble is currently an early stage prototype. As such Zuble is minimally tested and inherently unstable. It is provided for experimental, development, and demonstration purposes only. Zuble QML Types   |  Zuble C++ Classes   |  Zuble Overview
Zuble  0.1
Zuble Framework C++/QML extension API
ZblTableData.cpp
Go to the documentation of this file.
1 /*
2  * Zuble - A run-time system for QML/Javascript applications
3  * Copyright (C) 2015 Bob Dinitto
4  *
5  * Filename: ZblTableData.cpp
6  * Created on: 3/16/2015
7  * Author: Bob Dinitto
8  *
9  * Zuble is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include "ZblTableData.h"
26 #include "ZblException.h"
27 #include <QSet>
28 
29 namespace Zbl
30 {
31 
33 : m_columnCount(1), m_rowCount(0)
34 {}
35 
37 {
38  qDebug("format = row/column/role:data;");
39 
40  const int truncatePos = 15;
41 
42  QList<int>roleList = roles();
43  const int roleCount = roleList.count();
44 
45  QString outputRow;
46  QByteArray outputAscii;
47 
48 
49  for(int row=0; row<m_rowCount;row++)
50  {
51  outputRow.clear();
52 
53  for(int col=0; col<m_columnCount;col++)
54  {
55  for(int rl=0; rl<roleCount;rl++)
56  {
57  QString outputCell = "%1/%2/%3:%4;";
58 
59  int roleNum = roleList.at(rl);
60  QVariant data = getValue(roleNum, row, col);
61 
62  QString strData = data.toString();
63 
64  if(strData.count() > truncatePos)
65  {
66  strData.truncate(truncatePos);
67  strData += "...";
68  }
69  //outputRow += outputCell.arg(row).arg(col).arg(roleNum).arg(strData);
70  QString test = outputCell.arg(row).arg(col).arg(roleNum).arg(strData);
71  outputRow.append(test);
72  //qDebug("%s",test.toUtf8().constData());
73  //outputRow = "foo";
74  //outputRow.append(":bar");
75  //outputRow.append(test);
76  //qDebug("%d/%d/%d:%s;", row, col, roleNum, strData.toUtf8().constData());
77  }
78  }
79  outputAscii = outputRow.toUtf8();
80  qDebug("%s",outputAscii.constData());
81  }
82 }
83 
84 void ZblTableData::putValue(int role, int row, int col, const QVariant value)
85 {
86  if(!hasCell(role, row, col))
87  throw ZblException(QString("ZblTableData::putValue - nonexistent cell: "
88  "role %1, row %2, col %3").arg(role).arg(row).arg(col));
89 
90  zDataTable& dataTable = m_roles[role];
91 
92  zDataRow& dataRow = dataTable[row];
93 
94  QVariant& dataVariant = dataRow[col];
95 
96  dataVariant = value;
97 
98 }
99 
100 QVariant ZblTableData::getValue(int role, int row, int col) const
101 {
102  if(!hasCell(role, row, col))
103  throw ZblException(QString("ZblTableData::getValue - nonexistent cell: "
104  "role %1, row %2, col %3").arg(role).arg(row).arg(col));
105 
106  return m_roles.value(role).at(row).at(col);
107 }
108 
110  QVariant rows,
111  int startRow,
112  int col)
113 {
114  if(!rows.canConvert<zTableRowList>())
115  throw ZblException("ZblTableData::putTableColumnRows - Programming Error: "
116  "rows parameter must contain a ZTableRowList object.");
117 
118  zTableRowList rowList = rows.value<zTableRowList>();
119 
120  const int count = rowList.count();
121 
122  for(int row = 0; row < count; row++)
123  {
124  zTableRow nextRow = rowList.at(row);
125  QList<int> roles = nextRow.keys();
126  for(int roleIndex = 0; roleIndex < roles.count(); roleIndex++)
127  {
128  int nextRole = roles.at(roleIndex);
129  QVariant nextValue = nextRow.value(nextRole);
130  putValue(nextRole, startRow + row, col, nextValue);
131  }
132  }
133 }
134 
136  QList<int> roles,
137  int startRow,
138  int col,
139  int rowCount) const
140 {
141  qDebug("ZblTableData::getTableColumnRows");
142 
143  zTableRowList rows;
144 
145  zTableRow tempRow;
146 
147  QSet<int> eliminateDuplicates = QSet<int>::fromList(roles);
148 
149  QList<int> roleSet = eliminateDuplicates.toList();
150 
151  const int roleCount = roleSet.count();
152 
153  int lastRow;
154 
155  if(startRow + rowCount - 1 > m_rowCount)
156  lastRow = m_rowCount - startRow;
157  else
158  lastRow = startRow + rowCount - 1;
159 
160  qDebug("roleCount=%d, startRow=%d, lastRow=%d", roleCount, startRow, lastRow);
161 
162 
163  for(int row = startRow; row < lastRow; row++ )
164  {
165  for(int rol = 0; rol < roleCount; rol++)
166  {
167  const int nextRole = roleSet.at(rol);
168  qDebug("getting data value at row %d, col %d, role %d", row, col, nextRole);
169  //tempRow.insert(nextRole, getValue(nextRole, startRow + row, col));
170  tempRow.insert(nextRole, getValue(nextRole, row, col));
171  }
172  rows.append(tempRow);
173  tempRow.clear();
174  }
175 
176  QVariant vReturn = QVariant::fromValue<zTableRowList>(rows);
177 
178  return vReturn;
179 }
180 
181 
182 bool ZblTableData::hasCell(int role, int row, int col) const
183 {
184  if(!m_roles.contains(role))
185  return false;
186 
187  return hasCell(row, col);
188 }
189 
190 bool ZblTableData::hasCell(int row, int col) const
191 {
192  return(row >= 0 && m_rowCount > row && m_columnCount > col);
193 }
194 
196 {
197  pushRow(data, false);
198 }
199 
201 {
202  const int rowCount = data.size();
203 
204  if(!rowCount)
205  return;
206 
207  for(int i=0; i<rowCount; i++)
208  {
209  zRoleRow row = data.at(i);
210  pushRow(row, false);
211  }
212 
213 }
214 
216 {
217  pushRow(data, true);
218 }
219 
221 {
222  const int rowCount = data.size();
223 
224  if(!rowCount)
225  return;
226 
227  for(int i=rowCount-1; i>=0; i--)
228  {
229  zRoleRow row = data.at(i);
230  pushRow(row, true);
231  }
232 }
233 
234 void ZblTableData::removeRows(int row, int count)
235 {
236  if(row >= m_rowCount || count <= 0)
237  return;
238 
239  zRoleTable newRoles;
240 
241  QMapIterator<int, zDataTable> iRoles(m_roles);
242 
243  while(iRoles.hasNext())
244  {
245  iRoles.next();
246 
247  zDataTable dt = iRoles.value();
248 
249  int delCount = count;
250 
251  while(delCount--)
252  dt.removeAt(row);
253 
254  newRoles.insert(iRoles.key(), dt);
255  }
256 
257  m_roles = newRoles;
258 
259  m_rowCount -= count;
260 }
261 
263 {
264  if(!m_rowCount)
265  return;
266 
267  zRoleTable newRoles;
268 
269  zDataTable dt;
270 
271  QMapIterator<int, zDataTable> iRoles(m_roles);
272 
273  while(iRoles.hasNext())
274  {
275  iRoles.next();
276  newRoles.insert(iRoles.key(), dt);
277  }
278 
279  m_roles = newRoles;
280 
281  m_rowCount = 0;
282 }
283 
285 {
286  m_roles.clear();
287 
288  m_rowCount = 0;
289 }
290 
291 
292 
293 bool ZblTableData::addRole(int role)
294 {
295  if(m_rowCount > 0)
296  throw ZblException("ZblTableData::addRole - ERROR: can't add roles when "
297  "data table contains rows.");
298 
299  if(m_roles.contains(role))
300  return false;
301 
302  zDataTable newTable;
303 
304  m_roles.insert(role, newTable);
305 
306  return true;
307 }
308 
309 
311  int startRow,
312  const QString& text,
313  int column,
314  bool caseSensitive,
315  bool forwardDirection,
316  bool keySearch) const
317 {
318  // TBD: forwardDirection ignored!
319 
320  if(startRow >= m_rowCount || column >= m_columnCount)
321  return -1;
322 
323  const Qt::CaseSensitivity cs = caseSensitive ?
324  Qt::CaseSensitive : Qt::CaseInsensitive;
325 
326  int foundRow = -1;
327  bool foundFlag = false;
328 
329  QList<int>roleKeys(m_roles.keys());
330 
331  const int roleCount = roleKeys.count();
332 
333  for(int i=0; i < roleCount; i++)
334  {
335  const zDataTable& nextRoleTable = m_roles[roleKeys.at(i)];
336 
337  for(int j=startRow; j < m_rowCount; j++)
338  {
339  if(foundFlag && foundRow <= j)
340  break;
341 
342  const zDataRow& nextRoleRow = nextRoleTable[j];
343 
344  QString valueString = nextRoleRow[column].toString();
345 
346  if(keySearch)
347  {
348  // text matches the whole column
349 
350  if(QString::compare(text, valueString, cs) == 0)
351  {
352  foundFlag = true;
353  foundRow = j;
354  break;
355  }
356 
357  }
358  else
359  {
360  // text matches part of the column
361 
362  if(valueString.contains(text, cs))
363  {
364  foundFlag = true;
365  foundRow = j;
366  break;
367  }
368  }
369  }
370  }
371 
372  return foundRow;
373 }
374 
375 bool ZblTableData::copyColumn(int fromColumn, int toColumn)
376 {
377  QList<int>roleList = roles();
378  const int roleCount = roleList.count();
379 
380  for(int row=0; row < m_rowCount; row++)
381  {
382  for(int rl=0; rl<roleCount;rl++)
383  {
384  int roleNum = roleList.at(rl);
385  QVariant data = getValue(roleNum, row, fromColumn);
386  putValue(roleNum, row, toColumn, data);
387  }
388  }
389 }
390 
391 
392 void ZblTableData::pushRow(zRoleRow data, bool front)
393 {
394  // iterate the data map
395  // for each role
396  // append row to data table
397 
398  if(data.isEmpty())
399  throw ZblException("ZblTableData::appendRow - new row "
400  "contains no roles.");
401 
402  const int roleCount = data.size();
403 
404  if(roleCount != m_roles.size())
405  throw ZblException("ZblTableData::appendRow - new row's "
406  "role count not equivalent to number of data table roles.");
407 
408  QList<int> dataKeys = data.keys();
409 
410  QList<int> tableKeys = m_roles.keys();
411 
412  if(dataKeys != tableKeys)
413  throw ZblException("ZblTableData::appendRow - new row's "
414  "role types not equivalent to data table role types.");
415 
416  QList<int>::iterator nextKey = dataKeys.begin();
417  QList<int>::iterator lastKey = dataKeys.end();
418 
419  // ensure the column counts match
420  // TBD: optimize performance by taking this check out of loop for appendRows()!
421 
422  while(nextKey != lastKey)
423  {
424  const int roleKey = *nextKey++;
425 
426  zDataRow rowData = data.value(roleKey);
427 
428  if(rowData.size() != m_columnCount)
429  throw ZblException("ZblTableData::appendRow - new row's "
430  "column count not equivalent to number of data table columns.");
431  }
432 
433  // append the row to the table
434 
435  nextKey = dataKeys.begin();
436 
437  while(nextKey != lastKey)
438  {
439  const int roleKey = *nextKey++;
440 
441  zDataTable& dataTable = m_roles[roleKey];
442 
443  const zDataRow& dataRow = data.value(roleKey);
444 
445  //qDebug("ZblTableData::appendRow - appending role: %s",
446  // dataRow.at(0).toString().toUtf8().constData());
447 
448  if(front)
449  dataTable.prepend(dataRow);
450  else
451  dataTable.append(dataRow);
452  }
453 
454  m_rowCount++;
455 }
456 
457 
458 bool ZblTableData::hasRole(int role) const
459 {
460  return m_roles.contains(role);
461 }
462 
463 QList<int> ZblTableData::roles() const
464 {
465  return m_roles.keys();
466 }
467 
469 {
470  return m_roles.count();
471 }
472 
473 
475 {
476  return m_columnCount;
477 }
478 
480 {
481  if(m_rowCount > 0)
482  throw ZblException("ZblTableData::setColumnCount - ERROR: can't set column count when "
483  "data table contains rows.");
484 
485  m_columnCount = count;
486 }
487 
489 {
490  return m_rowCount;
491 }
492 
493 
494 } //Zbl
495 
void prependRows(zRoleRowList data)
Prepends a list of rows of role values to the table data.
void clearRoles()
Removes all roles and data rows from the data table.
int roleCount() const
Determines the current number of roles in the data table.
void putTableColumnRows(QVariant rows, int startRow, int col)
Replaces the current value for a set of rows for a single model column.
QVariant getTableColumnRows(QList< int > roles, int startRow, int col, int rowCount) const
Obtain data values for a set of rows from a single model column.
QMap< int, zDataRow > zRoleRow
Definition: ZblTableData.h:65
zRoleTable m_roles
A three dimensional array of child cell data. Dimensions of the array are role, row and column...
Definition: ZblTableData.h:395
void dumpData() const
Prints diagnostic information about the state of the contained data to debug output.
void prependRow(zRoleRow data)
Prepends a row of role values to the table data.
bool addRole(int role)
Adds the specified role to the data table. The table must not contain data rows when calling this met...
void removeRows(int row, int count)
Removes one or more rows from the table.
bool hasCell(int role, int row, int col) const
Determines if the specified cell and role combination exists in the data table.
QMap< int, QVariant > zTableRow
Definition: ZblTableData.h:69
int findNextItemRow(int startRow, const QString &text, int column=0, bool caseSensitive=true, bool forwardDirection=true, bool keySearch=false) const
int columnCount() const
Determines the number of columns in the data table.
bool hasRole(int role) const
Determines if a specified role already exists in the data table.
Definition: ZAndGate.cpp:6
void clearData()
Removes all rows from the data table.
QList< zTableRow > zTableRowList
Definition: ZblTableData.h:71
QList< int > roles() const
Determines which roles are in the data set.
bool copyColumn(int fromColumn, int toColumn)
QList< zRoleRow > zRoleRowList
Definition: ZblTableData.h:67
QVariant getValue(int role, int row, int col) const
Obtains the value of the specified cell and role. This is a blocking call.
void pushRow(zRoleRow data, bool front=false)
void appendRow(zRoleRow data)
Appends a row of role values to the table data.
int m_rowCount
The number of rows in the child data table.
Definition: ZblTableData.h:407
void setColumnCount(int count)
Sets the number of columns in the data table. This method fails if the data table contains rows...
void putValue(int role, int row, int col, const QVariant value)
Replaces the current value of a cell&#39;s role. This is a blocking call. with the specified value...
QList< QVariant > zDataRow
Definition: ZblTableData.h:61
Zuble&#39;s Qt Exception Object.
Definition: ZblException.h:45
QList< zDataRow > zDataTable
Definition: ZblTableData.h:63
void appendRows(zRoleRowList data)
Appends a list of rows of role values to the table data.
int m_columnCount
The number of columns in the child data table.
Definition: ZblTableData.h:401
QMap< int, zDataTable > zRoleTable
Definition: ZblTableData.h:73
int rowCount() const
Determines the number of rows in the data table.