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

0001 /*
0002     SPDX-FileCopyrightText: 2002-2010 Peter Hedlund <peter.hedlund@kdemail.net>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "kwqtableview.h"
0007 
0008 #include <QAbstractTextDocumentLayout>
0009 #include <QApplication>
0010 #include <QDBusInterface>
0011 #include <QDebug>
0012 #include <QFile>
0013 #include <QFileDialog>
0014 #include <QHeaderView>
0015 #include <QImageReader>
0016 #include <QLineEdit>
0017 #include <QList>
0018 #include <QPointer>
0019 #include <QPrintDialog>
0020 #include <QPrintPreviewDialog>
0021 #include <QPrinter>
0022 #include <QTextCursor>
0023 #include <QTextTable>
0024 
0025 #include <KLocalizedString>
0026 #include <KNotification>
0027 
0028 #include "kwqtablemodel.h"
0029 #include "keduvocdocument.h"
0030 #include "kwordquiz.h"
0031 #include "prefs.h"
0032 #include "kwqcommands.h"
0033 #include "kwqcleardialog.h"
0034 #include "kwordquiz_version.h"
0035 
0036 //krazy:excludeall=qclasses
0037 
0038 KWQTableView::KWQTableView(QUndoStack *undoStack, QWidget *parent)
0039     : QTableView(parent)
0040     , m_undoStack(undoStack)
0041 {
0042   m_model = 0;
0043 
0044   setSelectionMode(QAbstractItemView::ContiguousSelection);
0045   setSelectionBehavior(QAbstractItemView::SelectItems);
0046   setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked);
0047   setTabKeyNavigation(true);
0048   connect(horizontalHeader(), &QHeaderView::sectionResized, this, &KWQTableView::horizontalHeaderResized);
0049   connect(horizontalHeader(), &QHeaderView::sectionClicked, this, &KWQTableView::slotHeaderClicked);
0050   m_delegate = new KWQTableDelegate(this);
0051   setItemDelegate(m_delegate);
0052 
0053   setSortingEnabled(true);
0054   horizontalHeader()->setSortIndicatorShown(false);
0055   setWordWrap(true);
0056 
0057 }
0058 
0059 void KWQTableView::doPrint()
0060 {
0061   QPrinter printer;
0062 
0063   WQPrintDialogPage * p = new WQPrintDialogPage(this);
0064   p->setPrintStyle(Prefs::printStyle());
0065   QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, this);
0066   printDialog->setOptionTabs(QList<QWidget*>() << p);
0067   if (printDialog->exec() == QDialog::Accepted) {
0068     Prefs::setPrintStyle(p->printStyle());
0069     QTextDocument td;
0070     createPages(&printer, &td, true);
0071   }
0072   delete printDialog;
0073 }
0074 
0075 void KWQTableView::doPrintPreview()
0076 {
0077   QPrinter printer;
0078   QPrintPreviewDialog preview(&printer);
0079   
0080   connect(&preview, &QPrintPreviewDialog::paintRequested, this, &KWQTableView::slotPrintPreviewRequested);
0081   
0082   preview.exec();
0083 }
0084 
0085 void KWQTableView::slotPrintPreviewRequested(QPrinter* printer)
0086 {
0087   QTextDocument td;
0088   KWQTableView::createPages(printer, &td, true);
0089 }
0090 
0091 bool KWQTableView::doHtmlExport(const QUrl &url)
0092 {
0093   bool success = false;
0094 
0095   QUrl tmp(url);
0096   QFile data(tmp.path());
0097   if (data.open(QFile::WriteOnly)) {
0098     QPrinter printer;
0099     QTextDocument td;
0100     td.setMetaInformation(QTextDocument::DocumentTitle, model()->sourceModel()->document()->title());
0101     QTextStream out(&data);
0102 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0103     out.setCodec("utf-8");
0104 #endif
0105     createPages(&printer, &td, false);
0106 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0107     out << td.toHtml("utf-8");
0108 #else
0109     out << td.toHtml();
0110 #endif
0111     data.close();
0112     success = true;
0113   }
0114   return success;
0115 }
0116 
0117 void KWQTableView::createPages(QPrinter *printer, QTextDocument *textDoc, bool sendToPrinter)
0118 {
0119   printer->setFullPage(true);
0120   int myDpi = printer->logicalDpiY();
0121 
0122   if (Prefs::printStyle() == Prefs::EnumPrintStyle::Flashcard) {
0123     printer->setPageOrientation(QPageLayout::Landscape);
0124 
0125     int cardWidth = qRound(5 * qreal(myDpi));
0126     int cardHeight = qRound(3 * qreal(myDpi));
0127 
0128     QTextTable *table = textDoc->rootFrame()->lastCursorPosition().insertTable(model()->rowCount(), 2);
0129 
0130     QTextTableFormat tableFormat = table->format();
0131     tableFormat.setHeaderRowCount(0);
0132     tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_None);
0133     tableFormat.setCellSpacing(0);
0134     tableFormat.setCellPadding(0);
0135 
0136     QVector<QTextLength> constraints;
0137     constraints.append(QTextLength(QTextLength::FixedLength, cardWidth));
0138     constraints.append(QTextLength(QTextLength::FixedLength, cardWidth));
0139 
0140     tableFormat.setColumnWidthConstraints(constraints);
0141     table->setFormat(tableFormat);
0142 
0143     QTextBlockFormat headerFormat;
0144     headerFormat.setAlignment(Qt::AlignLeft);
0145 
0146     QTextCharFormat headerCharFormat;
0147     headerCharFormat.setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont));
0148 
0149     QTextBlockFormat cellFormat;
0150     cellFormat.setAlignment(Qt::AlignCenter);
0151 
0152     QTextCharFormat cellCharFormat;
0153     cellCharFormat.setFont(Prefs::editorFont());
0154 
0155     QTextFrameFormat cardFormat;
0156     cardFormat.setBorder(1);
0157     cardFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
0158     cardFormat.setBorderBrush(QBrush(Qt::black));
0159     cardFormat.setWidth(QTextLength(QTextLength::FixedLength, cardWidth));
0160     cardFormat.setHeight(QTextLength(QTextLength::FixedLength, cardHeight));
0161     cardFormat.setPadding(qRound(0.25 * myDpi));
0162 
0163     QTextFrameFormat lineFormat;
0164     lineFormat.setBorder(1);
0165     lineFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
0166     lineFormat.setBorderBrush(QBrush(Qt::black));
0167     lineFormat.setWidth(QTextLength(QTextLength::FixedLength, qRound(4.5 * myDpi)));
0168     lineFormat.setHeight(1.1); //1 is drawn as a box whereas this is drawn as a line. Strange...
0169     lineFormat.setPadding(0);
0170 
0171     QTextFrame *card;
0172     for (int i = 0; i < model()->rowCount(); i++) {
0173       for (int j = 0; j < model()->columnCount(); j++) {
0174         cardFormat.setPosition(QTextFrameFormat::FloatLeft);
0175         card = table->cellAt(i, j).firstCursorPosition().insertFrame(cardFormat);
0176         card->lastCursorPosition().insertText(model()->headerData(j, Qt::Horizontal, Qt::DisplayRole).toString(), headerCharFormat);
0177         card->lastCursorPosition().insertFrame(lineFormat);
0178         card->lastCursorPosition().insertBlock();
0179         card->lastCursorPosition().insertBlock();
0180         card->lastCursorPosition().insertBlock(cellFormat, cellCharFormat);
0181         card->lastCursorPosition().insertText(model()->data(model()->index(i, j)).toString(), cellCharFormat);
0182       }
0183     }
0184   }
0185   else
0186   {
0187     textDoc->rootFrame()->lastCursorPosition().insertText(QStringLiteral("kwordquiz %1").arg(KWORDQUIZ_VERSION_STRING));
0188 
0189     if (Prefs::printStyle() == Prefs::EnumPrintStyle::Exam)
0190       textDoc->rootFrame()->lastCursorPosition().insertText(' ' + i18n("Name:_____________________________ Date:__________"));
0191 
0192     QTextTable* table;
0193     if (Prefs::printStyle() == Prefs::EnumPrintStyle::Exam)
0194       table = textDoc->rootFrame()->lastCursorPosition().insertTable(model()->rowCount() + 1, model()->columnCount() + 2);
0195     else
0196       table = textDoc->rootFrame()->lastCursorPosition().insertTable(model()->rowCount() + 1, model()->columnCount() + 1);
0197 
0198     QTextTableFormat tableFormat = table->format();
0199     tableFormat.setHeaderRowCount(1);
0200     tableFormat.setBorder(1);
0201     tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
0202     tableFormat.setCellSpacing(0);
0203     tableFormat.setBorderBrush(QBrush(Qt::black));
0204     tableFormat.setCellPadding(2);
0205 
0206     QVector<QTextLength> constraints;
0207     constraints.append(QTextLength(QTextLength::FixedLength, verticalHeader()->width()));
0208     constraints.append(QTextLength(QTextLength::FixedLength, columnWidth(0)));
0209     constraints.append(QTextLength(QTextLength::FixedLength, columnWidth(1)));
0210     if (Prefs::printStyle() == Prefs::EnumPrintStyle::Exam)
0211         constraints.append(QTextLength(QTextLength::FixedLength, 50));
0212     tableFormat.setColumnWidthConstraints(constraints);
0213 
0214     table->setFormat(tableFormat);
0215 
0216     QTextBlockFormat headerFormat;
0217     headerFormat.setAlignment(Qt::AlignHCenter);
0218 
0219     QTextCharFormat headerCharFormat;
0220     headerCharFormat.setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont));
0221 
0222     QTextCursor cellCursor;
0223     cellCursor = table->cellAt(0, 1).firstCursorPosition();
0224     cellCursor.mergeBlockFormat(headerFormat);
0225     cellCursor.mergeCharFormat(headerCharFormat);
0226     cellCursor.insertText(model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString());
0227 
0228     cellCursor = table->cellAt(0, 2).firstCursorPosition();
0229     cellCursor.mergeBlockFormat(headerFormat);
0230     cellCursor.mergeCharFormat(headerCharFormat);
0231     cellCursor.insertText(model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString());
0232 
0233     if (Prefs::printStyle() == Prefs::EnumPrintStyle::Exam) {
0234       cellCursor = table->cellAt(0, 3).firstCursorPosition();
0235       cellCursor.mergeBlockFormat(headerFormat);
0236       cellCursor.mergeCharFormat(headerCharFormat);
0237       cellCursor.insertText(i18n("Score"));
0238     }
0239 
0240     headerCharFormat = cellCursor.charFormat();
0241     QTextCharFormat cellCharFormat = cellCursor.charFormat();
0242     cellCharFormat.setFont(Prefs::editorFont());
0243 
0244     for (int i = 0; i < model()->rowCount(); i++) {
0245       table->cellAt(i + 1, 0).firstCursorPosition().insertText(model()->headerData(i, Qt::Vertical, Qt::DisplayRole).toString(), headerCharFormat);
0246       table->cellAt(i + 1, 1).firstCursorPosition().insertText(model()->data(model()->index(i, 0)).toString(), cellCharFormat);
0247       if (Prefs::printStyle() == Prefs::EnumPrintStyle::List)
0248         table->cellAt(i + 1, 2).firstCursorPosition().insertText(model()->data(model()->index(i, 1)).toString(), cellCharFormat);
0249     }
0250   }
0251 
0252   if (sendToPrinter)
0253     textDoc->print(printer);
0254 }
0255 
0256 
0257 void KWQTableView::doEditCut()
0258 {
0259   if (state() == QAbstractItemView::EditingState)
0260   {
0261     if (QApplication::focusWidget())
0262     {
0263       QLineEdit *lineEdit = static_cast<QLineEdit*>(QApplication::focusWidget());
0264       lineEdit->cut();
0265     }
0266   }
0267   else
0268   {
0269     KWQCommandCut *kwqc = new KWQCommandCut(this);
0270     m_undoStack->push(kwqc);
0271   }
0272 }
0273 
0274 void KWQTableView::doEditCopy()
0275 {
0276   if (state() == QAbstractItemView::EditingState)
0277   {
0278     if (QApplication::focusWidget())
0279     {
0280       QLineEdit *lineEdit = static_cast<QLineEdit*>(QApplication::focusWidget());
0281       lineEdit->copy();
0282     }
0283   }
0284   else
0285   {
0286     copyToClipboard(this);
0287   }
0288 }
0289 
0290 void KWQTableView::doEditPaste()
0291 {
0292   if (state() == QAbstractItemView::EditingState)
0293   {
0294     if (QApplication::focusWidget())
0295     {
0296       QLineEdit *lineEdit = static_cast<QLineEdit*>(QApplication::focusWidget());
0297       lineEdit->paste();
0298     }
0299   }
0300   else
0301   {
0302     KWQCommandPaste *kwqc = new KWQCommandPaste(this);
0303     m_undoStack->push(kwqc);
0304   }
0305 }
0306 
0307 void KWQTableView::doEditClear()
0308 {
0309   if (state() == QAbstractItemView::EditingState)
0310   {
0311     if (QApplication::focusWidget())
0312     {
0313       QLineEdit *lineEdit = static_cast<QLineEdit*>(QApplication::focusWidget());
0314       lineEdit->clear();
0315     }
0316   }
0317   else
0318   {
0319     if (selectionHasMoreThanText()) {
0320       QPointer<KWQClearDialog> clearDialog = new KWQClearDialog(this);
0321       if (clearDialog->exec() == QDialog::Rejected) {
0322         delete clearDialog;
0323         return;
0324       }
0325       delete clearDialog;
0326     }
0327     else
0328     {
0329       Prefs::setClearAll(false);
0330       Prefs::setClearText(true);
0331       Prefs::setClearImageLink(false);
0332       Prefs::setClearSoundLink(false);
0333     }
0334     KWQCommandClear *kwqc = new KWQCommandClear(this);
0335     m_undoStack->push(kwqc);
0336   }
0337 }
0338 
0339 void KWQTableView::doEditInsert()
0340 {
0341   if (selectionModel()->currentIndex().isValid()) {
0342     KWQCommandInsert *kwqc = new KWQCommandInsert(this);
0343     m_undoStack->push(kwqc);
0344   }
0345 }
0346 
0347 void KWQTableView::doEditDelete()
0348 {
0349   if (selectionModel()->currentIndex().isValid()) {
0350     KWQCommandDelete *kwqc = new KWQCommandDelete(this);
0351     m_undoStack->push(kwqc);
0352   }
0353 }
0354 
0355 
0356 void KWQTableView::doEditMarkBlank()
0357 {
0358   if (state() == QAbstractItemView::EditingState)
0359   {
0360     if (QApplication::focusWidget())
0361     {
0362       QLineEdit *l = static_cast<QLineEdit*>(QApplication::focusWidget());
0363       if (l->text().length() > 0)
0364       {
0365         QString s = l->text();
0366         int cp = l->cursorPosition();
0367         if (!l->hasSelectedText())
0368         {
0369           if (!s[cp].isSpace() && !s[cp - 1].isSpace())
0370           {
0371             l->cursorWordBackward(false);
0372             int cp1 = l->cursorPosition();
0373             l->cursorWordForward(false);
0374             if (l->cursorPosition() != (int) s.length())
0375             {  while(l->text()[l->cursorPosition()].isSpace())
0376                 l->cursorBackward(false, 1);
0377             }
0378             int cp2 = l->cursorPosition();
0379             if (cp2 == (int) s.length())
0380               l->setSelection(cp1, cp2 - cp1);
0381             else
0382               l->setSelection(cp1, cp2 - cp1 - 1);
0383 
0384           }
0385           else
0386             return;
0387         }
0388 
0389         if (l->hasSelectedText())
0390         {
0391           QString st = l->selectedText();
0392           int len = st.length();
0393           st = st.prepend(delim_start);
0394           st = st.append(delim_end);
0395           int ss = l->selectionStart();
0396           s = s.replace(ss, len, st);
0397           l->setText(s);
0398           l->setSelection(ss, st.length());
0399         }
0400       }
0401     }
0402   }
0403 }
0404 
0405 void KWQTableView::doEditUnmarkBlank()
0406 {
0407   QString s;
0408 
0409   if (state() == QAbstractItemView::EditingState)
0410   {
0411     if (QApplication::focusWidget())
0412     {
0413       QLineEdit *l = static_cast<QLineEdit*>(QApplication::focusWidget());
0414       if (l->hasSelectedText())
0415       {
0416         QString ls = l->text();
0417         s = l->selectedText();
0418         int len = s.length();
0419         s.remove(delim_start);
0420         s.remove(delim_end);
0421         int ss = l->selectionStart();
0422         ls = ls.replace(ss, len, s);
0423         l->setText(ls);
0424         l->setSelection(ss, s.length());
0425       }
0426       else
0427       {
0428         if (l->text().length() > 0)
0429         {
0430           s = l->text();
0431           int cs = l->cursorPosition();
0432 
0433           int fr = s.lastIndexOf(delim_start, cs);
0434           if (fr > 0)
0435           {
0436             s = s.replace(fr, 1, QLatin1String(""));
0437             cs--;
0438           }
0439           int ff = s.indexOf(delim_end, cs);
0440           if (ff > 0)
0441             s = s.replace(ff, 1, QLatin1String(""));
0442 
0443           l->setText(s);
0444           l->setCursorPosition(cs);
0445         }
0446       }
0447     }
0448   }
0449   else
0450   {
0451     KWQCommandUnmarkBlank *kwqc = new KWQCommandUnmarkBlank(this);
0452     m_undoStack->push(kwqc);
0453   }
0454 }
0455 
0456 
0457 void KWQTableView::slotSpecChar(const QChar & c)
0458 {
0459   if (state() == QAbstractItemView::EditingState)
0460   {
0461     if (QApplication::focusWidget())
0462     {
0463       QLineEdit *l = static_cast<QLineEdit*>(QApplication::focusWidget());
0464       if (l->hasSelectedText())
0465       {
0466         QString ls = l->text();
0467         QString s = l->selectedText();
0468         int len = s.length();
0469         int ss = l->selectionStart();
0470         ls = ls.replace(ss, len, c);
0471         l->setText(ls);
0472         l->setSelection(ss, 1);
0473       }
0474       else
0475       {
0476         QString s = l->text();
0477         int i = l->cursorPosition();
0478         s.insert(i, c);
0479         l->setText(s);
0480         l->setCursorPosition(i + 1);
0481       }
0482     }
0483   }
0484   else
0485   {
0486     edit(currentIndex());
0487     if (QApplication::focusWidget())
0488     {
0489       QLineEdit *l = static_cast<QLineEdit*>(QApplication::focusWidget());
0490       l->setText(QString(c));
0491       l->setCursorPosition(1);
0492     }
0493   }
0494 }
0495 
0496 void KWQTableView::nextCell()
0497 {
0498   QItemSelectionModel * selModel = selectionModel();
0499   QModelIndexList indexes = selModel->selectedIndexes();
0500   QModelIndex currentIndex = selModel->currentIndex();
0501 
0502   int currentRow = currentIndex.row();
0503   int currentColumn = currentIndex.column();
0504   int newRow = currentRow;
0505   int newColumn = currentColumn;
0506 
0507   if (indexes.count() == 1) //one cell selected
0508   {
0509     switch(Prefs::enterMove())
0510     {
0511      case 0: //down
0512         if (currentRow == (model()->rowCount() - 1))
0513         {
0514           model()->insertRows(model()->rowCount(), 1, QModelIndex());
0515           newRow++;
0516         } else
0517           newRow++;
0518         break;
0519 
0520      case 1: //right
0521         if (currentRow == (model()->rowCount() - 1) && currentColumn == 1)
0522         {
0523           model()->insertRows(model()->rowCount(), 1, QModelIndex());
0524           newRow++;
0525           newColumn = 0;
0526         } else {
0527           if (currentColumn == 0)
0528             newColumn++;
0529           else {
0530             newRow++;
0531             newColumn--;
0532           }
0533         }
0534         break;
0535 
0536       case 2: //no move
0537         //do nothing
0538         break;
0539 
0540     }
0541 
0542     QModelIndex newIndex = model()->index(newRow, newColumn);
0543     selModel->clear();
0544     selModel->setCurrentIndex(newIndex, QItemSelectionModel::SelectCurrent);
0545   }
0546   else if (indexes.count() > 1) //a larger selection, move within it
0547   {
0548     QModelIndex topLeft = indexes.first();
0549     QModelIndex bottomRight = indexes.last();
0550 
0551     int tr = topLeft.row();
0552     int lc = topLeft.column();
0553     int br = bottomRight.row();
0554     int rc = bottomRight.column();
0555 
0556     switch(Prefs::enterMove())
0557     {
0558       case 0:
0559         if (currentRow == br)
0560         {
0561           newRow = tr;
0562           if (currentColumn < rc)
0563             newColumn = rc;
0564           else
0565             newColumn = lc;
0566         }
0567         else
0568           if (currentRow < br)
0569             newRow++;
0570         break;
0571       case 1:
0572         if (currentColumn == rc)
0573         {
0574           newColumn = lc;
0575           if (currentRow < br)
0576             newRow++;
0577           else
0578             newRow = tr;
0579         }
0580         else
0581           newColumn++;
0582         break;
0583       case 2:
0584         //do nothing
0585         break;
0586     }
0587 
0588     QModelIndex newIndex = model()->index(newRow, newColumn);
0589     selModel->setCurrentIndex(newIndex, QItemSelectionModel::Current);
0590   }
0591 
0592   if (newColumn != currentColumn)
0593     updateKeyboardLayout();
0594 }
0595 
0596 void KWQTableView::keyPressEvent(QKeyEvent * e)
0597 {
0598   if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)
0599   {
0600     e->accept();
0601     if (state() != QAbstractItemView::EditingState)
0602       nextCell();
0603     return;
0604   }
0605   QTableView::keyPressEvent(e);
0606 }
0607 
0608 void KWQTableView::slotCheckedAnswer(int i)
0609 {
0610   if (i == -1)
0611   {
0612     QModelIndex current = currentIndex();
0613     selectionModel()->clear();
0614     setCurrentIndex(current);
0615   }
0616   else
0617   {
0618     selectionModel()->clear();
0619     setCurrentIndex(model()->index(i, 0));
0620     selectRow(i);
0621   }
0622 }
0623 
0624 void KWQTableView::setFilterModel(KWQSortFilterModel *model)
0625 {
0626   QTableView::setModel(model);
0627   m_model = model;
0628   setCurrentIndex(model->index(0, 0));
0629   scrollTo(currentIndex());
0630   connect(verticalHeader(), &QHeaderView::sectionResized, this, &KWQTableView::verticalHeaderResized);
0631   connect(horizontalHeader(), &QHeaderView::sectionResized, this, &KWQTableView::horizontalHeaderResized);
0632   connect(m_model, &QAbstractItemModel::headerDataChanged, this, &KWQTableView::horizontalHeaderDataChanged);
0633 }
0634 
0635 void KWQTableView::closeEditor(QWidget * editor, QAbstractItemDelegate::EndEditHint hint)
0636 {
0637   QTableView::closeEditor(editor, hint);
0638   if (hint == QAbstractItemDelegate::SubmitModelCache) {
0639     adjustRow(currentIndex().row());
0640     nextCell();
0641   }
0642 }
0643 
0644 void KWQTableView::commitData(QWidget * editor)
0645 {
0646   QString currentText = model()->data(currentIndex(), Qt::DisplayRole).toString();
0647   QLineEdit *l = static_cast<QLineEdit*>(editor);
0648   QString newText = l->text();
0649   if (newText != currentText) {
0650     KWQCommandEntry *kwqc = new KWQCommandEntry(this, currentText, newText);
0651     m_undoStack->push(kwqc);
0652   }
0653   if (!newText.isEmpty()) {
0654     if (Prefs::enableBlanks())
0655       if (!m_model->sourceModel()->checkBlanksSyntax(newText) /*checkForBlank(newText, true)*/)
0656         KNotification::event(QStringLiteral("SyntaxError"), i18n("There is an error with the Fill-in-the-blank brackets"));
0657   }
0658   QTableView::commitData(editor);
0659 }
0660 
0661 void KWQTableView::adjustRow(int row)
0662 {
0663   // we want to make the row high enough to display content, but
0664   // if the user already made it even higher we keep that height
0665   //int r = currentIndex().row();
0666   int rh = rowHeight(row);
0667   resizeRowToContents(row);
0668   if (rh > rowHeight(row))
0669     setRowHeight(row, rh);
0670 }
0671 
0672 
0673 void KWQTableView::verticalHeaderResized(int , int , int)
0674 {
0675   //qDebug() << "Row resized\n";
0676 }
0677 
0678 void KWQTableView::horizontalHeaderResized(int logicalIndex, int oldSize, int newSize)
0679 {
0680   Q_UNUSED(oldSize);
0681   model()->setHeaderData(logicalIndex, Qt::Horizontal, QSize(newSize, 25), Qt::SizeHintRole);
0682 }
0683 
0684 void KWQTableView::horizontalHeaderDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast)
0685 {
0686     Q_UNUSED(orientation);
0687     Q_UNUSED(logicalFirst);
0688     Q_UNUSED(logicalLast);
0689     slotModelReset();
0690     updateKeyboardLayout();
0691 }
0692 
0693 
0694 void KWQTableView::slotModelReset()
0695 {
0696   setColumnWidth(0, qvariant_cast<QSize>(model()->headerData(0, Qt::Horizontal, Qt::SizeHintRole)).width());
0697   setColumnWidth(1, qvariant_cast<QSize>(model()->headerData(1, Qt::Horizontal, Qt::SizeHintRole)).width());
0698 }
0699 
0700 
0701 void KWQTableView::slotSortByColumn(int column)
0702 {
0703   QTableView::sortByColumn(column, Qt::AscendingOrder);
0704 }
0705 
0706 
0707 void KWQTableView::slotHeaderClicked(int column)
0708 {
0709   KWQCommandSort *kwqc = new KWQCommandSort(this, column);
0710   m_undoStack->push(kwqc);
0711 }
0712 
0713 
0714 void KWQTableView::doVocabImage()
0715 {
0716   QUrl currentUrl(model()->data(currentIndex(), KWQTableModel::ImageRole).toString());
0717   QStringList imageFormats;
0718   for(const QByteArray &b: QImageReader::supportedMimeTypes()) {
0719       if (! b.isEmpty()) imageFormats.append(QString(b));
0720   }
0721 
0722   QPointer<QFileDialog> imageOpenDialog = new QFileDialog(this);
0723   imageOpenDialog->setWindowTitle(i18nc("@title:window", "Select Image"));
0724   imageOpenDialog->setDirectory(currentUrl.path());
0725   imageOpenDialog->setMimeTypeFilters(imageFormats);
0726   imageOpenDialog->setAcceptMode(QFileDialog::AcceptOpen);
0727   imageOpenDialog->setFileMode(QFileDialog::ExistingFile);
0728   if (imageOpenDialog->exec() == QDialog::Accepted) {
0729       QUrl imageUrl = imageOpenDialog->selectedUrls().first();
0730       if (!imageUrl.isEmpty()) {
0731           KWQCommandImage *kwqc = new KWQCommandImage(this, imageUrl);
0732           m_undoStack->push(kwqc);
0733       }
0734   }
0735   delete imageOpenDialog;
0736 }
0737 
0738 
0739 void KWQTableView::doVocabSound()
0740 {
0741   QUrl currentUrl(model()->data(currentIndex(), KWQTableModel::SoundRole).toString());
0742 
0743   QUrl soundUrl = QFileDialog::getOpenFileUrl(this, i18nc("@title:window", "Select Sound"), currentUrl, i18n("All Files (*)"));
0744   if (!soundUrl.isEmpty()) {
0745     KWQCommandSound *kwqc = new KWQCommandSound(this, soundUrl);
0746     m_undoStack->push(kwqc);
0747   }
0748 }
0749 
0750 
0751 void KWQTableView::doVocabShuffle()
0752 {
0753   setFocus();
0754   KWQCommandShuffle *kwqc = new KWQCommandShuffle(this, 0);
0755   m_undoStack->push(kwqc);
0756 }
0757 
0758 
0759 void KWQTableView::updateKeyboardLayout()
0760 {
0761     QString layout;
0762     layout.clear();
0763     layout = model()->headerData(currentIndex().column(), Qt::Horizontal, KWQTableModel::KeyboardLayoutRole).toString();
0764 
0765     if (!layout.isEmpty()) {
0766         QDBusInterface kxkb(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"));
0767         if (kxkb.isValid())
0768             kxkb.call(QStringLiteral("setLayout"), layout);
0769     }
0770 }
0771 
0772 bool KWQTableView::selectionHasMoreThanText()
0773 {
0774   bool result = false;
0775   QModelIndexList indexes = selectionModel()->selectedIndexes();
0776   foreach (const QModelIndex &idx, indexes) {
0777      result = (!model()->data(idx, KWQTableModel::SoundRole).isNull() ||
0778                !model()->data(idx, KWQTableModel::ImageRole).isNull());
0779      if (result)
0780        break;
0781   }
0782 
0783   return result;
0784 }