AFUTrainer/mainwindow.cpp
2019-09-28 11:14:53 +02:00

819 lines
26 KiB
C++
Raw Permalink Blame History

/***************************************************************************
* Copyright (C) 2003-2007 by Oliver Saal *
* osaal@gmx.de *
* http://www.oliver-saal.de/software/afutrainer/ *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "mainwindow.h"
#include <qwhatsthis.h>
#include <qmessagebox.h>
#include <qfiledialog.h>
#include <qheaderview.h>
#include <qtextstream.h>
#include <qregexp.h>
#include <qdir.h>
#include <qsettings.h>
#include "dlglearn.h"
#include "dlglearnassistant.h"
#include "dlginformation.h"
#include "dlgexamselect.h"
#include "dlgexam.h"
#include "dlgexamstatistic.h"
#include "dlglearnstatistic.h"
#include "catalog.h"
CMainWindow::CMainWindow() : QMainWindow()
{
setupUi(this);
m_pSplitter = new QSplitter (this);
setCentralWidget (m_pSplitter);
m_pViewChapter = new QTreeView (m_pSplitter);
m_pViewChapter->setModel(&m_modelCatalog);
m_pViewChapter->header()->setStretchLastSection(false);
m_pViewChapter->header()->setResizeMode (0, QHeaderView::Stretch);
m_pViewChapter->header()->setResizeMode (1, QHeaderView::Interactive);
m_pViewChapter->header()->setResizeMode (3, QHeaderView::Interactive);
m_pViewChapter->header()->resizeSection(1, 45);
m_pViewChapter->header()->resizeSection(2, 150);
m_pViewChapter->header()->resizeSection(3, 20);
//m_pViewChapter->setSelectionBehavior(QAbstractItemView::SelectRows);
connect (m_pViewChapter->selectionModel(), SIGNAL(selectionChanged (const QItemSelection& , const QItemSelection& )), this, SLOT(onCatalogSelectionChanged (const QItemSelection& , const QItemSelection& )));
m_pSplitter2 = new QSplitter (m_pSplitter);
m_pSplitter2->setOrientation(Qt::Vertical);
m_pViewQuestions = new QTreeView (m_pSplitter2);
m_pViewQuestions->setModel(&m_modelQuestion);
m_pViewQuestions->header()->setStretchLastSection(false);
m_pViewQuestions->header()->setResizeMode (0, QHeaderView::Interactive);
m_pViewQuestions->header()->setResizeMode (1, QHeaderView::Stretch);
m_pViewQuestions->header()->resizeSection(0, 60);
m_pViewQuestions->header()->resizeSection(2, 20);
m_pViewQuestions->header()->resizeSection(3, 20);
m_pViewQuestions->header()->resizeSection(4, 100);
m_pViewQuestions->header()->resizeSection(5, 80);
m_pViewQuestions->header()->resizeSection(6, 80);
m_pViewQuestions->setRootIsDecorated(false);
connect (m_pViewQuestions->selectionModel(), SIGNAL(selectionChanged (const QItemSelection& , const QItemSelection& )), this, SLOT(onQuestionSelectionChanged (const QItemSelection& , const QItemSelection& )));
m_pTextQuestion = new QTextBrowser (m_pSplitter2);
m_pTextQuestion->setOpenExternalLinks(true);
//m_pTextQuestion->setReadOnly(true);
//connect (m_pTextQuestion, SIGNAL(anchorClicked (const QUrl &)), this, SLOT(onAnchorClicked (const QUrl &)));
m_pCatalog = 0;
connect (&m_rf, SIGNAL(loadFile(const QString&)), this, SLOT(onOpenFile(const QString&)));
m_rf.create(QString(), 8);
m_rf.insertToMenu(menuFile, actFileExit);
m_rf.setShowNoEntry(false);
m_rf.setShowSeperator(CRecentFiles::SeperatorBottom);
// open last file
onOpenFile(m_rf.recentFile(0));
#ifndef _DEBUG
actFileSave->setVisible(false);
actFileSaveAs->setVisible(false);
actFileImport->setVisible(false);
actFileImportUS->setVisible(false);
#endif
updateWindowTitle();
}
CMainWindow::~CMainWindow()
{
if (m_pCatalog) delete m_pCatalog;
}
void CMainWindow::updateWindowTitle()
{
QString str;
str = tr("AFUTrainer 3.0");
if (m_pCatalog)
{
str += " - ";
if (m_pCatalog->name().isEmpty())
str += tr("unbenannt");
else
str += m_pCatalog->name();
if (!m_pCatalog->fileName().isEmpty())
str += " [" + m_pCatalog->fileName() + "]";
}
setWindowTitle(str);
}
void CMainWindow::setCatalog (CCatalog *pCatalog)
{
m_modelCatalog.setModelData(pCatalog);
m_pViewChapter->expandAll();
if (m_pCatalog) delete m_pCatalog;
m_pCatalog = pCatalog;
m_modelQuestion.setModelData(0);
m_pTextQuestion->clear();
updateWindowTitle();
if (m_pCatalog == 0) return;
QDate d = m_pCatalog->validUntil();
if (d.isValid() && d < QDate::currentDate())
{
QString str = tr("<b>Dieser Fragenkatalog ist seit dem %1 nicht mehr g<>ltig!</b>").arg(d.toString(Qt::LocalDate));
if (!m_pCatalog->publisher().isEmpty())
str += tr("<p>Weitere Informationen zur G<>ltigkeit erhalten Sie vom Herausgeber:<br>")+m_pCatalog->publisher();
if (!m_pCatalog->contact().isEmpty())
str += tr("<p>Einen aktuellen Fragenkatalog f<>r den AFUTrainer erhalten Sie evt. von:<br>")+m_pCatalog->contact();
QMessageBox::warning(this, tr("Warnung"), str);
}
}
bool CMainWindow::checkForErrors()
{
QString str;
if (m_pCatalog == 0) return false;
str = m_pCatalog->checkForErrors();
if (str.isEmpty()) return false;
QMessageBox::critical(this, tr("Fehler im Fragenkatalog"), tr("Die gew<65>nschte Funktion kann nicht ausgef<65>hrt werden, da der Fragenkatalog folgende Fehler enth<74>lt:<p>")+ str);
return true;
}
bool CMainWindow::checkForHomeDir()
{
QString strDir = QDir::homePath() + "/.afutrainer/";
QDir dir;
if (dir.exists(strDir)) return true;
if (!dir.mkpath(strDir))
{
QMessageBox::critical(this, tr("Fehler"), tr("Konnte Verzeichnis %1 nicht anlegen!").arg(strDir));
return false;
}
return true;
}
void CMainWindow::on_actFileNew_triggered()
{
if (!checkForHomeDir()) return;
setCatalog(0);
}
void CMainWindow::on_actFileOpen_triggered()
{
QString strFileName;
if (!checkForHomeDir()) return;
strFileName = QFileDialog::getOpenFileName(this, tr("<EFBFBD>ffne Fragenkatalog"), QString(), tr("Amateur Radio Questionary Data Format (*.aqz)\nAlle Dateien (*.*)"));
onOpenFile(strFileName);
}
void CMainWindow::onOpenFile(const QString& strFileName)
{
CCatalog *pCatalog=0;
if (strFileName.isEmpty()) return;
pCatalog = new CCatalog;
if (pCatalog->load(strFileName, this))
{
setCatalog (pCatalog);
m_rf.setRecentFile(strFileName);
}
else
{
m_rf.removeFile(strFileName);
delete pCatalog;
}
}
void CMainWindow::on_actFileInformation_triggered()
{
CDlgInformation dlg(this);
if (!m_pCatalog)
{
QMessageBox::information(this, tr("Information"), tr("Kein Fragenkatalog geladen, zu dem Informationen angezeigt werden k<>nnten."));
return;
}
dlg.setup(m_pCatalog);
dlg.exec();
}
void CMainWindow::on_actFileSave_triggered()
{
if (!m_pCatalog) return;
if (m_pCatalog->fileName().isEmpty())
on_actFileSaveAs_triggered();
else
{
m_pCatalog->save(m_pCatalog->fileName(), this);
updateWindowTitle();
}
}
void CMainWindow::on_actFileSaveAs_triggered()
{
QString strFileName;
if (!m_pCatalog) return;
strFileName = QFileDialog::getSaveFileName(this, tr("Speichere Fragenkatalog"), QString(), tr("XML-Dateien (*.xml)\nAlle Dateien (*.*)"));
if (strFileName.isEmpty()) return;
m_pCatalog->save(strFileName, this);
updateWindowTitle();
}
bool ImportDE_isChapter(const QString& strLine)
{
if (strLine.contains(QRegExp ("^[0-9](\\.[0-9]+)*\\s\\w")))
return true;
else
return false;
}
int ImportDE_chapterLevel(const QString& strLine)
{
QString str = strLine.left(strLine.indexOf(' '));
return (str.count('.'));
}
bool ImportDE_isQuestion(const QString& strLine)
{
return strLine.contains(QRegExp("^[A-Z]{2,2}[0-9]{3,3}"));
}
bool ImportDE_isAnswer(const QString& strLine)
{
return strLine.contains(QRegExp("^[A-D]\\s")) || strLine.contains(QRegExp("^[A-D]$"));
}
void CMainWindow::on_actFileImport_triggered()
{
QString strFileName, strLine, strChapter;
CChapter *pChapter=0, *pTempChapter=0;
CQuestion *pQuestion=0;
int uCurrentLevel=-1, uLevel=-1;
enum LastAdded {None, Chapter, Question, Answer};
LastAdded la=None;
CCatalog *pCatalog=0;
strFileName = QFileDialog::getOpenFileName(this, tr("<EFBFBD>ffne Datei zum Fragenkatalog-Import"), QString("D:/projekte/afutrainer/fragenkataloge/2007-02/Klasse A Technik/"), tr("TXT-Dateien (*.txt)\nAlle Dateien (*.*)"));
if (strFileName.isEmpty()) return;
QFile file(strFileName);
if(!file.open(QIODevice::ReadOnly))
{
QMessageBox::information(this, tr("Fehler"), tr("Konnte Datei '%1' nicht zum Lesen <20>ffnen!").arg(strFileName));
return;
}
QTextStream in(&file);
pCatalog = new CCatalog();
while (!in.atEnd())
{
strLine = in.readLine().trimmed();
if (strLine.isEmpty() || strLine.contains(QRegExp("^Pr<50>fungsfragen")) || strLine.contains("^Bundesnetzagentur"))
{
la = None;
}
else if (ImportDE_isChapter(strLine)) // && (uCurrentLevel+1 == ImportDE_chapterLevel(strLine) || uCurrentLevel-1 == ImportDE_chapterLevel(strLine)))
{
uLevel = ImportDE_chapterLevel(strLine);
while (uCurrentLevel >= uLevel && pChapter)
{
pChapter = pChapter->parentChapter();
uCurrentLevel--;
}
pTempChapter = new CChapter();
if (pChapter == 0)
pCatalog->appendChapter(pTempChapter);
else
pChapter->appendChapter(pTempChapter);
pTempChapter->setText(strLine.mid(strLine.indexOf(' ') + 1));
pChapter = pTempChapter;
uCurrentLevel++;
strChapter += QString("%1 -- %2<br>").arg(uLevel).arg(strLine);
qDebug ("%i -- %s", uLevel, qPrintable(strLine));
la = Chapter;
}
else if (ImportDE_isQuestion(strLine))
{
pQuestion = new CQuestion();
pQuestion->setId (strLine.left(5));
pQuestion->setText (strLine.mid(6).trimmed());
if (pChapter)
{
pChapter->appendQuestion(pQuestion);
// update id of chapters
pTempChapter = pChapter;
uLevel = uCurrentLevel;
while (pTempChapter && uLevel >= 0)
{
if (pTempChapter->id().isEmpty())
pTempChapter->setId(pQuestion->id().at(uLevel));
pTempChapter = pTempChapter->parentChapter();
uLevel--;
}
}
else
delete pQuestion;
//qDebug (qPrintable(strLine));
la = Question;
}
else if (ImportDE_isAnswer(strLine))
{
CAnswer a(strLine.mid(2).trimmed(), strLine[0] == QChar('A'));
if (pQuestion)
pQuestion->appendAnswer(a);
//qDebug (qPrintable("\t"+strLine));
la = Answer;
}
else
{
if (la == Chapter && pChapter)
{
if (pChapter->text().isEmpty())
pChapter->appendText (strLine.trimmed());
else
pChapter->appendText (" " + strLine.trimmed());
}
else if (la == Question && pQuestion)
{
if (pQuestion->text().isEmpty() || pQuestion->text().right(1) == "-")
pQuestion->appendText (strLine.trimmed());
else
pQuestion->appendText (" " + strLine.trimmed());
}
else if (la == Answer && pQuestion && pQuestion->countAnswer() > 0)
{
QString strText = pQuestion->answerAt(pQuestion->countAnswer()-1).text();
if (strText.isEmpty() || strText.right(1) == "-")
pQuestion->answerAt(pQuestion->countAnswer()-1).appendText(strLine.trimmed());
else
pQuestion->answerAt(pQuestion->countAnswer()-1).appendText(" " + strLine.trimmed());
}
}
}
// Bilder hinzuf<75>gen
QList<CQuestion*> listPool = pCatalog->questionPool();
QDir dirPath(strFileName.left(strFileName.lastIndexOf('/')));
for (int i=0; i<listPool.size(); i++)
{
pQuestion = listPool.at(i);
QStringList strlFiles = dirPath.entryList(QStringList() << pQuestion->id().toLower()+"*");
for (int j=0; j<strlFiles.size(); j++)
{
QString strImgFile = strlFiles.at(j).toLower();
// <20>berpr<70>fen, ob Verweis
if (strImgFile.contains("_"))
{ // Ja, Verweis
QString strImgFile1 = strImgFile.left(strImgFile.indexOf('_'));
QString strImgFile2 = strImgFile.mid(strImgFile.indexOf('_') + 1);
QStringList strlFiles2 = dirPath.entryList(QStringList() << strImgFile2 + "*");
if (strlFiles2.size() == 0)
{
qDebug ("Verlinkte Datei %s von Frage %s existiert nicht. Link: %s", qPrintable(strImgFile2), qPrintable(strImgFile1), qPrintable(strImgFile));
}
else
{
qDebug ("Datei %s verlinkt auf reale Datei %s", qPrintable(strImgFile), qPrintable(strlFiles2.at(0)));
strImgFile = strlFiles2.at(0);
}
/*int idx = strlFiles.indexOf(QRegExp(strImgFile2 + "\\..*"));
if (idx < 0)
{
qDebug ("Verlinkte Datei %s von Frage %s existiert nicht. Link: %s", qPrintable(strImgFile2), qPrintable(strImgFile1), qPrintable(strImgFile));
}
else
{
qDebug ("Datei %s verlinkt auf reale Datei %s", qPrintable(strImgFile), qPrintable(strlFiles.at(idx)));
strImgFile = strlFiles.at(idx);
}*/
}
QString strLink = "<img src='" + strImgFile + "'>";
if (strImgFile.contains(QRegExp("f\\d*\\.")))
{ // Frage
qDebug("Adding image %s to question %s", qPrintable(strImgFile), qPrintable(pQuestion->id()));
pQuestion->appendText("<p>" + strLink + "</p>");
}
else if (strImgFile.contains("a.") && pQuestion->countAnswer() > 0)
{ // Antwort A
//qDebug("Adding image %s to answer A of question %s", qPrintable(strImgFile), qPrintable(pQuestion->id()));
pQuestion->answerAt(0).appendText("<p>" + strLink + "</p>");
}
else if (strImgFile.contains("b.") && pQuestion->countAnswer() > 1)
{ // Antwort B
//qDebug("Adding image %s to answer B of question %s", qPrintable(strImgFile), qPrintable(pQuestion->id()));
pQuestion->answerAt(1).appendText("<p>" + strLink + "</p>");
}
else if (strImgFile.contains("c.") && pQuestion->countAnswer() > 2)
{ // Antwort C
//qDebug("Adding image %s to answer C of question %s", qPrintable(strImgFile), qPrintable(pQuestion->id()));
pQuestion->answerAt(2).appendText("<p>" + strLink + "</p>");
}
else if (strImgFile.contains("d.") && pQuestion->countAnswer() > 3)
{ // Antwort D
//qDebug("Adding image %s to answer D of question %s", qPrintable(strImgFile), qPrintable(pQuestion->id()));
pQuestion->answerAt(3).appendText("<p>" + strLink + "</p>");
}
else
{
qDebug ("Konnte Grafik %s nicht zuordnen.\n\tM<EFBFBD>gliche Gr<47>nde: Frage oder Antwort existiert nicht. Dateiname der Grafik falsch geschrieben.", qPrintable(strImgFile));
}
}
}
pCatalog->setName("Importierter Katalog von " + strFileName);
QMessageBox::information(this, tr("Information"),
"Bitte Debug-Ausgabe <20>berpr<70>fen, ob alle Grafik-Dateien zugeordnet wurden!<p>"
"Bitte <20>berpr<70>fen, ob alle Kapitel korrekt erkannt wurden. "
"Wenn nicht, muss die TXT-Datei von Hand kontrolliert werden!<hr>"+strChapter);
qDebug("Weitere Vorgehensweise:\n\t1. Fragenkatalog als XML-Datei abspeichern.\n\t2. ggf. Korrekturen in der XML-Datei vornehmen\n\t3. XML-Datei und alle Grafik-Dateien in ein ZIP-Archiv packen und die Datei<65>nderung auf .atc <20>ndern.\n\tFertig!");
setCatalog (pCatalog);
}
bool ImportUS_isChapter(const QString& strLine)
{
if (strLine.contains(QRegExp("^SUBELEMENT")) || strLine.contains(QRegExp("^[A-Z][0-9][A-Z]\\s")))
return true;
else
return false;
}
bool ImportUS_isQuestion(const QString& strLine)
{
return strLine.contains(QRegExp("^[A-Z][0-9][A-Z][0-9]{2,2}"));
}
bool ImportUS_isAnswer(const QString& strLine)
{
return strLine.contains(QRegExp("^[A-D]\\.\\s"));
}
void CMainWindow::on_actFileImportUS_triggered()
{
QString strFileName, strLine, strChapter, str;
CChapter *pChapter=0, *pTempChapter=0;
CQuestion *pQuestion=0;
int uCurrentLevel=-1, uLevel=-1;
enum LastAdded {None, Chapter, Question, Answer};
LastAdded la=None;
CCatalog *pCatalog=0;
strFileName = QFileDialog::getOpenFileName(this, tr("<EFBFBD>ffne Datei zum Fragenkatalog-Import"), QString("D:/projekte/afutrainer/fragenkataloge/US/"), tr("TXT-Dateien (*.txt)\nAlle Dateien (*.*)"));
if (strFileName.isEmpty()) return;
QFile file(strFileName);
if(!file.open(QIODevice::ReadOnly))
{
QMessageBox::information(this, tr("Fehler"), tr("Konnte Datei '%1' nicht zum Lesen <20>ffnen!").arg(strFileName));
return;
}
QTextStream in(&file);
pCatalog = new CCatalog();
while (!in.atEnd())
{
strLine = in.readLine().trimmed();
if (strLine.isEmpty())
{
//la = None;
}
else if (strLine == "~~")
{
la = None;
}
else if (ImportUS_isChapter(strLine))
{
pTempChapter = new CChapter();
if (strLine.contains(QRegExp("^SUBELEMENT")))
{
uLevel = 0;
strLine = strLine.mid(strLine.indexOf(' ')+1);
pTempChapter->setId(strLine.left(2));
// str = strLine.mid(strLine.indexOf(QRegExp("[A-Z]"), 2));
// str.remove(QRegExp("\\[.*\\]"));
pTempChapter->setText(strLine.mid(strLine.indexOf(QRegExp("[A-Z]"), 2)));
}
else
{
uLevel = 1;
pTempChapter->setId(strLine.mid(2, 1));
// str = strLine.mid(strLine.indexOf(QRegExp("[A-Z]"), 3));
// str.remove(QRegExp("\\[.*\\]"));
pTempChapter->setText(strLine.mid(strLine.indexOf(QRegExp("[A-Z]"), 3)));
}
while (uCurrentLevel >= uLevel && pChapter)
{
pChapter = pChapter->parentChapter();
uCurrentLevel--;
}
if (!pChapter)
pCatalog->appendChapter(pTempChapter);
else
{
// pTempChapter->setExam("main", 1);
pChapter->appendChapter(pTempChapter);
}
strChapter += QString("%1 -- %2 - %3<br>").arg(uLevel).arg(pTempChapter->id(), pTempChapter->text());
pChapter = pTempChapter;
uCurrentLevel++;
la = Chapter;
}
else if (ImportUS_isQuestion(strLine))
{
pQuestion = new CQuestion();
pQuestion->setId (strLine.left(5));
pQuestion->setText (strLine.mid(6).trimmed());
if (pChapter)
pChapter->appendQuestion(pQuestion);
else
delete pQuestion;
//qDebug (qPrintable(strLine));
la = Question;
}
else if (ImportUS_isAnswer(strLine))
{
CAnswer a(strLine.mid(3).trimmed(), false);
if (pQuestion)
pQuestion->appendAnswer(a);
//qDebug (qPrintable("\t"+strLine));
la = Answer;
}
else
{
if (la == Chapter && pChapter)
{
if (pChapter->text().isEmpty())
pChapter->appendText (strLine.trimmed());
else
pChapter->appendText (" " + strLine.trimmed());
}
else if (la == Question && pQuestion)
{
if (pQuestion->text().isEmpty() || pQuestion->text().right(1) == "-")
pQuestion->appendText (strLine.trimmed());
else
pQuestion->appendText (" " + strLine.trimmed());
}
else if (la == Answer && pQuestion && pQuestion->countAnswer() > 0)
{
QString strText = pQuestion->answerAt(pQuestion->countAnswer()-1).text();
if (strText.isEmpty() || strText.right(1) == "-")
pQuestion->answerAt(pQuestion->countAnswer()-1).appendText(strLine.trimmed());
else
pQuestion->answerAt(pQuestion->countAnswer()-1).appendText(" " + strLine.trimmed());
}
}
}
// Fragen durchgehen und richtige Antworten eintragen
QList<CQuestion*> listPool = pCatalog->questionPool();
for (int i=0; i<listPool.size(); i++)
{
pQuestion = listPool.at(i);
QString strText = pQuestion->text();
int idx = strText.indexOf(QRegExp("\\([A-Z]\\)"));
if (idx == -1) continue;
int iCorrect = pQuestion->text().at(idx+1).toAscii() - 'A';
if (pQuestion->countAnswer() > iCorrect)
pQuestion->answerAt(iCorrect).setCorrect(true);
strText.remove(idx, 3);
idx = strText.indexOf(QRegExp("\\[.*\\]"));
if (idx >= 0)
{
int iLen = strText.indexOf(']', idx) - idx + 1;
CHint hint;
hint.appendQuestion(pQuestion->id());
hint.setAuthor("FCC");
hint.setText("See FCC rules part " + strText.mid(idx + 1, iLen - 2));
pCatalog->appendHint(hint);
strText.remove(idx, iLen);
}
pQuestion->setText(strText.trimmed());
}
// Kapitelnamen korrigieren
QList<CChapter*> listChapter = pCatalog->subChapters();
for (int i=0; i<listChapter.size(); i++)
{
pChapter = listChapter.at(i);
QString strText = pChapter->text();
//strText = strText.left(strText.indexOf(" - "));
strText.remove(QRegExp("\\[.*\\]"));
pChapter->setText(strText.trimmed());
}
// Allgemeine Angaben:
//pCatalog->setVersionText("");
pCatalog->setPublisher("NCVEC (National Conference of Volunteer Examiner Coordinators)<br>Question Pool Committee<br>http://www.ncvec.org/");
pCatalog->setContact("Oliver Saal, DM1OLI<br>http://www.oliver-saal.de/software/afutrainer/<br>Mail: osaal@gmx.de");
pCatalog->setName("Importierter Katalog von " + strFileName);
QMessageBox::information(this, tr("Information"),
"Bitte <20>berpr<70>fen, ob alle Kapitel korrekt erkannt wurden. "
"Wenn nicht, muss die TXT-Datei von Hand kontrolliert werden!<hr>"+strChapter);
qDebug("Weitere Vorgehensweise:\n\t1. Fragenkatalog als XML-Datei abspeichern.\n\t2. ggf. Korrekturen in der XML-Datei vornehmen\n\t3. XML-Datei und alle Grafik-Dateien in ein ZIP-Archiv packen und die Datei<65>nderung auf .atc <20>ndern.\n\tFertig!");
setCatalog (pCatalog);
}
void CMainWindow::on_actFileExit_triggered()
{
qApp->quit();
}
void CMainWindow::on_actQuestionAssistant_triggered()
{
CDlgLearnAssistant dlg(this);
CDlgLearn dlgLearn(this);
CChapter *pChapter=0;
if (m_pCatalog == 0) return;
if (checkForErrors()) return;
if (!dlg.setup(m_pCatalog))
{
QMessageBox::information(this, tr("Information"), tr("Derzeit gibt es keine Empfehlung des Lernassistentes."));
return;
}
if (dlg.exec() != QDialog::Accepted) return;
pChapter = dlg.selectedChapter();
if (pChapter == 0) return;
dlgLearn.go(m_pCatalog, pChapter);
m_pCatalog->saveStatistic(this);
}
void CMainWindow::on_actQuestionsLearn_triggered()
{
CDlgLearn dlg(this);
QModelIndexList list = m_pViewChapter->selectionModel()->selectedIndexes();
if (checkForErrors()) return;
if (list.isEmpty())
{
QMessageBox::information(this, tr("Information"), tr("Bitte ein Kapitel zum Lernen ausw<73>hlen!"));
return;
}
CChapter *p = (CChapter*)list.first().internalPointer();
Q_ASSERT(p != 0);
dlg.go(m_pCatalog, p);
m_pCatalog->saveStatistic(this);
}
void CMainWindow::on_actQuestionsLearnStatistics_triggered()
{
CDlgLearnStatistic dlg(this);
QModelIndexList list = m_pViewChapter->selectionModel()->selectedIndexes();
CChapter *p=0;
if (checkForErrors()) return;
if (list.isEmpty())
p = m_pCatalog;
else
p = (CChapter*)list.first().internalPointer();
dlg.go(p);
}
void CMainWindow::on_actQuestionsTest_triggered()
{
int iCount=0;
CExam exam;
if (checkForErrors()) return;
iCount = m_pCatalog->countExam();
if (iCount == 0)
{
QMessageBox::information(this, tr("Information"), tr("Dieser Fragenkatalog enth<74>lt keine Pr<50>fungen."));
return;
}
else if (iCount == 1)
{
exam = m_pCatalog->examAt(0);
}
else if (iCount > 1)
{
CDlgExamSelect dlg1(this);
dlg1.setup(m_pCatalog);
dlg1.exec();
if (dlg1.result() == QDialog::Rejected) return;
exam = m_pCatalog->examAt(dlg1.selectedExam());
}
CDlgExam dlg2(m_pCatalog, this);
if (dlg2.setup(exam))
dlg2.exec();
}
void CMainWindow::on_actQuestionsTestStatistics_triggered()
{
CDlgExamStatistic dlg(this);
if (checkForErrors()) return;
if (m_pCatalog->countExam() == 0)
{
QMessageBox::information(this, tr("Information"), tr("Dieser Fragenkatalog enth<74>lt keine Pr<50>fungen."));
return;
}
dlg.go(m_pCatalog);
}
void CMainWindow::on_actViewToolbar_toggled(bool bChecked)
{
if (bChecked)
toolBar->show();
else
toolBar->hide();
}
void CMainWindow::on_actViewStatusbar_toggled(bool bChecked)
{
if (bChecked)
statusbar->show();
else
statusbar->hide();
}
void CMainWindow::on_actHelpWhatsThis_triggered()
{
QWhatsThis::enterWhatsThisMode();
}
void CMainWindow::on_actHelpAbout_triggered()
{
QString str = tr("<b>AFUTrainer Version 3.0</b><br>"
"(c) 2003-2007 by Oliver Saal (DM1OLI)<br><hr>"
"EMail: osaal@gmx.de<br>"
"http://www.oliver-saal.de/software/afutrainer/<hr>"
"This program is free software; you can redistribute it and/or modify "
"it under the terms of the GNU General Public License as published by "
"the Free Software Foundation; either version 2 of the License, or "
"(at your option) any later version.<p>"
"This program is distributed in the hope that it will be useful, "
"but WITHOUT ANY WARRANTY; without even the implied warranty of "
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
"GNU General Public License for more details.<p>"
"You should have received a copy of the GNU General Public License "
"along with this program; if not, write to the "
"Free Software Foundation, Inc., "
"59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.");
QMessageBox::about(this,tr("<EFBFBD>ber..."), str);
}
void CMainWindow::on_actHelpAboutQt_triggered()
{
qApp->aboutQt();
}
void CMainWindow::onCatalogSelectionChanged (const QItemSelection& selected, const QItemSelection& deselected)
{
Q_UNUSED(deselected);
m_pTextQuestion->clear();
if (!selected.indexes().isEmpty())
{
CChapter *pChapter = (CChapter*)selected.indexes().first().internalPointer();
if (pChapter)
m_modelQuestion.setModelData(pChapter);
}
else
m_modelQuestion.clear();
}
void CMainWindow::onQuestionSelectionChanged (const QItemSelection& selected, const QItemSelection& deselected)
{
Q_UNUSED(deselected);
m_pTextQuestion->clear();
if (selected.indexes().isEmpty()) return;
CQuestion *pQuestion = (CQuestion*)selected.indexes().first().internalPointer();
if (pQuestion == 0) return;
m_pTextQuestion->setHtml(pQuestion->showText(m_pCatalog));
}
/*
void CMainWindow::onAnchorClicked (const QUrl &link)
{
QMessageBox::information(this, tr("Click"), link.toString());
m_pTextQuestion->home();
}
*/