1 /*
2 SPDX-FileCopyrightText: 2002-2010 Peter Hedlund <peter.hedlund@kdemail.net>
3 SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6 #include "kwqcommands.h"
7
8 #include <QApplication>
9 #include <QClipboard>
10 #include <QHeaderView>
11
12 #include "kwqtablemodel.h"
13
copyToClipboard(QTableView * view)14 void copyToClipboard(QTableView * view)
15 {
16 QModelIndexList selIndexes = view->selectionModel()->selectedIndexes();
17 if( selIndexes.isEmpty())
18 return;
19 int tr = selIndexes.first().row();
20 int lc = selIndexes.first().column();
21 int br = selIndexes.last().row();
22 int rc = selIndexes.last().column();
23
24 QString s;
25 for (int r = tr; r <= br; ++r)
26 {
27 for (int c = lc; c <= rc; ++c)
28 {
29 QVariant v = view->model()->data(view->model()->index(r, c, QModelIndex()), Qt::DisplayRole);
30 s.append(v.toString());
31 s.append('\t');
32 }
33 s.append('\n');
34 }
35 QApplication::clipboard()->setText(s.trimmed());
36 }
37
38
KWQUndoCommand(KWQTableView * view)39 KWQUndoCommand::KWQUndoCommand(KWQTableView * view) : QUndoCommand()
40 {
41 m_view = view;
42 m_currentIndex = m_view->selectionModel()->currentIndex();
43 m_selectedIndexes = m_view->selectionModel()->selectedIndexes();
44 if (m_selectedIndexes.isEmpty())
45 m_selectedIndexes.append(m_currentIndex);
46
47 foreach (const QModelIndex &index, m_selectedIndexes) {
48 IndexAndData id;
49 id.index = index;
50 id.data = m_view->model()->data(index, Qt::DisplayRole);
51 id.image = m_view->model()->data(index, KWQTableModel::ImageRole);
52 id.sound = m_view->model()->data(index, KWQTableModel::SoundRole);
53 id.height = m_view->rowHeight(index.row());
54 m_indexAndData.append(id);
55 }
56 }
57
58
undo()59 void KWQUndoCommand::undo()
60 {
61 m_view->selectionModel()->clear();
62 foreach (const IndexAndData &id, m_indexAndData) {
63 m_view->model()->setData(id.index, id.data, Qt::EditRole);
64 m_view->model()->setData(id.index, id.image, KWQTableModel::ImageRole);
65 m_view->model()->setData(id.index, id.sound, KWQTableModel::SoundRole);
66 m_view->selectionModel()->select(id.index, QItemSelectionModel::Select);
67 }
68 m_view->selectionModel()->setCurrentIndex(m_currentIndex, QItemSelectionModel::Current);
69 }
70
71
KWQCommandClear(KWQTableView * view)72 KWQCommandClear::KWQCommandClear(KWQTableView * view) : KWQUndoCommand(view)
73 {
74 setText(i18nc("@item:inmenu undo clear", "Clear"));
75 }
76
77
redo()78 void KWQCommandClear::redo()
79 {
80 view()->selectionModel()->clear();
81 foreach (const QModelIndex &index, oldSelectedIndexes()) {
82 if (Prefs::clearText() || Prefs::clearAll())
83 view()->model()->setData(index, QVariant(), Qt::EditRole);
84 if (Prefs::clearImageLink() || Prefs::clearAll())
85 view()->model()->setData(index, QVariant(), KWQTableModel::ImageRole);
86 if (Prefs::clearSoundLink() || Prefs::clearAll())
87 view()->model()->setData(index, QVariant(), KWQTableModel::SoundRole);
88 view()->selectionModel()->select(index, QItemSelectionModel::Select);
89 }
90 view()->selectionModel()->setCurrentIndex(oldCurrentIndex(), QItemSelectionModel::Current);
91 }
92
93
KWQCommandCut(KWQTableView * view)94 KWQCommandCut::KWQCommandCut(KWQTableView * view) : KWQCommandClear(view)
95 {
96 setText(i18nc("@item:inmenu undo cut", "Cut"));
97 }
98
99
redo()100 void KWQCommandCut::redo()
101 {
102 copyToClipboard(view());
103 KWQCommandClear::redo();
104 }
105
106
KWQCommandPaste(KWQTableView * view)107 KWQCommandPaste::KWQCommandPaste(KWQTableView * view) : KWQUndoCommand(view)
108 {
109 setText(i18nc("@item:inmenu undo paste", "Paste"));
110 m_rowCount = view->model()->rowCount();
111 }
112
undo()113 void KWQCommandPaste::undo()
114 {
115 foreach (const IndexAndData &id, m_pasteIndexAndData)
116 view()->model()->setData(id.index, id.data, Qt::EditRole);
117
118 while (view()->model()->rowCount(QModelIndex()) > m_rowCount) {
119 view()->model()->removeRows(view()->model()->rowCount() - 1, 1, QModelIndex());
120 }
121
122 KWQUndoCommand::undo();
123 }
124
redo()125 void KWQCommandPaste::redo()
126 {
127 QModelIndexList selIndexes = oldSelectedIndexes();
128 if(selIndexes.isEmpty())
129 return;
130 QModelIndex topLeft = view()->model()->index(selIndexes.first().row(), selIndexes.first().column(), QModelIndex());
131 QModelIndex bottomRight = view()->model()->index(selIndexes.last().row(), selIndexes.last().column(), QModelIndex());
132
133 int tr;
134 int lc;
135 int ar = tr = topLeft.row();
136 int ac = lc = topLeft.column();
137 int rc = bottomRight.column();
138 int br = bottomRight.row();
139
140 QString s = QApplication::clipboard()->text();
141 QStringList sl;
142 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
143 sl = s.split('\n', QString::SkipEmptyParts);
144 #else
145 sl = s.split('\n', Qt::SkipEmptyParts);
146 #endif
147 if (sl.isEmpty())
148 return;
149 QStringList sr;
150 int i = 0;
151
152 if (selIndexes.count() == 1) //one cell selected
153 {
154 //Do we need to add entries (rows)?
155 while (sl.count() + tr > view()->model()->rowCount(QModelIndex())) {
156 view()->model()->insertRows(view()->model()->rowCount(), 1, QModelIndex());
157 }
158
159 br = tr + sl.count() - 1;
160
161 if (lc == 0) //left col?
162 if (sl[0].indexOf('\t') > -1)
163 rc = 1; //expand to second column;
164
165 while (i < sl.count() && br <= view()->model()->rowCount(QModelIndex())) {
166 ac = lc;
167
168 sr = sl.at(i).split('\t');
169 int c = 0;
170 while (ac <= rc) {
171 IndexAndData id;
172 id.index = view()->model()->index(ar, ac);
173 id.data = view()->model()->data(id.index, Qt::DisplayRole);
174 m_pasteIndexAndData.append(id);
175 if (c < sr.count())
176 view()->model()->setData(id.index, QVariant(sr[c]), Qt::EditRole);
177 view()->selectionModel()->select(id.index, QItemSelectionModel::Select);
178 ac++;
179 c++;
180 }
181 ar++;
182 i++;
183 }
184 }
185 else
186 {
187 while (i < sl.count() && ar <= br) {
188 ac = lc;
189
190 sr = sl.at(i).split('\t');
191 int c = 0;
192 while (ac <= rc) {
193 if (view()->selectionModel()->isSelected(view()->model()->index(ar, ac)))
194 if (c < sr.count())
195 view()->model()->setData(view()->model()->index(ar, ac), QVariant(sr[c]), Qt::EditRole);
196 ac++;
197 c++;
198 }
199 ar++;
200 i++;
201 }
202 }
203 }
204
205
KWQCommandSort(QTableView * view,int column)206 KWQCommandSort::KWQCommandSort(QTableView * view, int column)
207 {
208 m_view = view;
209 m_column = column;
210 setText(i18nc("@item:inmenu undo sort", "Sort"));
211 }
212
213
undo()214 void KWQCommandSort::undo()
215 {
216 m_view->setUpdatesEnabled(false);
217 static_cast<KWQSortFilterModel*>(m_view->model())->restoreNativeOrder();
218 m_view->horizontalHeader()->setSortIndicatorShown(false);
219 m_view->setUpdatesEnabled(true);
220 }
221
222
redo()223 void KWQCommandSort::redo()
224 {
225 int currentRow = m_view->currentIndex().row();
226 int currentColumn = m_view->currentIndex().column();
227 m_view->sortByColumn(m_column, Qt::AscendingOrder);
228 m_view->horizontalHeader()->setSortIndicatorShown(true);
229 m_view->horizontalHeader()->setSortIndicator(m_column, m_view->horizontalHeader()->sortIndicatorOrder());
230 m_view->setCurrentIndex(m_view->model()->index(currentRow, currentColumn, QModelIndex()));
231 }
232
233
KWQCommandShuffle(QTableView * view,int column)234 KWQCommandShuffle::KWQCommandShuffle(QTableView * view, int column) : KWQCommandSort(view, column)
235 {
236 m_view = view;
237 setText(i18nc("@item:inmenu undo shuffle", "Shuffle"));
238 }
239
undo()240 void KWQCommandShuffle::undo()
241 {
242 KWQCommandSort::undo();
243 }
244
redo()245 void KWQCommandShuffle::redo()
246 {
247 int currentRow = m_view->currentIndex().row();
248 int currentColumn = m_view->currentIndex().column();
249 static_cast<KWQSortFilterModel*>(m_view->model())->shuffle();
250 m_view->horizontalHeader()->setSortIndicatorShown(false);
251 m_view->setCurrentIndex(m_view->model()->index(currentRow, currentColumn, QModelIndex()));
252 }
253
254
KWQCommandInsert(KWQTableView * view)255 KWQCommandInsert::KWQCommandInsert(KWQTableView * view) : KWQUndoCommand(view)
256 {
257 setText(i18nc("@item:inmenu undo insert", "Insert"));
258 }
259
undo()260 void KWQCommandInsert::undo()
261 {
262 QModelIndexList selIndexes = oldSelectedIndexes();
263 QModelIndex topLeft = view()->model()->index(selIndexes.first().row(), selIndexes.first().column(), QModelIndex());
264 QModelIndex bottomRight = view()->model()->index(selIndexes.last().row(), selIndexes.last().column(), QModelIndex());
265
266 view()->model()->removeRows(topLeft.row(), bottomRight.row() - topLeft.row() + 1, QModelIndex());
267
268 view()->selectionModel()->clear();
269 view()->setCurrentIndex(view()->model()->index(oldCurrentIndex().row(), oldCurrentIndex().column(), QModelIndex()));
270 view()->selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
271 }
272
redo()273 void KWQCommandInsert::redo()
274 {
275 QModelIndexList selIndexes = oldSelectedIndexes();
276 QModelIndex topLeft = view()->model()->index(selIndexes.first().row(), selIndexes.first().column(), QModelIndex());
277 QModelIndex bottomRight = view()->model()->index(selIndexes.last().row(), selIndexes.last().column(), QModelIndex());
278
279 view()->model()->insertRows(topLeft.row(), bottomRight.row() - topLeft.row() + 1, QModelIndex());
280
281 view()->selectionModel()->clear();
282 view()->setCurrentIndex(view()->model()->index(oldCurrentIndex().row(), oldCurrentIndex().column(), QModelIndex()));
283 view()->selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
284 }
285
286
KWQCommandDelete(KWQTableView * view)287 KWQCommandDelete::KWQCommandDelete(KWQTableView * view) : KWQUndoCommand(view)
288 {
289 setText(i18nc("@item:inmenu undo delete", "Delete"));
290 }
291
292
undo()293 void KWQCommandDelete::undo()
294 {
295 QModelIndexList selIndexes = oldSelectedIndexes();
296 QModelIndex topLeft = view()->model()->index(selIndexes.first().row(), selIndexes.first().column(), QModelIndex());
297 QModelIndex bottomRight = view()->model()->index(selIndexes.last().row(), selIndexes.last().column(), QModelIndex());
298
299 view()->model()->insertRows(topLeft.row(), bottomRight.row() - topLeft.row() + 1, QModelIndex());
300
301 foreach (const IndexAndData &id, m_deleteIndexAndData)
302 view()->model()->setData(id.index, id.data, Qt::EditRole);
303
304 view()->selectionModel()->clear();
305 view()->setCurrentIndex(view()->model()->index(oldCurrentIndex().row(), oldCurrentIndex().column(), QModelIndex()));
306 view()->selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
307 }
308
309
redo()310 void KWQCommandDelete::redo()
311 {
312 QModelIndexList selIndexes = oldSelectedIndexes();
313 QModelIndex topLeft = view()->model()->index(selIndexes.first().row(), selIndexes.first().column(), QModelIndex());
314 QModelIndex bottomRight = view()->model()->index(selIndexes.last().row(), selIndexes.last().column(), QModelIndex());
315
316 QModelIndex topLeftDeletion = view()->model()->index(selIndexes.first().row(), 0, QModelIndex());
317 QModelIndex bottomRightDeletion = view()->model()->index(selIndexes.last().row(), 1, QModelIndex());
318
319 QItemSelection deletion(topLeftDeletion, bottomRightDeletion);
320 m_deleteIndexAndData.clear();
321 foreach (const QModelIndex &idx, deletion.indexes()) {
322 IndexAndData id;
323 id.index = idx;
324 id.data = view()->model()->data(id.index, Qt::DisplayRole);
325 m_deleteIndexAndData.append(id);
326 }
327
328 view()->model()->removeRows(topLeft.row(), bottomRight.row() - topLeft.row() + 1, QModelIndex());
329
330 view()->selectionModel()->clear();
331 view()->setCurrentIndex(view()->model()->index(oldCurrentIndex().row(), oldCurrentIndex().column(), QModelIndex()));
332 view()->selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
333 }
334
335
KWQCommandUnmarkBlank(KWQTableView * view)336 KWQCommandUnmarkBlank::KWQCommandUnmarkBlank(KWQTableView * view) : KWQUndoCommand(view)
337 {
338 setText(i18nc("@item:inmenu undo unmark blank", "Unmark Blank"));
339 }
340
341
redo()342 void KWQCommandUnmarkBlank::redo()
343 {
344 QString s;
345 view()->selectionModel()->clear();
346 foreach (const QModelIndex &index, oldSelectedIndexes())
347 {
348 s = view()->model()->data(index, Qt::DisplayRole).toString();
349 s = s.remove(delim_start);
350 s = s.remove(delim_end);
351 view()->model()->setData(index, QVariant(s), Qt::EditRole);
352 view()->selectionModel()->select(index, QItemSelectionModel::Select);
353 }
354 view()->selectionModel()->setCurrentIndex(oldCurrentIndex(), QItemSelectionModel::Current);
355 }
356
357
KWQCommandIdentifiers(KWQTableView * view,const ColumnDataList & newColumnData)358 KWQCommandIdentifiers::KWQCommandIdentifiers(KWQTableView * view, const ColumnDataList &newColumnData) : KWQUndoCommand(view)
359 {
360 setText(i18nc("@item:inmenu undo column titles", "Column Settings"));
361 m_oldColumnData.clear();
362 ColumnData columnData;
363 columnData.identifier = view->model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString();
364 columnData.layout = view->model()->headerData(0, Qt::Horizontal, KWQTableModel::KeyboardLayoutRole).toString();
365 columnData.width = view->model()->headerData(0, Qt::Horizontal, Qt::SizeHintRole).toSize().width();
366 m_oldColumnData.append(columnData);
367
368 columnData.identifier = view->model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString();
369 columnData.layout = view->model()->headerData(1, Qt::Horizontal, KWQTableModel::KeyboardLayoutRole).toString();
370 columnData.width = view->model()->headerData(1, Qt::Horizontal, Qt::SizeHintRole).toSize().width();
371 m_oldColumnData.append(columnData);
372
373 m_newColumnData = newColumnData;
374 }
375
376
undo()377 void KWQCommandIdentifiers::undo()
378 {
379 view()->model()->setHeaderData(0, Qt::Horizontal, m_oldColumnData[0].identifier, Qt::EditRole);
380 view()->model()->setHeaderData(1, Qt::Horizontal, m_oldColumnData[1].identifier, Qt::EditRole);
381
382 view()->model()->setHeaderData(0, Qt::Horizontal, m_oldColumnData[0].layout, KWQTableModel::KeyboardLayoutRole);
383 view()->model()->setHeaderData(1, Qt::Horizontal, m_oldColumnData[1].layout, KWQTableModel::KeyboardLayoutRole);
384
385 view()->model()->setHeaderData(0, Qt::Horizontal, QSize(m_oldColumnData[0].width, 25), Qt::SizeHintRole);
386 view()->model()->setHeaderData(1, Qt::Horizontal, QSize(m_oldColumnData[1].width, 25), Qt::SizeHintRole);
387 }
388
389
redo()390 void KWQCommandIdentifiers::redo()
391 {
392 view()->model()->setHeaderData(0, Qt::Horizontal, m_newColumnData[0].identifier, Qt::EditRole);
393 view()->model()->setHeaderData(1, Qt::Horizontal, m_newColumnData[1].identifier, Qt::EditRole);
394
395 view()->model()->setHeaderData(0, Qt::Horizontal, m_newColumnData[0].layout, KWQTableModel::KeyboardLayoutRole);
396 view()->model()->setHeaderData(1, Qt::Horizontal, m_newColumnData[1].layout, KWQTableModel::KeyboardLayoutRole);
397
398 view()->model()->setHeaderData(0, Qt::Horizontal, QSize(m_newColumnData[0].width, 25), Qt::SizeHintRole);
399 view()->model()->setHeaderData(1, Qt::Horizontal, QSize(m_newColumnData[1].width, 25), Qt::SizeHintRole);
400 }
401
402
KWQCommandImage(KWQTableView * view,const QUrl & newUrl)403 KWQCommandImage::KWQCommandImage(KWQTableView *view, const QUrl &newUrl) : KWQUndoCommand(view), m_newUrl(newUrl)
404 {
405 setText(i18nc("@item:inmenu undo link image", "Link Image"));
406 m_oldUrl = QUrl(view->model()->data(oldCurrentIndex(), KWQTableModel::ImageRole).toString());
407 }
408
409
undo()410 void KWQCommandImage::undo()
411 {
412 view()->model()->setData(oldCurrentIndex(), QVariant(m_oldUrl), KWQTableModel::ImageRole);
413 }
414
415
redo()416 void KWQCommandImage::redo()
417 {
418 view()->model()->setData(oldCurrentIndex(), QVariant(m_newUrl), KWQTableModel::ImageRole);
419 }
420
421
KWQCommandSound(KWQTableView * view,const QUrl & newUrl)422 KWQCommandSound::KWQCommandSound(KWQTableView *view, const QUrl &newUrl) : KWQUndoCommand(view), m_newUrl(newUrl)
423 {
424 setText(i18nc("@item:inmenu undo link sound", "Link Sound"));
425 m_oldUrl = QUrl(view->model()->data(oldCurrentIndex(), KWQTableModel::SoundRole).toString());
426 }
427
428
undo()429 void KWQCommandSound::undo()
430 {
431 view()->model()->setData(oldCurrentIndex(), QVariant(m_oldUrl), KWQTableModel::SoundRole);
432 }
433
434
redo()435 void KWQCommandSound::redo()
436 {
437 view()->model()->setData(oldCurrentIndex(), QVariant(m_newUrl), KWQTableModel::SoundRole);
438 }
439