File indexing completed on 2023-05-30 10:45:26

0001 /*
0002     SPDX-FileCopyrightText: 2006-2010 Peter Hedlund <peter.hedlund@kdemail.net>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "kwqtablemodel.h"
0007 
0008 #include <KLocalizedString>
0009 
0010 #include "prefs.h"
0011 #include "documentsettings.h"
0012 #include "keduvocexpression.h"
0013 
0014 KWQTableModel::KWQTableModel(QObject * parent) : QAbstractTableModel(parent)
0015 {
0016   m_doc = 0;
0017   m_decorationCache = new KImageCache(QStringLiteral("kwordquiz"), 10485760);
0018 }
0019 
0020 KWQTableModel::~KWQTableModel()
0021 {
0022   delete m_decorationCache;
0023 }
0024 
0025 int KWQTableModel::rowCount(const QModelIndex & parent) const
0026 {
0027   if (parent.isValid())
0028     return 0;
0029   return m_doc->lesson()->entryCount(KEduVocLesson::Recursive);
0030 }
0031 
0032 int KWQTableModel::columnCount(const QModelIndex & parent) const
0033 {
0034   if (parent.isValid())
0035     return 0;
0036   return 2;
0037 }
0038 
0039 QVariant KWQTableModel::data(const QModelIndex & index, int role) const
0040 {
0041   if (!index.isValid())
0042     return QVariant();
0043 
0044   QPixmap ip;
0045   QString image;
0046 
0047   switch (role) {
0048     case Qt::FontRole:
0049       return QVariant(Prefs::editorFont());
0050 
0051     case Qt::DisplayRole:
0052       return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->text();
0053 
0054     case Qt::DecorationRole:
0055       image = m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->imageUrl().toLocalFile();
0056       if (!image.isEmpty()) {
0057         if (!m_decorationCache->findPixmap(image, &ip)) {
0058           ip = QPixmap(image).scaled(QSize(22, 22), Qt::KeepAspectRatio);
0059           m_decorationCache->insertPixmap(image, ip);
0060         }
0061       }
0062       return ip;
0063 
0064     case KWQTableModel::ImageRole:
0065       return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->imageUrl().toLocalFile();
0066 
0067     case KWQTableModel::SoundRole:
0068       return m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->soundUrl().toLocalFile();
0069 
0070     default:
0071       return QVariant();
0072   }
0073 }
0074 
0075 QVariant KWQTableModel::headerData(int section, Qt::Orientation orientation, int role) const
0076 {
0077   if (orientation == Qt::Horizontal)
0078   {
0079     if (section < 0 || section > 1)
0080       return QVariant();
0081 
0082     if (role == Qt::DisplayRole) {
0083       return m_doc->identifier(section).name();
0084     }
0085 
0086     if (role == Qt::SizeHintRole) {
0087       DocumentSettings documentSettings(m_doc->url().url());
0088       documentSettings.read();
0089       return QSize(documentSettings.sizeHintColumn(section), 25);
0090     }
0091 
0092     if (role == KWQTableModel::KeyboardLayoutRole) {
0093       DocumentSettings documentSettings(m_doc->url().url());
0094       documentSettings.read();
0095       return documentSettings.keyboardLayoutColumn(section);
0096     }
0097 
0098     return QVariant();
0099   }
0100   else
0101     return QAbstractTableModel::headerData(section, orientation, role);
0102 }
0103 
0104 Qt::ItemFlags KWQTableModel::flags(const QModelIndex & index) const
0105 {
0106   if (!index.isValid())
0107     return Qt::ItemIsEnabled;
0108 
0109   return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
0110 }
0111 
0112 bool KWQTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
0113 {
0114   if (!index.isValid())
0115     return false;
0116 
0117   switch (role) {
0118     case Qt::EditRole:
0119       m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->setTranslation(index.column(), value.toString());
0120       break;
0121 
0122     case KWQTableModel::ImageRole:
0123       m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->setImageUrl(value.toUrl());
0124       break;
0125 
0126     case KWQTableModel::SoundRole:
0127       m_doc->lesson()->entries(KEduVocLesson::Recursive).value(index.row())->translation(index.column())->setSoundUrl(value.toUrl());
0128       break;
0129   }
0130 
0131   Q_EMIT dataChanged(index, index);
0132   return true;
0133 }
0134 
0135 bool KWQTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role)
0136 {
0137   if (orientation == Qt::Horizontal) {
0138     if (section < 0 || section > 1)
0139       return false;
0140 
0141     if (role == Qt::EditRole) {
0142       m_doc->identifier(section).setName(value.toString());
0143     }
0144 
0145     if (role == Qt::SizeHintRole) {
0146       DocumentSettings documentSettings(m_doc->url().url());
0147       documentSettings.setSizeHintColumn(section, qvariant_cast<QSize>(value).width());
0148       documentSettings.save();
0149     }
0150 
0151     if (role == KWQTableModel::KeyboardLayoutRole) {
0152       DocumentSettings documentSettings(m_doc->url().url());
0153       documentSettings.setKeyboardLayoutColumn(section, value.toString());
0154       documentSettings.save();
0155     }
0156 
0157     Q_EMIT headerDataChanged(orientation, section, section);
0158     return true;
0159   }
0160   return false;
0161 }
0162 
0163 
0164 bool KWQTableModel::insertRows(int row, int count, const QModelIndex & parent)
0165 {
0166   Q_UNUSED(parent);
0167   if (count < 1 || row < 0 || row > m_doc->lesson()->entryCount(KEduVocLesson::Recursive))
0168     return false;
0169 
0170   KEduVocLesson * cl = currentLesson(row);
0171 
0172   beginInsertRows(QModelIndex(), row, row + count - 1);
0173 
0174   for (int i = row; i < row + count; i++)
0175     cl->insertEntry(i, new KEduVocExpression); //m_doc->lesson()->insertEntry(i, new KEduVocExpression);
0176 
0177   endInsertRows();
0178   m_doc->setModified(true);
0179   return true;
0180 }
0181 
0182 bool KWQTableModel::removeRows(int row, int count, const QModelIndex & parent)
0183 {
0184   Q_UNUSED(parent);
0185   if (count < 1 || row < 0 || row + count > m_doc->lesson()->entryCount(KEduVocLesson::Recursive) || count >= m_doc->lesson()->entryCount(KEduVocLesson::Recursive))
0186     return false;
0187 
0188   int bottomRow = row + count -1;
0189   beginRemoveRows(QModelIndex(), row, row + count - 1);
0190 
0191   for (int i = bottomRow; i >= row; i--) {
0192     KEduVocExpression* entry = m_doc->lesson()->entries(KEduVocLesson::Recursive).value(i);
0193     entry->lesson()->removeEntry(entry);
0194     delete entry;
0195   }
0196 
0197   endRemoveRows();
0198   m_doc->setModified(true);
0199   return true;
0200 }
0201 
0202 void KWQTableModel::setDocument(KEduVocDocument * doc)
0203 {
0204   beginResetModel();
0205   m_doc = doc;
0206   endResetModel();
0207 }
0208 
0209 bool KWQTableModel::isEmpty()
0210 {
0211   if (m_doc->url().fileName() == i18n("Untitled")){
0212     int rc = rowCount(QModelIndex());
0213     for (int i = 0; i < rc; i++)
0214       if (!data(index(i, 0), Qt::DisplayRole).toString().isEmpty() || !data(index(i, 1), Qt::DisplayRole).toString().isEmpty())
0215         return false;
0216 
0217     return true;
0218   }
0219   else
0220     return false;
0221 }
0222 
0223 
0224 bool KWQTableModel::checkBlanksSyntax(const QString & text) const
0225 {
0226   if (!Prefs::enableBlanks())
0227     return true;
0228 
0229   bool result = false;
0230   int openCount = 0;
0231   int closeCount = 0;
0232   QVector<int> openPos(0);
0233   QVector<int> closePos(0);
0234 
0235   for (int i = 0; i< text.length(); ++i)
0236   {
0237     if (text[i] == delim_start)
0238     {
0239       openCount++;
0240       openPos.resize(openCount);
0241       openPos[openCount - 1] = i;
0242     }
0243 
0244     if (text[i] == delim_end)
0245     {
0246       closeCount++;
0247       closePos.resize(closeCount);
0248       closePos[closeCount - 1] = i;
0249     }
0250   }
0251 
0252   if (openCount == 0 && closeCount == 0)
0253     return true;
0254 
0255   if (openCount > 0 && closeCount > 0)
0256     if (openPos.size() == closePos.size())
0257       for (int i = 0; i < openPos.size(); ++i)
0258         result = (openPos[i] < closePos[i]);
0259 
0260   return result;
0261 }
0262 
0263 bool KWQTableModel::checkSyntax() const
0264 {
0265   int errorCount = 0;
0266 
0267   for (int r = 0; r < rowCount(QModelIndex()); ++r)
0268   {
0269     QString s = data(index(r, 0, QModelIndex()), Qt::DisplayRole).toString();
0270     if (s.length() > 0)
0271       for (int i = 0; i <= s.length(); ++i)
0272         if (s[i] == delim_start || s[i] == delim_end)
0273           if (!checkBlanksSyntax(s))
0274             errorCount++;
0275     s = data(index(r, 1, QModelIndex()), Qt::DisplayRole).toString();
0276     if (s.length() > 0)
0277       for (int i = 0; i <= s.length(); ++i)
0278         if (s[i] == delim_start || s[i] == delim_end)
0279           if (!checkBlanksSyntax(s))
0280             errorCount++;
0281   }
0282 
0283   return (errorCount == 0);
0284 }
0285 
0286 KEduVocLesson * KWQTableModel::currentLesson(int row)
0287 {
0288   int i = 0;
0289   QList<KEduVocContainer *>  lessons = m_doc->lesson()->childContainers();
0290   foreach(KEduVocContainer * c, lessons) {
0291     if (c->containerType() == KEduVocLesson::Lesson) {
0292       i += c->entryCount();
0293       if (i >= row)
0294         return static_cast<KEduVocLesson *>(c);
0295     }
0296   }
0297   return m_doc->lesson();
0298 }