1 /***************************************************************************
2 rktextmatrix - description
3 -------------------
4 begin : Thu Nov 08 2007
5 copyright : (C) 2007, 2010, 2012 by Thomas Friedrichsmeier
6 email : thomas.friedrichsmeier@kdemail.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "rktextmatrix.h"
19
20 #include <QApplication>
21 #include <QClipboard>
22 #include <QMimeData>
23
24 #include "../debug.h"
25
RKTextMatrix()26 RKTextMatrix::RKTextMatrix () {
27 RK_TRACE (EDITOR);
28
29 clear ();
30 }
31
RKTextMatrix(const RKTextMatrix & copy)32 RKTextMatrix::RKTextMatrix (const RKTextMatrix& copy) {
33 RK_TRACE (EDITOR);
34
35 colcount = copy.colcount;
36 rows = copy.rows;
37 }
38
~RKTextMatrix()39 RKTextMatrix::~RKTextMatrix () {
40 RK_TRACE (EDITOR);
41 }
42
43 // static
matrixFromClipboard()44 RKTextMatrix RKTextMatrix::matrixFromClipboard () {
45 RK_TRACE (EDITOR);
46
47 const QMimeData* data = QApplication::clipboard ()->mimeData ();
48 // actually, we don't care, whether tsv or plain gets pasted - it's both
49 // treated the same. We should however encourage external senders to
50 // provided the two in order.
51 if (data->hasFormat ("text/tab-separated-values")) {
52 RK_DEBUG (EDITOR, DL_DEBUG, "paste tsv");
53 return (matrixFromSeparatedValues (QString::fromLocal8Bit (data->data ("text/tab-separated-values"))));
54 } else if (data->hasText ()) {
55 RK_DEBUG (EDITOR, DL_DEBUG, "paste plain text");
56 return (matrixFromSeparatedValues (data->text ()));
57 }
58
59 return RKTextMatrix ();
60 }
61
62 // static
matrixFromSeparatedValues(const QString & text,const QRegExp & tab,const QChar & brk)63 RKTextMatrix RKTextMatrix::matrixFromSeparatedValues (const QString& text, const QRegExp& tab, const QChar& brk) {
64 RK_TRACE (EDITOR);
65
66 RKTextMatrix ret;
67 if (text.isEmpty ()) return ret;
68
69 QStringList textrows = text.split (brk);
70 if (textrows.last ().isEmpty ()) textrows.removeLast (); // some apps append a trailing line break
71 for (int i = 0; i < textrows.size (); ++i) {
72 QStringList split = textrows[i].split (tab);
73 ret.appendRow (split);
74 }
75
76 return ret;
77 }
78
toTabSeparatedValues() const79 QString RKTextMatrix::toTabSeparatedValues () const {
80 RK_TRACE (EDITOR);
81
82 QString ret;
83 for (int row = 0; row < rows.size (); ++row) {
84 if (row) ret.append ('\n');
85 ret.append (rows[row].join (QChar ('\t')));
86 }
87 return ret;
88 }
89
copyToClipboard() const90 void RKTextMatrix::copyToClipboard () const {
91 RK_TRACE (EDITOR);
92
93 QString text = toTabSeparatedValues ();
94 QMimeData* data = new QMimeData ();
95 data->setText (text);
96 data->setData ("text/tab-separated-values", text.toLocal8Bit ());
97 QApplication::clipboard()->setMimeData (data);
98 }
99
transformed(bool reverse_h,bool reverse_v,bool transpose) const100 RKTextMatrix RKTextMatrix::transformed (bool reverse_h, bool reverse_v, bool transpose) const {
101 RK_TRACE (EDITOR);
102
103 RKTextMatrix ret;
104 if (isEmpty ()) return ret; // empty matrices would violate some assumptions of the following code
105
106 const int maxrow = rows.size () - 1; // for easier typing
107 const int maxcol = rows[0].size () - 1;
108
109 if (transpose) ret.upsize (maxcol, maxrow); // set dimensions from the start to save a few cycles
110 else ret.upsize (maxrow, maxcol);
111
112 for (int row=0; row <= maxrow; ++row) {
113 for (int col=0; col <= maxcol; ++col) {
114 int dest_row = row;
115 if (reverse_v) dest_row = maxrow - row;
116 int dest_col = col;
117 if (reverse_h) dest_col = maxcol - col;
118
119 if (transpose) {
120 int dummy = dest_row;
121 dest_row = dest_col;
122 dest_col = dummy;
123 }
124
125 ret.setText (dest_row, dest_col, rows[row][col]);
126 }
127 }
128
129 return ret;
130 }
131
setText(int row,int col,const QString & text)132 void RKTextMatrix::setText (int row, int col, const QString& text) {
133 // RK_TRACE (EDITOR);
134
135 upsize (row, col);
136 rows[row][col] = text;
137 }
138
setColumn(int column,const QString * textarray,int length)139 void RKTextMatrix::setColumn (int column, const QString* textarray, int length) {
140 RK_TRACE (EDITOR);
141
142 upsize (length - 1, column);
143 for (int i = 0; i < length; ++i) {
144 rows[i][column] = textarray[i];
145 }
146 }
147
appendRow(const QStringList & row)148 void RKTextMatrix::appendRow (const QStringList& row) {
149 RK_TRACE (EDITOR);
150
151 QStringList _row = row;
152 while (colcount > _row.size ()) _row.append (QString ());
153 rows.append (_row);
154 upsize (rows.size ()-1, row.size ()-1);
155 }
156
getText(int row,int col) const157 QString RKTextMatrix::getText (int row, int col) const {
158 // RK_TRACE (EDITOR);
159
160 if (row > rows.size ()) return QString ();
161 if (col > colcount) return QString ();
162 return (rows[row][col]);
163 }
164
getColumn(int col) const165 QStringList RKTextMatrix::getColumn (int col) const {
166 RK_TRACE (EDITOR);
167
168 if (col > colcount) {
169 return QStringList ();
170 }
171
172 QStringList ret;
173 ret.reserve (rows.size ());
174 for (int i = 0; i < rows.size (); ++i) {
175 ret.append (rows[i][col]);
176 }
177 return ret;
178 }
179
getRow(int row) const180 QStringList RKTextMatrix::getRow (int row) const {
181 RK_TRACE (EDITOR);
182
183 if (row >= rows.size ()) return (QStringList ());
184 RK_ASSERT (rows[row].size () == colcount);
185 return (rows[row]);
186 }
187
clear()188 void RKTextMatrix::clear () {
189 RK_TRACE (EDITOR);
190
191 rows.clear ();
192 colcount = 0;
193 }
194
isEmpty() const195 bool RKTextMatrix::isEmpty () const {
196 RK_TRACE (EDITOR);
197
198 if (rows.isEmpty() || (colcount == 0)) return true;
199 return false;
200 }
201
upsize(int newmaxrow,int newmaxcol)202 void RKTextMatrix::upsize (int newmaxrow, int newmaxcol) {
203 // RK_TRACE (EDITOR);
204
205 while (newmaxrow >= rows.size ()) {
206 QStringList list;
207 for (int i = 0; i < colcount; ++i) list.append (QString ());
208 rows.append(list);
209 }
210
211 if (newmaxcol >= colcount) {
212 for (int i = 0; i < rows.size (); ++i) {
213 while (newmaxcol >= rows[i].size ()) rows[i].append (QString());
214 }
215 colcount = newmaxcol + 1;
216 }
217 }
218