1 /*
2 SPDX-FileCopyrightText: 2006-2010 Peter Hedlund <peter.hedlund@kdemail.net>
3 SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6 #include "kwqtablemodel.h"
7
8 #include <KLocalizedString>
9
10 #include "prefs.h"
11 #include "documentsettings.h"
12 #include "keduvocexpression.h"
13
KWQTableModel(QObject * parent)14 KWQTableModel::KWQTableModel(QObject * parent) : QAbstractTableModel(parent)
15 {
16 m_doc = 0;
17 m_decorationCache = new KImageCache(QStringLiteral("kwordquiz"), 10485760);
18 }
19
~KWQTableModel()20 KWQTableModel::~KWQTableModel()
21 {
22 delete m_decorationCache;
23 }
24
rowCount(const QModelIndex & parent) const25 int KWQTableModel::rowCount(const QModelIndex & parent) const
26 {
27 if (parent.isValid())
28 return 0;
29 return m_doc->lesson()->entryCount(KEduVocLesson::Recursive);
30 }
31
columnCount(const QModelIndex & parent) const32 int KWQTableModel::columnCount(const QModelIndex & parent) const
33 {
34 if (parent.isValid())
35 return 0;
36 return 2;
37 }
38
data(const QModelIndex & index,int role) const39 QVariant KWQTableModel::data(const QModelIndex & index, int role) const
40 {
41 if (!index.isValid())
42 return QVariant();
43
44 QPixmap ip;
45 QString image;
46
47 switch (role) {
48 case Qt::FontRole:
49 return QVariant(Prefs::editorFont());
50
51 case Qt::DisplayRole:
52 return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->text();
53
54 case Qt::DecorationRole:
55 image = m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->imageUrl().toLocalFile();
56 if (!image.isEmpty()) {
57 if (!m_decorationCache->findPixmap(image, &ip)) {
58 ip = QPixmap(image).scaled(QSize(22, 22), Qt::KeepAspectRatio);
59 m_decorationCache->insertPixmap(image, ip);
60 }
61 }
62 return ip;
63
64 case KWQTableModel::ImageRole:
65 return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->imageUrl().toLocalFile();
66
67 case KWQTableModel::SoundRole:
68 return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->soundUrl().toLocalFile();
69
70 default:
71 return QVariant();
72 }
73 }
74
headerData(int section,Qt::Orientation orientation,int role) const75 QVariant KWQTableModel::headerData(int section, Qt::Orientation orientation, int role) const
76 {
77 if (orientation == Qt::Horizontal)
78 {
79 if (section < 0 || section > 1)
80 return QVariant();
81
82 if (role == Qt::DisplayRole) {
83 return m_doc->identifier(section).name();
84 }
85
86 if (role == Qt::SizeHintRole) {
87 DocumentSettings documentSettings(m_doc->url().url());
88 documentSettings.read();
89 return QSize(documentSettings.sizeHintColumn(section), 25);
90 }
91
92 if (role == KWQTableModel::KeyboardLayoutRole) {
93 DocumentSettings documentSettings(m_doc->url().url());
94 documentSettings.read();
95 return documentSettings.keyboardLayoutColumn(section);
96 }
97
98 return QVariant();
99 }
100 else
101 return QAbstractTableModel::headerData(section, orientation, role);
102 }
103
flags(const QModelIndex & index) const104 Qt::ItemFlags KWQTableModel::flags(const QModelIndex & index) const
105 {
106 if (!index.isValid())
107 return Qt::ItemIsEnabled;
108
109 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
110 }
111
setData(const QModelIndex & index,const QVariant & value,int role)112 bool KWQTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
113 {
114 if (!index.isValid())
115 return false;
116
117 switch (role) {
118 case Qt::EditRole:
119 m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->setTranslation(index.column(), value.toString());
120 break;
121
122 case KWQTableModel::ImageRole:
123 m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->setImageUrl(value.toUrl());
124 break;
125
126 case KWQTableModel::SoundRole:
127 m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->setSoundUrl(value.toUrl());
128 break;
129 }
130
131 Q_EMIT dataChanged(index, index);
132 return true;
133 }
134
setHeaderData(int section,Qt::Orientation orientation,const QVariant & value,int role)135 bool KWQTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role)
136 {
137 if (orientation == Qt::Horizontal) {
138 if (section < 0 || section > 1)
139 return false;
140
141 if (role == Qt::EditRole) {
142 m_doc->identifier(section).setName(value.toString());
143 }
144
145 if (role == Qt::SizeHintRole) {
146 DocumentSettings documentSettings(m_doc->url().url());
147 documentSettings.setSizeHintColumn(section, qvariant_cast<QSize>(value).width());
148 documentSettings.save();
149 }
150
151 if (role == KWQTableModel::KeyboardLayoutRole) {
152 DocumentSettings documentSettings(m_doc->url().url());
153 documentSettings.setKeyboardLayoutColumn(section, value.toString());
154 documentSettings.save();
155 }
156
157 Q_EMIT headerDataChanged(orientation, section, section);
158 return true;
159 }
160 return false;
161 }
162
163
insertRows(int row,int count,const QModelIndex & parent)164 bool KWQTableModel::insertRows(int row, int count, const QModelIndex & parent)
165 {
166 Q_UNUSED(parent);
167 if (count < 1 || row < 0 || row > m_doc->lesson()->entryCount(KEduVocLesson::Recursive))
168 return false;
169
170 KEduVocLesson * cl = currentLesson(row);
171
172 beginInsertRows(QModelIndex(), row, row + count - 1);
173
174 for (int i = row; i < row + count; i++)
175 cl->insertEntry(i, new KEduVocExpression); //m_doc->lesson()->insertEntry(i, new KEduVocExpression);
176
177 endInsertRows();
178 m_doc->setModified(true);
179 return true;
180 }
181
removeRows(int row,int count,const QModelIndex & parent)182 bool KWQTableModel::removeRows(int row, int count, const QModelIndex & parent)
183 {
184 Q_UNUSED(parent);
185 if (count < 1 || row < 0 || row + count > m_doc->lesson()->entryCount(KEduVocLesson::Recursive) || count >= m_doc->lesson()->entryCount(KEduVocLesson::Recursive))
186 return false;
187
188 int bottomRow = row + count -1;
189 beginRemoveRows(QModelIndex(), row, row + count - 1);
190
191 for (int i = bottomRow; i >= row; i--) {
192 KEduVocExpression* entry = m_doc->lesson()->entries(KEduVocLesson::Recursive).value(i);
193 entry->lesson()->removeEntry(entry);
194 delete entry;
195 }
196
197 endRemoveRows();
198 m_doc->setModified(true);
199 return true;
200 }
201
setDocument(KEduVocDocument * doc)202 void KWQTableModel::setDocument(KEduVocDocument * doc)
203 {
204 beginResetModel();
205 m_doc = doc;
206 endResetModel();
207 }
208
isEmpty()209 bool KWQTableModel::isEmpty()
210 {
211 if (m_doc->url().fileName() == i18n("Untitled")){
212 int rc = rowCount(QModelIndex());
213 for (int i = 0; i < rc; i++)
214 if (!data(index(i, 0), Qt::DisplayRole).toString().isEmpty() || !data(index(i, 1), Qt::DisplayRole).toString().isEmpty())
215 return false;
216
217 return true;
218 }
219 else
220 return false;
221 }
222
223
checkBlanksSyntax(const QString & text) const224 bool KWQTableModel::checkBlanksSyntax(const QString & text) const
225 {
226 if (!Prefs::enableBlanks())
227 return true;
228
229 bool result = false;
230 int openCount = 0;
231 int closeCount = 0;
232 QVector<int> openPos(0);
233 QVector<int> closePos(0);
234
235 for (int i = 0; i< text.length(); ++i)
236 {
237 if (text[i] == delim_start)
238 {
239 openCount++;
240 openPos.resize(openCount);
241 openPos[openCount - 1] = i;
242 }
243
244 if (text[i] == delim_end)
245 {
246 closeCount++;
247 closePos.resize(closeCount);
248 closePos[closeCount - 1] = i;
249 }
250 }
251
252 if (openCount == 0 && closeCount == 0)
253 return true;
254
255 if (openCount > 0 && closeCount > 0)
256 if (openPos.size() == closePos.size())
257 for (int i = 0; i < openPos.size(); ++i)
258 result = (openPos[i] < closePos[i]);
259
260 return result;
261 }
262
checkSyntax() const263 bool KWQTableModel::checkSyntax() const
264 {
265 int errorCount = 0;
266
267 for (int r = 0; r < rowCount(QModelIndex()); ++r)
268 {
269 QString s = data(index(r, 0, QModelIndex()), Qt::DisplayRole).toString();
270 if (s.length() > 0)
271 for (int i = 0; i <= s.length(); ++i)
272 if (s[i] == delim_start || s[i] == delim_end)
273 if (!checkBlanksSyntax(s))
274 errorCount++;
275 s = data(index(r, 1, QModelIndex()), Qt::DisplayRole).toString();
276 if (s.length() > 0)
277 for (int i = 0; i <= s.length(); ++i)
278 if (s[i] == delim_start || s[i] == delim_end)
279 if (!checkBlanksSyntax(s))
280 errorCount++;
281 }
282
283 return (errorCount == 0);
284 }
285
currentLesson(int row)286 KEduVocLesson * KWQTableModel::currentLesson(int row)
287 {
288 int i = 0;
289 QList<KEduVocContainer *> lessons = m_doc->lesson()->childContainers();
290 foreach(KEduVocContainer * c, lessons) {
291 if (c->containerType() == KEduVocLesson::Lesson) {
292 i += c->entryCount();
293 if (i >= row)
294 return static_cast<KEduVocLesson *>(c);
295 }
296 }
297 return m_doc->lesson();
298 }
299