Engauge Digitizer  2
WindowModelBase.cpp
1 /******************************************************************************************************
2  * (C) 2016 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 "EngaugeAssert.h"
8 #include "Logger.h"
9 #include <QItemSelectionModel>
10 #include <QMimeData>
11 #include <QTableView>
12 #include <QTextStream>
13 #include "WindowModelBase.h"
14 #include "WindowTable.h"
15 
17  m_view (0)
18 {
19 }
20 
21 WindowModelBase::~WindowModelBase()
22 {
23 }
24 
25 int WindowModelBase::fold2dIndexes (int row,
26  int col,
27  int rowLow,
28  int colLow,
29  int colHigh) const
30 {
31  return (row - rowLow) * (colHigh - colLow + 1) + (col - colLow);
32 }
33 
34 QMimeData *WindowModelBase::mimeData(const QModelIndexList &indexes) const
35 {
36  if (indexes.isEmpty ()) {
37  return Q_NULLPTR;
38  }
39 
40  QMimeData *data = new QMimeData ();
41 
42  data->setHtml (selectionAsHtml ());
43  data->setText (selectionAsText (m_delimiter));
44 
45  return data;
46 }
47 
49 {
50  ENGAUGE_CHECK_PTR (m_view);
51 
52  int rowLow, colLow, rowHigh, colHigh;
53  QVector<QString> table;
54 
55  // Get raw data as a rectangular table. Size may be zero
56  selectionAsTable (rowLow,
57  colLow,
58  rowHigh,
59  colHigh,
60  table);
61 
62  // Concatenate table into output string
63  QString html;
64  QTextStream str (&html);
65 
66  str << "<table>";
67  for (int row = rowLow; row <= rowHigh; row++) {
68  str << "<tr>";
69  for (int col = colLow; col <= colHigh; col++) {
70  str << "<td>" << table [fold2dIndexes (row, col, rowLow, colLow, colHigh)] << "</td>";
71  }
72  str << "<tr>\n";
73  }
74  str << "</table>";
75 
76  return html;
77 }
78 
79 void WindowModelBase::selectionAsTable (int &rowLow,
80  int &colLow,
81  int &rowHigh,
82  int &colHigh,
83  QVector<QString> &table) const
84 {
85  // This algorithm supports any arbitrary set of selected cells. Specifically, the cells do not need
86  // to be in a rectangular pattern. A rectangular grid that encompasses all selected cells will be created
87 
88  QItemSelectionModel *selectionModel = m_view->selectionModel ();
89  QModelIndexList selection = selectionModel->selectedIndexes ();
90 
91  if (selection.size () > 0) {
92 
93  // Gather input. Initialization of row/col limits is needed only to keep some compilers happy
94  rowLow = 0;
95  colLow = 0;
96  rowHigh = 0;
97  colHigh = 0;
98  bool isFirst = true;
99  for (QModelIndexList::const_iterator itr = selection.begin(); itr != selection.end(); itr++) {
100  QModelIndex index = *itr;
101  if (isFirst || index.row () < rowLow ) rowLow = index.row ();
102  if (isFirst || index.row () > rowHigh) rowHigh = index.row ();
103  if (isFirst || index.column () < colLow ) colLow = index.column ();
104  if (isFirst || index.column () > colHigh) colHigh = index.column ();
105  isFirst = false;
106  }
107 
108  int numRows = rowHigh - rowLow + 1;
109  int numCols = colHigh - colLow + 1;
110 
111  // Put data into two dimensional rowXcolumn table is handled as a flattened vector. Table is initialized
112  // with empty strings
113  table.resize (numRows * numCols);
114 
115  for (int i = 0; i < selection.size (); i++) {
116  QModelIndex index = selection [i];
117  QVariant d = data (index);
118  QString text = d.toString ();
119  table [fold2dIndexes (index.row(), index.column(), rowLow, colLow, colHigh)] = text;
120  }
121  } else {
122 
123  // Table has zero size
124  rowLow = 0;
125  colLow = 0;
126  rowHigh = -1;
127  colHigh = -1;
128 
129  }
130 }
131 
132 QString WindowModelBase::selectionAsText (ExportDelimiter delimiter) const
133 {
134  const bool NOT_GNUPLOT = false;
135 
136  ENGAUGE_CHECK_PTR (m_view);
137 
138  int rowLow, colLow, rowHigh, colHigh;
139  QVector<QString> table;
140 
141  // Get raw data as a rectangular table. Size may be zero
142  selectionAsTable (rowLow,
143  colLow,
144  rowHigh,
145  colHigh,
146  table);
147 
148  // Concatenate table into output string
149  QString text;
150  QTextStream str (&text);
151  for (int row = rowLow; row <= rowHigh; row++) {
152  QString delimiterStr;
153  for (int col = colLow; col <= colHigh; col++) {
154  str << delimiterStr << table [fold2dIndexes (row, col, rowLow, colLow, colHigh)];
155  delimiterStr = exportDelimiterToText (delimiter,
156  NOT_GNUPLOT);
157  }
158  str << "\n";
159  }
160 
161  return text;
162 }
163 
164 void WindowModelBase::setDelimiter (ExportDelimiter delimiter)
165 {
166  m_delimiter = delimiter;
167 }
168 
170 {
171  m_view = &view;
172 }
QMimeData * mimeData(const QModelIndexList &indexes) const
Support dragging of multiple cells.
QString selectionAsText(ExportDelimiter delimiter) const
Convert the selection into exportable text which is good for text editors.
QString selectionAsHtml() const
Convert the selection into exportable html which is good for spreadsheets.
void setView(WindowTable &view)
Save the view so this class can access the current selection.
void setDelimiter(ExportDelimiter delimiter)
Save output delimiter.
Table view class with support for both drag-and-drop and copy-and-paste.
Definition: WindowTable.h:17
WindowModelBase()
Single constructor.