Initial commit.
3066
APPNOTE.TXT
Normal file
122
AQDF-Format/afutrainer30.dtd
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<!--
|
||||
* 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. *
|
||||
|
||||
Hinweis: Wenn HTML in Tags erlaubt ist, wird darauf explizit hingewiesen.
|
||||
HTML wird dann entweder in CDATA-Blöcke (wie <![CDATA[ <b>fette Schrift</b> ]]>) gepackt
|
||||
oder mit < codiert (<answertext correct="true">42*10<sup>-3</sup> A.</answertext>).
|
||||
-->
|
||||
|
||||
<!ELEMENT afutrainer (title,publisher,version,valid,contact,comment?,options?,exam*,hint*,chapter+)>
|
||||
<!-- Version des AFUTrainer-Formats - hier: 3.0 -->
|
||||
<!ATTLIST afutrainer version (3.0) #REQUIRED>
|
||||
<!-- Datum, an dem diese XML-Datei erstellt wurde. -->
|
||||
<!ATTLIST afutrainer created CDATA #REQUIRED>
|
||||
|
||||
<!-- Titel (ausführlich/lang) des Fragenkatalogs -->
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
<!-- Kurzbezeichnung des Fragenkatalogs -->
|
||||
<!ATTLIST title short CDATA #IMPLIED>
|
||||
<!-- unique wird benötigt, um Lernstatistiken unabh. vom Dateinamen
|
||||
und eindeutig auf dem System abzuspeichern -->
|
||||
<!ATTLIST title unique CDATA #REQUIRED>
|
||||
|
||||
<!-- Angaben zum Original-Fragenkatalog, Urheber: (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT publisher (#PCDATA)>
|
||||
|
||||
<!-- Version/Auflage des Original-Fragenkataloges (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT version (#PCDATA)>
|
||||
<!-- Original-Versions-Datum -->
|
||||
<!ATTLIST version published CDATA #REQUIRED>
|
||||
|
||||
<!-- Gültigkeitszeitraum des Katalogs -->
|
||||
<!ELEMENT valid EMPTY>
|
||||
<!ATTLIST valid from CDATA #REQUIRED>
|
||||
<!ATTLIST valid until CDATA #IMPLIED>
|
||||
|
||||
<!-- Ansprechparter für den XML-Fragenkatalog (z.B. bei Fehlern): (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT contact (#PCDATA)>
|
||||
|
||||
<!-- Kommentar zum Fragenkatalog (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT comment (#PCDATA)>
|
||||
|
||||
<!-- Diverse Optionen -->
|
||||
<!ELEMENT options EMPTY>
|
||||
<!-- Wird die Reihenfolge der Antworten beim Abfragen immer durchgetauscht? Default: Ja -->
|
||||
<!ATTLIST options mixanswers (true|false) "true">
|
||||
|
||||
<!-- Definition einer Prüfung -->
|
||||
<!ELEMENT exam (exam_part+)>
|
||||
<!-- Eindeutige Kennung (für Prüfungsstatistiken) -->
|
||||
<!ATTLIST exam id CDATA #REQUIRED>
|
||||
<!-- Name/Bezeichnung der Prüfung -->
|
||||
<!ATTLIST exam name CDATA #REQUIRED>
|
||||
<!-- Dauer der Prüfung in Minuten, 0 für unbegrenzt -->
|
||||
<!ATTLIST exam duration CDATA #REQUIRED>
|
||||
<!-- Max. erlaubte Anzahl von Fehlerpunkten zum Bestehen der Prüfung -->
|
||||
<!ATTLIST exam maxerrorpoints CDATA #REQUIRED>
|
||||
|
||||
<!-- Teil einer Prüfung
|
||||
Enthält regulären Ausdruck nach den Regeln von http://doc.trolltech.com/4.2/qregexp.html#details
|
||||
Es werden für die Prüfungszusammenstellung 'count' Fragen ausgewählt,
|
||||
deren 'id' diesem regulären Ausdruck entsprechen.
|
||||
Bsp: <exam_part count="5">TA\d\d\d</exam_part>
|
||||
=> Es sind 5 Fragen in der Prüfung, die mit TA beginnen und anschließend 3 Ziffern haben
|
||||
-->
|
||||
<!ELEMENT exam_part (#PCDATA)>
|
||||
<!ATTLIST exam_part count CDATA #REQUIRED>
|
||||
|
||||
<!-- Hilfetexte/Bemerkungen zu einzelnen Fragen (Codiertes HTML erlaubt, s.o.)
|
||||
Es ist möglich, ein Hilfetext mehreren Fragen zuzuordnen und auch einer Frage mehrere Texte zuzuordnen
|
||||
-->
|
||||
<!ELEMENT hint (#PCDATA)>
|
||||
<!-- Zugeordnete Fragen, durch Leerzeichen und/oder Komma und/oder Semikolon getrennt-->
|
||||
<!ATTLIST hint question CDATA #REQUIRED>
|
||||
<!-- Autor des Hilfetextes -->
|
||||
<!ATTLIST hint author CDATA #IMPLIED>
|
||||
<!-- Datum -->
|
||||
<!ATTLIST hint date CDATA #IMPLIED>
|
||||
|
||||
<!-- Kapitel eines Fragenkatalogs -->
|
||||
<!ELEMENT chapter (chapter*, question*)>
|
||||
<!-- Bezeichnung/Name des Kapitels -->
|
||||
<!ATTLIST chapter name CDATA #REQUIRED>
|
||||
<!-- Eindeutige ID des Kapitels -->
|
||||
<!ATTLIST chapter id CDATA #REQUIRED>
|
||||
|
||||
<!-- Frage -->
|
||||
<!ELEMENT question (textquestion, textanswer+, comment?)>
|
||||
<!-- Eindeutige Kennung der Frage -->
|
||||
<!ATTLIST question id CDATA #REQUIRED>
|
||||
<!-- Letze Änderung der Frage -->
|
||||
<!ATTLIST question changed CDATA #IMPLIED>
|
||||
<!-- Fehlerpunkte beim falsch beantworten, Default: 1 -->
|
||||
<!ATTLIST question errorpoints CDATA "1">
|
||||
<!-- Ist die Frage aktiv bzw. prüfungsrelevant? Default: true -->
|
||||
<!ATTLIST question active (true|false) "true">
|
||||
|
||||
<!-- Fragentext (Codiertes HTML erlaubt, s.o.) -->
|
||||
<!ELEMENT textquestion (#PCDATA)>
|
||||
|
||||
<!-- Antwort auf eine Frage (Codiertes HTML erlaubt, s.o.) -->
|
||||
<!ELEMENT textanswer (#PCDATA)>
|
||||
<!-- Ist diese Anwort richtig oder falsch? (Default: false = falsch)-->
|
||||
<!ATTLIST textanswer correct (true|false) "false">
|
108
AQDF-Format/aqdf.dtd
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<!--
|
||||
AQDF (Amateur Radio Questionary Data Format) DTD
|
||||
|
||||
XML-DTD by Oliver Saal, Junghard Bippes and Dominik Dresel (c) 2003-2007
|
||||
License: GPL v2 or later
|
||||
|
||||
Hinweis: Wenn HTML in Tags erlaubt ist, wird darauf explizit hingewiesen.
|
||||
HTML wird dann entweder in CDATA-Blöcke (wie <![CDATA[ <b>fette Schrift</b> ]]>) gepackt
|
||||
oder mit < codiert (<answertext correct="true">42*10<sup>-3</sup> A.</answertext>).
|
||||
-->
|
||||
|
||||
<!ELEMENT aqdf (title,publisher,version,valid,contact,comment?,options?,exam*,hint*,chapter+)>
|
||||
<!-- Version des AFUTrainer-Formats - hier: 3.0 -->
|
||||
<!ATTLIST aqdf version (1.0) #REQUIRED>
|
||||
<!-- Datum, an dem diese XML-Datei erstellt wurde. -->
|
||||
<!ATTLIST aqdf created CDATA #REQUIRED>
|
||||
|
||||
<!-- Titel (ausführlich/lang) des Fragenkatalogs -->
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
<!-- Kurzbezeichnung des Fragenkatalogs -->
|
||||
<!ATTLIST title short CDATA #IMPLIED>
|
||||
<!-- unique wird benötigt, um Lernstatistiken unabh. vom Dateinamen
|
||||
und eindeutig auf dem System abzuspeichern -->
|
||||
<!ATTLIST title unique CDATA #REQUIRED>
|
||||
|
||||
<!-- Angaben zum Original-Fragenkatalog, Urheber: (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT publisher (#PCDATA)>
|
||||
|
||||
<!-- Version/Auflage des Original-Fragenkataloges (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT version (#PCDATA)>
|
||||
<!-- Original-Versions-Datum -->
|
||||
<!ATTLIST version published CDATA #REQUIRED>
|
||||
|
||||
<!-- Gültigkeitszeitraum des Katalogs -->
|
||||
<!ELEMENT valid EMPTY>
|
||||
<!ATTLIST valid from CDATA #REQUIRED>
|
||||
<!ATTLIST valid until CDATA #IMPLIED>
|
||||
|
||||
<!-- Ansprechparter für den XML-Fragenkatalog (z.B. bei Fehlern): (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT contact (#PCDATA)>
|
||||
|
||||
<!-- Kommentar zum Fragenkatalog (Codiertes HTML erlaubt, s.o.)-->
|
||||
<!ELEMENT comment (#PCDATA)>
|
||||
|
||||
<!-- Diverse Optionen -->
|
||||
<!ELEMENT options EMPTY>
|
||||
<!-- Wird die Reihenfolge der Antworten beim Abfragen immer durchgetauscht? Default: Ja -->
|
||||
<!ATTLIST options mixanswers (true|false) "true">
|
||||
|
||||
<!-- Definition einer Prüfung -->
|
||||
<!ELEMENT exam (exam_part+)>
|
||||
<!-- Eindeutige Kennung (für Prüfungsstatistiken) -->
|
||||
<!ATTLIST exam id CDATA #REQUIRED>
|
||||
<!-- Name/Bezeichnung der Prüfung -->
|
||||
<!ATTLIST exam name CDATA #REQUIRED>
|
||||
<!-- Dauer der Prüfung in Minuten, 0 für unbegrenzt -->
|
||||
<!ATTLIST exam duration CDATA #REQUIRED>
|
||||
<!-- Max. erlaubte Anzahl von Fehlerpunkten zum Bestehen der Prüfung -->
|
||||
<!ATTLIST exam maxerrorpoints CDATA #REQUIRED>
|
||||
|
||||
<!-- Teil einer Prüfung
|
||||
Enthält regulären Ausdruck nach den Regeln von http://doc.trolltech.com/4.2/qregexp.html#details
|
||||
Es werden für die Prüfungszusammenstellung 'count' Fragen ausgewählt,
|
||||
deren 'id' diesem regulären Ausdruck entsprechen.
|
||||
Bsp: <exam_part count="5">TA\d\d\d</exam_part>
|
||||
=> Es sind 5 Fragen in der Prüfung, die mit TA beginnen und anschließend 3 Ziffern haben
|
||||
-->
|
||||
<!ELEMENT exam_part (#PCDATA)>
|
||||
<!ATTLIST exam_part count CDATA #REQUIRED>
|
||||
|
||||
<!-- Hilfetexte/Bemerkungen zu einzelnen Fragen (Codiertes HTML erlaubt, s.o.)
|
||||
Es ist möglich, ein Hilfetext mehreren Fragen zuzuordnen und auch einer Frage mehrere Texte zuzuordnen
|
||||
-->
|
||||
<!ELEMENT hint (#PCDATA)>
|
||||
<!-- Zugeordnete Fragen, durch Leerzeichen und/oder Komma und/oder Semikolon getrennt-->
|
||||
<!ATTLIST hint question CDATA #REQUIRED>
|
||||
<!-- Autor des Hilfetextes -->
|
||||
<!ATTLIST hint author CDATA #IMPLIED>
|
||||
<!-- Datum -->
|
||||
<!ATTLIST hint date CDATA #IMPLIED>
|
||||
|
||||
<!-- Kapitel eines Fragenkatalogs -->
|
||||
<!ELEMENT chapter (chapter*, question*)>
|
||||
<!-- Bezeichnung/Name des Kapitels -->
|
||||
<!ATTLIST chapter name CDATA #REQUIRED>
|
||||
<!-- Eindeutige ID des Kapitels -->
|
||||
<!ATTLIST chapter id CDATA #REQUIRED>
|
||||
|
||||
<!-- Frage -->
|
||||
<!ELEMENT question (textquestion, textanswer+, comment?)>
|
||||
<!-- Eindeutige Kennung der Frage -->
|
||||
<!ATTLIST question id CDATA #REQUIRED>
|
||||
<!-- Letze Änderung der Frage -->
|
||||
<!ATTLIST question changed CDATA #IMPLIED>
|
||||
<!-- Fehlerpunkte beim falsch beantworten, Default: 1 -->
|
||||
<!ATTLIST question errorpoints CDATA "1">
|
||||
<!-- Ist die Frage aktiv bzw. prüfungsrelevant? Default: true -->
|
||||
<!ATTLIST question active (true|false) "true">
|
||||
|
||||
<!-- Fragentext (Codiertes HTML erlaubt, s.o.) -->
|
||||
<!ELEMENT textquestion (#PCDATA)>
|
||||
|
||||
<!-- Antwort auf eine Frage (Codiertes HTML erlaubt, s.o.) -->
|
||||
<!ELEMENT textanswer (#PCDATA)>
|
||||
<!-- Ist diese Anwort richtig oder falsch? (Default: false = falsch)-->
|
||||
<!ATTLIST textanswer correct (true|false) "false">
|
75
AQDF-Format/aqdf.xml
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-15"?>
|
||||
<!--
|
||||
AQDF (Amateur Radio Questionary Data Format) XML
|
||||
by Oliver Saal, Junghard Bippes and Dominik Dresel (c) 2007
|
||||
License: GPL v2 or later
|
||||
-->
|
||||
<!DOCTYPE aqdf SYSTEM "http://www.oliver-saal.de/software/afutrainer/download/aqdf10.dtd">
|
||||
|
||||
|
||||
<aqdf version="1" name="DL Technik Klasse E (ab 02/2007)" created="2007-03-27" >
|
||||
|
||||
<!-- Wird benötigt um die Lernstatistiken eindeutig abzuspeichern -
|
||||
falls sich der Dateiname (z.B. wegen neuer Fragenkatalog-Auflage) ändern
|
||||
sollte: -->
|
||||
<unique_name>DL-E-2006</unique_name>
|
||||
|
||||
<!-- Titel des Fragenkataloges -->
|
||||
<title>Prüfungsfragen im Prüfungsteil Technische Kenntnisse bei Prüfungen zum Erwerb von Amateurfunkzeugnissen der Klasse E</title>
|
||||
|
||||
<!-- Angaben zum Original-Fragenkatalog, Urheber: -->
|
||||
<author>Bundesnetzagentur<br>Referat 225<br>Canisiusstraße 21<br>55122 Mainz<br>E-Mail: Poststelle@BNetzA.de<br>Fax: 06131 - 18 5644</author>
|
||||
|
||||
<!-- Version des Fragenkataloges -->
|
||||
<version published="2006-09-01">1. Auflage, September 2006</version>
|
||||
|
||||
<!-- Gültigkeitsdauer -->
|
||||
<valid from="2007-02-01" to="" />
|
||||
|
||||
<!-- Wer ist Ansprechparter für den XML-Fragenkatalog (z.B. bei Fehlern): -->
|
||||
<contact>Oliver Saal, DM1OLI<br>http://www.oliver-saal.de/software/afutrainer/<br>Mail:osaal@gmx.de</contact>
|
||||
|
||||
<!-- Kommentar: (z.B: Frage xyz korrigiert...) -->
|
||||
<comment></comment>
|
||||
|
||||
<!-- Diverse Optionen -->
|
||||
<options mixanswers="1" />
|
||||
|
||||
<!-- Fragenauswahl pro Kapitel -->
|
||||
<exam id="T" name="Technische Kenntnisse Klasse E" duration="60" maxerrorpoints="9">
|
||||
<exam_part count="1">TA\d\d\d</exam_part>
|
||||
<...>
|
||||
</exam>
|
||||
|
||||
<!-- Bemerkungen zu den Fragen -->
|
||||
<hint question="TB103, TB104" author="Oliver Saal (DM1OLI) osaal@gmx.de" date="2004-03-25">Bronze und Messing sind Metalle und damit Leiter. Desweiteren leitet Konstantan und Graphitstaub ebenfalls den elektrischen Strom.</hint>
|
||||
|
||||
|
||||
<hint question="B..." author="Fragenkatalog Bundesnetzagentur">
|
||||
<![CDATA[
|
||||
<table>
|
||||
<tr><th>Zu übermittelnder<br>Buchstabe</th><th>Schlüsselwort</th><th>Aussprache des<br>Schlüsselworts</th></tr>
|
||||
<tr><td>A</td><td>Alfa</td><td><u>AL</u> FAH</td></tr>
|
||||
<tr><td>Z</td><td>Zoulou</td><td><u>SUH</u> LUH</td></tr>
|
||||
</table>
|
||||
Die zu betonenden Silben sind <u>unterstrichen</u>.
|
||||
]]>
|
||||
</hint>
|
||||
|
||||
<chapter name="Prüfungsfragen im Prüfungsteil Technische Kenntnisse der Klasse E" id="T" >
|
||||
<chapter name="Allgemeine mathematische Grundkenntnisse und Größen" id="A" >
|
||||
<chapter name="Allgemeine mathematische Grundkenntnisse" id="1" >
|
||||
<question id="TA101" changed="2006-09-23" errorpoints="1" active="true">
|
||||
<textquestion>0,042 A entspricht</textquestion>
|
||||
<textanswer correct="true">42*10<sup>-3</sup> A.</textanswer>
|
||||
<textanswer correct="false">42*10<sup>3</sup> A.</textanswer>
|
||||
<textanswer correct="false">42*10<sup>-2</sup> A.</textanswer>
|
||||
<textanswer correct="false">42*10<sup>-1</sup> A.</textanswer>
|
||||
<remark>geändert 2006-09-22, 2006-09-23 DF1IAV</remark>
|
||||
<link>www.dj4uf.de/lehrg/a01/a01.html#Abg_Einheiten</link>
|
||||
</question>
|
||||
</chapter>
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
||||
</aqdf>
|
BIN
Abfragestrategie.odt
Normal file
261
Doxyfile
Normal file
|
@ -0,0 +1,261 @@
|
|||
# Doxyfile 1.5.1-p1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = AFUTrainer
|
||||
PROJECT_NUMBER = 2.2
|
||||
OUTPUT_DIRECTORY = D:/projekte/Software/afutrainer/afutrainer-2.2/doc/
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = YES
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = D:/projekte/Software/afutrainer/afutrainer-2.2/
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = D:/projekte/Software/afutrainer/afutrainer-2.2
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = YES
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# AFUTrainer
|
||||
|
||||
This is a "fork" by Oliver Saal. The word "fork" is in quotation marks, since the original is not on any VCS (at least to my knowledge). The original source code and question files can be found on O.S.'s [website](http://www.oliver-saal.de/software/afutrainer/).
|
BIN
afutrainer.ico
Normal file
After Width: | Height: | Size: 2.2 KiB |
61
afutrainer.pro
Normal file
|
@ -0,0 +1,61 @@
|
|||
win32 {
|
||||
TEMPLATE = vcapp
|
||||
}
|
||||
else {
|
||||
TEMPLATE = app
|
||||
}
|
||||
TARGET = afutrainer
|
||||
QT += qt gui xml
|
||||
|
||||
HEADERS = mainwindow.h \
|
||||
catalogmodel.h \
|
||||
questionmodel.h \
|
||||
dlglearn.h \
|
||||
dlgviewquestion.h \
|
||||
question.h \
|
||||
chapter.h \
|
||||
catalog.h \
|
||||
dlglearnassistant.h \
|
||||
answer.h \
|
||||
helper.h \
|
||||
chaptermodel.h \
|
||||
osziparchive.h \
|
||||
dlginformation.h \
|
||||
exam.h \
|
||||
dlgexam.h \
|
||||
dlgexamselect.h \
|
||||
error.h \
|
||||
tools.h \
|
||||
dlglearnstatistic.h \
|
||||
dlgexamstatistic.h \
|
||||
plotwidget.h \
|
||||
recentfiles.h
|
||||
|
||||
SOURCES = main.cpp \
|
||||
mainwindow.cpp \
|
||||
catalogmodel.cpp \
|
||||
questionmodel.cpp \
|
||||
dlglearn.cpp \
|
||||
dlgviewquestion.cpp \
|
||||
question.cpp \
|
||||
chapter.cpp \
|
||||
catalog.cpp \
|
||||
dlglearnassistant.cpp \
|
||||
answer.cpp \
|
||||
helper.cpp \
|
||||
chaptermodel.cpp \
|
||||
osziparchive.cpp \
|
||||
dlginformation.cpp \
|
||||
exam.cpp \
|
||||
dlgexam.cpp \
|
||||
dlgexamselect.cpp \
|
||||
error.cpp \
|
||||
tools.cpp \
|
||||
dlglearnstatistic.cpp \
|
||||
dlgexamstatistic.cpp \
|
||||
plotwidget.cpp \
|
||||
recentfiles.cpp
|
||||
|
||||
FORMS = mainwindow.ui dlglearn.ui dlgviewquestion.ui dlglearnassistant.ui dlginformation.ui dlgexamselect.ui dlgexam.ui dlglearnstatistic.ui dlgexamstatistic.ui
|
||||
RC_FILE = afutrainer.rc
|
||||
RESOURCES += afutrainer.qrc
|
36
afutrainer.qrc
Normal file
|
@ -0,0 +1,36 @@
|
|||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>icons/16x16/book1.png</file>
|
||||
<file>icons/16x16/button_ok.png</file>
|
||||
<file>icons/16x16/button_cancel.png</file>
|
||||
<file>icons/16x16/cancel.png</file>
|
||||
<file>icons/16x16/clock.png</file>
|
||||
<file>icons/16x16/contexthelp.png</file>
|
||||
<file>icons/16x16/exit.png</file>
|
||||
<file>icons/16x16/filenew.png</file>
|
||||
<file>icons/16x16/fileopen.png</file>
|
||||
<file>icons/16x16/filesave.png</file>
|
||||
<file>icons/16x16/filesaveas.png</file>
|
||||
<file>icons/16x16/finish.png</file>
|
||||
<file>icons/16x16/folder.png</file>
|
||||
<file>icons/16x16/idea.png</file>
|
||||
<file>icons/16x16/idea_gray.png</file>
|
||||
<file>icons/16x16/idea_info.png</file>
|
||||
<file>icons/16x16/info.png</file>
|
||||
<file>icons/16x16/level0.png</file>
|
||||
<file>icons/16x16/level1.png</file>
|
||||
<file>icons/16x16/level2.png</file>
|
||||
<file>icons/16x16/level3.png</file>
|
||||
<file>icons/16x16/level4.png</file>
|
||||
<file>icons/16x16/level5.png</file>
|
||||
<file>icons/16x16/next.png</file>
|
||||
<file>icons/16x16/previous.png</file>
|
||||
<file>icons/16x16/start.png</file>
|
||||
<file>icons/16x16/stats.png</file>
|
||||
<file>icons/16x16/stop.png</file>
|
||||
<file>icons/16x16/viewmag.png</file>
|
||||
<file>icons/32x32/idea.png</file>
|
||||
<file>icons/32x32/qt.png</file>
|
||||
<file>translations/qt_de.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
1
afutrainer.rc
Normal file
|
@ -0,0 +1 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "afutrainer.ico"
|
119
answer.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
/***************************************************************************
|
||||
* 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 "answer.h"
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
|
||||
|
||||
CAnswer::CAnswer(const QString& strText, const bool bCorrect)
|
||||
{
|
||||
m_strText = strText;
|
||||
m_bIsCorrect = bCorrect;
|
||||
}
|
||||
|
||||
void CAnswer::clear()
|
||||
{
|
||||
m_strText.clear();
|
||||
m_bIsCorrect = false;
|
||||
}
|
||||
|
||||
QString CAnswerClicked::tr (const char *sourceText, const char *comment)
|
||||
{
|
||||
return QCoreApplication::translate("CAnswerClicked", sourceText, comment);
|
||||
}
|
||||
|
||||
void CAnswerClicked::clear()
|
||||
{
|
||||
m_dt = QDateTime::currentDateTime();
|
||||
m_uAnswer=0;
|
||||
m_uNeededTime=0;
|
||||
}
|
||||
|
||||
bool CAnswerClicked::operator < (const CAnswerClicked& ac) const
|
||||
{
|
||||
return m_dt < ac.m_dt;
|
||||
}
|
||||
|
||||
QString CAnswerClicked::answerText(const unsigned uAnswer)
|
||||
{
|
||||
QString strRet;
|
||||
for (int i=0; i<32; i++)
|
||||
{
|
||||
if (uAnswer & (1<<i))
|
||||
{
|
||||
if (!strRet.isEmpty())
|
||||
strRet += ", ";
|
||||
strRet += QChar('A' + i);
|
||||
}
|
||||
}
|
||||
return strRet;
|
||||
}
|
||||
|
||||
QString CAnswerClicked::answerText() const
|
||||
{
|
||||
return answerText(m_uAnswer);
|
||||
}
|
||||
|
||||
QString CAnswerClicked::neededTimeText() const
|
||||
{
|
||||
if (m_uNeededTime < 1000)
|
||||
return tr("< 1 sec");
|
||||
else if (m_uNeededTime < 60000)
|
||||
return tr("%1 sec").arg(m_uNeededTime / 1000);
|
||||
else
|
||||
return tr("%1:%2 min").arg(m_uNeededTime / 60000).arg((m_uNeededTime / 1000) % 60, 2, 10, QChar('0'));
|
||||
}
|
||||
|
||||
bool CAnswerClicked::isCorrect(const QList<CAnswer>& listAnswer) const
|
||||
{
|
||||
unsigned uMask=0;
|
||||
for (int i=0; i<listAnswer.size(); i++)
|
||||
{
|
||||
if (listAnswer.at(i).isCorrect())
|
||||
uMask |= (1<<i);
|
||||
}
|
||||
return (m_uAnswer == uMask);
|
||||
}
|
||||
|
||||
bool CAnswerClicked::load (QDomElement elem)
|
||||
{
|
||||
bool bOk=false;
|
||||
if (elem.tagName() != "answer_clicked") return false;
|
||||
m_dt = QDateTime::fromString (elem.attribute("datetime"), Qt::ISODate);
|
||||
if (!m_dt.isValid()) return false;
|
||||
m_uAnswer = elem.attribute("answer_code").toUInt(&bOk);
|
||||
if (!bOk) return false;
|
||||
m_uNeededTime = elem.attribute("needed_time").toUInt(&bOk);
|
||||
if (!bOk) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAnswerClicked::save (QDomElement& parent, QDomDocument& doc) const
|
||||
{
|
||||
QDomElement elem = doc.createElement("answer_clicked");
|
||||
|
||||
elem.setAttribute("datetime", m_dt.toString(Qt::ISODate));
|
||||
elem.setAttribute("answer_code", QString("%1").arg(m_uAnswer));
|
||||
elem.setAttribute("needed_time", QString("%1").arg(m_uNeededTime));
|
||||
parent.appendChild(elem);
|
||||
}
|
||||
|
142
answer.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ANSWER_H
|
||||
#define ANSWER_H
|
||||
|
||||
#include <qstring.h>
|
||||
#include <qdom.h>
|
||||
#include <qlist.h>
|
||||
#include <qdatetime.h>
|
||||
|
||||
//! Die Klasse CAnswer speichert eine einzelne Antwort auf eine Frage
|
||||
/*!
|
||||
Das Schreiben und Lesen von XML-Daten wird von der Klasse CQuestion übernommen
|
||||
*/
|
||||
|
||||
class CAnswer
|
||||
{
|
||||
public:
|
||||
//! Standard-Konstruktor
|
||||
/*! Initialisiert die Klasse, indem die Funktion clear() aufgerufen wird. */
|
||||
CAnswer() { clear(); }
|
||||
|
||||
//! Konstruktor inkl. setzen eines Textes und ob die Antwort richtig ist
|
||||
/*!
|
||||
\param strText Antworttext
|
||||
\param bCorrect true: Die Antwort ist korrekt
|
||||
\sa m_strText, m_bIsCorrect
|
||||
*/
|
||||
CAnswer(const QString& strText, const bool bCorrect);
|
||||
|
||||
//! Standard-Destruktor
|
||||
/*! In der Standard-Implementierung tut der Destruktor nichts. */
|
||||
~CAnswer() {}
|
||||
|
||||
//! Zurücksetzen aller Werte
|
||||
/*! Es werden alle Daten der Antwort gelöscht. */
|
||||
void clear();
|
||||
//! Überprüfen, ob die Klasse eine Antwort enthält
|
||||
/*! \return true: Die Klasse ist leer und enthält keine Antwort */
|
||||
inline bool isEmpty() const { return m_strText.isEmpty(); }
|
||||
|
||||
//! Auslesen, ob diese Antwort richtig ist
|
||||
/*! \return true: Die Antwort ist richtig */
|
||||
inline bool isCorrect() const { return m_bIsCorrect; }
|
||||
//! Auslesen des Antworttextes
|
||||
/*! \return Antworttext */
|
||||
inline QString text() const { return m_strText; }
|
||||
//! Setzen, ob diese Antwort richtig ist
|
||||
/*!
|
||||
\param bCorrect true: Die Antwort ist korrekt
|
||||
\sa m_bIsCorrect
|
||||
*/
|
||||
inline void setCorrect (const bool bCorrect) { m_bIsCorrect = bCorrect; }
|
||||
//! Setzen des Antworttextes
|
||||
/*!
|
||||
\param strText Antworttext
|
||||
\sa m_strText
|
||||
*/
|
||||
inline void setText(const QString& strText) { m_strText = strText; }
|
||||
|
||||
//! Anhängen eines Textes an den Antworttext
|
||||
/*!
|
||||
\param strText Anzuhängender Text
|
||||
\sa m_strText
|
||||
*/
|
||||
inline void appendText(const QString& strText) { m_strText += strText; }
|
||||
|
||||
protected:
|
||||
//! Antworttext
|
||||
/*!
|
||||
Der Antworttext darf HTML-Code und HTML-Verweise auf Grafiken/Bilder enthalten. Bei Verweisen ist zu achten, dass kein Verzeichnis angegeben werden darf!
|
||||
|
||||
Default: leer
|
||||
*/
|
||||
QString m_strText;
|
||||
//! Richtige oder falsche Antwort
|
||||
/*! Default: false */
|
||||
bool m_bIsCorrect;
|
||||
};
|
||||
|
||||
//! Die Klasse CAnswerClicked speichert eine einzelne Beantwortung des Benutzers
|
||||
/*!
|
||||
*/
|
||||
|
||||
class CAnswerClicked
|
||||
{
|
||||
public:
|
||||
//! Standard-Konstruktor
|
||||
/*! Initialisiert die Klasse, indem die Funktion clear() aufgerufen wird. */
|
||||
CAnswerClicked () { clear(); }
|
||||
CAnswerClicked (const unsigned uAnswer, const unsigned uNeededTime)
|
||||
{ m_uAnswer = uAnswer; m_dt = QDateTime::currentDateTime(); m_uNeededTime = uNeededTime; }
|
||||
//! Standard-Destruktor
|
||||
/*! In der Standard-Implementierung tut der Destruktor nichts. */
|
||||
~CAnswerClicked () {}
|
||||
|
||||
//! Zurücksetzen aller Werte
|
||||
/*! Es werden alle Daten auf Default-Werte zurückgesetzt. */
|
||||
void clear();
|
||||
|
||||
inline QDateTime dateTime() const { return m_dt; }
|
||||
inline unsigned neededTime() const { return m_uNeededTime; }
|
||||
inline unsigned answer() const { return m_uAnswer; }
|
||||
static QString answerText(const unsigned uAnswer);
|
||||
QString answerText() const;
|
||||
QString neededTimeText() const;
|
||||
|
||||
bool isCorrect(const QList<CAnswer>& listAnswer) const;
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc) const;
|
||||
|
||||
static QString tr (const char *sourceText, const char *comment=0);
|
||||
|
||||
bool operator < (const CAnswerClicked& ac) const;
|
||||
|
||||
protected:
|
||||
QDateTime m_dt; //!< Zeitstempel der Antwort
|
||||
unsigned m_uAnswer; //!< Antwort-Bitmaske
|
||||
unsigned m_uNeededTime; //!< Benötigte Zeit in ms
|
||||
};
|
||||
|
||||
#endif
|
433
catalog.cpp
Normal file
|
@ -0,0 +1,433 @@
|
|||
/***************************************************************************
|
||||
* 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 "catalog.h"
|
||||
#include "osziparchive.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include <qdir.h>
|
||||
#include <qfile.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qtextstream.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
CCatalog::~CCatalog()
|
||||
{
|
||||
qDeleteAll(m_listFiles);
|
||||
}
|
||||
|
||||
void CCatalog::clear()
|
||||
{
|
||||
CChapter::clear();
|
||||
m_bMixAnswers = true;
|
||||
m_bSort = false;
|
||||
m_strFileName.clear();
|
||||
m_listHint.clear();
|
||||
m_strUniqueName.clear();
|
||||
qDeleteAll(m_listFiles);
|
||||
m_strPublisher.clear();
|
||||
m_strContact.clear();
|
||||
m_dateValidFrom = QDate();
|
||||
m_dateValidUntil = QDate();
|
||||
m_dateCreated = QDate();
|
||||
m_datePublished = QDate();
|
||||
m_strVersion.clear();
|
||||
m_listExam.clear();
|
||||
m_listExamStat.clear();
|
||||
}
|
||||
|
||||
bool CCatalog::isEmpty()
|
||||
{
|
||||
return m_strText.isEmpty();
|
||||
}
|
||||
|
||||
bool CCatalog::isValid() const
|
||||
{
|
||||
if (m_dateValidFrom.isValid() && QDate::currentDate() < m_dateValidFrom) return false;
|
||||
if (m_dateValidUntil.isValid() && QDate::currentDate() > m_dateValidUntil) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCatalog::hasHints (const QString& strQuestionId) const
|
||||
{
|
||||
for (int i=0; i<m_listHint.size(); i++)
|
||||
{
|
||||
if (m_listHint.at(i).hasQuestion(strQuestionId)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString CCatalog::hintText (const QString& strQuestionId) const
|
||||
{
|
||||
QString str;
|
||||
if (strQuestionId.isEmpty()) return QString();
|
||||
for (int i=0; i<m_listHint.size(); i++)
|
||||
{
|
||||
if (m_listHint.at(i).hasQuestion(strQuestionId))
|
||||
str += m_listHint[i].showText();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
bool CCatalog::load (const QString& strFileName, QWidget *pParent)
|
||||
{
|
||||
QDomDocument doc;
|
||||
QDomElement elemRoot, e;
|
||||
QDomNode n;
|
||||
QString str, strXML;
|
||||
int iErrLine, iErrCol;
|
||||
double dVersion=0.0;
|
||||
CChapter *pChapter=0;
|
||||
|
||||
if (strFileName.right(3).toLower() != "aqz") return false;
|
||||
|
||||
CZipArchive zip;
|
||||
if (!zip.open(strFileName, CZipArchive::OpenReadOnly))
|
||||
{
|
||||
QMessageBox::critical(pParent, pParent->tr("Datei-Fehler"), pParent->tr("Konnte folgende Datei nicht zum Lesen öffnen:\n%1").arg(strFileName));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fragen entpacken
|
||||
CZipFile *pzfQuestions = zip.findFile("questions.xml");
|
||||
if (pzfQuestions == 0)
|
||||
{
|
||||
QMessageBox::critical(pParent, pParent->tr("Datei-Fehler"), pParent->tr("Konnte in der Datei '%1' keine Fragen finden.").arg(strFileName));
|
||||
return false;
|
||||
}
|
||||
strXML = QString::fromUtf8(pzfQuestions->deflateToByteArray());
|
||||
|
||||
clear();
|
||||
|
||||
// Alle Grafiken in temp. Dateien entpacken
|
||||
// pParent->setCursor(Qt::WaitCursor);
|
||||
for (int i=0; i<zip.fileCount(); i++)
|
||||
{
|
||||
CZipFile *pzf = zip.fileAt(i);
|
||||
str = pzf->fileName().right(3);
|
||||
if (str == "png" || str == "jpg" || str == "gif" || str == "bmp")
|
||||
{ // Datei entpacken und Pfade im XML anpassen
|
||||
str = QDir::temp().absoluteFilePath(pzf->fileName()+".XXXXXX");
|
||||
QTemporaryFile *ptf = new QTemporaryFile(str);
|
||||
ptf->open();
|
||||
str = ptf->fileName();
|
||||
pzf->deflateToFile(*ptf);
|
||||
ptf->close();
|
||||
m_listFiles.append(ptf);
|
||||
strXML.replace(pzf->fileName(), str);
|
||||
//qDebug ("Deflating %s to %s", qPrintable(pzf->fileName()), qPrintable(str));
|
||||
}
|
||||
}
|
||||
// pParent->setCursor(Qt::ArrowCursor);
|
||||
|
||||
if (!doc.setContent(strXML, true, &str, &iErrLine, &iErrCol))
|
||||
{
|
||||
QMessageBox::critical(pParent, pParent->tr("XML-Fehler"), pParent->tr("Fragenkatalog: ") + strFileName + "\n" + str + "\n" + QString (pParent->tr("Zeile: %1 Spalte %2")).arg(iErrLine).arg(iErrCol));
|
||||
return false;
|
||||
}
|
||||
|
||||
elemRoot = doc.documentElement ();
|
||||
if (elemRoot.tagName() != "aqdf")
|
||||
{
|
||||
QMessageBox::critical(pParent, pParent->tr("Datei-Fehler"), pParent->tr("Unbekanntes XML-Datenformat '%1'.").arg(elemRoot.tagName()));
|
||||
return false;
|
||||
}
|
||||
//m_strText = elemRoot.attribute ("name");
|
||||
m_dateCreated = QDate::fromString(elemRoot.attribute("created"), Qt::ISODate);
|
||||
dVersion = elemRoot.attribute("version").toDouble();
|
||||
if (dVersion != 1.0)
|
||||
{
|
||||
QMessageBox::information(pParent, pParent->tr("Information"), pParent->tr("Kann die Dateiversion %1 des Fragenkatalogs '%2' nicht lesen.").arg(dVersion).arg(strFileName));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
n = elemRoot.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
e = n.toElement ();
|
||||
if (e.tagName() == QString ("chapter"))
|
||||
{
|
||||
pChapter = new CChapter();
|
||||
if (pChapter->load (e))
|
||||
appendChapter(pChapter);
|
||||
else
|
||||
delete pChapter;
|
||||
}
|
||||
else if (e.tagName() == QString ("exam"))
|
||||
{
|
||||
CExam exam;
|
||||
if (exam.load(e)) m_listExam.append(exam);
|
||||
}
|
||||
else if (e.tagName () == "hint")
|
||||
{
|
||||
CHint hint;
|
||||
if (hint.load (e))
|
||||
m_listHint.append (hint);
|
||||
}
|
||||
else if (e.tagName () == "title")
|
||||
{
|
||||
m_strText = e.text();
|
||||
m_strUniqueName = e.attribute("unique");
|
||||
}
|
||||
else if (e.tagName () == "comment")
|
||||
m_strComment = e.text();
|
||||
else if (e.tagName () == "contact")
|
||||
m_strContact = e.text();
|
||||
else if (e.tagName () == "publisher")
|
||||
m_strPublisher = e.text();
|
||||
else if (e.tagName() == "valid")
|
||||
{
|
||||
m_dateValidFrom = QDate::fromString(e.attribute("from"), Qt::ISODate);
|
||||
m_dateValidUntil = QDate::fromString(e.attribute("until"), Qt::ISODate);
|
||||
}
|
||||
else if (e.tagName() == "version")
|
||||
{
|
||||
m_datePublished = QDate::fromString(e.attribute("published"), Qt::ISODate);
|
||||
m_strVersion = e.text();
|
||||
}
|
||||
else if (e.tagName() == "options")
|
||||
{
|
||||
m_bMixAnswers = QVariant(e.attribute("mixanswers", "true")).toBool();
|
||||
m_bSort = QVariant(e.attribute("sort", "false")).toBool();
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
|
||||
if (m_strUniqueName.isEmpty())
|
||||
m_strUniqueName = QDir(strFileName).dirName();
|
||||
|
||||
if (m_bSort) sortAll();
|
||||
|
||||
loadStatistic (pParent);
|
||||
updateStatistic();
|
||||
|
||||
m_strFileName = strFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCatalog::save (const QString& strFileName, QWidget *pParent)
|
||||
{
|
||||
QFile file (strFileName);
|
||||
|
||||
if (strFileName.isEmpty()) return false;
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::critical(pParent, QString(pParent->tr("Datei-Fehler")), pParent->tr("Konnte folgende Datei nicht zum Schreiben öffnen:\n")+strFileName);
|
||||
return false;
|
||||
}
|
||||
QTextStream out(&file);
|
||||
|
||||
QDomDocument doc("afutrainer");
|
||||
QDomElement elemRoot = doc.createElement("afutrainer");
|
||||
//elemRoot.setAttribute("name", name());
|
||||
elemRoot.setAttribute("version", 3.0);
|
||||
elemRoot.setAttribute("created", QDate::currentDate().toString(Qt::ISODate));
|
||||
doc.appendChild(elemRoot);
|
||||
|
||||
|
||||
// save unique name
|
||||
QDomElement elemTitle = createXmlTextElement("title", name(), doc);
|
||||
elemTitle.setAttribute("unique", m_strUniqueName);
|
||||
elemRoot.appendChild (elemTitle);
|
||||
|
||||
// save comment
|
||||
if (!m_strComment.isEmpty())
|
||||
elemRoot.appendChild (createXmlTextElement("comment", m_strComment, doc));
|
||||
|
||||
// save contact
|
||||
if (!m_strContact.isEmpty())
|
||||
elemRoot.appendChild (createXmlTextElement("contact", m_strContact, doc));
|
||||
|
||||
// save publisher
|
||||
if (!m_strPublisher.isEmpty())
|
||||
elemRoot.appendChild (createXmlTextElement("publisher", m_strPublisher, doc));
|
||||
|
||||
// save version
|
||||
QDomElement elemVersion = createXmlTextElement("version", m_strVersion, doc);
|
||||
elemVersion.setAttribute("published", m_datePublished.toString(Qt::ISODate));
|
||||
elemRoot.appendChild(elemVersion);
|
||||
|
||||
// save dates
|
||||
if (m_dateValidFrom.isValid() || m_dateValidUntil.isValid())
|
||||
{
|
||||
QDomElement elemValid = doc.createElement("valid");
|
||||
elemValid.setAttribute("from", m_dateValidFrom.toString(Qt::ISODate));
|
||||
elemValid.setAttribute("until", m_dateValidUntil.toString(Qt::ISODate));
|
||||
elemRoot.appendChild(elemValid);
|
||||
}
|
||||
|
||||
// TODO: save tests
|
||||
|
||||
|
||||
// save chapters
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
m_listChapter[i]->save(elemRoot, doc);
|
||||
|
||||
// save helpers
|
||||
for (int i=0; i<m_listHint.size(); i++)
|
||||
m_listHint[i].save(elemRoot, doc);
|
||||
|
||||
out << doc.toString();
|
||||
|
||||
m_strFileName = strFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CCatalog::statisticFileName() const
|
||||
{
|
||||
QDir dir;
|
||||
QString str = dir.homePath()+QString("/.afutrainer/") + m_strUniqueName + QString(".stat.xml");
|
||||
Q_ASSERT(!m_strUniqueName.isEmpty());
|
||||
return (str);
|
||||
}
|
||||
|
||||
bool CCatalog::loadStatistic(QWidget *pParent)
|
||||
{
|
||||
QDomDocument doc;
|
||||
QDomElement elemRoot, e;
|
||||
QDomNode n;
|
||||
QFile file (statisticFileName());
|
||||
QString strVerzeichnis, str, strXML;
|
||||
int iErrLine, iErrCol;
|
||||
|
||||
if (!file.exists()) return true;
|
||||
if (!file.open (QIODevice::ReadOnly))
|
||||
{
|
||||
QMessageBox::critical(pParent, QString(pParent->tr("Datei-Fehler")), pParent->tr("Konnte folgende Datei nicht zum Lesen öffnen:\n")+statisticFileName());
|
||||
return false;
|
||||
}
|
||||
QTextStream in (&file);
|
||||
strXML = in.readAll();
|
||||
|
||||
if (!doc.setContent(strXML, true, &str, &iErrLine, &iErrCol))
|
||||
{
|
||||
QMessageBox::critical(pParent, pParent->tr("XML-Fehler"), pParent->tr("Statistik zum Fragenkatalog: ") + statisticFileName() + "\n" + str + "\n" + QString (pParent->tr("Zeile: %1 Spalte %2")).arg(iErrLine).arg(iErrCol));
|
||||
return false;
|
||||
}
|
||||
file.close ();
|
||||
|
||||
elemRoot = doc.documentElement ();
|
||||
if (doc.doctype().name() != "AFUTrainerStatistics") return false;
|
||||
if (elemRoot.tagName() != "statistic") return false;
|
||||
|
||||
n = elemRoot.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
e = n.toElement ();
|
||||
if (e.tagName() == QString ("learning"))
|
||||
{
|
||||
loadLearnStatistic(e);
|
||||
}
|
||||
else if (e.tagName() == QString("exams"))
|
||||
loadExamStatistic(e);
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCatalog::saveStatistic(QWidget *pParent)
|
||||
{
|
||||
QDomDocument doc ("AFUTrainerStatistics");
|
||||
QString strFileName = statisticFileName();
|
||||
QFile file (strFileName);
|
||||
|
||||
if (m_strUniqueName.isEmpty()) return false;
|
||||
QDomElement elemRoot = doc.createElement ("statistic");
|
||||
elemRoot.setAttribute ("name", name());
|
||||
elemRoot.setAttribute("version", 2);
|
||||
elemRoot.setAttribute("date", QDate::currentDate().toString(Qt::ISODate));
|
||||
doc.appendChild (elemRoot);
|
||||
|
||||
QDomElement elemLearn = doc.createElement ("learning");
|
||||
elemRoot.appendChild (elemLearn);
|
||||
|
||||
saveLearnStatistic(elemLearn, doc);
|
||||
|
||||
QDomElement elemExams = doc.createElement ("exams");
|
||||
elemRoot.appendChild (elemExams);
|
||||
saveExamStatistic(elemExams, doc);
|
||||
|
||||
if (!file.open (QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::critical (pParent, pParent->tr("Fehler"), pParent->tr("Konnte folgende Datei nicht zum Schreiben öffnen.\n")+strFileName);
|
||||
return false;
|
||||
}
|
||||
QTextStream out(&file);
|
||||
out << doc.toString ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCatalog::loadExamStatistic (QDomElement& elemRoot)
|
||||
{
|
||||
QDomNode n;
|
||||
QDomElement e;
|
||||
|
||||
n = elemRoot.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
e = n.toElement ();
|
||||
if (e.tagName() == QString ("exam"))
|
||||
{
|
||||
CExamStat es;
|
||||
if (es.load(e)) m_listExamStat.append(es);
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCatalog::saveExamStatistic (QDomElement& parent, QDomDocument& doc)
|
||||
{
|
||||
for (int i=0; i<m_listExamStat.size(); i++)
|
||||
{
|
||||
m_listExamStat.at(i).save (parent, doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QList<CChapter*> CCatalog::chapters()
|
||||
{
|
||||
QList<CChapter*> list;
|
||||
list.append(this);
|
||||
list << subChapters();
|
||||
return list;
|
||||
}
|
||||
|
||||
CExam CCatalog::examById(const QString& strId) const
|
||||
{
|
||||
for (int i=0; i<m_listExam.size(); i++)
|
||||
{
|
||||
if (m_listExam.at(i).id() == strId)
|
||||
return m_listExam.at(i);
|
||||
}
|
||||
return CExam();
|
||||
}
|
120
catalog.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CATALOG_H
|
||||
#define CATALOG_H
|
||||
|
||||
#include "chapter.h"
|
||||
#include "exam.h"
|
||||
|
||||
#include <qlist.h>
|
||||
#include <qtemporaryfile.h>
|
||||
|
||||
class CCatalog : public CChapter
|
||||
{
|
||||
public:
|
||||
CCatalog() : CChapter() { clear(); }
|
||||
~CCatalog();
|
||||
|
||||
void clear();
|
||||
bool isEmpty();
|
||||
|
||||
inline QString name() const { return m_strText; }
|
||||
inline void setName(const QString& strName) { m_strText = strName; }
|
||||
|
||||
inline QString contact() const { return m_strContact; }
|
||||
inline void setContact(const QString& strContact) { m_strContact = strContact; }
|
||||
inline QString publisher() const { return m_strPublisher; }
|
||||
inline void setPublisher(const QString& strPublisher) { m_strPublisher = strPublisher; }
|
||||
|
||||
// Validation
|
||||
inline QDate validFrom() const { return m_dateValidFrom; }
|
||||
inline void setValidFrom(const QDate& date) { m_dateValidFrom = date; }
|
||||
inline QDate validUntil() const { return m_dateValidUntil; }
|
||||
inline void setValidUntil(const QDate& date) { m_dateValidUntil = date; }
|
||||
bool isValid() const;
|
||||
inline QDate created() const { return m_dateCreated; }
|
||||
inline void setCreated(const QDate& date) { m_dateCreated = date; }
|
||||
inline QDate published() const { return m_datePublished; }
|
||||
inline void setPublished(const QDate& date) { m_datePublished = date; }
|
||||
inline QString versionText() const { return m_strVersion; }
|
||||
inline void setVersionText(const QString& str) { m_strVersion = str; }
|
||||
|
||||
// file operations
|
||||
inline QString fileName() const { return m_strFileName; }
|
||||
bool load (const QString& strFileName, QWidget *pParent);
|
||||
bool save (const QString& strFileName, QWidget *pParent);
|
||||
|
||||
bool loadStatistic(QWidget *pParent);
|
||||
bool saveStatistic(QWidget *pParent);
|
||||
|
||||
// hints
|
||||
inline int countHint() const { return m_listHint.size(); }
|
||||
inline const CHint& hintAt(int i) const { return m_listHint.at(i); }
|
||||
inline CHint& hintAt(int i) { return m_listHint[i]; }
|
||||
inline void appendHint(const CHint& a) { m_listHint.append(a); }
|
||||
bool hasHints (const QString& strQuestionId) const;
|
||||
QString hintText (const QString& strQuestionId) const;
|
||||
|
||||
// exams
|
||||
inline int countExam() const { return m_listExam.size(); }
|
||||
inline const CExam& examAt(int i) const { return m_listExam.at(i); }
|
||||
inline CExam& examAt(int i) { return m_listExam[i]; }
|
||||
inline void appendExam(const CExam& a) { m_listExam.append(a); }
|
||||
CExam examById(const QString& strId) const;
|
||||
|
||||
inline void appendExamStat(const CExamStat& a) { m_listExamStat.append(a); }
|
||||
inline int countExamStat() const { return m_listExamStat.size(); }
|
||||
inline const CExamStat& examStatAt(int i) const { return m_listExamStat.at(i); }
|
||||
|
||||
// options
|
||||
inline bool useMixedAnswers() const { return m_bMixAnswers; }
|
||||
|
||||
// others
|
||||
QList<CChapter*> chapters();
|
||||
|
||||
protected:
|
||||
QString statisticFileName() const;
|
||||
bool loadExamStatistic (QDomElement& elemRoot);
|
||||
void saveExamStatistic (QDomElement& parent, QDomDocument& doc);
|
||||
|
||||
protected:
|
||||
QString m_strFileName;
|
||||
QString m_strUniqueName;
|
||||
QList<QTemporaryFile*> m_listFiles;
|
||||
|
||||
QList<CHint> m_listHint;
|
||||
QString m_strContact;
|
||||
QString m_strPublisher;
|
||||
QDate m_dateValidFrom;
|
||||
QDate m_dateValidUntil;
|
||||
QDate m_dateCreated;
|
||||
QDate m_datePublished;
|
||||
QString m_strVersion;
|
||||
QList<CExam> m_listExam;
|
||||
QList<CExamStat> m_listExamStat;
|
||||
|
||||
// Optionen
|
||||
bool m_bMixAnswers;
|
||||
bool m_bSort;
|
||||
};
|
||||
|
||||
#endif
|
205
catalogmodel.cpp
Normal file
|
@ -0,0 +1,205 @@
|
|||
/***************************************************************************
|
||||
* 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 "catalogmodel.h"
|
||||
|
||||
#include "catalog.h"
|
||||
|
||||
#define COL_CHAPTER 0
|
||||
#define COL_QUESTION 1
|
||||
#define COL_ASSIST 2
|
||||
#define COL_AVG 3
|
||||
|
||||
CCatalogModel::CCatalogModel (QObject *pParent) : QAbstractItemModel (pParent)
|
||||
{
|
||||
m_pCatalog = 0;
|
||||
}
|
||||
|
||||
CCatalogModel::~CCatalogModel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CCatalogModel::onLanguageChanged()
|
||||
{
|
||||
headerDataChanged(Qt::Horizontal, 0, columnCount()-1);
|
||||
}
|
||||
|
||||
void CCatalogModel::setModelData (CCatalog *pCatalog)
|
||||
{
|
||||
reset();
|
||||
m_pCatalog = pCatalog;
|
||||
reset();
|
||||
}
|
||||
|
||||
int CCatalogModel::columnCount (const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant CCatalogModel::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Vertical) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == COL_CHAPTER)
|
||||
return tr("Kapitel");
|
||||
else if (section == COL_QUESTION)
|
||||
return tr("Fragen");
|
||||
else if (section == COL_AVG)
|
||||
return tr("Ø");
|
||||
else if (section == COL_ASSIST)
|
||||
return tr("Lernassistent");
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (section == COL_CHAPTER)
|
||||
return tr("Kapitelname\nBitte markieren Sie das Kapitel, das Sie lernen möchten.");
|
||||
else if (section == COL_QUESTION)
|
||||
return tr("Anzahl d. Fragen inkl. Unterkapitel");
|
||||
else if (section == COL_AVG)
|
||||
return tr("Durchschnittlicher Lernfortschritt");
|
||||
else if (section == COL_ASSIST)
|
||||
return tr("Empfehlung des Lernassistentes");
|
||||
}
|
||||
else if (role == Qt::WhatsThisRole)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant CCatalogModel::data (const QModelIndex& index, int role) const
|
||||
{
|
||||
CChapter *p = (CChapter*) index.internalPointer();
|
||||
|
||||
if (m_pCatalog == 0 || !index.isValid()) return QVariant();
|
||||
|
||||
if (role == Qt::TextAlignmentRole && index.column() == COL_QUESTION) return Qt::AlignRight;
|
||||
|
||||
if (p == 0) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == COL_CHAPTER)
|
||||
{
|
||||
if (p->id().isEmpty())
|
||||
return p->text();
|
||||
else
|
||||
return p->id() + " - " + p->text();
|
||||
}
|
||||
else if (index.column() == COL_QUESTION)
|
||||
return QString("%1").arg(p->countSubQuestion());
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationText();
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (index.column() == COL_CHAPTER)
|
||||
return QIcon(":/icons/16x16/folder.png");
|
||||
else if (index.column() == COL_AVG)
|
||||
{
|
||||
return p->levelAvgIcon();
|
||||
}
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationIcon(m_pCatalog);
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (index.column() == COL_AVG)
|
||||
{
|
||||
return QString ("%1 - Kennzahl: %2").arg(p->/*statistic().*/levelAvgText()).arg(p->/*statistic().*/levelAvg(), 4, 'f', 2);
|
||||
}
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationToolTip();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool CCatalogModel::hasChildren (const QModelIndex& parent) const
|
||||
{
|
||||
CChapter *p = (CChapter*) parent.internalPointer();
|
||||
|
||||
if (m_pCatalog == 0) return false;
|
||||
|
||||
if (parent.isValid() && p)
|
||||
return (p->countChapter() > 0);
|
||||
else // root item
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex CCatalogModel::index (int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
CChapter *pParent = (CChapter*) parent.internalPointer();
|
||||
|
||||
if (!parent.isValid())
|
||||
{ // root item
|
||||
return createIndex (row, column, (void*) m_pCatalog);
|
||||
}
|
||||
else
|
||||
{
|
||||
// take entry from parent item
|
||||
if (row > pParent->countChapter())
|
||||
return QModelIndex();
|
||||
return createIndex (row, column, (void*)pParent->chapterAt(row));
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex CCatalogModel::parent (const QModelIndex& index) const
|
||||
{
|
||||
CChapter *pIndex = (CChapter*) index.internalPointer();
|
||||
int iRow=0;
|
||||
|
||||
if (pIndex == 0 || pIndex->parentChapter() == 0) // root item
|
||||
return QModelIndex(); // has no parent
|
||||
|
||||
CChapter *pParent = pIndex->parentChapter();
|
||||
if (pParent->parentChapter())
|
||||
iRow = pParent->parentChapter()->indexOfChapter(pParent);
|
||||
else // parent is the root item (parent of the parent doesn't exist)
|
||||
iRow = 0;
|
||||
|
||||
return createIndex (iRow, 0 /*index.column()*/, pParent);
|
||||
}
|
||||
|
||||
int CCatalogModel::rowCount (const QModelIndex& parent) const
|
||||
{
|
||||
CChapter *pParent = (CChapter*) parent.internalPointer();
|
||||
|
||||
if (m_pCatalog == 0 || m_pCatalog->isEmpty()) return 0;
|
||||
|
||||
if (!parent.isValid()) // root item
|
||||
return 1;
|
||||
|
||||
return pParent->countChapter();
|
||||
}
|
||||
|
55
catalogmodel.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CATALOGMODEL_H
|
||||
#define CATALOGMODEL_H
|
||||
|
||||
#include <qabstractitemmodel.h>
|
||||
|
||||
class CCatalog;
|
||||
|
||||
class CCatalogModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CCatalogModel (QObject *pParent=0);
|
||||
~CCatalogModel();
|
||||
|
||||
void setModelData (CCatalog *pCatalog);
|
||||
|
||||
public:
|
||||
virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
|
||||
virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
|
||||
virtual bool hasChildren (const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
|
||||
virtual QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QModelIndex parent ( const QModelIndex & index ) const;
|
||||
virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
|
||||
|
||||
public slots:
|
||||
void onLanguageChanged();
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
808
chapter.cpp
Normal file
|
@ -0,0 +1,808 @@
|
|||
/***************************************************************************
|
||||
* 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 "catalog.h"
|
||||
#include <qcoreapplication.h>
|
||||
|
||||
|
||||
QString CChapter::tr (const char *sourceText, const char *comment)
|
||||
{
|
||||
return QCoreApplication::translate("CChapter", sourceText, comment);
|
||||
}
|
||||
|
||||
void CChapter::clear()
|
||||
{
|
||||
m_pParentChapter=0;
|
||||
m_strId.clear();
|
||||
m_strText.clear();
|
||||
m_strComment.clear();
|
||||
m_recom = RecommendationNone;
|
||||
m_recom2 = RecommendationNone;
|
||||
qDeleteAll(m_listChapter);
|
||||
qDeleteAll(m_listQuestion);
|
||||
m_bHasLearningNew = false;
|
||||
m_bHasKnownQuestions = false;
|
||||
m_bHasKnownQuestionsRepeatToday = false;
|
||||
m_uNeverAskedCount = 0;
|
||||
for (int i=0; i<=LEVEL_MAX; i++) m_uLevelCount[i] = 0;
|
||||
for (int i=0; i<=RecommendationMax; i++) m_uRecomCount[i] = 0;
|
||||
// m_mapExam.clear();
|
||||
}
|
||||
|
||||
int CChapter::countSubQuestion() const
|
||||
{
|
||||
int i=0, iRet=0;
|
||||
for (i=0; i<m_listChapter.size(); i++)
|
||||
iRet += m_listChapter.at(i)->countSubQuestion();
|
||||
return (iRet + m_listQuestion.size());
|
||||
}
|
||||
|
||||
bool CChapter::load (QDomElement elem)
|
||||
{
|
||||
CChapter *pChapter=0;
|
||||
|
||||
if (elem.tagName () != QString ("chapter")) return false;
|
||||
if (!elem.hasAttribute ("name")) return false;
|
||||
// if (pParent != NULL && !elem.hasAttribute ("id")) return false;
|
||||
m_strId = elem.attribute ("id");
|
||||
m_strText = elem.attribute ("name");
|
||||
QDomNode n = elem.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
QDomElement e = n.toElement ();
|
||||
if (e.tagName() == "comment")
|
||||
m_strComment = e.text();
|
||||
else if (e.tagName() == QString ("chapter"))
|
||||
{
|
||||
pChapter = new CChapter();
|
||||
if (pChapter->load (e))
|
||||
appendChapter(pChapter);
|
||||
else
|
||||
delete pChapter;
|
||||
}
|
||||
else if (e.tagName() == QString ("question"))
|
||||
{
|
||||
CQuestion *pQuestion = new CQuestion();
|
||||
if (pQuestion->load (e))
|
||||
appendQuestion(pQuestion);
|
||||
else
|
||||
delete pQuestion;
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
updateStatistic();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CChapter::save (QDomElement& parent, QDomDocument& doc)
|
||||
{
|
||||
QDomElement elem = doc.createElement("chapter");
|
||||
|
||||
elem.setAttribute("name", text());
|
||||
elem.setAttribute("id", id());
|
||||
|
||||
if (!m_strComment.isEmpty())
|
||||
{
|
||||
QDomElement elemComment = doc.createElement("comment");
|
||||
QDomText textComment = doc.createTextNode(text());
|
||||
elemComment.appendChild(textComment);
|
||||
elem.appendChild(elemComment);
|
||||
}
|
||||
|
||||
parent.appendChild(elem);
|
||||
|
||||
// save exams
|
||||
/* QStringList strl = m_mapExam.keys();
|
||||
for (int i=0; i<strl.size(); i++)
|
||||
{
|
||||
QDomElement e = doc.createElement("exam");
|
||||
e.setAttribute("id", strl.at(i));
|
||||
e.setAttribute("questions", QString("%1").arg(m_mapExam[strl.at(i)]));
|
||||
elem.appendChild(e);
|
||||
}
|
||||
*/
|
||||
// save chapters
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
m_listChapter[i]->save(elem, doc);
|
||||
}
|
||||
|
||||
// save questions
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
m_listQuestion[i]->save(elem, doc);
|
||||
}
|
||||
}
|
||||
|
||||
bool CChapter::loadLearnStatistic (QDomElement elem)
|
||||
{
|
||||
QList<CQuestion*> listQuestionPool = questionPool();
|
||||
|
||||
if (elem.tagName () != QString ("learning")) return false;
|
||||
|
||||
QDomNode n = elem.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
QDomElement e = n.toElement ();
|
||||
if (e.tagName() == QString ("question"))
|
||||
{
|
||||
QString strId = e.attribute("id");
|
||||
for (int i=0; i<listQuestionPool.size(); i++)
|
||||
{
|
||||
if (listQuestionPool.at(i)->id() == strId)
|
||||
listQuestionPool[i]->loadLearnStatistic(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
updateRecommendation();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CChapter::saveLearnStatistic (QDomElement& parent, QDomDocument& doc)
|
||||
{
|
||||
// questions from sub-chapters
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
m_listChapter[i]->saveLearnStatistic(parent, doc);
|
||||
}
|
||||
|
||||
// save questions
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
m_listQuestion[i]->saveLearnStatistic(parent, doc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CChapter::checkForErrors() const
|
||||
{
|
||||
QString str;
|
||||
|
||||
// check chapters
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
str += m_listChapter[i]->checkForErrors();
|
||||
}
|
||||
|
||||
// check questions
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
str += m_listQuestion[i]->checkForErrors();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
QList<CChapter*> CChapter::subChapters() const
|
||||
{
|
||||
QList<CChapter*> list;
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
list << m_listChapter.at(i);
|
||||
list << m_listChapter[i]->subChapters();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<CQuestion*> CChapter::questionPool() const
|
||||
{
|
||||
QList<CQuestion*> list;
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
list << m_listChapter[i]->questionPool();
|
||||
}
|
||||
list << m_listQuestion;
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<CQuestion*> CChapter::questionPoolLevel(const unsigned uLevel) const
|
||||
{
|
||||
QList<CQuestion*> list;
|
||||
int i;
|
||||
for (i=0; i<m_listChapter.size(); i++)
|
||||
list << m_listChapter[i]->questionPoolLevel(uLevel);
|
||||
for (i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
if (m_listQuestion.at(i)->level() == uLevel)
|
||||
list.append (m_listQuestion.at(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<CQuestion*> CChapter::questionPoolDeepen() const
|
||||
{
|
||||
QList<CQuestion*> list;
|
||||
int i;
|
||||
for (i=0; i<m_listChapter.size(); i++)
|
||||
list << m_listChapter[i]->questionPoolDeepen();
|
||||
for (i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
CQuestion *q = m_listQuestion.at(i);
|
||||
if (q->level() == LEVEL_VERYOFTEN && !q->isNeverAsked())
|
||||
list.append (q);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<CQuestion*> CChapter::questionPoolRepeat(const QDate d) const
|
||||
{
|
||||
QList<CQuestion*> list;
|
||||
int i;
|
||||
for (i=0; i<m_listChapter.size(); i++)
|
||||
list << m_listChapter[i]->questionPoolRepeat(d);
|
||||
for (i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
CQuestion *q = m_listQuestion.at(i);
|
||||
if (q->repeatDate() <= d)
|
||||
list.append (q);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void CChapter::updateStatisticCount()
|
||||
{
|
||||
/* for (int i=0; i<m_listQuestion.size(); i++)
|
||||
if (m_listQuestion.at(i)->isLearningNew()) return true;
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
if (m_listChapter.at(i)->isLearningNew()) return true;
|
||||
|
||||
return false;
|
||||
*/
|
||||
// Alle Statistiken zurücksetzen
|
||||
m_uNeverAskedCount = 0;
|
||||
m_bHasLearningNew = false;
|
||||
m_bHasKnownQuestions = false;
|
||||
m_bHasKnownQuestionsRepeatToday = false;
|
||||
for (int i=0; i<=LEVEL_MAX; i++) m_uLevelCount[i] = 0;
|
||||
|
||||
// Zuerst Statistiken für Unterkapitel berechnen und integrieren
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
CChapter *p = m_listChapter.at(i);
|
||||
p->updateStatisticCount();
|
||||
for (int j=0; j<=LEVEL_MAX; j++)
|
||||
m_uLevelCount[j] += p->m_uLevelCount[j];
|
||||
m_uNeverAskedCount += p->m_uNeverAskedCount;
|
||||
if (p->hasLearningNewQuestions()) m_bHasLearningNew = true;
|
||||
if (p->hasKnownQuestions()) m_bHasKnownQuestions = true;
|
||||
if (p->hasKnownQuestionsRepeatToday()) m_bHasKnownQuestionsRepeatToday = true;
|
||||
}
|
||||
|
||||
// Anschließend Statistiken für eigene Fragen neu berechnen und hinzufügen
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
CQuestion *q = m_listQuestion.at(i);
|
||||
if (q->isNeverAsked()) m_uNeverAskedCount++;
|
||||
m_uLevelCount[q->level()]++;
|
||||
if (q->isLearningNew()) m_bHasLearningNew = true;
|
||||
if (q->isKnownQuestion()) m_bHasKnownQuestions = true;
|
||||
if (q->isKnownQuestion() && q->isRepeatToday()) m_bHasKnownQuestionsRepeatToday = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CChapter::updateRecommendationStatistic()
|
||||
{
|
||||
for (int i=0; i<RecommendationMax; i++) m_uRecomCount[i] = 0;
|
||||
m_uRecomCount[recommendation()]=1;
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
CChapter *p = m_listChapter.at(i);
|
||||
p->updateRecommendationStatistic();
|
||||
for (int j=0; j<RecommendationMax; j++)
|
||||
m_uRecomCount[j] += p->m_uRecomCount[j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Berechnet die Statistik für das Kapitel inkl. aller Unterkapitel neu.
|
||||
*/
|
||||
void CChapter::updateStatistic()
|
||||
{
|
||||
updateStatisticCount();
|
||||
updateRecommendation();
|
||||
updateRecommendationStatistic();
|
||||
}
|
||||
|
||||
/*
|
||||
CRecommendation CChapter::recommendation() const
|
||||
{
|
||||
CRecommendation r;
|
||||
r.create(this);
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
CRecommendationStatistic CChapter::recommendationStatistic() const
|
||||
{
|
||||
CRecommendationStatistic rs;
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
rs.append(m_listChapter.at(i)->recommendationStatistic());
|
||||
}
|
||||
//TODO
|
||||
// rs.append(recommendation());
|
||||
return rs;
|
||||
}
|
||||
*/
|
||||
|
||||
QString CChapter::idWithParents() const
|
||||
{
|
||||
CChapter *pParent=m_pParentChapter;
|
||||
QString str;
|
||||
str = id();
|
||||
while (pParent != 0)
|
||||
{
|
||||
str = pParent->id() + str;
|
||||
pParent = pParent->m_pParentChapter;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*!
|
||||
Das empfohlene Wiederholdatum eines Kapitels das frühestete Datum,
|
||||
an dem eine Frage des Kapitels oder Unterkapitels wiederholt werden sollte.
|
||||
\return Datum, wann das Kapitel wiederholt werden soll.
|
||||
Gibt es kein solches Datum, so wird ein ungültiges Datum (QDate::isValid()) zurückgegeben.
|
||||
Hinweis: Das Datum kann auch in der Vergangenheit liegen!
|
||||
*/
|
||||
QDate CChapter::repeatDate() const
|
||||
{
|
||||
QDate d;
|
||||
QList<CQuestion*> list = questionPool();
|
||||
|
||||
for (int i=0; i<list.size(); i++)
|
||||
{
|
||||
QDate dq = list.at(i)->repeatDate();
|
||||
if (!dq.isValid()) continue;
|
||||
if (!d.isValid() || dq < d) d = dq;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/*!
|
||||
Die Variable m_recomRepeatDate muss up to date sein!
|
||||
|
||||
\return Lernempfehlung dieses Kapitels ohne Berücksichtigung evt. vorhandener ünter- oder übergeordneter Kapitel.
|
||||
|
||||
\sa m_recomRepeatDate
|
||||
*/
|
||||
CChapter::Recommendation CChapter::recommendationIndividual() const
|
||||
{
|
||||
if (!m_recomRepeatDate.isValid())
|
||||
return RecommendationLearnNew;
|
||||
else if (m_recomRepeatDate <= QDate::currentDate())
|
||||
{
|
||||
if (hasLearningNewQuestions() && !hasKnownQuestionsRepeatToday())
|
||||
return RecommendationLearnNew;
|
||||
else
|
||||
return RecommendationRepeatToday;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (countNeverAsked() > 0)
|
||||
return RecommendationLearnNew;
|
||||
else
|
||||
return RecommendationRepeatLater;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Aktualisiert die Lernempfehlung für dieses Kapitel und alle Unterkapitel
|
||||
\sa m_recom
|
||||
*/
|
||||
void CChapter::updateRecommendation()
|
||||
{
|
||||
m_recom = RecommendationNone;
|
||||
m_recom2 = RecommendationNone;
|
||||
|
||||
m_recomRepeatDate = repeatDate(); /*QDate();*/
|
||||
if (m_listChapter.isEmpty() && m_listQuestion.isEmpty()) return;
|
||||
|
||||
if (m_pParentChapter && m_pParentChapter->recommendation() != RecommendationSubChapter)
|
||||
m_recom = RecommendationParentChapter;
|
||||
else
|
||||
{
|
||||
if (countSubQuestion() > 20)
|
||||
{ // Nur wenn in den Unterkapiteln zusammen mehr als x Fragen sind, zuerst die Unterkapitel einzeln lernen lassen
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
CChapter *p = m_listChapter.at(i);
|
||||
if (p->levelAvg() < LEVEL_NORMAL || p->countNeverAsked() > 0)
|
||||
m_recom = RecommendationSubChapter;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_recom == RecommendationNone)
|
||||
{
|
||||
//m_recomRepeatDate = repeatDate();
|
||||
m_recom = recommendationIndividual();
|
||||
}
|
||||
}
|
||||
|
||||
// Alternative Empfehlung
|
||||
if (m_recom == RecommendationParentChapter || m_recom == RecommendationSubChapter)
|
||||
{
|
||||
m_recom2 = recommendationIndividual();
|
||||
if (m_recom2 != RecommendationLearnNew && m_recom2 != RecommendationRepeatToday)
|
||||
m_recom2 = RecommendationNone;
|
||||
}
|
||||
|
||||
// find recommended questions
|
||||
m_listQuestionRecommended.clear();
|
||||
QList<CQuestion*> list = questionPool();
|
||||
for (int i=0; i<list.size(); i++)
|
||||
{
|
||||
CQuestion *q = list.at(i);
|
||||
if (m_recom == RecommendationLearnNew || m_recom2 == RecommendationLearnNew)
|
||||
{
|
||||
if (q->isNeverAsked() || q->isLearningNew())
|
||||
m_listQuestionRecommended.append(q);
|
||||
}
|
||||
else if (m_recom == RecommendationRepeatToday || m_recom2 == RecommendationRepeatToday)
|
||||
{
|
||||
if (q->isRepeatToday())
|
||||
m_listQuestionRecommended.append(q);
|
||||
}
|
||||
}
|
||||
|
||||
// update child chapters
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
CChapter *p = m_listChapter.at(i);
|
||||
p->updateRecommendation();
|
||||
//m_listQuestionRecommended << p->m_listQuestionRecommended;
|
||||
}
|
||||
}
|
||||
/*
|
||||
bool CChapter::hasRecommendedQuestions() const
|
||||
{
|
||||
return (m_recom == RecommendationLearnNew || m_recom == RecommendationRepeatToday);
|
||||
}
|
||||
|
||||
QList<CQuestion*> CChapter::recommendedQuestions() const
|
||||
{
|
||||
QList<CQuestion*> listRet, list = questionPool();
|
||||
|
||||
if (m_recom != RecommendationLearnNew && m_recom != RecommendationRepeatToday) return listRet;
|
||||
|
||||
for (int i=0; i<list.size(); i++)
|
||||
{
|
||||
CQuestion *q = list.at(i);
|
||||
switch (m_recom)
|
||||
{
|
||||
case RecommendationLearnNew:
|
||||
if (q->isNeverAsked() || q->isLearningNew())
|
||||
listRet.append(q);
|
||||
break;
|
||||
case RecommendationRepeatToday:
|
||||
if (q->isRepeatToday())
|
||||
listRet.append(q);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return listRet;
|
||||
}
|
||||
*/
|
||||
|
||||
QString CChapter::recommendationText(const Recommendation r, const QDate dRepeat)
|
||||
{
|
||||
unsigned uDays=0;
|
||||
switch (r)
|
||||
{
|
||||
default:
|
||||
case RecommendationNone:
|
||||
return tr("Keine Lernempfehlung");
|
||||
case RecommendationSubChapter:
|
||||
return tr("Zuerst Unterkapitel lernen");
|
||||
case RecommendationParentChapter:
|
||||
return tr("Übergeordnetes Kapitel lernen");
|
||||
case RecommendationLearnNew:
|
||||
return tr("Neue Fragen lernen");
|
||||
case RecommendationRepeatToday:
|
||||
return tr("Heute wiederholen");
|
||||
case RecommendationRepeatLater:
|
||||
uDays = QDate::currentDate().daysTo(dRepeat);
|
||||
if (uDays == 1)
|
||||
return tr("Morgen wiederholen");
|
||||
else
|
||||
return tr("In %1 Tagen wiederholen").arg(uDays);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString CChapter::recommendationText() const
|
||||
{
|
||||
return recommendationText(m_recom, m_recomRepeatDate);
|
||||
}
|
||||
|
||||
QString CChapter::recommendationToolTip() const
|
||||
{
|
||||
QString str = recommendationText();
|
||||
unsigned uCount = recommendedQuestionCount();
|
||||
if (hasRecommendedQuestions() && m_recom2 == RecommendationNone)
|
||||
{
|
||||
str += " ";
|
||||
if (uCount == 1)
|
||||
str += tr("(1 Frage)");
|
||||
else
|
||||
str += tr("(%1 Fragen)").arg(uCount);
|
||||
}
|
||||
if (m_recom2 != RecommendationNone)
|
||||
{
|
||||
str += "\n" + tr("Alternativ: ");
|
||||
if (m_recom2 == RecommendationLearnNew)
|
||||
{
|
||||
if (uCount == 1)
|
||||
str += tr("1 neue Frage lernen");
|
||||
else
|
||||
str += tr("%1 neue Fragen lernen").arg(uCount);
|
||||
}
|
||||
else if (m_recom2 == RecommendationRepeatToday)
|
||||
{
|
||||
if (uCount == 1)
|
||||
str += tr("1 Frage wiederholen");
|
||||
else
|
||||
str += tr("%1 Fragen wiederholen").arg(uCount);
|
||||
}
|
||||
else
|
||||
str += recommendationText (m_recom2, m_recomRepeatDate);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
QString CChapter::recommendationTextExtended(const CCatalog *pCatalog) const
|
||||
{
|
||||
unsigned uDays=0;
|
||||
QString str;
|
||||
|
||||
switch (m_recom)
|
||||
{
|
||||
default:
|
||||
case RecommendationNone:
|
||||
str = tr("Keine Lernempfehlung");
|
||||
break;
|
||||
case RecommendationSubChapter:
|
||||
str = tr("Dieses Kapitel enthält Unterkapitel, dessen Fragen Sie noch nicht ausreichend gelernt haben.\nEs wird empohlen in kleinen Etappen zu lernen und damit zuerst die Unterkapitel zu vertiefen.");
|
||||
break;
|
||||
case RecommendationParentChapter:
|
||||
if (levelAvgRounded() >= LEVEL_NORMAL)
|
||||
str = tr("Sie können die Fragen dieses Kapitels gut beantworten.\n");
|
||||
str += tr("Es wird empfohlen, alle Fragen des übergeordneten Kapitels gemischt zusammen zu lernen.");
|
||||
break;
|
||||
case RecommendationLearnNew:
|
||||
if (!isRecommendedNow(pCatalog))
|
||||
str = tr("Es gibt andere Kapitel, deren Fragen heute wiederholt werden sollten. Bitte lernen Sie diese Kapitel zuerst.");
|
||||
else
|
||||
str = tr("Bitte beantworten Sie alle neuen Fragen mindestens einmal richtig.");
|
||||
break;
|
||||
case RecommendationRepeatToday:
|
||||
str = tr("Bitte lernen Sie alle heute zu wiederholenden Fragen, bis sie eine Lernfortschritts-Stufe höher eingestuft sind.");
|
||||
break;
|
||||
case RecommendationRepeatLater:
|
||||
uDays = QDate::currentDate().daysTo(m_recomRepeatDate);
|
||||
if (uDays > 1)
|
||||
str = tr("Die Wiederholung dieses Kapitels ist erst in %1 Tagen geplant.\n").arg(uDays);
|
||||
else
|
||||
str = tr("Die Wiederholung dieses Kapitels ist erst für morgen geplant.\n");
|
||||
if (pCatalog->m_uRecomCount[RecommendationRepeatToday] > 0)
|
||||
str += tr("Es gibt andere Kapitel, deren Fragen heute wiederholt werden müssen. Bitte lernen Sie diese Kapitel zuerst.");
|
||||
else if (pCatalog->m_uRecomCount[RecommendationLearnNew] > 0)
|
||||
str += tr("Bitte lernen Sie zuerst Kapitel mit neuen Fragen.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasRecommendedQuestions() && isRecommendedNow(pCatalog))
|
||||
str += tr("<p>Dafür sind noch %1 Fragen zu lernen.").arg(recommendedQuestionCount());
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
QString CChapter::recommendationTextExtended2(const CCatalog *pCatalog) const
|
||||
{
|
||||
QString str;
|
||||
|
||||
if (m_recom2 == RecommendationLearnNew || (m_recom == RecommendationLearnNew && !isRecommendedNow(pCatalog)))
|
||||
{
|
||||
//str = tr("Bitte beantworten Sie alle neuen Fragen mindestens einmal richtig.");
|
||||
str = tr("Alternativ können Sie jetzt die neuen Fragen dieses Kapitels lernen (%1 Fragen).").arg(recommendedQuestionCount());
|
||||
}
|
||||
else if (m_recom2 == RecommendationRepeatToday)
|
||||
{
|
||||
if (m_recom == RecommendationSubChapter)
|
||||
str = tr("Bitte lernen Sie alle heute zu wiederholenden Fragen, bis sie eine Lernfortschritts-Stufe höher eingestuft sind (%1 Fragen).").arg(recommendedQuestionCount());
|
||||
else
|
||||
str = tr("Alternativ können Sie jetzt die heute zu wiederholenden Fragen dieses Kapitels lernen (%1 Fragen).").arg(recommendedQuestionCount());
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
QString CChapter::recommendationIconName(const Recommendation r, const CCatalog *pCatalog)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case RecommendationSubChapter:
|
||||
return QString(":/icons/16x16/button_cancel.png");
|
||||
case RecommendationParentChapter:
|
||||
return QString(":/icons/16x16/button_ok.png");
|
||||
case RecommendationLearnNew:
|
||||
if (pCatalog->m_uRecomCount[RecommendationRepeatToday] > 0)
|
||||
return QString(":/icons/16x16/idea_gray.png");
|
||||
else
|
||||
return QString(":/icons/16x16/idea.png");
|
||||
case RecommendationRepeatToday:
|
||||
return QString(":/icons/16x16/idea.png");
|
||||
case RecommendationRepeatLater:
|
||||
return QString(":/icons/16x16/idea_gray.png");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString CChapter::recommendationIconName(const CCatalog *pCatalog) const
|
||||
{
|
||||
return recommendationIconName(m_recom, pCatalog);
|
||||
}
|
||||
|
||||
/*!
|
||||
\return true: Kapitel kann jetzt gelernt werden,
|
||||
false: Kapitel sollte überhaupt nicht oder erst später gelernt werden
|
||||
*/
|
||||
|
||||
bool CChapter::isRecommendedNow(const CCatalog *pCatalog) const
|
||||
{
|
||||
switch (m_recom)
|
||||
{
|
||||
case RecommendationSubChapter:
|
||||
if (pCatalog->m_uRecomCount[RecommendationRepeatToday] > 0)
|
||||
return true;
|
||||
break;
|
||||
case RecommendationRepeatToday:
|
||||
return true;
|
||||
case RecommendationLearnNew:
|
||||
if (pCatalog->m_uRecomCount[RecommendationRepeatToday] == 0)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
\return true: Das Kapitel enthält noch neue Fragen, die gerade (="heute") gelernt werden
|
||||
bool CChapter::isLearningNew() const
|
||||
{
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
if (m_listQuestion.at(i)->isLearningNew()) return true;
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
if (m_listChapter.at(i)->isLearningNew()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
CDayStatistic CChapter::dayStatistic (const QDate& date) const
|
||||
{
|
||||
CDayStatistic dsRet, ds;
|
||||
QList<CQuestion*> listPool = questionPool();
|
||||
|
||||
for (int i=0; i<listPool.size(); i++)
|
||||
{
|
||||
ds = listPool.at(i)->dayStatistic(date);
|
||||
dsRet += ds;
|
||||
}
|
||||
if (listPool.size() != 0) dsRet.m_dLevel /= listPool.size();
|
||||
return dsRet;
|
||||
}
|
||||
|
||||
CDayStatistic CChapter::completeStatistic() const
|
||||
{
|
||||
return dayStatistic(QDate());
|
||||
}
|
||||
|
||||
QDateTime CChapter::firstAnswerClicked() const
|
||||
{
|
||||
QList<CQuestion*> listPool = questionPool();
|
||||
QDateTime dtRet, dt;
|
||||
|
||||
for (int i=0; i<listPool.size(); i++)
|
||||
{
|
||||
dt = listPool.at(i)->firstClicked();
|
||||
if (dt.isNull()) continue;
|
||||
if (dtRet.isNull() || dt < dtRet) dtRet = dt;
|
||||
}
|
||||
return dtRet;
|
||||
}
|
||||
|
||||
double CChapter::levelAvg() const
|
||||
{
|
||||
double d=0.0;
|
||||
double dCount=0.0;
|
||||
|
||||
for (int i=0; i<=LEVEL_MAX; i++)
|
||||
{
|
||||
d += m_uLevelCount[i] * i;
|
||||
dCount += m_uLevelCount[i];
|
||||
}
|
||||
if (dCount != 0.0) d /= dCount;
|
||||
return d;
|
||||
}
|
||||
|
||||
unsigned CChapter::levelAvgRounded() const
|
||||
{
|
||||
return ((unsigned) (levelAvg()+0.5));
|
||||
}
|
||||
|
||||
QString CChapter::levelAvgText() const
|
||||
{
|
||||
return QString("%1").arg(CQuestion::levelText(levelAvgRounded()));
|
||||
}
|
||||
|
||||
QIcon CChapter::levelAvgIcon() const
|
||||
{
|
||||
return QIcon(CQuestion::levelIconName(levelAvgRounded()));
|
||||
}
|
||||
|
||||
QPixmap CChapter::levelAvgPixmap() const
|
||||
{
|
||||
return QPixmap(CQuestion::levelIconName(levelAvgRounded()));
|
||||
}
|
||||
|
||||
static bool chapterLessThan(const CChapter *c1, const CChapter *c2)
|
||||
{
|
||||
return c1->id() < c2->id();
|
||||
}
|
||||
|
||||
void CChapter::sortSubChapters(bool bSortQuestions)
|
||||
{
|
||||
if (bSortQuestions) sortQuestions();
|
||||
qSort (m_listChapter.begin(), m_listChapter.end(), chapterLessThan);
|
||||
|
||||
for (int i=0; i<m_listChapter.size(); i++)
|
||||
{
|
||||
m_listChapter.at(i)->sortSubChapters(bSortQuestions);
|
||||
}
|
||||
}
|
||||
|
||||
static bool questionLessThan(const CQuestion *q1, const CQuestion *q2)
|
||||
{
|
||||
return q1->id() < q2->id();
|
||||
}
|
||||
|
||||
void CChapter::sortQuestions()
|
||||
{
|
||||
qSort (m_listQuestion.begin(), m_listQuestion.end(), questionLessThan);
|
||||
}
|
||||
|
242
chapter.h
Normal file
|
@ -0,0 +1,242 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CHAPTER_H
|
||||
#define CHAPTER_H
|
||||
|
||||
#include "question.h"
|
||||
//#include "recommendation.h"
|
||||
//#include "chapterstatistic.h"
|
||||
|
||||
#include <qmap.h>
|
||||
|
||||
//! Die Klasse CChapter speichert ein Kapitel mit allen Unterkapiteln und Fragen
|
||||
/*!
|
||||
*/
|
||||
|
||||
class CChapter
|
||||
{
|
||||
public:
|
||||
//! Empfehlung für Kapitel
|
||||
enum Recommendation
|
||||
{
|
||||
RecommendationNone=0, //!< Keine Emfehlung
|
||||
RecommendationSubChapter=1, //!< Untergeordnetes Kapitel lernen
|
||||
RecommendationParentChapter=2, //!< Übergeordnetes Kapitel lernen
|
||||
RecommendationRepeatToday=3, //!< Kapitel heute wiederholen
|
||||
RecommendationLearnNew=4, //!< Neue Fragen lernen
|
||||
RecommendationRepeatLater=5, //!< Kapitel später wiederholen
|
||||
RecommendationMax=6 //!< Für for-Schleifen, etc.
|
||||
};
|
||||
|
||||
//! Standard-Konstruktor
|
||||
/*! Initialisiert die Klasse, indem die Funktion clear() aufgerufen wird. */
|
||||
CChapter() { clear(); }
|
||||
|
||||
//! Standard-Destruktor
|
||||
/*! Es werden alle Unterkapitel und Fragen dieses Kapitels aus dem Speicher gelöscht. */
|
||||
~CChapter() { qDeleteAll(m_listChapter); qDeleteAll(m_listQuestion); }
|
||||
|
||||
//! Zurücksetzen aller Werte
|
||||
/*! Es werden alle Unterkapitel und Fragen dieses Kapitels aus dem Speicher gelöscht und alle andere Daten auf die Default-Werte zurückgesetzt. */
|
||||
void clear();
|
||||
|
||||
//! Elternkapitel auslesen
|
||||
/*!
|
||||
\return Elternkapitel m_pParentChapter
|
||||
\sa setParentChapter(), m_pParentChapter
|
||||
*/
|
||||
inline CChapter* parentChapter() const { return m_pParentChapter; }
|
||||
|
||||
//! Elternkapitel setzen
|
||||
/*!
|
||||
Durch diese Funktion wird lediglich die Variable m_pParentChapter gesetzt, jedoch nicht die Statistiken
|
||||
des Eltern-Kapitels aktualisiert.
|
||||
|
||||
\param pChapter Das zu setzende Elternkapitel dieses Kapitels
|
||||
\sa parentChapter(), m_pParentChapter
|
||||
*/
|
||||
inline void setParentChapter(CChapter *pChapter) { m_pParentChapter = pChapter; }
|
||||
|
||||
//! ID dieses Kapitels auslesen
|
||||
inline QString id() const { return m_strId; }
|
||||
//! ID dieses Kapitels zusammengesetzt mit allen IDs der Eltern-Kapitel auslesen
|
||||
QString idWithParents() const;
|
||||
//! Kapitelbeschreibung auslesen
|
||||
inline QString text() const { return m_strText; }
|
||||
//! Kommentar
|
||||
inline QString comment() const { return m_strComment; }
|
||||
|
||||
//! ID setzen
|
||||
inline void setId (const QString& strId) { m_strId = strId; }
|
||||
//! Kapitelbeschreibung setzen
|
||||
inline void setText (const QString& strText) { m_strText = strText; }
|
||||
//! Kommentar setzen
|
||||
inline void setComment (const QString& strComment) { m_strComment = strComment; }
|
||||
|
||||
//! Anhängen eines Textes an die Kapitelbeschreibung
|
||||
/*!
|
||||
\param strText Anzuhängender Text
|
||||
\sa m_strText
|
||||
*/
|
||||
inline void appendText(const QString& strText) { m_strText += strText; }
|
||||
|
||||
|
||||
//! Anzahl der Unterkapitel ermitteln
|
||||
/*! \return Anzahl der Unterkapitel */
|
||||
inline int countChapter() const { return m_listChapter.size(); }
|
||||
inline const CChapter* chapterAt(int i) const { return m_listChapter.at(i); }
|
||||
inline int indexOfChapter(CChapter* c) const { return m_listChapter.indexOf(c); }
|
||||
inline void appendChapter(CChapter* c) { m_listChapter.append(c); c->setParentChapter(this); }
|
||||
// inline void removeChapter(int i) { delete m_listChapter.takeAt(i); }
|
||||
QList<CChapter*> subChapters() const;
|
||||
inline void sortAll() { sortSubChapters(true); sortQuestions(); }
|
||||
void sortSubChapters(bool bSortQuestions);
|
||||
void sortQuestions();
|
||||
|
||||
//! Anzahl der Fragen dieses Kapitels und aller Unterkapitel ermitteln
|
||||
/*! \return Anzahl der Fragen */
|
||||
int countSubQuestion() const;
|
||||
//! Anzahl der Fragen dieses Kapitels (ohne Unterkapitel) ermitteln
|
||||
/*! \return Anzahl der Fragen */
|
||||
inline int countQuestion() const { return m_listQuestion.size(); }
|
||||
inline const CQuestion* questionAt(int i) const { return m_listQuestion.at(i); }
|
||||
inline CQuestion* questionAt(int i) { return m_listQuestion.at(i); }
|
||||
inline void appendQuestion(CQuestion* q) { m_listQuestion.append(q); q->setParentChapter(this); }
|
||||
|
||||
QList<CQuestion*> questionPool() const;
|
||||
QList<CQuestion*> questionPoolLevel(const unsigned uLevel) const;
|
||||
QList<CQuestion*> questionPoolDeepen() const;
|
||||
QList<CQuestion*> questionPoolRepeat(const QDate d=QDate::currentDate()) const;
|
||||
|
||||
|
||||
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc);
|
||||
bool loadLearnStatistic (QDomElement elem);
|
||||
bool saveLearnStatistic (QDomElement& parent, QDomDocument& doc);
|
||||
|
||||
QString checkForErrors() const;
|
||||
|
||||
|
||||
// Kapitelstatistik auslesen
|
||||
/*
|
||||
\return Kapitelstatistik (Variable m_cs)
|
||||
\sa m_cs
|
||||
*/
|
||||
// inline CChapterStatistic statistic() const { return m_cs; }
|
||||
|
||||
|
||||
//! @name Funktionen zur Statistik
|
||||
//@{
|
||||
void updateStatistic(); //!< Kapitelstatistik aktualisieren
|
||||
//! Anzahl der Fragen einer bestimmten Abfragehäufigkeit
|
||||
inline unsigned countQuestion(const unsigned uLevel) const { return m_uLevelCount[uLevel]; }
|
||||
double levelAvg() const; //!< Durchschnittlicher Lernfortschritt des Kapitels
|
||||
unsigned levelAvgRounded() const; //!< Durchschnittlicher, gerundeter Lernfortschritt des Kapitels
|
||||
QString levelAvgText() const; //!< Durchschnittlicher Lernfortschritt als Text
|
||||
QIcon levelAvgIcon() const; //!< Icon zum durchschnittlichen Lernfortschritt
|
||||
QPixmap levelAvgPixmap() const; //!< Pixmap zum durchschnittlichen Lernfortschritt
|
||||
//! Anzahl der noch nie abgefragen Fragen
|
||||
inline unsigned countNeverAsked() const { return m_uNeverAskedCount; }
|
||||
//!< Kapitel inkl. Unterkapitel enthalten Fragen, die gerade gelernt werden
|
||||
inline bool hasLearningNewQuestions() const { return m_bHasLearningNew; }
|
||||
inline bool hasKnownQuestions() const { return m_bHasKnownQuestions; }
|
||||
inline bool hasKnownQuestionsRepeatToday() const { return m_bHasKnownQuestionsRepeatToday; }
|
||||
|
||||
CDayStatistic dayStatistic (const QDate& date) const; //<! Statistik eines Tages
|
||||
CDayStatistic completeStatistic() const; //<! Statistik des kompletten Zeitraums
|
||||
QDateTime firstAnswerClicked() const; //<! Datum, zu dem zum allerersten Mal eine Frage beantwortet wurde
|
||||
//@}
|
||||
|
||||
//! @name Funktionen zur Lernempfehlung
|
||||
//@{
|
||||
QDate repeatDate() const; //!< Wiederhol-Datum des Kapitels
|
||||
//! Lernempfehlung für das Kapitel
|
||||
/*! \return Lernempfehlung (Variable m_recom) \sa m_recom */
|
||||
inline Recommendation recommendation() const { return m_recom; }
|
||||
QString recommendationIconName(const CCatalog *pCatalog) const; //!< Name des Icons zur Lernempfehlung ermitteln
|
||||
//! Ermittelt Icon zur Lernempfehlung
|
||||
inline QIcon recommendationIcon (const CCatalog *pCatalog) const { return QIcon (recommendationIconName(pCatalog)); }
|
||||
QString recommendationText() const; //!< Lernempfehlungstext (kurz)
|
||||
QString recommendationTextExtended(const CCatalog *pCatalog) const; //!< Lernempfehlungstext (ausführlich)
|
||||
QString recommendationToolTip() const; //!< Lernempfehlungstext für Tooltip
|
||||
bool isRecommendedNow(const CCatalog *pCatalog) const; //!< Kapitel sollte jetzt gelernt werden
|
||||
//! Anzahl der Unterkapitel mit einer bestimmten Lernempfehlung
|
||||
inline unsigned recommendationCount(const Recommendation r) const { return m_uRecomCount[r]; }
|
||||
//! Fragen, die beantwortet müssen, um die Lernempfehlung zu erfüllen
|
||||
inline QList<CQuestion*> recommendedQuestions() const { return m_listQuestionRecommended; }
|
||||
//! Kapitel hat Fragen, die beantwortet müssen, um die Lernempfehlung zu erfüllen
|
||||
inline bool hasRecommendedQuestions() const { return m_listQuestionRecommended.size() > 0; }
|
||||
//! Anzahl der Fragen, die beantwortet müssen, um die Lernempfehlung zu erfüllen
|
||||
inline int recommendedQuestionCount() const { return m_listQuestionRecommended.size(); }
|
||||
//! Alternative Lernempfehlung für das Kapitel
|
||||
inline Recommendation recommendation2() const { return m_recom2; }
|
||||
QString recommendationTextExtended2(const CCatalog *pCatalog) const; //!< Alternativer Lernempfehlungstext (ausführlich)
|
||||
//@}
|
||||
|
||||
//! @name Funktionen zu Prüfungen
|
||||
//@{
|
||||
// inline void setExam(const QString& strId, const unsigned uQuestionCount) { m_mapExam.insert(strId, uQuestionCount); }
|
||||
// inline unsigned examQuestionCount(const QString& strId) const { return m_mapExam[strId]; }
|
||||
//@}
|
||||
|
||||
// static
|
||||
static QString tr (const char *sourceText, const char *comment=0);
|
||||
static QString recommendationText(const Recommendation r, const QDate dRepeat);
|
||||
static QString recommendationIconName(const Recommendation r, const CCatalog *pCatalog);
|
||||
|
||||
protected:
|
||||
void updateStatisticCount(); //!< Zählt alle Fragen des Kapitels (inkl. Unterkapitel) für die Statistik
|
||||
void updateRecommendation(); //!< Lernempfehlung für das Kapitel (inkl. Unterkapitel) aktualisieren
|
||||
void updateRecommendationStatistic(); //!< Statistik über Lernempfehlungen für das Kapitel (inkl. Unterkapitel) aktualisieren
|
||||
Recommendation recommendationIndividual() const; //!< Empfehlung nur für dieses Kapitel, Unterkapitel und Elternkapitel werden ignoriert
|
||||
|
||||
protected:
|
||||
CChapter *m_pParentChapter; //!< Übergeordnetes Kapitel
|
||||
QString m_strId; //!< ID des Kapitels
|
||||
QString m_strText; //!< Name des Kapitels
|
||||
QString m_strComment; //!< Kommentar
|
||||
|
||||
QList<CChapter*> m_listChapter; //!< Liste mit Unterkapiteln
|
||||
QList<CQuestion*> m_listQuestion; //!< Liste mit Fragen
|
||||
|
||||
// Statistik
|
||||
unsigned m_uLevelCount[LEVEL_MAX+1]; //!< Anzahl der Fragen einer bestimmten Abfragehäufigkeit
|
||||
unsigned m_uNeverAskedCount; //!< Anzahl der Fragen, die noch nie abgefragt wurden
|
||||
unsigned m_uRecomCount[RecommendationMax]; //!< Anzahl der Unterkapitel (inkl. selbst) mit bestimmter Lernempfehlung
|
||||
bool m_bHasLearningNew; //!< Kapitel enthält Fragen, die gerade neu gelernt werden
|
||||
bool m_bHasKnownQuestions; //!< Kapitel enthält Fragen, die seit mind. gestern bekannt sind
|
||||
bool m_bHasKnownQuestionsRepeatToday; //!< Kapitel enthält Fragen, die seit mind. gestern bekannt sind und heute wiederholt werden sollten
|
||||
|
||||
Recommendation m_recom; //!< Lernempfehlung
|
||||
Recommendation m_recom2; //!< Alternative Lernempfehlung
|
||||
|
||||
//! Empfohlenes Datum zur Wiederholung der Fragen
|
||||
/*! Diese Variable wird mit der Funktion updateRecommendation() aktualisiert */
|
||||
QDate m_recomRepeatDate;
|
||||
//! Liste mit Fragen zum Erfüllen der Lernempfehlung
|
||||
/*! Diese Liste wird mit der Funktion updateRecommendation() aktualisiert */
|
||||
QList<CQuestion*> m_listQuestionRecommended;
|
||||
};
|
||||
|
||||
#endif
|
184
chaptermodel.cpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
/***************************************************************************
|
||||
* 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 "chaptermodel.h"
|
||||
#include "catalog.h"
|
||||
|
||||
#include <qtextdocument.h>
|
||||
|
||||
#define COL_CHAPTER 0
|
||||
#define COL_QUESTION 1
|
||||
#define COL_ASSIST 2
|
||||
#define COL_AVG 3
|
||||
|
||||
CChapterModel::CChapterModel(QObject *pParent) : QAbstractItemModel (pParent)
|
||||
{
|
||||
m_pCatalog = 0;
|
||||
}
|
||||
|
||||
CChapterModel::~CChapterModel()
|
||||
{
|
||||
}
|
||||
|
||||
void CChapterModel::onLanguageChanged()
|
||||
{
|
||||
headerDataChanged(Qt::Horizontal, 0, columnCount()-1);
|
||||
}
|
||||
|
||||
void CChapterModel::clear()
|
||||
{
|
||||
m_listChapter.clear();
|
||||
m_pCatalog = 0;
|
||||
reset();
|
||||
}
|
||||
|
||||
void CChapterModel::setModelData (CCatalog *pCatalog, QList<CChapter*> listChapter)
|
||||
{
|
||||
m_listChapter = listChapter;
|
||||
m_pCatalog = pCatalog;
|
||||
reset();
|
||||
}
|
||||
|
||||
int CChapterModel::columnCount (const QModelIndex & parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant CChapterModel::data (const QModelIndex & index, int role) const
|
||||
{
|
||||
CChapter *p = (CChapter*) index.internalPointer();
|
||||
|
||||
if (m_pCatalog == 0 || !index.isValid()) return QVariant();
|
||||
|
||||
if (role == Qt::TextAlignmentRole && index.column() == COL_QUESTION) return Qt::AlignRight;
|
||||
|
||||
if (p == 0) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == COL_CHAPTER)
|
||||
{
|
||||
if (p->id().isEmpty())
|
||||
return p->text();
|
||||
else
|
||||
return p->idWithParents() + " - " + p->text();
|
||||
}
|
||||
else if (index.column() == COL_QUESTION)
|
||||
return QString("%1").arg(p->countSubQuestion());
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationText();
|
||||
/* CRecommendation r(p);
|
||||
return r.textShort();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (index.column() == COL_CHAPTER)
|
||||
return QIcon(":/icons/16x16/folder.png");
|
||||
else if (index.column() == COL_AVG)
|
||||
{
|
||||
return p->levelAvgIcon();
|
||||
}
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationIcon(m_pCatalog);
|
||||
//TODO return p->recommendation().icon(m_pCatalog);
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (index.column() == COL_AVG)
|
||||
{
|
||||
return QString ("%1 - Kennzahl: %2").arg(p->/*statistic().*/levelAvgText()).arg(p->/*statistic().*/levelAvg(), 4, 'f', 2);
|
||||
}
|
||||
else if (index.column() == COL_ASSIST)
|
||||
{
|
||||
return p->recommendationToolTip();
|
||||
//TODO return p->recommendation().recommendationText(m_pCatalog);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool CChapterModel::hasChildren (const QModelIndex & parent) const
|
||||
{
|
||||
if (parent.isValid()) return false;
|
||||
return (!m_listChapter.isEmpty());
|
||||
}
|
||||
|
||||
QVariant CChapterModel::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Vertical) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == COL_CHAPTER)
|
||||
return tr("Kapitel");
|
||||
else if (section == COL_QUESTION)
|
||||
return tr("Fragen");
|
||||
else if (section == COL_AVG)
|
||||
return tr("Ø");
|
||||
else if (section == COL_ASSIST)
|
||||
return tr("Lernassistent");
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (section == COL_CHAPTER)
|
||||
return tr("Kapitelname\nBitte markieren Sie das Kapitel, das Sie lernen möchten.");
|
||||
else if (section == COL_QUESTION)
|
||||
return tr("Anzahl d. Fragen inkl. Unterkapitel");
|
||||
else if (section == COL_AVG)
|
||||
return tr("Durchschnittlicher Lernfortschritt");
|
||||
else if (section == COL_ASSIST)
|
||||
return tr("Empfehlung des Lernassistentes");
|
||||
}
|
||||
else if (role == Qt::WhatsThisRole)
|
||||
{
|
||||
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex CChapterModel::index (int row, int column, const QModelIndex & parent) const
|
||||
{
|
||||
CChapter *p=0;
|
||||
|
||||
if (parent.isValid() || row >= m_listChapter.size()) return QModelIndex();
|
||||
p = m_listChapter.at (row);
|
||||
return createIndex (row, column, (void*)p);
|
||||
}
|
||||
|
||||
QModelIndex CChapterModel::parent (const QModelIndex & index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int CChapterModel::rowCount (const QModelIndex & parent) const
|
||||
{
|
||||
if (parent.isValid()) return 0;
|
||||
return m_listChapter.size();
|
||||
}
|
||||
|
60
chaptermodel.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CHAPTERMODEL_H
|
||||
#define CHAPTERMODEL_H
|
||||
|
||||
#include <qabstractitemmodel.h>
|
||||
|
||||
class CChapter;
|
||||
class CCatalog;
|
||||
|
||||
class CChapterModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CChapterModel(QObject *pParent=0);
|
||||
~CChapterModel();
|
||||
|
||||
void clear();
|
||||
void setModelData (CCatalog *pCatalog, QList<CChapter*> listChapter);
|
||||
|
||||
public:
|
||||
virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
|
||||
virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
|
||||
virtual bool hasChildren (const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
|
||||
virtual QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const;
|
||||
virtual QModelIndex parent ( const QModelIndex & index ) const;
|
||||
virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
|
||||
|
||||
public slots:
|
||||
void onLanguageChanged();
|
||||
|
||||
protected:
|
||||
void recalcColumn();
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
QList<CChapter*> m_listChapter;
|
||||
};
|
||||
|
||||
#endif // CHAPTERMODEL_H
|
300
dlgexam.cpp
Normal file
|
@ -0,0 +1,300 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlgexam.h"
|
||||
#include "question.h"
|
||||
#include "error.h"
|
||||
#include "catalog.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
CDlgExam::CDlgExam (CCatalog *pCatalog, QWidget *pParent) : QDialog (pParent, Qt::WindowMaximizeButtonHint)
|
||||
{
|
||||
m_pCatalog = pCatalog;
|
||||
m_iCurrentQuestion = -1;
|
||||
m_bIsFinished = false;
|
||||
m_bTimeout = false;
|
||||
setupUi(this);
|
||||
connect (&m_timer, SIGNAL(timeout()), this, SLOT(onTimer()));
|
||||
}
|
||||
|
||||
CDlgExam::~CDlgExam ()
|
||||
{
|
||||
}
|
||||
|
||||
bool CDlgExam::setup (const CExam& exam)
|
||||
{
|
||||
m_exam = exam;
|
||||
labHeader->setText(exam.name());
|
||||
|
||||
try
|
||||
{
|
||||
m_listQuestion = exam.createQuestionPool(m_pCatalog->questionPool());
|
||||
}
|
||||
catch (CError e)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Fehler"), e.toHtml());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_listAnswerMask.clear();
|
||||
while (m_listAnswerMask.size() < m_listQuestion.size())
|
||||
m_listAnswerMask.append(0);
|
||||
|
||||
// Antworten bei Bedarf durchmischen
|
||||
if (m_pCatalog->useMixedAnswers())
|
||||
{
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
m_listQuestion.at(i)->mixAnswers();
|
||||
}
|
||||
init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDlgExam::init()
|
||||
{
|
||||
// Zeitbalken & Zeitüberwachung
|
||||
m_timer.setInterval(1000);
|
||||
m_timer.start();
|
||||
m_dtStart = QDateTime::currentDateTime();
|
||||
pgTime->setMaximum (m_exam.duration() * 60);
|
||||
|
||||
// Sonstiges
|
||||
pgQuestions->setMaximum (m_listQuestion.size());
|
||||
m_bIsFinished = false;
|
||||
m_bTimeout = false;
|
||||
labMaxWrong->setText(QString("%1").arg(m_exam.maxErrorPoints()));
|
||||
|
||||
// Navigation
|
||||
spinBox->setRange (1, m_listQuestion.size());
|
||||
spinBox->setValue(1);
|
||||
m_iCurrentQuestion = 1;
|
||||
|
||||
// Alles updaten
|
||||
updateNavi();
|
||||
showQuestion();
|
||||
updateProgressTimer();
|
||||
updateProgressQuestion();
|
||||
}
|
||||
|
||||
void CDlgExam::onTimer()
|
||||
{
|
||||
updateProgressTimer();
|
||||
}
|
||||
|
||||
void CDlgExam::updateNavi()
|
||||
{
|
||||
pbFirst->setEnabled (spinBox->value() > spinBox->minimum());
|
||||
pbPrev->setEnabled (spinBox->value() > spinBox->minimum());
|
||||
pbNext->setEnabled (spinBox->value() < spinBox->maximum());
|
||||
pbLast->setEnabled (spinBox->value() < spinBox->maximum());
|
||||
}
|
||||
|
||||
unsigned CDlgExam::answeredQuestionCount()
|
||||
{
|
||||
unsigned u=0;
|
||||
for (int i=0; i<m_listAnswerMask.size(); i++)
|
||||
{
|
||||
if (m_listAnswerMask.at(i) != 0) u++;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
void CDlgExam::updateProgressQuestion()
|
||||
{
|
||||
unsigned uAnswered = answeredQuestionCount();
|
||||
labProgressQuestions->setText(tr("%1 von %2").arg(uAnswered).arg(m_listAnswerMask.size()));
|
||||
pgQuestions->setValue(uAnswered);
|
||||
}
|
||||
|
||||
void CDlgExam::updateProgressTimer()
|
||||
{
|
||||
QDateTime dt = QDateTime::currentDateTime();
|
||||
unsigned uSecs = m_dtStart.secsTo(dt);
|
||||
|
||||
labProgessTime->setText(tr("Abgelaufene Zeit: %1:%2 min von %3:00 min")
|
||||
.arg(uSecs / 60)
|
||||
.arg(uSecs % 60, 2, 10, QChar('0'))
|
||||
.arg(m_exam.duration()));
|
||||
|
||||
pgTime->setValue (uSecs);
|
||||
|
||||
if (uSecs > m_exam.duration()*60)
|
||||
{
|
||||
m_bTimeout = true;
|
||||
m_timer.stop();
|
||||
QMessageBox::information(this, tr("Information"), tr("Die Zeit ist abgelaufen.\nDie Prüfung wird deswegen beendet."));
|
||||
on_pbFinish_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
void CDlgExam::on_pbFirst_clicked()
|
||||
{
|
||||
spinBox->setValue(1);
|
||||
}
|
||||
|
||||
void CDlgExam::on_pbPrev_clicked()
|
||||
{
|
||||
int iNew = spinBox->value() - 1;
|
||||
if (iNew < 1) iNew = 1;
|
||||
spinBox->setValue(iNew);
|
||||
}
|
||||
|
||||
void CDlgExam::on_pbNext_clicked()
|
||||
{
|
||||
int iNew = spinBox->value() + 1;
|
||||
if (iNew > m_listQuestion.size()) iNew = m_listQuestion.size();
|
||||
spinBox->setValue(iNew);
|
||||
}
|
||||
|
||||
void CDlgExam::on_pbLast_clicked()
|
||||
{
|
||||
spinBox->setValue(m_listQuestion.size());
|
||||
}
|
||||
|
||||
void CDlgExam::on_spinBox_valueChanged(int i)
|
||||
{
|
||||
Q_UNUSED(i);
|
||||
onQuestionChanged();
|
||||
}
|
||||
|
||||
void CDlgExam::saveCurrentAnswer()
|
||||
{
|
||||
unsigned uAnswerMask=0;
|
||||
if (m_iCurrentQuestion >= 0)
|
||||
{ // Antwort zur aktuellen Frage abspeichern
|
||||
if (rbA->isChecked()) uAnswerMask |= 1;
|
||||
if (rbB->isChecked()) uAnswerMask |= 2;
|
||||
if (rbC->isChecked()) uAnswerMask |= 4;
|
||||
if (rbD->isChecked()) uAnswerMask |= 8;
|
||||
m_listAnswerMask[m_iCurrentQuestion] = uAnswerMask;
|
||||
}
|
||||
}
|
||||
|
||||
void CDlgExam::onQuestionChanged()
|
||||
{
|
||||
saveCurrentAnswer();
|
||||
updateNavi();
|
||||
updateProgressQuestion();
|
||||
showQuestion(); // neue Frage anzeigen
|
||||
}
|
||||
|
||||
void CDlgExam::showQuestion()
|
||||
{
|
||||
CQuestion *q=0;
|
||||
unsigned uAnswerMask;
|
||||
QString str;
|
||||
|
||||
m_iCurrentQuestion = spinBox->value()-1;
|
||||
q = m_listQuestion.at(m_iCurrentQuestion);
|
||||
uAnswerMask = m_listAnswerMask.at(m_iCurrentQuestion);
|
||||
str = q->learnText(m_pCatalog, m_bIsFinished, false);
|
||||
if (m_bIsFinished)
|
||||
{
|
||||
str += "<hr><p><b>";
|
||||
if (!q->isCorrectAnswer(uAnswerMask))
|
||||
str += "<font color='red'>";
|
||||
else
|
||||
str += "<font color='green'>";
|
||||
|
||||
str += q->correctionText(uAnswerMask) + "</font></p>";
|
||||
}
|
||||
textBrowser->setHtml(str);
|
||||
|
||||
rbA->setChecked(uAnswerMask & 1);
|
||||
rbB->setChecked(uAnswerMask & 2);
|
||||
rbC->setChecked(uAnswerMask & 4);
|
||||
rbD->setChecked(uAnswerMask & 8);
|
||||
rbNoIdea->setChecked(uAnswerMask == 0);
|
||||
}
|
||||
|
||||
void CDlgExam::on_pbFinish_clicked()
|
||||
{
|
||||
unsigned uCorrect=0, uWrong=0, uAnsweredCount = answeredQuestionCount(), uErrorPoints=0;
|
||||
bool bSaveStat=true, bPassed=false;
|
||||
QDateTime dt = QDateTime::currentDateTime();
|
||||
unsigned uSecs = m_dtStart.secsTo(dt);
|
||||
|
||||
saveCurrentAnswer();
|
||||
if (uAnsweredCount < (unsigned)m_listQuestion.size() && !m_bTimeout)
|
||||
{
|
||||
if (QMessageBox::question (this,
|
||||
tr("Sicherheitsabfrage"),
|
||||
tr("Sie haben noch nicht alle Fragen beantwortet.\nWirklich abgeben?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) return;
|
||||
}
|
||||
|
||||
m_timer.stop();
|
||||
pbFinish->setEnabled(false);
|
||||
rbA->setEnabled(false);
|
||||
rbB->setEnabled(false);
|
||||
rbC->setEnabled(false);
|
||||
rbD->setEnabled(false);
|
||||
rbNoIdea->setEnabled(false);
|
||||
pbCancel->setText(tr("Beenden"));
|
||||
m_bIsFinished = true;
|
||||
showQuestion();
|
||||
|
||||
for (int i=0; i<m_listQuestion.size(); i++)
|
||||
{
|
||||
CQuestion *q = m_listQuestion.at(i);
|
||||
unsigned uAnswerMask = m_listAnswerMask.at(i);
|
||||
if (q->isCorrectAnswer(uAnswerMask))
|
||||
uCorrect++;
|
||||
else
|
||||
{
|
||||
uWrong++;
|
||||
uErrorPoints+=q->errorPoints();
|
||||
}
|
||||
}
|
||||
labCorrect->setText(QString("%1").arg(uCorrect));
|
||||
labWrong->setText(QString("%1").arg(uWrong));
|
||||
|
||||
if (uAnsweredCount < (unsigned)m_listQuestion.size()/2)
|
||||
{
|
||||
bPassed = false;
|
||||
bSaveStat = false;
|
||||
labResult->setText(tr("Ohne Wertung\n(Nicht bestanden)"));
|
||||
QMessageBox::information(this, tr("Information"), tr("Sie haben weniger als die Hälfte aller Fragen beantwortet.\nDiese Prüfung wird deswegen nicht gewertet."));
|
||||
}
|
||||
else if (uErrorPoints > m_exam.maxErrorPoints())
|
||||
{
|
||||
bPassed = false;
|
||||
labResult->setText(tr("<font color='red'>Nicht bestanden</font>"));
|
||||
QMessageBox::information(this, tr("Ergebnis"), tr("Sie haben die Prüfung leider nicht bestanden."));
|
||||
}
|
||||
else
|
||||
{
|
||||
bPassed = true;
|
||||
labResult->setText(tr("<font color='green'>Bestanden</font>"));
|
||||
QMessageBox::information(this, tr("Ergebnis"), tr("<b>Herzlichen Glückwunsch!</b><p>Sie haben die Prüfung bestanden!"));
|
||||
}
|
||||
|
||||
if (bSaveStat)
|
||||
{ // Prüfungsstatistik speichern
|
||||
CExamStat es(m_exam);
|
||||
es.setSecs(uSecs);
|
||||
es.setQuestions(m_listQuestion, m_listAnswerMask);
|
||||
es.setResult(uCorrect, uWrong, uErrorPoints, bPassed);
|
||||
m_pCatalog->appendExamStat(es);
|
||||
m_pCatalog->saveStatistic(this);
|
||||
}
|
||||
}
|
81
dlgexam.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "exam.h"
|
||||
|
||||
#include "ui_dlgexam.h"
|
||||
#include <qdialog.h>
|
||||
#include <qtimer.h>
|
||||
#include <qdatetime.h>
|
||||
|
||||
class CCatalog;
|
||||
class CQuestion;
|
||||
|
||||
class CDlgExam : public QDialog, Ui::DlgExam
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgExam (CCatalog *pCatalog, QWidget *pParent=0);
|
||||
~CDlgExam ();
|
||||
|
||||
bool setup (const CExam& exam);
|
||||
|
||||
protected:
|
||||
void init();
|
||||
void updateNavi();
|
||||
void updateProgressQuestion();
|
||||
void updateProgressTimer();
|
||||
void showQuestion();
|
||||
void onQuestionChanged();
|
||||
unsigned answeredQuestionCount();
|
||||
void saveCurrentAnswer();
|
||||
|
||||
protected slots:
|
||||
void onTimer();
|
||||
void on_pbFirst_clicked();
|
||||
void on_pbPrev_clicked();
|
||||
void on_pbNext_clicked();
|
||||
void on_pbLast_clicked();
|
||||
void on_spinBox_valueChanged(int i);
|
||||
void on_pbFinish_clicked();
|
||||
|
||||
inline void on_rbA_toggled(bool bChecked) { Q_UNUSED(bChecked); saveCurrentAnswer(); updateProgressQuestion(); }
|
||||
inline void on_rbB_toggled(bool bChecked) { Q_UNUSED(bChecked); saveCurrentAnswer(); updateProgressQuestion(); }
|
||||
inline void on_rbC_toggled(bool bChecked) { Q_UNUSED(bChecked); saveCurrentAnswer(); updateProgressQuestion(); }
|
||||
inline void on_rbD_toggled(bool bChecked) { Q_UNUSED(bChecked); saveCurrentAnswer(); updateProgressQuestion(); }
|
||||
inline void on_rbNoIdea_toggled(bool bChecked) { Q_UNUSED(bChecked); saveCurrentAnswer(); updateProgressQuestion(); }
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
CExam m_exam;
|
||||
|
||||
QList<CQuestion*> m_listQuestion;
|
||||
QList<unsigned> m_listAnswerMask;
|
||||
QTimer m_timer;
|
||||
QDateTime m_dtStart;
|
||||
QDateTime m_dtStop;
|
||||
int m_iCurrentQuestion;
|
||||
bool m_bIsFinished;
|
||||
bool m_bTimeout;
|
||||
};
|
||||
|
529
dlgexam.ui
Normal file
|
@ -0,0 +1,529 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgExam</class>
|
||||
<widget class="QDialog" name="DlgExam" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>607</width>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Prüfungssimulation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labHeader" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Bezeichnung</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Frage</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Ihre Antwort</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbA" >
|
||||
<property name="text" >
|
||||
<string>&A</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbB" >
|
||||
<property name="text" >
|
||||
<string>&B</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbC" >
|
||||
<property name="text" >
|
||||
<string>&C</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>C</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbD" >
|
||||
<property name="text" >
|
||||
<string>&D</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>D</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbNoIdea" >
|
||||
<property name="text" >
|
||||
<string>&Keine Ahnung</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3" >
|
||||
<property name="title" >
|
||||
<string>Navigation</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbFirst" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><<</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbPrev" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbNext" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbLast" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Zeit</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labProgessTime" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="pgTime" >
|
||||
<property name="value" >
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Beantwortete Fragen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labProgressQuestions" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="pgQuestions" >
|
||||
<property name="value" >
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Auswertung</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Richtige Antworten:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Falsche Antworten:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labWrong" >
|
||||
<property name="text" >
|
||||
<string>?</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labCorrect" >
|
||||
<property name="text" >
|
||||
<string>?</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>max. erlaubte falsche Antworten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labMaxWrong" >
|
||||
<property name="text" >
|
||||
<string>10</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labResult" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbFinish" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Abgeben && auswerten</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCancel" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Abbrechen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>pbCancel</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>DlgExam</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>468</x>
|
||||
<y>482</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>514</x>
|
||||
<y>501</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
93
dlgexamselect.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlgexamselect.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
#include <qheaderview.h>
|
||||
#include "catalog.h"
|
||||
|
||||
CDlgExamSelect::CDlgExamSelect (QWidget *pParent) : QDialog (pParent)
|
||||
{
|
||||
m_pCatalog = 0;
|
||||
m_iSelectedExam = -1;
|
||||
setupUi(this);
|
||||
|
||||
twList->headerItem()->setText(0, tr("Name"));
|
||||
twList->headerItem()->setText(1, tr("Dauer (min)"));
|
||||
//twList->header()->setStretchLastSection(false);
|
||||
twList->header()->resizeSection(0, 370);
|
||||
//twList->header()->resizeSection(1, 70);
|
||||
|
||||
}
|
||||
|
||||
CDlgExamSelect::~CDlgExamSelect ()
|
||||
{
|
||||
}
|
||||
|
||||
void CDlgExamSelect::setup (const CCatalog *pCatalog)
|
||||
{
|
||||
m_pCatalog = pCatalog;
|
||||
for (int i=0; i<m_pCatalog->countExam(); i++)
|
||||
{
|
||||
CExam exam = m_pCatalog->examAt(i);
|
||||
QTreeWidgetItem *pItem = new QTreeWidgetItem (twList);
|
||||
pItem->setText(0, exam.name());
|
||||
pItem->setText(1, QString("%1 min").arg(exam.duration()));
|
||||
pItem->setTextAlignment(1, Qt::AlignRight);
|
||||
pItem->setData(0, Qt::UserRole, i);
|
||||
}
|
||||
}
|
||||
|
||||
void CDlgExamSelect::on_twList_currentItemChanged (QTreeWidgetItem *current, QTreeWidgetItem *previous)
|
||||
{
|
||||
Q_UNUSED(previous);
|
||||
if (current)
|
||||
{
|
||||
m_iSelectedExam = current->data(0, Qt::UserRole).toInt();
|
||||
CExam exam = m_pCatalog->examAt(m_iSelectedExam);
|
||||
labName->setText(exam.name());
|
||||
labComment->setText(exam.comment());
|
||||
labDuration->setText(QString("%1 min").arg(exam.duration()));
|
||||
labQuestions->setText(QString("%1").arg(exam.questionCount()));
|
||||
labError->setText(QString("%1").arg(exam.maxErrorPoints()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iSelectedExam = -1;
|
||||
labName->clear();
|
||||
labComment->clear();
|
||||
labDuration->clear();
|
||||
labQuestions->clear();
|
||||
labError->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CDlgExamSelect::on_buttonBox_accepted()
|
||||
{
|
||||
if (m_iSelectedExam == -1)
|
||||
{
|
||||
QMessageBox::information(this, tr("Information"), tr("Bitte eine Prüfung auswählen!"));
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
}
|
||||
|
46
dlgexamselect.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui_dlgexamselect.h"
|
||||
#include <qdialog.h>
|
||||
|
||||
class CCatalog;
|
||||
|
||||
class CDlgExamSelect : public QDialog, Ui::DlgExamSelect
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgExamSelect (QWidget *pParent=0);
|
||||
~CDlgExamSelect ();
|
||||
|
||||
void setup (const CCatalog *pCatalog);
|
||||
inline int selectedExam() const { return m_iSelectedExam; }
|
||||
|
||||
protected slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_twList_currentItemChanged (QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
|
||||
protected:
|
||||
const CCatalog *m_pCatalog;
|
||||
int m_iSelectedExam;
|
||||
};
|
178
dlgexamselect.ui
Normal file
|
@ -0,0 +1,178 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgExamSelect</class>
|
||||
<widget class="QDialog" name="DlgExamSelect" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>491</width>
|
||||
<height>418</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Prüfung auswählen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Verfügbare Prüfungen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="twList" >
|
||||
<property name="rootIsDecorated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Detailinformation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labName" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>3</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labComment" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labDuration" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="labQuestions" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLabel" name="labError" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Max. erlaubte Fehler:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Anzahl Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Dauer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Hinweise:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Bezeichnung:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>twList</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DlgExamSelect</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>291</x>
|
||||
<y>384</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
109
dlgexamstatistic.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlgexamstatistic.h"
|
||||
#include "catalog.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
#include <qheaderview.h>
|
||||
|
||||
CDlgExamStatistic::CDlgExamStatistic(QWidget *pParent) : QDialog(pParent)
|
||||
{
|
||||
m_pCatalog = 0;
|
||||
setupUi(this);
|
||||
|
||||
twExamStat->headerItem()->setText(0, "Datum/Uhrzeit");
|
||||
twExamStat->headerItem()->setText(1, "Ergebnis");
|
||||
twExamStat->headerItem()->setText(2, "Fehler");
|
||||
twExamStat->headerItem()->setText(3, "Dauer");
|
||||
twExamStat->headerItem()->setText(4, "Ø pro Frage");
|
||||
|
||||
twExamStat->header()->resizeSection(0, 130);
|
||||
twExamStat->header()->resizeSection(2, 50);
|
||||
twExamStat->header()->resizeSection(3, 75);
|
||||
}
|
||||
|
||||
void CDlgExamStatistic::go (CCatalog *pCatalog)
|
||||
{
|
||||
m_pCatalog = pCatalog;
|
||||
|
||||
if (pCatalog->countExamStat() == 0)
|
||||
{
|
||||
QMessageBox::information(parentWidget(), tr("Information"), tr("Es wurden bisher noch keine Prüfungen durchgeführt."));
|
||||
return;
|
||||
}
|
||||
|
||||
cbExam->clear();
|
||||
for (int i=0; i<pCatalog->countExam(); i++)
|
||||
{
|
||||
cbExam->addItem(pCatalog->examAt(i).name(), pCatalog->examAt(i).id());
|
||||
}
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
void CDlgExamStatistic::on_cbExam_currentIndexChanged (int index)
|
||||
{
|
||||
QString strExamId = cbExam->itemData(index).toString();
|
||||
CExam exam = m_pCatalog->examById(strExamId);
|
||||
unsigned uExamCount=0, uPassedCount=0, uFailedCount=0, uErrorCount=0, uDuration=0, uQuestions=0;
|
||||
QTreeWidgetItem *pItem=0;
|
||||
|
||||
twExamStat->clear();
|
||||
|
||||
labExamQCount->setText(QString::number(exam.questionCount()));
|
||||
labExamTime->setText(QString("%1 min").arg(exam.duration()));
|
||||
labExamWrong->setText(QString::number(exam.maxErrorPoints()));
|
||||
|
||||
for (int i=0; i<m_pCatalog->countExamStat(); i++)
|
||||
{
|
||||
CExamStat es = m_pCatalog->examStatAt(i);
|
||||
if (es.id() != strExamId) continue;
|
||||
uExamCount++;
|
||||
if (es.passed()) uPassedCount++; else uFailedCount++;
|
||||
uErrorCount += es.errorPoints();
|
||||
uDuration += es.duration();
|
||||
uQuestions += es.correctAnswers() + es.wrongAnswers();
|
||||
pItem = new QTreeWidgetItem (twExamStat);
|
||||
pItem->setText(0, es.datetime().toString(Qt::LocalDate));
|
||||
pItem->setText(1, es.passed() ? tr("Bestanden") : tr("Nicht bestanden"));
|
||||
pItem->setText(2, QString::number(es.errorPoints()));
|
||||
pItem->setTextAlignment(2, Qt::AlignRight);
|
||||
pItem->setText(3, QString("%1 m %2 s").arg(es.duration() / 60).arg(es.duration() % 60, 2, 10, QChar('0')));
|
||||
pItem->setTextAlignment(3, Qt::AlignRight);
|
||||
unsigned uQuestionCount = es.correctAnswers() + es.wrongAnswers();
|
||||
if (uQuestionCount != 0)
|
||||
pItem->setText(4, QString("%1 m %2 s").arg(es.duration() / uQuestionCount / 60).arg(es.duration() / uQuestionCount % 60, 2, 10, QChar('0')));
|
||||
else
|
||||
pItem->setText(4, "--");
|
||||
pItem->setTextAlignment(4, Qt::AlignRight);
|
||||
}
|
||||
|
||||
labExamCount->setText(QString::number(uExamCount));
|
||||
labExamPassed->setText(uExamCount != 0 ? QString::number(uPassedCount) : "--");
|
||||
labExamFailed->setText(uExamCount != 0 ? QString::number(uFailedCount) : "--");
|
||||
labExamPassedP->setText(uExamCount != 0 ? QString("%1 %").arg((double)uPassedCount / uExamCount * 100.0, 0, 'f', 1) : "--");
|
||||
labExamFailedP->setText(uExamCount != 0 ? QString("%1 %").arg((double)uFailedCount / uExamCount * 100.0, 0, 'f', 1) : "--");
|
||||
labAvgWrong->setText(uExamCount != 0 ? QString::number(uErrorCount / uExamCount) : "--");
|
||||
labTimeExam->setText(uExamCount != 0 ? QString("%1 m %2 s").arg(uDuration / uExamCount / 60).arg(uDuration / uExamCount % 60, 2, 10, QChar('0')) : "--");
|
||||
labTimeQuestion->setText(uQuestions != 0 ? QString("%1 m %2 s").arg(uDuration / uQuestions / 60).arg(uDuration / uQuestions % 60, 2, 10, QChar('0')) : "--");
|
||||
}
|
||||
|
43
dlgexamstatistic.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qdialog.h>
|
||||
#include "ui_dlgexamstatistic.h"
|
||||
|
||||
class CCatalog;
|
||||
|
||||
class CDlgExamStatistic : public QDialog, Ui::DlgExamStatistic
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgExamStatistic(QWidget *pParent=0);
|
||||
~CDlgExamStatistic() {}
|
||||
|
||||
void go (CCatalog *pCatalog);
|
||||
|
||||
protected slots:
|
||||
void on_cbExam_currentIndexChanged (int index);
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
};
|
367
dlgexamstatistic.ui
Normal file
|
@ -0,0 +1,367 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgExamStatistic</class>
|
||||
<widget class="QDialog" name="DlgExamStatistic" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>452</width>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Prüfungs-Statistik</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Prüfung:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbExam" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>3</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Prüfungs-Rahmenbedinungen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labExamWrong" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labExamQCount" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_13" >
|
||||
<property name="text" >
|
||||
<string>Verfügbare Zeit:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_14" >
|
||||
<property name="text" >
|
||||
<string>Max. erlaubte Anzahl falscher Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Anzahl der Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labExamTime" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_18" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Statistik</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="labAvgWrong" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labExamPassed" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labExamFailed" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>davon bestanden:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Durchschn. Anzahl falscher Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>davon nicht bestanden:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labExamCount" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="QLabel" name="labExamPassedP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="labExamFailedP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Anzahl Prüfungen durchgeführt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Durchschn. benötigte Zeit pro Prüfung / pro Frage:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLabel" name="labTimeExam" >
|
||||
<property name="text" >
|
||||
<string>0 m 0 s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<widget class="QLabel" name="labTimeQuestion" >
|
||||
<property name="text" >
|
||||
<string>0 m 0 s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_19" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Liste durchgeführter Prüfungen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="twExamStat" >
|
||||
<property name="rootIsDecorated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>cbExam</tabstop>
|
||||
<tabstop>twExamStat</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DlgExamStatistic</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DlgExamStatistic</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
51
dlginformation.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlginformation.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#include "catalog.h"
|
||||
|
||||
CDlgInformation::CDlgInformation (QWidget *pParent) : QDialog(pParent)
|
||||
{
|
||||
m_pCatalog=0;
|
||||
setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CDlgInformation::setup(CCatalog *pCatalog)
|
||||
{
|
||||
labName->setText(pCatalog->name());
|
||||
labVersion->setText(pCatalog->versionText());
|
||||
labPublished->setText(pCatalog->published().toString(Qt::LocalDate));
|
||||
labStatQuestion->setText(QString("%1").arg(pCatalog->countSubQuestion()));
|
||||
labStatChapter->setText(QString("%1").arg(pCatalog->subChapters().size()));
|
||||
labValidFrom->setText(pCatalog->validFrom().toString(Qt::LocalDate));
|
||||
labValidUntil->setText(pCatalog->validUntil().toString(Qt::LocalDate));
|
||||
labDate->setText(pCatalog->created().toString(Qt::LocalDate));
|
||||
labComment->setText(pCatalog->comment());
|
||||
labPublisher->setText(pCatalog->publisher());
|
||||
labContact->setText(pCatalog->contact());
|
||||
return true;
|
||||
}
|
||||
|
47
dlginformation.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DLGINFORMATION_H
|
||||
#define DLGINFORMATION_H
|
||||
|
||||
#include <qdialog.h>
|
||||
#include "ui_dlginformation.h"
|
||||
|
||||
class CCatalog;
|
||||
|
||||
class CDlgInformation : public QDialog, Ui::DlgInformation
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgInformation (QWidget *pParent=0);
|
||||
~CDlgInformation () {}
|
||||
|
||||
bool setup(CCatalog *pCatalog);
|
||||
|
||||
protected slots:
|
||||
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
304
dlginformation.ui
Normal file
|
@ -0,0 +1,304 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgInformation</class>
|
||||
<widget class="QDialog" name="DlgInformation" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>366</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Datei-Information</string>
|
||||
</property>
|
||||
<property name="windowIcon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/info.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5" >
|
||||
<property name="title" >
|
||||
<string>Original-Fragenkatalog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="7" column="1" >
|
||||
<widget class="QLabel" name="labPublisher" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" >
|
||||
<widget class="QLabel" name="labStatChapter" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="QLabel" name="labStatQuestion" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLabel" name="labValidUntil" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labName" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labVersion" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labPublished" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="labValidFrom" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Herausgeber:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Anzahl der Kapitel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Anzahl der Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Gültig bis:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Gültig ab:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Datum:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4" >
|
||||
<property name="title" >
|
||||
<string>AFUTrainer-Fragenkatalog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labContact" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_13" >
|
||||
<property name="text" >
|
||||
<string>Erstellt von:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labComment" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="labDate" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>3</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Kommentar:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Erstellt am:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="afutrainer.qrc" />
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DlgInformation</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DlgInformation</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
435
dlglearn.cpp
Normal file
|
@ -0,0 +1,435 @@
|
|||
/***************************************************************************
|
||||
* 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 "catalog.h"
|
||||
#include "dlglearn.h"
|
||||
#include "dlgviewquestion.h"
|
||||
#include "dlglearnassistant.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
CDlgLearn::CDlgLearn (QWidget *pParent) : QDialog (pParent, Qt::WindowMaximizeButtonHint)
|
||||
{
|
||||
m_pCatalog = 0;
|
||||
m_pChapter = 0;
|
||||
m_pQuestion=0;
|
||||
m_pLastQuestion=0;
|
||||
m_uLastAnswerMask=0;
|
||||
m_bHintsUsed=false;
|
||||
m_uElapsedBeforeBreak=0;
|
||||
#ifdef _DEBUG
|
||||
m_bCheatEnable=true;
|
||||
#else
|
||||
m_bCheatEnable=false;
|
||||
#endif
|
||||
m_bAssistantEnable=true;
|
||||
setupUi(this);
|
||||
|
||||
if (!m_bAssistantEnable)
|
||||
gbAssistant->hide();
|
||||
}
|
||||
|
||||
CDlgLearn::~CDlgLearn()
|
||||
{
|
||||
}
|
||||
|
||||
void CDlgLearn::go (CCatalog *pCatalog, CChapter *pChapter)
|
||||
{
|
||||
Q_ASSERT (pChapter != 0);
|
||||
m_pCatalog = pCatalog;
|
||||
setNewChapter(pChapter);
|
||||
|
||||
m_ds = pCatalog->dayStatistic(QDate::currentDate());
|
||||
onUpdateDS();
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
void CDlgLearn::setNewChapter(CChapter *pChapter)
|
||||
{
|
||||
m_pQuestion=0;
|
||||
m_bHintsUsed=false;
|
||||
m_pChapter = pChapter;
|
||||
m_listQuestion = m_pChapter->questionPool();
|
||||
nextQuestion();
|
||||
}
|
||||
|
||||
void CDlgLearn::updateStatistic()
|
||||
{
|
||||
const int w=60, h=16;
|
||||
|
||||
// CHAPTER STATISTICS
|
||||
labChapter->setText (m_pChapter->text());
|
||||
labChapterCount->setText(QString("%1").arg(m_listQuestion.size()));
|
||||
labChapterVeryOften->setText(QString("%1").arg(m_pChapter->countQuestion(0)));
|
||||
labChapterOften->setText(QString("%1").arg(m_pChapter->countQuestion(1)));
|
||||
labChapterNormal->setText(QString("%1").arg(m_pChapter->countQuestion(2)));
|
||||
labChapterRare->setText(QString("%1").arg(m_pChapter->countQuestion(3)));
|
||||
labChapterVeryRare->setText(QString("%1").arg(m_pChapter->countQuestion(4)));
|
||||
labChapterExtremeRare->setText(QString("%1").arg(m_pChapter->countQuestion(5)));
|
||||
labChapterAvgText->setText(m_pChapter->levelAvgText());
|
||||
labChapterAvgIcon->setPixmap(m_pChapter->levelAvgPixmap());
|
||||
labChapterAvgIcon->setToolTip(QString("Kennzahl: %1").arg(m_pChapter->levelAvg(), 4, 'g', 2));
|
||||
|
||||
double dQuestionCount = m_listQuestion.size(), dPercent;
|
||||
// dPercent = (double)m_listQuestion.size()/(double)m_pCatalog->countSubQuestion();
|
||||
// labChapterCountBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
// labChapterCountBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(0)/dQuestionCount;
|
||||
labChapterVeryOftenBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterVeryOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(1)/dQuestionCount;
|
||||
labChapterOftenBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(2)/dQuestionCount;
|
||||
labChapterNormalBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterNormalBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(3)/dQuestionCount;
|
||||
labChapterRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(4)/dQuestionCount;
|
||||
labChapterVeryRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterVeryRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(5)/dQuestionCount;
|
||||
labChapterExtremeRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterExtremeRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
|
||||
// QUESTION STATISTICS
|
||||
labQuestion->setText (tr("Frage %1").arg(m_pQuestion->id()));
|
||||
labQuestionLevelIcon->setPixmap(m_pQuestion->levelPixmap());
|
||||
labQuestionLevelText->setText(m_pQuestion->levelText());
|
||||
if (m_pQuestion->clickedCorrectSuccessive() != 0)
|
||||
labQuestionSuccessive->setText(tr("%1x richtig").arg(m_pQuestion->clickedCorrectSuccessive()));
|
||||
else if (m_pQuestion->clickedWrongSuccessive() != 0)
|
||||
labQuestionSuccessive->setText(tr("%1x falsch").arg(m_pQuestion->clickedWrongSuccessive()));
|
||||
else
|
||||
labQuestionSuccessive->setText(tr("--"));
|
||||
|
||||
labQuestionCount->setText(QString("%1").arg(m_pQuestion->clickedCount()));
|
||||
labQuestionCorrect->setText(QString("%1").arg(m_pQuestion->clickedCorrect()));
|
||||
labQuestionWrong->setText(QString("%1").arg(m_pQuestion->clickedWrong()));
|
||||
QDateTime dtLastClicked = m_pQuestion->lastClicked();
|
||||
if (!dtLastClicked.isValid())
|
||||
labQuestionDate->setText("--");
|
||||
else
|
||||
{
|
||||
labQuestionDate->setText(m_pQuestion->lastClickedText());
|
||||
}
|
||||
|
||||
onUpdateDS();
|
||||
}
|
||||
|
||||
void CDlgLearn::updateLearnAssistant()
|
||||
{
|
||||
QString strRecom1, strRecom2, str;
|
||||
QPixmap pixRecom1, pixRecom2, pix;
|
||||
|
||||
// first recommendation
|
||||
strRecom1 = m_pChapter->recommendationTextExtended(m_pCatalog);
|
||||
if (m_pChapter->isRecommendedNow(m_pCatalog))
|
||||
strRecom1 = "<font color='green'>" + strRecom1 + "</font>";
|
||||
else
|
||||
strRecom1 = "<font color='red'>" + strRecom1 + "</font>";
|
||||
pixRecom1 = QPixmap (m_pChapter->recommendationIconName (m_pCatalog));
|
||||
|
||||
// second recommendation
|
||||
strRecom2 = m_pChapter->recommendationTextExtended2(m_pCatalog);
|
||||
pixRecom2 = QPixmap (m_pChapter->recommendationIconName (m_pChapter->recommendation2(), m_pCatalog));
|
||||
|
||||
|
||||
if (m_pChapter->recommendation() == CChapter::RecommendationSubChapter && m_pChapter->recommendation2() == CChapter::RecommendationRepeatToday)
|
||||
{
|
||||
labRecommendationIcon->setPixmap (pixRecom2);
|
||||
labRecommendation->setText("<font color='green'>" + strRecom2 + "</font>");
|
||||
}
|
||||
else
|
||||
{
|
||||
str = strRecom1;
|
||||
if (!strRecom2.isEmpty())
|
||||
str += "<p><font color='green'>" + strRecom2 + "</font>";
|
||||
labRecommendationIcon->setPixmap (pixRecom1);
|
||||
labRecommendation->setText(str);
|
||||
}
|
||||
}
|
||||
|
||||
CQuestion *CDlgLearn::findNextQuestion()
|
||||
{
|
||||
CQuestion *p = 0;
|
||||
|
||||
if (m_bAssistantEnable && m_pChapter->hasRecommendedQuestions())
|
||||
{
|
||||
// if (afu_random (0, 99) >= 0) // hier kann ggf. das Verhältnis zwischen RecommendedQuestion und Zufalls-Question ausgewählt werden
|
||||
// {
|
||||
p = findNextTargetQuestion();
|
||||
// Wichtig: p kann hier immernoch 0 sein! Dies bedeutet, dass keine passende Frage im TargetPool gefunden wurde.
|
||||
// }
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
p = findNextPoolQuestion();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
CQuestion *CDlgLearn::findNextTargetQuestion()
|
||||
{
|
||||
CQuestion *pQuestion=0;
|
||||
QList<CQuestion*> list = m_pChapter->recommendedQuestions();
|
||||
int iSize = list.size();
|
||||
unsigned uRnd=0;
|
||||
|
||||
if (iSize == 0) return 0;
|
||||
if (iSize == 1)
|
||||
{
|
||||
if (list.at(0) == m_pQuestion)
|
||||
// Regel: Niemals die gleiche Frage mehrfach hintereinander
|
||||
// -> kann hier nicht erfüllt werden -> 0 zurückgeben -> hole Frage aus allg. Pool (siehe findNextQuestion)
|
||||
return 0;
|
||||
else
|
||||
return list.at(0);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
uRnd = afu_random (0, iSize-1);
|
||||
pQuestion = list.at(uRnd);
|
||||
}
|
||||
while (m_pQuestion == pQuestion);
|
||||
|
||||
return pQuestion;
|
||||
}
|
||||
|
||||
CQuestion *CDlgLearn::findNextPoolQuestion()
|
||||
{
|
||||
CQuestion *pQuestion=0;
|
||||
unsigned uCountQuestion[LEVEL_MAX+1];
|
||||
unsigned uRnd=0, uLevel=0;
|
||||
int i=0;
|
||||
unsigned uGewichtung[LEVEL_MAX+1], uEdge[LEVEL_MAX+1];
|
||||
unsigned uRndMax = 0;
|
||||
|
||||
memset (uCountQuestion, 0, sizeof(unsigned)*(LEVEL_MAX+1));
|
||||
for (i=0;i<m_listQuestion.size(); i++)
|
||||
{
|
||||
uLevel = m_listQuestion[i]->level();
|
||||
Q_ASSERT(uLevel < LEVEL_MAX+1);
|
||||
if (uLevel > LEVEL_MAX) continue;
|
||||
uCountQuestion[uLevel]++;
|
||||
}
|
||||
|
||||
uGewichtung[LEVEL_MAX] = 1;
|
||||
uRndMax = 1;
|
||||
for (i=LEVEL_MAX-1; i>=0; i--)
|
||||
{
|
||||
uRndMax += uGewichtung[i+1];
|
||||
uGewichtung[i] = uRndMax;
|
||||
}
|
||||
|
||||
for (i=0; i<=LEVEL_MAX; i++)
|
||||
uGewichtung[i] *= uCountQuestion[i];
|
||||
|
||||
uRndMax=0;
|
||||
for (i=0; i<=LEVEL_MAX; i++)
|
||||
{
|
||||
uLevel = LEVEL_MAX-i;
|
||||
uRndMax += uGewichtung[uLevel];
|
||||
uEdge[uLevel] = uRndMax;
|
||||
}
|
||||
|
||||
do /* diese Schleife verhindert, dass eine Frage zweimal hintereinander kommt */
|
||||
{
|
||||
do /* diese Schleife wählt die Abfragehäufigkeit aus */
|
||||
{
|
||||
uRnd = afu_random (1, uRndMax);
|
||||
uLevel = LEVEL_MAX;
|
||||
while (uLevel != LEVEL_VERYOFTEN && uRnd > uEdge[uLevel])
|
||||
uLevel--;
|
||||
|
||||
Q_ASSERT(uCountQuestion[uLevel] != 0); // Wenn hier assertion failed => algorithmus falsch
|
||||
}
|
||||
while (uCountQuestion[uLevel] == 0);
|
||||
|
||||
// Zufällige Frage bestimmen
|
||||
uRnd = afu_random (1, uCountQuestion[uLevel]);
|
||||
for (i=0; i<m_listQuestion.size()-1; i++)
|
||||
if (m_listQuestion[i]->level() == uLevel && --uRnd == 0) break;
|
||||
}
|
||||
while (m_pQuestion == m_listQuestion[i] && m_listQuestion.size() > 1);
|
||||
pQuestion = m_listQuestion[i];
|
||||
return pQuestion;
|
||||
}
|
||||
|
||||
void CDlgLearn::nextQuestion()
|
||||
{
|
||||
QString str, strCheat;
|
||||
|
||||
if (m_listQuestion.size() == 0)
|
||||
{
|
||||
QMessageBox::critical (this, "Fehler", "Es gibt keine Fragen, die gelernt werden könnten!");
|
||||
accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pQuestion)
|
||||
{ // Save current question as new last question
|
||||
pbLastQuestion->setEnabled(true);
|
||||
m_pLastQuestion = m_pQuestion;
|
||||
}
|
||||
|
||||
m_pQuestion = findNextQuestion();
|
||||
|
||||
// show answer
|
||||
m_pQuestion->mixAnswers();
|
||||
|
||||
str = m_pQuestion->learnText(m_pCatalog, true, false);
|
||||
if (m_bCheatEnable)
|
||||
{
|
||||
strCheat = "<p><font size=-1><i><b>Schummel-Modus</b><br>Richtige Antwort: " + CAnswerClicked::answerText (m_pQuestion->correctAnswerMask()) + "</i>";
|
||||
strCheat += "<br>Empfohlene Wiederholung: " + m_pQuestion->repeatDateText();
|
||||
strCheat += QString("<br>isLearningNew(): %1").arg(m_pQuestion->isLearningNew());
|
||||
|
||||
strCheat += "</font><p>";
|
||||
}
|
||||
teQuestion->setHtml(strCheat + str);
|
||||
|
||||
pbShowHelper->setEnabled (m_pCatalog->hasHints(m_pQuestion->id()));
|
||||
m_bHintsUsed = false;
|
||||
m_timeElapsed.restart();
|
||||
updateStatistic();
|
||||
updateLearnAssistant();
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbAnswerA_clicked()
|
||||
{
|
||||
handleAnswer(0);
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbAnswerB_clicked()
|
||||
{
|
||||
handleAnswer(1);
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbAnswerC_clicked()
|
||||
{
|
||||
handleAnswer(2);
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbAnswerD_clicked()
|
||||
{
|
||||
handleAnswer(3);
|
||||
}
|
||||
|
||||
void CDlgLearn::handleAnswer(const int i)
|
||||
{
|
||||
unsigned uAnswerMask = 1<<i;
|
||||
|
||||
if (!m_pQuestion->isCorrectAnswer(uAnswerMask))
|
||||
{
|
||||
QMessageBox::information(this, tr("Hinweis"), m_pQuestion->correctionText(uAnswerMask));
|
||||
}
|
||||
m_uLastAnswerMask=uAnswerMask;
|
||||
|
||||
if (!m_bHintsUsed)
|
||||
{
|
||||
m_pQuestion->registerAnswerClicked(uAnswerMask, m_timeElapsed.elapsed() + m_uElapsedBeforeBreak);
|
||||
|
||||
bool bIsRecommendedOld = m_pChapter->isRecommendedNow(m_pCatalog) ;
|
||||
|
||||
m_pCatalog->updateStatistic();
|
||||
m_ds = m_pCatalog->dayStatistic(QDate::currentDate());
|
||||
|
||||
if (bIsRecommendedOld && !m_pChapter->isRecommendedNow(m_pCatalog))
|
||||
{
|
||||
QMessageBox msgBox(this);
|
||||
QPushButton *pbAssistant = msgBox.addButton(tr("Assistent"), QMessageBox::AcceptRole);
|
||||
QPushButton *pbIgnore = msgBox.addButton(QMessageBox::Ignore);
|
||||
QPushButton *pbExit = msgBox.addButton(QMessageBox::Cancel);
|
||||
pbAssistant->setIcon(QIcon(":/icons/16x16/idea_info.png"));
|
||||
pbAssistant->setToolTip(tr("Lern-Assistent aufrufen"));
|
||||
pbIgnore->setToolTip(tr("Meldung ignorieren, dieses Kapitel weiterlernen"));
|
||||
pbExit->setToolTip(tr("Lernmodus beenden"));
|
||||
msgBox.setText(tr("<b>Herzlichen Glückwunsch!</b><p>Sie haben das heutige Lernziel für dieses Kapitel erreicht.<br>Bitte folgen Sie den weiteren Empfehlungen des Lernassistents."));
|
||||
msgBox.setWindowTitle(tr("Ziel erreicht"));
|
||||
|
||||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == pbExit)
|
||||
{
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
else if (msgBox.clickedButton() == pbAssistant)
|
||||
{
|
||||
on_pbLearnAssistant_clicked();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
nextQuestion();
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbShowHelper_clicked()
|
||||
{
|
||||
m_bHintsUsed = true;
|
||||
QString str = m_pQuestion->learnText(m_pCatalog, true, true);
|
||||
teQuestion->setHtml(str);
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbLastQuestion_clicked()
|
||||
{
|
||||
CDlgViewQuestion dlg(this);
|
||||
dlg.go(m_pCatalog, m_pLastQuestion, m_uLastAnswerMask);
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbSkip_clicked()
|
||||
{
|
||||
m_uLastAnswerMask=0;
|
||||
nextQuestion();
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbQuit_clicked()
|
||||
{
|
||||
m_pCatalog->updateStatistic();
|
||||
accept();
|
||||
}
|
||||
|
||||
void CDlgLearn::on_pbLearnAssistant_clicked()
|
||||
{
|
||||
CDlgLearnAssistant dlg(this);
|
||||
CChapter *pChapter=0;
|
||||
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;
|
||||
setNewChapter(pChapter);
|
||||
}
|
||||
|
||||
void CDlgLearn::onUpdateDS()
|
||||
{
|
||||
labDSTime->setText(QString("%1 h %2 m").arg(m_ds.timeExpediture()/1000/3600).arg(m_ds.timeExpediture()/1000/60 % 60, 2, 10, QChar('0')));
|
||||
labDSCount->setText(QString::number(m_ds.clickedCount()));
|
||||
labDSCorrect->setText(QString::number(m_ds.clickedCorrect()));
|
||||
labDSWrong->setText(QString::number(m_ds.clickedWrong()));
|
||||
}
|
84
dlglearn.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DLGLEARN_H
|
||||
#define DLGLEARN_H
|
||||
|
||||
#include <qdialog.h>
|
||||
#include <qlist.h>
|
||||
#include <qdatetime.h>
|
||||
#include "question.h"
|
||||
|
||||
#include "ui_dlglearn.h"
|
||||
|
||||
class CChapter;
|
||||
class CCatalog;
|
||||
|
||||
class CDlgLearn : public QDialog, Ui::DlgLearn
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgLearn (QWidget *pParent=0);
|
||||
~CDlgLearn();
|
||||
|
||||
void go (CCatalog *pCatalog, CChapter *pChapter);
|
||||
|
||||
protected:
|
||||
void setNewChapter(CChapter *pChapter);
|
||||
void updateStatistic();
|
||||
void updateLearnAssistant();
|
||||
void nextQuestion();
|
||||
CQuestion *findNextQuestion();
|
||||
CQuestion *findNextPoolQuestion();
|
||||
CQuestion *findNextTargetQuestion();
|
||||
|
||||
void handleAnswer(const int i);
|
||||
|
||||
protected slots:
|
||||
void on_pbAnswerA_clicked();
|
||||
void on_pbAnswerB_clicked();
|
||||
void on_pbAnswerC_clicked();
|
||||
void on_pbAnswerD_clicked();
|
||||
void on_pbShowHelper_clicked();
|
||||
void on_pbSkip_clicked();
|
||||
void on_pbLastQuestion_clicked();
|
||||
void on_pbQuit_clicked();
|
||||
void on_pbLearnAssistant_clicked();
|
||||
void onUpdateDS();
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
CChapter *m_pChapter;
|
||||
QList<CQuestion*> m_listQuestion;
|
||||
CQuestion *m_pQuestion;
|
||||
CQuestion *m_pLastQuestion;
|
||||
unsigned m_uLastAnswerMask;
|
||||
bool m_bHintsUsed;
|
||||
QTime m_timeElapsed;
|
||||
unsigned m_uElapsedBeforeBreak; // if the user makes a break
|
||||
bool m_bMsgBoxTargetReachedShowed;
|
||||
CDayStatistic m_ds;
|
||||
|
||||
bool m_bAssistantEnable;
|
||||
bool m_bCheatEnable;
|
||||
};
|
||||
|
||||
#endif
|
1139
dlglearn.ui
Normal file
117
dlglearnassistant.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlglearnassistant.h"
|
||||
|
||||
#include <qheaderview.h>
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#include "catalog.h"
|
||||
|
||||
CDlgLearnAssistant::CDlgLearnAssistant (QWidget *pParent) : QDialog(pParent)
|
||||
{
|
||||
m_pCatalog=0;
|
||||
setupUi(this);
|
||||
|
||||
tvChapters->setModel (&m_modelChapter);
|
||||
tvChapters->header()->setStretchLastSection(false);
|
||||
tvChapters->header()->setResizeMode (0, QHeaderView::Stretch);
|
||||
tvChapters->header()->setResizeMode (1, QHeaderView::Interactive);
|
||||
tvChapters->header()->setResizeMode (3, QHeaderView::Interactive);
|
||||
tvChapters->header()->resizeSection(1, 50);
|
||||
tvChapters->header()->resizeSection(2, 140);
|
||||
tvChapters->header()->resizeSection(3, 20);
|
||||
}
|
||||
|
||||
|
||||
bool CDlgLearnAssistant::setup(CCatalog *pCatalog)
|
||||
{
|
||||
bool bEnableRepeat;
|
||||
QList<CChapter*> listAll, listNow, listToday, listSelected;
|
||||
CChapter *c;
|
||||
|
||||
m_pCatalog = pCatalog;
|
||||
if (pCatalog->recommendationCount (CChapter::RecommendationRepeatToday) > 0)
|
||||
{
|
||||
bEnableRepeat = true;
|
||||
labRepeat->setText(tr("Es sind %1 Fragen vorhanden").arg(pCatalog->recommendedQuestions().count()));
|
||||
rbRepeat->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bEnableRepeat = false;
|
||||
labRepeat->setText(tr("Keine Fragen vorhanden."));
|
||||
rbList->setChecked(true);
|
||||
}
|
||||
rbRepeat->setEnabled(bEnableRepeat);
|
||||
labRepeat->setEnabled(bEnableRepeat);
|
||||
|
||||
// update list
|
||||
listAll = pCatalog->chapters();
|
||||
for (int i=0; i<listAll.size(); i++)
|
||||
{
|
||||
c = listAll.at(i);
|
||||
if (c->isRecommendedNow(pCatalog))
|
||||
listNow << c;
|
||||
else if (c->recommendation() == CChapter::RecommendationLearnNew)
|
||||
listToday << c;
|
||||
}
|
||||
|
||||
listSelected << listNow << listToday;
|
||||
m_modelChapter.setModelData (pCatalog, listSelected);
|
||||
|
||||
if (!bEnableRepeat && listSelected.isEmpty()) return false;
|
||||
|
||||
updateEnable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDlgLearnAssistant::updateEnable()
|
||||
{
|
||||
labRepeat->setEnabled(rbRepeat->isChecked());
|
||||
tvChapters->setEnabled(rbList->isChecked());
|
||||
}
|
||||
|
||||
|
||||
void CDlgLearnAssistant::on_buttonBox_accepted()
|
||||
{
|
||||
QModelIndexList list = tvChapters->selectionModel()->selectedIndexes();
|
||||
if (rbList->isChecked() && list.isEmpty())
|
||||
{
|
||||
QMessageBox::information(this, tr("Information"), tr("Bitte markieren Sie in der Liste ein Kapitel, das Sie lernen möchten!"));
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
}
|
||||
|
||||
CChapter* CDlgLearnAssistant::selectedChapter()
|
||||
{
|
||||
QModelIndexList list = tvChapters->selectionModel()->selectedIndexes();
|
||||
if (rbRepeat->isChecked())
|
||||
return m_pCatalog;
|
||||
if (rbList->isChecked())
|
||||
{
|
||||
if (list.isEmpty()) return 0;
|
||||
return (CChapter*)list.first().internalPointer();
|
||||
}
|
||||
return 0;
|
||||
}
|
56
dlglearnassistant.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DLGLEARNASSISTANT_H
|
||||
#define DLGLEARNASSISTANT_H
|
||||
|
||||
#include <qdialog.h>
|
||||
#include "ui_dlglearnassistant.h"
|
||||
|
||||
#include "chaptermodel.h"
|
||||
|
||||
class CDlgLearnAssistant : public QDialog, Ui::DlgLearnAssistant
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgLearnAssistant (QWidget *pParent=0);
|
||||
~CDlgLearnAssistant () {}
|
||||
|
||||
bool setup(CCatalog *pCatalog);
|
||||
CChapter* selectedChapter();
|
||||
|
||||
protected slots:
|
||||
void on_buttonBox_accepted();
|
||||
inline void on_rbList_toggled() { updateEnable(); }
|
||||
inline void on_rbRepeat_toggled() { updateEnable(); }
|
||||
|
||||
protected:
|
||||
void updateEnable();
|
||||
|
||||
protected:
|
||||
CCatalog *m_pCatalog;
|
||||
CChapterModel m_modelChapter;
|
||||
|
||||
// CRecommendation m_recomDeepen;
|
||||
// CRecommendation m_recomRepeat;
|
||||
};
|
||||
|
||||
#endif
|
112
dlglearnassistant.ui
Normal file
|
@ -0,0 +1,112 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgLearnAssistant</class>
|
||||
<widget class="QDialog" name="DlgLearnAssistant" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>493</width>
|
||||
<height>422</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Lern-Assistent</string>
|
||||
</property>
|
||||
<property name="windowIcon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/idea_info.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Vorschläge des Lern-Assistents</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbRepeat" >
|
||||
<property name="text" >
|
||||
<string>Alle heute zu wiederholenden Fragen lernen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labRepeat" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbList" >
|
||||
<property name="text" >
|
||||
<string>Kapitel aus folgender Liste lernen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="tvChapters" >
|
||||
<property name="rootIsDecorated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>rbRepeat</tabstop>
|
||||
<tabstop>rbList</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="afutrainer.qrc" />
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DlgLearnAssistant</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>293</x>
|
||||
<y>397</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>416</x>
|
||||
<y>418</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
417
dlglearnstatistic.cpp
Normal file
|
@ -0,0 +1,417 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlglearnstatistic.h"
|
||||
#include "chapter.h"
|
||||
#include "tools.h"
|
||||
#include "plotwidget.h"
|
||||
|
||||
#include <qdatetime.h>
|
||||
|
||||
CDlgLearnStatistic::CDlgLearnStatistic(QWidget *pParent) : QDialog(pParent)
|
||||
{
|
||||
|
||||
|
||||
m_pChapter = 0;
|
||||
setupUi(this);
|
||||
cbPeriod->addItem(tr("2 Wochen"), 14);
|
||||
cbPeriod->addItem(tr("1 Monat"), 30);
|
||||
cbPeriod->addItem(tr("3 Monate"), 90);
|
||||
cbPeriod->addItem(tr("6 Monate"), 30*6);
|
||||
cbPeriod->addItem(tr("1 Jahr"), 365);
|
||||
cbPeriod->setCurrentIndex(0);
|
||||
|
||||
m_pPlotLevel = new CPlotWidget(groupLevel);
|
||||
m_pPlotLevel->setFrameShape(QFrame::Panel);
|
||||
m_pPlotLevel->setFrameShadow(QFrame::Sunken);
|
||||
groupLevel->layout()->addWidget(m_pPlotLevel);
|
||||
|
||||
m_pPlotLevel->setBorderDistance(25, 5, 5, 25);
|
||||
m_pPlotLevel->setLimitY(0.0, 5.5);
|
||||
m_pPlotLevel->setBorderPen(QPen(Qt::black));
|
||||
m_pPlotLevel->setBorder(CPlotWidget::BorderLeft | CPlotWidget::BorderBottom);
|
||||
m_pPlotLevel->setTicY(1.0);
|
||||
|
||||
QList<CPlotWidgetTic> listTics;
|
||||
for (int i=0; i<=LEVEL_MAX; i++)
|
||||
{
|
||||
CPlotWidgetTic tic (i, QPixmap(CQuestion::levelIconName(i)));
|
||||
listTics.append(tic);
|
||||
}
|
||||
m_pPlotLevel->setTicListY(listTics);
|
||||
|
||||
m_pPlotClicked = new CPlotWidget(groupClicked);
|
||||
m_pPlotClicked->setFrameShape(QFrame::Panel);
|
||||
m_pPlotClicked->setFrameShadow(QFrame::Sunken);
|
||||
groupClicked->layout()->addWidget(m_pPlotClicked);
|
||||
|
||||
m_pPlotClicked->setType(CPlotWidget::PlotBarsSum);
|
||||
m_pPlotClicked->setBarOffset(-0.5);
|
||||
m_pPlotClicked->setBorderDistance(25, 5, 5, 25);
|
||||
|
||||
// Zeitaufwand
|
||||
cbPeriod2->addItem(tr("2 Wochen"), 14);
|
||||
cbPeriod2->addItem(tr("1 Monat"), 30);
|
||||
cbPeriod2->addItem(tr("3 Monate"), 90);
|
||||
cbPeriod2->addItem(tr("6 Monate"), 30*6);
|
||||
cbPeriod2->addItem(tr("1 Jahr"), 365);
|
||||
cbPeriod2->setCurrentIndex(0);
|
||||
|
||||
m_pPlotTime = new CPlotWidget(groupTimeExpediture);
|
||||
m_pPlotTime->setFrameShape(QFrame::Panel);
|
||||
m_pPlotTime->setFrameShadow(QFrame::Sunken);
|
||||
groupTimeExpediture->layout()->addWidget(m_pPlotTime);
|
||||
|
||||
m_pPlotTime->setType(CPlotWidget::PlotBarsSum);
|
||||
m_pPlotTime->setBarOffset(-0.5);
|
||||
m_pPlotTime->setBorderDistance(25, 5, 5, 25);
|
||||
/*
|
||||
m_pPlotTimePerQuestion = new CPlotWidget(groupTimeExpediturePerQuestion);
|
||||
m_pPlotTimePerQuestion->setFrameShape(QFrame::Panel);
|
||||
m_pPlotTimePerQuestion->setFrameShadow(QFrame::Sunken);
|
||||
groupTimeExpediturePerQuestion->layout()->addWidget(m_pPlotTimePerQuestion);
|
||||
|
||||
m_pPlotTimePerQuestion->setType(CPlotWidget::PlotLines);
|
||||
m_pPlotTimePerQuestion->setBorderDistance(25, 5, 5, 25);
|
||||
*/
|
||||
}
|
||||
|
||||
void CDlgLearnStatistic::go(CChapter *pChapter)
|
||||
{
|
||||
m_pChapter = pChapter;
|
||||
updateTable();
|
||||
updateHistory();
|
||||
updateTimeExpediture();
|
||||
exec();
|
||||
}
|
||||
|
||||
|
||||
void CDlgLearnStatistic::updateTable()
|
||||
{
|
||||
const int w=60, h=16;
|
||||
QList<CQuestion*> listQuestion = m_pChapter->questionPool();
|
||||
CDayStatistic ds;
|
||||
|
||||
// CHAPTER STATISTICS
|
||||
labChapter->setText (m_pChapter->text());
|
||||
labChapterCount->setText(QString("%1").arg(listQuestion.size()));
|
||||
labChapterVeryOften->setText(QString("%1").arg(m_pChapter->countQuestion(0)));
|
||||
labChapterOften->setText(QString("%1").arg(m_pChapter->countQuestion(1)));
|
||||
labChapterNormal->setText(QString("%1").arg(m_pChapter->countQuestion(2)));
|
||||
labChapterRare->setText(QString("%1").arg(m_pChapter->countQuestion(3)));
|
||||
labChapterVeryRare->setText(QString("%1").arg(m_pChapter->countQuestion(4)));
|
||||
labChapterExtremeRare->setText(QString("%1").arg(m_pChapter->countQuestion(5)));
|
||||
labChapterAvgText->setText(m_pChapter->levelAvgText());
|
||||
labChapterAvgIcon->setPixmap(m_pChapter->levelAvgPixmap());
|
||||
labChapterAvgIcon->setToolTip(QString("Kennzahl: %1").arg(m_pChapter->levelAvg(), 4, 'g', 2));
|
||||
|
||||
double dQuestionCount = listQuestion.size(), dPercent=0.0;
|
||||
dPercent = (double)m_pChapter->countQuestion(0)/dQuestionCount;
|
||||
labChapterVeryOftenBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterVeryOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(1)/dQuestionCount;
|
||||
labChapterOftenBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterOftenBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(2)/dQuestionCount;
|
||||
labChapterNormalBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterNormalBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(3)/dQuestionCount;
|
||||
labChapterRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(4)/dQuestionCount;
|
||||
labChapterVeryRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterVeryRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
dPercent = (double)m_pChapter->countQuestion(5)/dQuestionCount;
|
||||
labChapterExtremeRareBar->setPixmap(createProgressBar(w, h, dPercent));
|
||||
labChapterExtremeRareBar->setToolTip(QString("%1 %").arg(dPercent * 100, 0, 'f', 1));
|
||||
|
||||
ds = m_pChapter->dayStatistic(QDate());
|
||||
labClickCount->setText(QString::number(ds.clickedCount()));
|
||||
labClickCorrect->setText(QString::number(ds.clickedCorrect()));
|
||||
labClickWrong->setText(QString::number(ds.clickedWrong()));
|
||||
labClickCorrectP->setText(ds.clickedCount() != 0 ? QString("%1 %").arg(100.0 * ds.clickedCorrect() / ds.clickedCount(), 0, 'f', 1) : "--");
|
||||
labClickWrongP->setText(ds.clickedCount() != 0 ? QString("%1 %").arg(100.0 * ds.clickedWrong() / ds.clickedCount(), 0, 'f', 1) : "--");
|
||||
labTimeExpediture->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpediture() / 3600000).arg(ds.timeExpediture() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpediture()/1000 % 60, 2, 10, QChar('0')));
|
||||
labTimeExpeditureCorrect->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpeditureCorrect() / 3600000).arg(ds.timeExpeditureCorrect() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpeditureCorrect()/1000 % 60, 2, 10, QChar('0')));
|
||||
labTimeExpeditureWrong->setText(QString("%1 h %2 m %3 s").arg(ds.timeExpeditureWrong() / 3600000).arg(ds.timeExpeditureWrong() / 60000 % 60, 2, 10, QChar('0')).arg(ds.timeExpeditureWrong()/1000 % 60, 2, 10, QChar('0')));
|
||||
labTimeExpeditureCorrectP->setText(ds.timeExpediture() != 0 ? QString("%1 %").arg(100.0 * ds.timeExpeditureCorrect() / ds.timeExpediture(), 0, 'f', 1) : "--");
|
||||
labTimeExpeditureWrongP->setText(ds.timeExpediture() != 0 ? QString("%1 %").arg(100.0 * ds.timeExpeditureWrong() / ds.timeExpediture(), 0, 'f', 1) : "--");
|
||||
labTimePerQuestion->setText(ds.clickedCount() != 0 ? QString("%2 m %3 s").arg(ds.timeExpediture() / ds.clickedCount() / 60000).arg(ds.timeExpediture() / 1000 / ds.clickedCount() % 60, 2, 10, QChar('0')) : "--");
|
||||
labTimePerQuestionCorrect->setText(ds.clickedCorrect() != 0 ? QString("%2 m %3 s").arg(ds.timeExpeditureCorrect() / ds.clickedCorrect() / 60000).arg(ds.timeExpeditureCorrect() / 1000 / ds.clickedCorrect() % 60, 2, 10, QChar('0')) : "--");
|
||||
labTimePerQuestionWrong->setText(ds.clickedWrong() != 0 ? QString("%2 m %3 s").arg(ds.timeExpeditureWrong() / ds.clickedWrong() / 60000).arg(ds.timeExpeditureWrong() / 1000 / ds.clickedWrong() % 60, 2, 10, QChar('0')) : "--");
|
||||
}
|
||||
|
||||
void CDlgLearnStatistic::on_cbPeriod_currentIndexChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
updateHistory();
|
||||
}
|
||||
|
||||
void CDlgLearnStatistic::updateHistory()
|
||||
{
|
||||
int iDays = cbPeriod->itemData(cbPeriod->currentIndex()).toInt(), idx=0;
|
||||
CPlotWidgetCurve curveLevel, curveClickedCorrect, curveClickedWrong;
|
||||
QDate date = QDate::currentDate();
|
||||
CDayStatistic ds;
|
||||
QList<CPlotWidgetTic> listTics;
|
||||
CPlotWidgetTic tic;
|
||||
bool bAddTic=false;
|
||||
unsigned uMaxClicked=0;
|
||||
|
||||
if (m_pChapter == 0) return;
|
||||
setCursor(Qt::WaitCursor);
|
||||
date = date.addDays(-iDays);
|
||||
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
tic.setFillType(CPlotWidgetTic::FillAll);
|
||||
tic.setPen(QPen(Qt::darkGray));
|
||||
|
||||
while (date <= QDate::currentDate())
|
||||
{
|
||||
if (bAddTic)
|
||||
{
|
||||
bAddTic=false;
|
||||
tic.setPos(idx-1);
|
||||
if (listTics.size() % 2)
|
||||
tic.setBrush(QBrush(Qt::white));
|
||||
else
|
||||
tic.setBrush(QBrush(QColor(232,232,232)));
|
||||
listTics.append(tic);
|
||||
}
|
||||
|
||||
ds = m_pChapter->dayStatistic(date);
|
||||
curveLevel.append(CPlotWidgetPoint(idx, ds.level()));
|
||||
curveClickedCorrect.append(CPlotWidgetPoint((double)idx, ds.clickedCorrect()));
|
||||
curveClickedWrong.append(CPlotWidgetPoint((double)idx, ds.clickedWrong()));
|
||||
if (ds.clickedCount() > uMaxClicked) uMaxClicked = ds.clickedCount();
|
||||
|
||||
date = date.addDays(1);
|
||||
|
||||
// X-Tics
|
||||
if (iDays <= 14)
|
||||
{ // daily tics
|
||||
tic.setText(date.toString("ddd"));
|
||||
tic.setWidth(1);
|
||||
if (date.dayOfWeek() == Qt::Monday)
|
||||
tic.setLineType(CPlotWidgetTic::LinePlot);
|
||||
else
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
|
||||
bAddTic=true;
|
||||
}
|
||||
else if (iDays <= 90 && date.dayOfWeek() == Qt::Monday)
|
||||
{
|
||||
tic.setText(QString("KW %1").arg(date.weekNumber()));
|
||||
tic.setWidth(7);
|
||||
bAddTic=true;
|
||||
}
|
||||
else if (iDays > 90 && date.day() == 1)
|
||||
{
|
||||
tic.setText(date.toString("MMM"));
|
||||
tic.setWidth(date.daysInMonth());
|
||||
if (date.month() == 1)
|
||||
tic.setLineType(CPlotWidgetTic::LinePlot);
|
||||
else
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
bAddTic=true;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
m_pPlotLevel->setTicListX(listTics);
|
||||
m_pPlotClicked->setTicListX(listTics);
|
||||
|
||||
|
||||
curveLevel.setPen(QPen(Qt::darkBlue));
|
||||
curveClickedCorrect.setPen(QPen(Qt::green));
|
||||
curveClickedCorrect.setBrush(QBrush(Qt::green));
|
||||
curveClickedWrong.setPen(QPen(Qt::red));
|
||||
curveClickedWrong.setBrush(QBrush(Qt::red));
|
||||
|
||||
|
||||
m_pPlotLevel->clearCurves();
|
||||
m_pPlotLevel->appendCurve(curveLevel);
|
||||
m_pPlotLevel->update();
|
||||
|
||||
m_pPlotClicked->clearCurves();
|
||||
m_pPlotClicked->appendCurve(curveClickedCorrect);
|
||||
m_pPlotClicked->appendCurve(curveClickedWrong);
|
||||
m_pPlotClicked->update();
|
||||
|
||||
unsigned uDiffBase[] = {1, 2, 5, 10}, uDiffMulti=1, uDiff=0, uDiffCount=0;
|
||||
idx = 0;
|
||||
do
|
||||
{
|
||||
if (idx == 4) { idx = 0; uDiffMulti*=10; }
|
||||
uDiff = uDiffBase[idx] * uDiffMulti;
|
||||
uDiffCount = (uMaxClicked / uDiff) + 1;
|
||||
idx++;
|
||||
}
|
||||
while (uDiffCount > 9);
|
||||
|
||||
m_pPlotClicked->setLimitY(0, uDiffCount * uDiff + uDiff/2);
|
||||
|
||||
listTics.clear();
|
||||
tic.clear();
|
||||
tic.setTextFlags(Qt::AlignRight | Qt::AlignVCenter);
|
||||
for (unsigned u=0; u<=uDiffCount * uDiff; u+=uDiff)
|
||||
{
|
||||
tic.setPos(u);
|
||||
tic.setText(QString("%1").arg(u));
|
||||
listTics.append(tic);
|
||||
}
|
||||
m_pPlotClicked->setTicListY(listTics);
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
|
||||
void CDlgLearnStatistic::on_cbPeriod2_currentIndexChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
updateTimeExpediture();
|
||||
}
|
||||
|
||||
void CDlgLearnStatistic::updateTimeExpediture()
|
||||
{
|
||||
int iDays = cbPeriod2->itemData(cbPeriod2->currentIndex()).toInt(), idx=0;
|
||||
CPlotWidgetCurve curveTimeWrong, curveTimeCorrect,curveTimePQWrong, curveTimePQCorrect; // PQ=per question
|
||||
QDate date = QDate::currentDate();
|
||||
CDayStatistic ds;
|
||||
QList<CPlotWidgetTic> listTics;
|
||||
CPlotWidgetTic tic;
|
||||
bool bAddTic=false;
|
||||
unsigned uMaxTime=0;
|
||||
|
||||
if (m_pChapter == 0) return;
|
||||
setCursor(Qt::WaitCursor);
|
||||
date = date.addDays(-iDays);
|
||||
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
tic.setFillType(CPlotWidgetTic::FillAll);
|
||||
tic.setPen(QPen(Qt::darkGray));
|
||||
|
||||
while (date <= QDate::currentDate())
|
||||
{
|
||||
if (bAddTic)
|
||||
{
|
||||
bAddTic=false;
|
||||
tic.setPos(idx-1);
|
||||
if (listTics.size() % 2)
|
||||
tic.setBrush(QBrush(Qt::white));
|
||||
else
|
||||
tic.setBrush(QBrush(QColor(232,232,232)));
|
||||
listTics.append(tic);
|
||||
}
|
||||
|
||||
ds = m_pChapter->dayStatistic(date);
|
||||
curveTimeWrong.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureWrong()/1000.0/60.0));
|
||||
curveTimeCorrect.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureCorrect()/1000.0/60.0));
|
||||
/* if (ds.clickedWrong() > 0)
|
||||
curveTimePQWrong.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureWrong()/1000.0/60.0/(double)ds.clickedWrong()));
|
||||
else
|
||||
curveTimePQWrong.append(CPlotWidgetPoint(idx, 0));
|
||||
if (ds.clickedCorrect() > 0)
|
||||
curveTimePQCorrect.append(CPlotWidgetPoint(idx, (double)ds.timeExpeditureCorrect()/1000.0/60.0/(double)ds.clickedCorrect()));
|
||||
else
|
||||
curveTimePQWrong.append(CPlotWidgetPoint(idx, 0));*/
|
||||
if (ds.timeExpediture()/1000/60 > uMaxTime) uMaxTime = ds.timeExpediture()/1000/60;
|
||||
|
||||
date = date.addDays(1);
|
||||
|
||||
// X-Tics
|
||||
if (iDays <= 14)
|
||||
{ // daily tics
|
||||
tic.setText(date.toString("ddd"));
|
||||
tic.setWidth(1);
|
||||
if (date.dayOfWeek() == Qt::Monday)
|
||||
tic.setLineType(CPlotWidgetTic::LinePlot);
|
||||
else
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
|
||||
bAddTic=true;
|
||||
}
|
||||
else if (iDays <= 90 && date.dayOfWeek() == Qt::Monday)
|
||||
{
|
||||
tic.setText(QString("KW %1").arg(date.weekNumber()));
|
||||
tic.setWidth(7);
|
||||
bAddTic=true;
|
||||
}
|
||||
else if (iDays > 90 && date.day() == 1)
|
||||
{
|
||||
tic.setText(date.toString("MMM"));
|
||||
tic.setWidth(date.daysInMonth());
|
||||
if (date.month() == 1)
|
||||
tic.setLineType(CPlotWidgetTic::LinePlot);
|
||||
else
|
||||
tic.setLineType(CPlotWidgetTic::LineNone);
|
||||
bAddTic=true;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
m_pPlotTime->setTicListX(listTics);
|
||||
//m_pPlotTimePerQuestion->setTicListX(listTics);
|
||||
|
||||
curveTimeCorrect.setPen(QPen(Qt::green));
|
||||
curveTimeCorrect.setBrush(QBrush(Qt::green));
|
||||
curveTimeWrong.setPen(QPen(Qt::red));
|
||||
curveTimeWrong.setBrush(QBrush(Qt::red));
|
||||
|
||||
m_pPlotTime->clearCurves();
|
||||
m_pPlotTime->appendCurve(curveTimeCorrect);
|
||||
m_pPlotTime->appendCurve(curveTimeWrong);
|
||||
m_pPlotTime->update();
|
||||
/*
|
||||
m_pPlotTimePerQuestion->clearCurves();
|
||||
m_pPlotTimePerQuestion->appendCurve(curveTimePQCorrect);
|
||||
m_pPlotTimePerQuestion->appendCurve(curveTimePQWrong);
|
||||
m_pPlotTimePerQuestion->setAutoLimitRoundY(0.1);
|
||||
m_pPlotTimePerQuestion->update();
|
||||
*/
|
||||
unsigned uDiffBase[] = {1, 2, 5, 10}, uDiffMulti=1, uDiff=0, uDiffCount=0;
|
||||
idx = 0;
|
||||
do
|
||||
{
|
||||
if (idx == 4) { idx = 0; uDiffMulti*=10; }
|
||||
uDiff = uDiffBase[idx] * uDiffMulti;
|
||||
uDiffCount = (uMaxTime / uDiff) + 1;
|
||||
idx++;
|
||||
}
|
||||
while (uDiffCount > 9);
|
||||
|
||||
m_pPlotTime->setLimitY(0, uDiffCount * uDiff + uDiff/2);
|
||||
|
||||
listTics.clear();
|
||||
tic.clear();
|
||||
tic.setTextFlags(Qt::AlignRight | Qt::AlignVCenter);
|
||||
for (unsigned u=0; u<=uDiffCount * uDiff; u+=uDiff)
|
||||
{
|
||||
tic.setPos(u);
|
||||
tic.setText(QString("%1").arg(u));
|
||||
listTics.append(tic);
|
||||
}
|
||||
m_pPlotTime->setTicListY(listTics);
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
54
dlglearnstatistic.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qdialog.h>
|
||||
#include "ui_dlglearnstatistic.h"
|
||||
|
||||
class CChapter;
|
||||
class CPlotWidget;
|
||||
|
||||
class CDlgLearnStatistic : public QDialog, Ui::DlgLearnStatistic
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgLearnStatistic(QWidget *pParent=0);
|
||||
~CDlgLearnStatistic() {}
|
||||
|
||||
void go(CChapter *pChapter);
|
||||
|
||||
protected slots:
|
||||
void on_cbPeriod_currentIndexChanged(int index);
|
||||
void on_cbPeriod2_currentIndexChanged(int index);
|
||||
|
||||
protected:
|
||||
void updateTable();
|
||||
void updateHistory();
|
||||
void updateTimeExpediture();
|
||||
|
||||
protected:
|
||||
CChapter *m_pChapter;
|
||||
CPlotWidget *m_pPlotLevel;
|
||||
CPlotWidget *m_pPlotClicked;
|
||||
CPlotWidget *m_pPlotTime;
|
||||
// CPlotWidget *m_pPlotTimePerQuestion;
|
||||
};
|
991
dlglearnstatistic.ui
Normal file
|
@ -0,0 +1,991 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgLearnStatistic</class>
|
||||
<widget class="QDialog" name="DlgLearnStatistic" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>502</width>
|
||||
<height>552</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Lernstatistik</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labChapter" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>MS Shell Dlg 2</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Kapitel-Name</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget" >
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab" >
|
||||
<attribute name="title" >
|
||||
<string>Aktueller Status</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Lernfortschritt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="7" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Durchschnittlicher Lernfortschritt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3" >
|
||||
<widget class="QLabel" name="labChapterRareBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" >
|
||||
<widget class="QLabel" name="labChapterCountBar" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<widget class="QLabel" name="labChapterVeryRare" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>Anfänger:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<widget class="QLabel" name="labChapterRare" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2" >
|
||||
<widget class="QLabel" name="labChapterAvgText" >
|
||||
<property name="toolTip" >
|
||||
<string>0.0 = Ahnungslos<br>1.0 = Anfänger<br>2.0 = Fortgeschritten<br>3.0 = Experte<br>4.0 = Freak<br>5.0 = Professor</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="label_14" >
|
||||
<property name="text" >
|
||||
<string>Freak:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3" >
|
||||
<widget class="QLabel" name="labChapterNormalBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="labChapterCount" >
|
||||
<property name="toolTip" >
|
||||
<string>Gesamt-Anzahl der Fragen dieses Kapitels</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" >
|
||||
<widget class="QLabel" name="labChapterExtremeRare" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Fortgeschritten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="labChapterOften" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="QLabel" name="labChapterVeryOften" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level3.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level0.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Anzahl der Fragen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QLabel" name="labChapterNormal" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3" >
|
||||
<widget class="QLabel" name="labChapterExtremeRareBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_13" >
|
||||
<property name="text" >
|
||||
<string>Experte:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Professor:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level2.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" >
|
||||
<widget class="QLabel" name="labChapterAvgIcon" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level0.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" >
|
||||
<widget class="QLabel" name="label_19" >
|
||||
<property name="toolTip" >
|
||||
<string>Smiley mit Doktorhut</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level5.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level4.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" >
|
||||
<widget class="QLabel" name="labChapterVeryOftenBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>3</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Ahnungslos:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" >
|
||||
<widget class="QLabel" name="labChapterOftenBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3" >
|
||||
<widget class="QLabel" name="labChapterVeryRareBar" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>1</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap resource="afutrainer.qrc" >:/icons/16x16/level1.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_16" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Abfragen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labClickCorrect" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="labClickCorrectP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_20" >
|
||||
<property name="text" >
|
||||
<string>davon falsche Antworten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_18" >
|
||||
<property name="text" >
|
||||
<string>davon richtige Antworten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="labClickWrong" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_17" >
|
||||
<property name="text" >
|
||||
<string>Abfragen gesamt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labClickCount" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QLabel" name="labClickWrongP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="label_28" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Anzahl </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="label_29" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Anteil </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Zeitaufwand</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QLabel" name="labTimeExpeditureWrongP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="labTimeExpeditureCorrectP" >
|
||||
<property name="text" >
|
||||
<string>0.0 %</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_22" >
|
||||
<property name="text" >
|
||||
<string>davon für richtige Antworten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" >
|
||||
<widget class="QLabel" name="labTimePerQuestionCorrect" >
|
||||
<property name="text" >
|
||||
<string>0 m 0 s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3" >
|
||||
<widget class="QLabel" name="labTimePerQuestionWrong" >
|
||||
<property name="text" >
|
||||
<string>0 m 0 s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_21" >
|
||||
<property name="text" >
|
||||
<string>Zeitaufwand gesamt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLabel" name="labTimeExpediture" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLabel" name="labTimeExpeditureWrong" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_23" >
|
||||
<property name="text" >
|
||||
<string>davon für falsche Antworten:</string>
|
||||
</property>
|
||||
<property name="indent" >
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLabel" name="labTimeExpeditureCorrect" >
|
||||
<property name="text" >
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="label_25" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Dauer </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="label_26" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Anteil </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" >
|
||||
<widget class="QLabel" name="label_27" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Ø pro Frage </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" >
|
||||
<widget class="QLabel" name="labTimePerQuestion" >
|
||||
<property name="text" >
|
||||
<string>0 m 0 s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2" >
|
||||
<attribute name="title" >
|
||||
<string>Zeitlicher Verlauf</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Zeitraum:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPeriod" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupLevel" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Lernfortschritt</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupClicked" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Abfragen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3" >
|
||||
<attribute name="title" >
|
||||
<string>Zeitaufwand</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_30" >
|
||||
<property name="text" >
|
||||
<string>Zeitraum:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPeriod2" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupTimeExpediture" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Zeitaufwand [min]</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
<tabstop>cbPeriod</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DlgLearnStatistic</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DlgLearnStatistic</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
43
dlgviewquestion.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************
|
||||
* 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 "dlgviewquestion.h"
|
||||
#include "catalog.h"
|
||||
|
||||
void CDlgViewQuestion::go (CCatalog *pCatalog, CQuestion *pQuestion, const unsigned uAnswer)
|
||||
{
|
||||
QString str;
|
||||
Q_ASSERT (pCatalog != 0);
|
||||
if (!pQuestion) return;
|
||||
str = pQuestion->learnText(pCatalog, true, true);
|
||||
str += "<p><b>";
|
||||
if (uAnswer != 0 && pQuestion->isCorrectAnswer(uAnswer))
|
||||
str += "<font color='green'>";
|
||||
else if (uAnswer != 0)
|
||||
str += "<font color='red'>";
|
||||
|
||||
str += pQuestion->correctionText(uAnswer);
|
||||
str += "</font></b></p>";
|
||||
textBrowser->setHtml(str);
|
||||
setWindowTitle (tr("Frage") + " " + pQuestion->id());
|
||||
exec();
|
||||
}
|
44
dlgviewquestion.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DLGVIEWQUESTION_H
|
||||
#define DLGVIEWQUESTION_H
|
||||
|
||||
#include <qdialog.h>
|
||||
#include "ui_dlgviewquestion.h"
|
||||
|
||||
class CQuestion;
|
||||
class CCatalog;
|
||||
|
||||
class CDlgViewQuestion : public QDialog, Ui::DlgViewQuestion
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CDlgViewQuestion(QWidget *pParent) : QDialog(pParent) { setupUi(this); }
|
||||
~CDlgViewQuestion() { }
|
||||
|
||||
void go (CCatalog *pCatalog, CQuestion *pQuestion, const unsigned uAnswer=0);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
|
||||
#endif // DLGVIEWQUESTION_H
|
99
dlgviewquestion.ui
Normal file
|
@ -0,0 +1,99 @@
|
|||
<ui version="4.0" >
|
||||
<class>DlgViewQuestion</class>
|
||||
<widget class="QDialog" name="DlgViewQuestion" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<height>577</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Frage ansehen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbOK" >
|
||||
<property name="text" >
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>textBrowser</tabstop>
|
||||
<tabstop>pbOK</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>pbOK</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>DlgViewQuestion</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>367</x>
|
||||
<y>566</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>358</x>
|
||||
<y>293</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
98
error.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 1999-2005 by Oliver Saal *
|
||||
* http://www.oliver-saal.de/ *
|
||||
* osaal@gmx.de *
|
||||
* *
|
||||
* 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 "error.h"
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
|
||||
#ifdef ERROR_USE_SQL
|
||||
#include <qsqlerror.h>
|
||||
#include <qmap.h>
|
||||
//#include <qmapiterator.h>
|
||||
#include <qvariant.h>
|
||||
#endif
|
||||
|
||||
CError::CError ()
|
||||
{
|
||||
m_uLine = 0;
|
||||
}
|
||||
|
||||
CError::CError (const QString& strFunc, const QString& strFile, const unsigned int uLine)
|
||||
{
|
||||
m_strFunction = strFunc;
|
||||
m_strFile = strFile;
|
||||
m_uLine = uLine;
|
||||
}
|
||||
|
||||
CError::CError (const QString& strText, const QString& strFunc, const QString& strFile, const unsigned int uLine)
|
||||
{
|
||||
m_strText = strText;
|
||||
m_strFunction = strFunc;
|
||||
m_strFile = strFile;
|
||||
m_uLine = uLine;
|
||||
}
|
||||
|
||||
#ifdef ERROR_USE_SQL
|
||||
|
||||
CError::CError (const QString& strText, const QSqlDatabase* pDB, const QString& strFunc, const QString& strFile, const unsigned int uLine)
|
||||
{
|
||||
m_strText = QString ("%1\n%3").arg (strText, pDB->lastError().text());
|
||||
m_strFunction = strFunc;
|
||||
m_strFile = strFile;
|
||||
m_uLine = uLine;
|
||||
}
|
||||
|
||||
CError::CError (const QString& strText, const QSqlQuery& query, const QString& strFunc, const QString& strFile, const unsigned int uLine)
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
m_strText = QString ("%1\nSQL: %2\n").arg (strText, query.lastQuery());
|
||||
map = query.boundValues();
|
||||
if (!map.isEmpty())
|
||||
{
|
||||
m_strText+="Bound values:\n";
|
||||
QMap<QString, QVariant>::const_iterator i = map.constBegin();
|
||||
while (i != map.constEnd())
|
||||
{
|
||||
m_strText += QString ("%1 / %2 ==> %4\n").arg (i.key(), i.value().typeName(), i.value().isNull() ? "NULL" : i.value().toString());
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
m_strText += query.lastError().text();
|
||||
m_strFunction = strFunc;
|
||||
m_strFile = strFile;
|
||||
m_uLine = uLine;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString CError::toPlainText() const
|
||||
{
|
||||
return QObject::tr("%1\n\nFunction: %2\nFile: %3 Line: %4\n").arg(m_strText, m_strFunction, m_strFile).arg(m_uLine);
|
||||
}
|
||||
|
||||
QString CError::toHtml() const
|
||||
{
|
||||
QString str = m_strText;
|
||||
str.replace ('\n', "<br>");
|
||||
return QObject::tr("<p><font color='red'><b>%1</b></font><br>Function: %2<br>File: %3 Line: %4</p><br>\n").arg(str, m_strFunction, m_strFile).arg(m_uLine);
|
||||
}
|
||||
|
78
error.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 1999-2007 by Oliver Saal *
|
||||
* http://www.oliver-saal.de/ *
|
||||
* osaal@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
//#define ERROR_USE_SQL
|
||||
|
||||
#ifndef __PRETTY_FUNCTION__
|
||||
# if defined __FUNCSIG__
|
||||
# define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
# elif defined __func__
|
||||
# define __PRETTY_FUNCTION__ __func__
|
||||
# else
|
||||
# define __PRETTY_FUNCTION__ __FILE__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <qstring.h>
|
||||
|
||||
#ifdef ERROR_USE_SQL
|
||||
#include <qsqlquery.h>
|
||||
|
||||
#define THROW_TRANSACTION(x) throw CError (tr("Could not start database transaction."), x, __PRETTY_FUNCTION__, __FILE__, __LINE__);
|
||||
#define THROW_COMMIT(x) throw CError (tr("Could not commit database transaction."), x, __PRETTY_FUNCTION__, __FILE__, __LINE__);
|
||||
#endif
|
||||
|
||||
class CError
|
||||
{
|
||||
public:
|
||||
CError ();
|
||||
CError (const QString& strFunc, const QString& strFile, const unsigned int uLine);
|
||||
CError (const QString& strText, const QString& strFunc, const QString& strFile, const unsigned int uLine);
|
||||
#ifdef ERROR_USE_SQL
|
||||
CError (const QString& strText, const QSqlDatabase* pDB, const QString& strFunc, const QString& strFile, const unsigned int uLine);
|
||||
CError (const QString& strText, const QSqlQuery& query, const QString& strFunc, const QString& strFile, const unsigned int uLine);
|
||||
#endif
|
||||
|
||||
inline void preText (const QString& str) { m_strText = str + m_strText; }
|
||||
inline void postText (const QString& str) { m_strText += str; }
|
||||
|
||||
inline QString text() const { return m_strText; }
|
||||
inline QString function() const { return m_strFunction; }
|
||||
inline QString file() const { return m_strFile; }
|
||||
inline unsigned line() const { return m_uLine; }
|
||||
|
||||
QString toPlainText() const;
|
||||
QString toHtml() const;
|
||||
|
||||
protected:
|
||||
QString m_strText;
|
||||
QString m_strFunction;
|
||||
QString m_strFile;
|
||||
unsigned int m_uLine;
|
||||
};
|
||||
|
||||
|
||||
#endif // ERROR_H
|
306
exam.cpp
Normal file
|
@ -0,0 +1,306 @@
|
|||
/***************************************************************************
|
||||
* 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 "exam.h"
|
||||
#include "question.h"
|
||||
#include "error.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include <qregexp.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
//#define DEBUGMSG
|
||||
|
||||
void CExamPart::clear()
|
||||
{
|
||||
m_iQuestionCount = 0;
|
||||
m_strRegExp.clear();
|
||||
}
|
||||
|
||||
bool CExamPart::load (QDomElement elem)
|
||||
{
|
||||
if (elem.tagName() != QString ("exam_part")) return false;
|
||||
m_iQuestionCount = elem.attribute("count").toUInt();
|
||||
if (m_iQuestionCount == 0) return false;
|
||||
m_strGroup = elem.attribute("group");
|
||||
m_strRegExp = elem.text ();
|
||||
if (m_strRegExp.isEmpty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CExamPart::save (QDomElement& parent, QDomDocument& doc) const
|
||||
{
|
||||
QDomElement elemRoot = doc.createElement("exam_part");
|
||||
|
||||
elemRoot.setAttribute("count", QString("%1").arg(m_iQuestionCount));
|
||||
elemRoot.setAttribute("group", m_strGroup);
|
||||
elemRoot.appendChild(doc.createTextNode(m_strRegExp));
|
||||
|
||||
parent.appendChild(elemRoot);
|
||||
}
|
||||
|
||||
QList<CQuestion*> CExamPart::createQuestionPool(const QList<CQuestion*>& listAllQuestions) const
|
||||
{
|
||||
QList<CQuestion*> listRet, listSelected;
|
||||
QRegExp regexp(m_strRegExp);
|
||||
int i=0;
|
||||
CQuestion *q=0;
|
||||
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("\tPart Group = '%s' RegExp '%s' mit %i Fragen", qPrintable (m_strGroup), qPrintable(m_strRegExp), m_iQuestionCount);
|
||||
#endif
|
||||
|
||||
// Alle Fragen raussuchen, die dem RegExp entsprechen
|
||||
for (i=0; i<listAllQuestions.size(); i++)
|
||||
{
|
||||
q = listAllQuestions.at(i);
|
||||
if (!m_strGroup.isEmpty() && !q->groups().contains(m_strGroup, Qt::CaseInsensitive))
|
||||
continue;
|
||||
|
||||
if (regexp.exactMatch(q->id()))
|
||||
{
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("\t\tAdding Question '%s'", qPrintable (q->id()));
|
||||
#endif
|
||||
listSelected.append(q);
|
||||
}
|
||||
}
|
||||
|
||||
if (listSelected.size() < questionCount())
|
||||
{
|
||||
throw CError (
|
||||
QString("Für den regulären Ausdruck '%1' wurden nur %2 Fragen gefunden - zu wenig, um daraus %3 Fragen für die Prüfung auszuwählen.")
|
||||
.arg(m_strRegExp).arg(listSelected.size()).arg(questionCount()), __PRETTY_FUNCTION__, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("\tStarte Auswahlverfahren...");
|
||||
#endif
|
||||
for (i=0; i < questionCount(); i++)
|
||||
{
|
||||
int rnd = afu_random (0, listSelected.size()-1);
|
||||
q = listSelected.at(rnd);
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("\t\tSelected question '%s'", qPrintable (q->id()));
|
||||
#endif
|
||||
listRet.append (q);
|
||||
listSelected.removeAt(rnd);
|
||||
}
|
||||
|
||||
return listRet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CExam::clear()
|
||||
{
|
||||
m_strId.clear();
|
||||
m_strName.clear();
|
||||
m_strComment.clear();
|
||||
m_uDuration = 0;
|
||||
m_uMaxErrorPoints = 0;
|
||||
m_listParts.clear();
|
||||
}
|
||||
|
||||
bool CExam::load (QDomElement elem)
|
||||
{
|
||||
if (elem.tagName() != QString ("exam")) return false;
|
||||
|
||||
m_strId = elem.attribute("id");
|
||||
m_strName = elem.attribute("name");
|
||||
m_uDuration = elem.attribute("duration").toUInt();
|
||||
m_uMaxErrorPoints = elem.attribute("maxerrorpoints").toUInt();
|
||||
m_strComment = elem.attribute("comment");
|
||||
|
||||
if (m_strName.isEmpty()) return false;
|
||||
if (m_uDuration == 0) return false;
|
||||
|
||||
QDomNode n = elem.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
QDomElement e = n.toElement ();
|
||||
if (e.tagName() == QString ("exam_part"))
|
||||
{
|
||||
CExamPart ep;
|
||||
if (ep.load(e)) m_listParts.append(ep);
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CExam::save (QDomElement& parent, QDomDocument& doc) const
|
||||
{
|
||||
QDomElement elemRoot = doc.createElement("exam");
|
||||
|
||||
elemRoot.setAttribute("id", m_strId);
|
||||
elemRoot.setAttribute("name", m_strName);
|
||||
elemRoot.setAttribute("duration", QString("%1").arg(m_uDuration));
|
||||
elemRoot.setAttribute("maxerrorpoints", QString("%1").arg(m_uMaxErrorPoints));
|
||||
elemRoot.setAttribute("comment", m_strComment);
|
||||
for (int i=0; i<m_listParts.size(); i++)
|
||||
m_listParts.at(i).save(elemRoot, doc);
|
||||
|
||||
parent.appendChild(elemRoot);
|
||||
}
|
||||
|
||||
unsigned CExam::questionCount() const
|
||||
{
|
||||
unsigned u=0;
|
||||
for (int i=0; i<m_listParts.size(); i++)
|
||||
{
|
||||
u += m_listParts.at(i).questionCount();
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
QList<CQuestion*> CExam::createQuestionPool(const QList<CQuestion*>& listAllQuestions) const
|
||||
{
|
||||
QList<CQuestion*> listRet;
|
||||
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("Erzeuge Prüfungsfragen für '%s'", qPrintable(name()));
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
for (int i=0; i<m_listParts.size(); i++)
|
||||
{
|
||||
listRet << m_listParts.at(i).createQuestionPool(listAllQuestions);
|
||||
}
|
||||
}
|
||||
catch (CError e)
|
||||
{
|
||||
e.preText(QString("Konnte Prüfung '%1' nicht erzeugen.").arg(name()));
|
||||
throw;
|
||||
}
|
||||
|
||||
#ifdef DEBUGMSG
|
||||
qDebug ("Insg. %i Prüfungsfragen ausgewählt", listRet.size());
|
||||
for (int i=0; i<listRet.size(); i++)
|
||||
qDebug ("\t%i. Frage ID '%s'", i+1, qPrintable(listRet.at(i)->id()));
|
||||
#endif
|
||||
|
||||
return listRet;
|
||||
}
|
||||
|
||||
CExamStat::CExamStat(const CExam& exam)
|
||||
{
|
||||
clear();
|
||||
m_strId = exam.id();
|
||||
}
|
||||
|
||||
void CExamStat::clear()
|
||||
{
|
||||
m_strId.clear();
|
||||
m_dt = QDateTime::currentDateTime();
|
||||
m_uSecs = 0;
|
||||
|
||||
m_strlQuestionId.clear();
|
||||
m_listAnswer.clear();
|
||||
|
||||
m_uCorrect = 0;
|
||||
m_uWrong = 0;
|
||||
m_uErrorPoints = 0;
|
||||
m_bPassed = false;
|
||||
}
|
||||
|
||||
void CExamStat::setQuestions(const QList<CQuestion*>& listQuestion, const QList<unsigned>& listAnswerMask)
|
||||
{
|
||||
for (int i=0; i<listQuestion.size(); i++)
|
||||
{
|
||||
CQuestion *q = listQuestion.at(i);
|
||||
m_strlQuestionId.append(q->id());
|
||||
m_listAnswer.append(q->orderedAnswerMask(listAnswerMask.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
void CExamStat::setResult (const unsigned uCorrect, const unsigned uWrong, const unsigned uErrorPoints, const bool bPassed)
|
||||
{
|
||||
m_uCorrect = uCorrect;
|
||||
m_uWrong = uWrong;
|
||||
m_uErrorPoints = uErrorPoints;
|
||||
m_bPassed = bPassed;
|
||||
}
|
||||
|
||||
bool CExamStat::load (QDomElement elem)
|
||||
{
|
||||
if (elem.tagName() != QString ("exam")) return false;
|
||||
|
||||
m_strId = elem.attribute("id");
|
||||
m_uSecs = elem.attribute("secs").toUInt();
|
||||
m_dt = QDateTime::fromString(elem.attribute("datetime"), Qt::ISODate);
|
||||
m_uCorrect = elem.attribute("correct").toUInt();
|
||||
m_uWrong = elem.attribute("wrong").toUInt();
|
||||
m_uErrorPoints = elem.attribute("errorpoints").toUInt();
|
||||
m_bPassed = QVariant(elem.attribute("passed")).toBool();
|
||||
|
||||
if (m_strId.isEmpty()) return false;
|
||||
if (m_uSecs == 0) return false;
|
||||
|
||||
QDomNode n = elem.firstChild();
|
||||
while (!n.isNull())
|
||||
{
|
||||
if (n.isElement ())
|
||||
{
|
||||
QDomElement e = n.toElement ();
|
||||
if (e.tagName() == QString ("question"))
|
||||
{
|
||||
QString strId = e.attribute("id");
|
||||
if (!strId.isEmpty())
|
||||
{
|
||||
m_strlQuestionId.append (strId);
|
||||
m_listAnswer.append(e.attribute("answer").toUInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
n = n.nextSibling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CExamStat::save (QDomElement& parent, QDomDocument& doc) const
|
||||
{
|
||||
QDomElement elemRoot = doc.createElement("exam");
|
||||
|
||||
elemRoot.setAttribute("id", m_strId);
|
||||
elemRoot.setAttribute("secs", QString("%1").arg(m_uSecs));
|
||||
elemRoot.setAttribute("datetime", m_dt.toString(Qt::ISODate));
|
||||
elemRoot.setAttribute("correct", QString("%1").arg(m_uCorrect));
|
||||
elemRoot.setAttribute("wrong", QString("%1").arg(m_uWrong));
|
||||
elemRoot.setAttribute("errorpoints", QString("%1").arg(m_uErrorPoints));
|
||||
elemRoot.setAttribute("passed", QString("%1").arg(m_bPassed));
|
||||
for (int i=0; i<m_strlQuestionId.size(); i++)
|
||||
{
|
||||
QDomElement elemQuestion = doc.createElement("question");
|
||||
elemQuestion.setAttribute("id", m_strlQuestionId.at(i));
|
||||
elemQuestion.setAttribute("answer", m_listAnswer.at(i));
|
||||
elemRoot.appendChild(elemQuestion);
|
||||
}
|
||||
|
||||
parent.appendChild(elemRoot);
|
||||
}
|
||||
|
142
exam.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef EXAM_H
|
||||
#define EXAM_H
|
||||
|
||||
#include <qstring.h>
|
||||
#include <qlist.h>
|
||||
#include <qdom.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qstringlist.h>
|
||||
|
||||
class CQuestion;
|
||||
|
||||
class CExamPart
|
||||
{
|
||||
public:
|
||||
CExamPart() { clear(); }
|
||||
~CExamPart() {}
|
||||
|
||||
void clear();
|
||||
|
||||
inline int questionCount() const { return m_iQuestionCount; }
|
||||
inline void setQuestionCount(int i) { m_iQuestionCount = i; }
|
||||
|
||||
inline QString group() const { return m_strGroup; }
|
||||
inline void setGroup(const QString& str) { m_strGroup = str; }
|
||||
|
||||
inline QString regexp() const { return m_strRegExp; }
|
||||
inline void setRegExp(const QString& str) { m_strRegExp = str; }
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc) const;
|
||||
|
||||
QList<CQuestion*> createQuestionPool(const QList<CQuestion*>& listAllQuestions) const;
|
||||
|
||||
protected:
|
||||
int m_iQuestionCount;
|
||||
QString m_strGroup;
|
||||
QString m_strRegExp;
|
||||
};
|
||||
|
||||
class CExam
|
||||
{
|
||||
public:
|
||||
CExam() { clear(); }
|
||||
~CExam() {}
|
||||
|
||||
//! Zurücksetzen aller Werte
|
||||
/*! Es werden alle Daten der Prüfung gelöscht. */
|
||||
void clear();
|
||||
|
||||
//! ID abfragen
|
||||
inline QString id() const { return m_strId; }
|
||||
//! ID setzen
|
||||
inline void setId(const QString& strId) { m_strId = strId; }
|
||||
|
||||
inline QString name() const { return m_strName; }
|
||||
inline QString comment() const { return m_strComment; }
|
||||
unsigned duration() const { return m_uDuration; }
|
||||
unsigned maxErrorPoints() const { return m_uMaxErrorPoints; }
|
||||
|
||||
unsigned questionCount() const;
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc) const;
|
||||
|
||||
QList<CQuestion*> createQuestionPool(const QList<CQuestion*>& listAllQuestions) const;
|
||||
|
||||
protected:
|
||||
QString m_strId; //< ID der Prüfung
|
||||
QString m_strName; //< Name / Bezeichnung
|
||||
QString m_strComment; //< Kommentar / Hinweis
|
||||
unsigned m_uDuration; //< Prüfungsdauer in min
|
||||
unsigned m_uMaxErrorPoints; //< Max. Anzahl an erlaubten Fehlerpunkten, um die Prüfung zu bestehen
|
||||
QList<CExamPart> m_listParts; //< Abschnitte, aus denen sich die Prüfung zusammensetzt.
|
||||
};
|
||||
|
||||
class CExamStat
|
||||
{
|
||||
public:
|
||||
CExamStat() { clear(); }
|
||||
CExamStat(const CExam& exam);
|
||||
~CExamStat() {}
|
||||
|
||||
//! Zurücksetzen aller Werte
|
||||
/*! Es werden alle Daten dieser Prüfungsstatistik gelöscht. */
|
||||
void clear();
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc) const;
|
||||
|
||||
//! ID abfragen
|
||||
inline QString id() const { return m_strId; }
|
||||
//! ID setzen
|
||||
inline void setId(const QString& strId) { m_strId = strId; }
|
||||
|
||||
inline void setSecs(const unsigned uSecs) { m_uSecs = uSecs; }
|
||||
void setQuestions(const QList<CQuestion*>& listQuestion, const QList<unsigned>& listAnswerMask);
|
||||
void setResult (const unsigned uCorrect, const unsigned uWrong, const unsigned uErrorPoints, const bool bPassed);
|
||||
|
||||
inline unsigned duration() const { return m_uSecs; }
|
||||
inline bool passed() const { return m_bPassed; }
|
||||
inline unsigned correctAnswers() const { return m_uCorrect; }
|
||||
inline unsigned wrongAnswers() const { return m_uWrong; }
|
||||
inline unsigned errorPoints() const { return m_uErrorPoints; }
|
||||
QDateTime datetime() const { return m_dt; }
|
||||
|
||||
protected:
|
||||
QString m_strId; //< ID der Prüfung
|
||||
QDateTime m_dt; //< Datum/Uhrzeit
|
||||
unsigned m_uSecs; //< Benötigte Zeit in sec
|
||||
|
||||
QStringList m_strlQuestionId; //< IDs der Fragen
|
||||
QList<unsigned> m_listAnswer; //< Antworten
|
||||
|
||||
unsigned m_uCorrect; //< Anzahl d. richtigen Fragen
|
||||
unsigned m_uWrong; //< Anzahl d. falschen Fragen
|
||||
unsigned m_uErrorPoints; //< Fehlerpunkte
|
||||
bool m_bPassed; //< Bestanden Ja/Nein
|
||||
};
|
||||
|
||||
#endif
|
||||
|
84
helper.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
/***************************************************************************
|
||||
* 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 "helper.h"
|
||||
#include "catalog.h"
|
||||
|
||||
void CHint::clear()
|
||||
{
|
||||
m_strlQuestionId.clear();
|
||||
m_strAuthor.clear();
|
||||
m_date = QDate();
|
||||
m_strText.clear();
|
||||
m_strComment.clear();
|
||||
}
|
||||
|
||||
bool CHint::load (QDomElement elem)
|
||||
{
|
||||
QString str;
|
||||
|
||||
if (elem.tagName() != QString ("hint")) return false;
|
||||
m_strAuthor = elem.attribute ("author", "AFUTrainer-Hilfe");
|
||||
m_date = QDate::fromString(elem.attribute ("date"), Qt::ISODate);
|
||||
str = elem.attribute("question");
|
||||
str = str.replace(' ', ';').replace(',', ';');
|
||||
m_strlQuestionId = str.split(";", QString::SkipEmptyParts);
|
||||
m_strComment = elem.attribute ("comment");
|
||||
m_strText = elem.text ();
|
||||
|
||||
if (m_strText.isEmpty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHint::save (QDomElement& parent, QDomDocument& doc)
|
||||
{
|
||||
QDomElement elemRoot = doc.createElement("hint");
|
||||
if (!m_strAuthor.isEmpty()) elemRoot.setAttribute("author", m_strAuthor);
|
||||
if (m_date.isValid()) elemRoot.setAttribute("date", m_date.toString(Qt::ISODate));
|
||||
elemRoot.setAttribute("question", m_strlQuestionId.join(";"));
|
||||
if (!m_strComment.isEmpty()) elemRoot.setAttribute("comment", m_strComment);
|
||||
parent.appendChild(elemRoot);
|
||||
elemRoot.appendChild(doc.createTextNode(m_strText));
|
||||
}
|
||||
|
||||
QString CHint::showText() const
|
||||
{
|
||||
QString str;
|
||||
|
||||
/* if (text().isEmpty())
|
||||
{
|
||||
if (pCatalog)
|
||||
return pCatalog->hintText(id());
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
*/
|
||||
/* str = "<p><table cellspacing='0' border='0' width='100%'>";
|
||||
str += "<tr><td bgcolor='gray'><b>"+author()+"</b></td>";
|
||||
str += "<td bgcolor='gray' align='right'><b>"+dateString()+"</b></td></tr>";
|
||||
str += "<tr><td colspan='2'>"+text()+"</td></tr>";
|
||||
str += "<tr><td colspan='2'> </td></tr>";
|
||||
str += "</table></p>";
|
||||
*/
|
||||
|
||||
str += "<p>" + text() + "</p>"; //"<p><i><font size=-1>" + author() + " " + date() + "</font></i></p>";
|
||||
return (str);
|
||||
}
|
71
helper.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef HELPER_H
|
||||
#define HELPER_H
|
||||
|
||||
#include <qstring.h>
|
||||
#include <qdom.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qstringlist.h>
|
||||
|
||||
class CCatalog;
|
||||
|
||||
class CHint
|
||||
{
|
||||
public:
|
||||
CHint() { clear(); }
|
||||
~CHint() {}
|
||||
|
||||
void clear();
|
||||
|
||||
inline void appendQuestion(const QString& id) { if (!hasQuestion(id)) m_strlQuestionId.append(id); }
|
||||
inline void removeQuestion(const QString& id) { m_strlQuestionId.removeAll(id); }
|
||||
inline bool hasQuestion(const QString& id) const { return m_strlQuestionId.contains(id); }
|
||||
|
||||
inline QString author() const { return m_strAuthor; }
|
||||
inline void setAuthor(const QString& strAuthor) { m_strAuthor = strAuthor; }
|
||||
|
||||
inline QDate date() const { return m_date; }
|
||||
inline QString dateString() const { return m_date.toString(Qt::LocalDate); }
|
||||
inline void setDate (const QDate& date) { m_date = date; }
|
||||
|
||||
inline QString text() const { return m_strText; }
|
||||
inline void setText(const QString& strText) { m_strText = strText; }
|
||||
|
||||
inline QString comment() const { return m_strComment; }
|
||||
inline void setComment (const QString& strComment) { m_strComment = strComment; }
|
||||
|
||||
|
||||
QString showText() const;
|
||||
|
||||
bool load (QDomElement elem);
|
||||
void save (QDomElement& parent, QDomDocument& doc);
|
||||
|
||||
protected:
|
||||
QStringList m_strlQuestionId;
|
||||
QString m_strAuthor;
|
||||
QDate m_date;
|
||||
QString m_strText;
|
||||
QString m_strComment;
|
||||
};
|
||||
|
||||
#endif
|
BIN
icons/16x16/book1.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/16x16/button_cancel.png
Normal file
After Width: | Height: | Size: 963 B |
BIN
icons/16x16/button_ok.png
Normal file
After Width: | Height: | Size: 661 B |
BIN
icons/16x16/cancel.png
Normal file
After Width: | Height: | Size: 890 B |
BIN
icons/16x16/clock.png
Normal file
After Width: | Height: | Size: 875 B |
BIN
icons/16x16/contexthelp.png
Normal file
After Width: | Height: | Size: 948 B |
BIN
icons/16x16/exit.png
Normal file
After Width: | Height: | Size: 830 B |
BIN
icons/16x16/filenew.png
Normal file
After Width: | Height: | Size: 725 B |
BIN
icons/16x16/fileopen.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/16x16/filesave.png
Normal file
After Width: | Height: | Size: 838 B |
BIN
icons/16x16/filesaveas.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/16x16/finish.png
Normal file
After Width: | Height: | Size: 827 B |
BIN
icons/16x16/folder.png
Normal file
After Width: | Height: | Size: 646 B |
BIN
icons/16x16/help.png
Normal file
After Width: | Height: | Size: 997 B |
BIN
icons/16x16/idea.png
Normal file
After Width: | Height: | Size: 829 B |
BIN
icons/16x16/idea_gray.png
Normal file
After Width: | Height: | Size: 459 B |
BIN
icons/16x16/idea_info.png
Normal file
After Width: | Height: | Size: 813 B |
BIN
icons/16x16/info.png
Normal file
After Width: | Height: | Size: 855 B |
BIN
icons/16x16/level0.png
Normal file
After Width: | Height: | Size: 821 B |
BIN
icons/16x16/level1.png
Normal file
After Width: | Height: | Size: 843 B |
BIN
icons/16x16/level1a.png
Normal file
After Width: | Height: | Size: 820 B |
BIN
icons/16x16/level2.png
Normal file
After Width: | Height: | Size: 831 B |
BIN
icons/16x16/level2a.png
Normal file
After Width: | Height: | Size: 815 B |
BIN
icons/16x16/level3.png
Normal file
After Width: | Height: | Size: 772 B |
BIN
icons/16x16/level3a.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
icons/16x16/level4.png
Normal file
After Width: | Height: | Size: 733 B |
BIN
icons/16x16/level5.png
Normal file
After Width: | Height: | Size: 728 B |
BIN
icons/16x16/next.png
Normal file
After Width: | Height: | Size: 835 B |
BIN
icons/16x16/previous.png
Normal file
After Width: | Height: | Size: 862 B |
BIN
icons/16x16/start.png
Normal file
After Width: | Height: | Size: 852 B |
BIN
icons/16x16/stats.png
Normal file
After Width: | Height: | Size: 163 B |
BIN
icons/16x16/stop.png
Normal file
After Width: | Height: | Size: 907 B |
BIN
icons/16x16/viewmag.png
Normal file
After Width: | Height: | Size: 1,023 B |
BIN
icons/32x32/idea.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/32x32/qt.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/64x16-old/veryrare.png
Normal file
After Width: | Height: | Size: 480 B |
BIN
icons/64x16/level0.png
Normal file
After Width: | Height: | Size: 861 B |
BIN
icons/64x16/level1.png
Normal file
After Width: | Height: | Size: 901 B |
BIN
icons/64x16/level2.png
Normal file
After Width: | Height: | Size: 889 B |
BIN
icons/64x16/level3.png
Normal file
After Width: | Height: | Size: 839 B |
BIN
icons/64x16/level4.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
icons/level.xcf
Normal file
BIN
icons/veryrare.xcf
Normal file
42
main.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************
|
||||
* 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 <qapplication.h>
|
||||
#include <qtranslator.h>
|
||||
#include <time.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
QApplication app (argc, argv);
|
||||
QTranslator translator;
|
||||
app.setOrganizationName ("osaal");
|
||||
app.setApplicationName ("AFUTrainer");
|
||||
|
||||
translator.load(":/translations/qt_de");
|
||||
app.installTranslator(&translator);
|
||||
|
||||
srand (time (NULL));
|
||||
|
||||
CMainWindow mw;
|
||||
mw.show();
|
||||
return app.exec();
|
||||
}
|
819
mainwindow.cpp
Normal file
|
@ -0,0 +1,819 @@
|
|||
/***************************************************************************
|
||||
* 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ünschte Funktion kann nicht ausgeführt werden, da der Fragenkatalog folgende Fehler enthä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("Ö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("Ö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 öffnen!").arg(strFileName));
|
||||
return;
|
||||
}
|
||||
QTextStream in(&file);
|
||||
pCatalog = new CCatalog();
|
||||
|
||||
while (!in.atEnd())
|
||||
{
|
||||
strLine = in.readLine().trimmed();
|
||||
if (strLine.isEmpty() || strLine.contains(QRegExp("^Prü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ü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();
|
||||
// Überprü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ögliche Grü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 überprüfen, ob alle Grafik-Dateien zugeordnet wurden!<p>"
|
||||
"Bitte überprü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änderung auf .atc ä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("Ö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 ö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 überprü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änderung auf .atc ä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ä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ält keine Prü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ält keine Prü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("Ü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();
|
||||
}
|
||||
*/
|
91
mainwindow.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/***************************************************************************
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <qmainwindow.h>
|
||||
#include <qsplitter.h>
|
||||
#include <qtreeview.h>
|
||||
#include <qtextbrowser.h>
|
||||
|
||||
#include "catalogmodel.h"
|
||||
#include "questionmodel.h"
|
||||
#include "recentfiles.h"
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class CMainWindow : public QMainWindow, protected Ui::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CMainWindow();
|
||||
~CMainWindow();
|
||||
|
||||
protected:
|
||||
void setCatalog (CCatalog *pCatalog);
|
||||
void updateWindowTitle();
|
||||
bool checkForErrors();
|
||||
bool checkForHomeDir();
|
||||
|
||||
protected slots:
|
||||
void on_actFileNew_triggered();
|
||||
void on_actFileOpen_triggered();
|
||||
void on_actFileInformation_triggered();
|
||||
void on_actFileSave_triggered();
|
||||
void on_actFileSaveAs_triggered();
|
||||
void on_actFileImport_triggered();
|
||||
void on_actFileImportUS_triggered();
|
||||
void on_actFileExit_triggered();
|
||||
void on_actQuestionAssistant_triggered();
|
||||
void on_actQuestionsLearn_triggered();
|
||||
void on_actQuestionsLearnStatistics_triggered();
|
||||
void on_actQuestionsTest_triggered();
|
||||
void on_actQuestionsTestStatistics_triggered();
|
||||
void on_actViewToolbar_toggled(bool bChecked);
|
||||
void on_actViewStatusbar_toggled(bool bChecked);
|
||||
void on_actHelpWhatsThis_triggered();
|
||||
void on_actHelpAbout_triggered();
|
||||
void on_actHelpAboutQt_triggered();
|
||||
|
||||
void onCatalogSelectionChanged (const QItemSelection& selected, const QItemSelection& deselected);
|
||||
void onQuestionSelectionChanged (const QItemSelection& selected, const QItemSelection& deselected);
|
||||
|
||||
void onOpenFile(const QString& strFileName);
|
||||
|
||||
// void onAnchorClicked (const QUrl &link );
|
||||
|
||||
protected:
|
||||
CRecentFiles m_rf;
|
||||
QSplitter *m_pSplitter; // splitter widget
|
||||
QTreeView *m_pViewChapter; // listview chapters
|
||||
QTreeView *m_pViewQuestions; // listview questions
|
||||
QSplitter *m_pSplitter2;
|
||||
QTextBrowser *m_pTextQuestion;
|
||||
|
||||
CCatalog *m_pCatalog;
|
||||
CCatalogModel m_modelCatalog;
|
||||
CQuestionModel m_modelQuestion;
|
||||
};
|
||||
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
397
mainwindow.ui
Normal file
|
@ -0,0 +1,397 @@
|
|||
<ui version="4.0" >
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>AFUTrainer 3.0</string>
|
||||
</property>
|
||||
<property name="windowIcon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/32x32/idea.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" />
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_Hilfe" >
|
||||
<property name="title" >
|
||||
<string>&Hilfe</string>
|
||||
</property>
|
||||
<addaction name="actHelpWhatsThis" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actHelpAbout" />
|
||||
<addaction name="actHelpAboutQt" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Ansicht" >
|
||||
<property name="title" >
|
||||
<string>&Ansicht</string>
|
||||
</property>
|
||||
<addaction name="actViewToolbar" />
|
||||
<addaction name="actViewStatusbar" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Fragen" >
|
||||
<property name="title" >
|
||||
<string>&Fragen</string>
|
||||
</property>
|
||||
<addaction name="actQuestionsLearn" />
|
||||
<addaction name="actQuestionAssistant" />
|
||||
<addaction name="actQuestionsLearnStatistics" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actQuestionsTest" />
|
||||
<addaction name="actQuestionsTestStatistics" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuFile" >
|
||||
<property name="title" >
|
||||
<string>&Datei</string>
|
||||
</property>
|
||||
<addaction name="actFileNew" />
|
||||
<addaction name="actFileOpen" />
|
||||
<addaction name="actFileInformation" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actFileSave" />
|
||||
<addaction name="actFileSaveAs" />
|
||||
<addaction name="actFileImport" />
|
||||
<addaction name="actFileImportUS" />
|
||||
<addaction name="actFileExit" />
|
||||
</widget>
|
||||
<addaction name="menuFile" />
|
||||
<addaction name="menu_Fragen" />
|
||||
<addaction name="menu_Ansicht" />
|
||||
<addaction name="menu_Hilfe" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar" />
|
||||
<widget class="QToolBar" name="toolBar" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<attribute name="toolBarArea" >
|
||||
<number>4</number>
|
||||
</attribute>
|
||||
<addaction name="actFileOpen" />
|
||||
<addaction name="actFileInformation" />
|
||||
<addaction name="actFileExit" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actQuestionsLearn" />
|
||||
<addaction name="actQuestionAssistant" />
|
||||
<addaction name="actQuestionsLearnStatistics" />
|
||||
<addaction name="actQuestionsTest" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actHelpWhatsThis" />
|
||||
</widget>
|
||||
<action name="actFileOpen" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/fileopen.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Ö&ffnen</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Öffnet einen Fragenkatalog</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Öffnet einen Fragenkatalog</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Datei öffnen</b><p>Öffnet einen existierenden Fragenkatalog</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileExit" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/exit.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Beenden</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Beendet den AFUTrainer</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Beendet den AFUTrainer</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Beenden</b><p>Beendet den AFUTrainer</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Alt+F4</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actViewToolbar" >
|
||||
<property name="checkable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Werkzeugleiste</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Aktiviert/deaktiviert die Werkzeugleiste</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Aktiviert/deaktiviert die Werkzeugleiste</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Werkzeugleiste</b><p>Aktiviert/deaktiviert die Werkzeugleiste</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actViewStatusbar" >
|
||||
<property name="checkable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Statusleiste</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Aktiviert/deaktiviert die Statusleiste</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Aktiviert/deaktiviert die Statusleiste</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Statusleiste</b><p>Aktiviert/deaktiviert die Statusleiste</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actHelpAbout" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/idea.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Über...</string>
|
||||
</property>
|
||||
<property name="iconText" >
|
||||
<string>Über</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Über den AFUTrainer</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Über den AFUTrainer</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Über</b><p>Copyright-Hinweise und Autoren</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actHelpWhatsThis" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/contexthelp.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Was ist &das?</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Was ist das?</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Shift+F1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionsView" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/viewmag.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Ansehen...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Zeigt ausgewählte Frage an</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Zeigt ausgewählte Frage an</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Frage ansehen</b><p>Zeigt die Frage mit Anworten und Statistik<br>in einem neuen Fenster an</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionsLearn" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/idea.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Lernen...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Fragen lernen</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Fragen lernen</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Fragen lernen</b><p>Hier können Sie die Fragen lernen. Eine Frage wird so lange abgefragt, bis Sie sie richtig beantworten können.</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F4</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionsLearnStatistics" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/stats.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Lernstatistik...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Zeigt Lernstatistik des ausgewählten Kapitels an</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Zeigt Lernstatistik des ausgewählten Kapitels an</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Lernstatistik</b><p>Zeigt Lernstatistik des ausgewählten Kapitels an</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionsTest" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/clock.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Prüfungssimulation...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Simuliert die Prüfung</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Simuliert die Prüfung</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Prüfungssimulation</b><p>Sie erhalten zufällig generierte Fragenbögen,<br>die Sie in vorgegebener Zeit lösen müssen!</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionsTestStatistics" >
|
||||
<property name="text" >
|
||||
<string>&Prüfstatistik...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Zeigt Ergebnisse der Prüfungssimulationen an</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Zeigt Ergebnisse der Prüfungssimulationen an</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Prüfstatistik</b><p>Sie erhalten eine detaillierte Auflistung<br>der Ergebnisse der Prüfungssimulationen.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actHelpAboutQt" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/32x32/qt.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Über &Qt...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Über die Qt-Bibliothek</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Über die Qt-Bibliothek</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Über Qt</b><p>Zeigt Copyright-Hinweise zur verwendeten Qt-Bibliothek an</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileImport" >
|
||||
<property name="text" >
|
||||
<string>&Import DE...</string>
|
||||
</property>
|
||||
<property name="iconText" >
|
||||
<string>Import DE</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Import DE</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileNew" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/filenew.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Neu</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileSave" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/filesave.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Speichern</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileSaveAs" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/filesaveas.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Speichern &unter...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actQuestionAssistant" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/idea_info.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Lern-Assistent...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Ruft den Lern-Assistenten auf</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Ruft den Lern-Assistenten auf</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Lern-Assistent</b><p>Der Lern-Assistent hilft Ihnen beim Auswahl der zu lerndenden Fragen.</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileImportUS" >
|
||||
<property name="text" >
|
||||
<string>Import US...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actFileInformation" >
|
||||
<property name="icon" >
|
||||
<iconset resource="afutrainer.qrc" >:/icons/16x16/info.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>&Information...</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Informationen zum Fragenkatalog</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Zeigt Informationen zum Fragenkatalog an.</string>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
<string><b>Information</b><p>Zeigt Informationen, wie z.B. Gültigkeitseitraum, Herausgeber, Version,... zum aktuell geladenen Fragenkatalog an.</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="afutrainer.qrc" />
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
467
osziparchive.cpp
Normal file
|
@ -0,0 +1,467 @@
|
|||
|
||||
#include "osziparchive.h"
|
||||
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
#include <qbytearray.h>
|
||||
#include <qdatastream.h>
|
||||
#include <qtextstream.h>
|
||||
|
||||
|
||||
void CZipFileHeader::clear()
|
||||
{
|
||||
m_uVersionMadeBy = 0;
|
||||
m_uVersionNeeded = 0;
|
||||
m_uFlags = 0;
|
||||
m_uCompression = 0;
|
||||
m_uTime = 0;
|
||||
m_uDate = 0;
|
||||
m_uCRC = 0;
|
||||
m_uSizeCompressed = 0;
|
||||
m_uSizeUncompressed = 0;
|
||||
m_uDiskNumberStart = 0;
|
||||
m_uInternalFileAttributes = 0;
|
||||
m_uExternalFileAttributes = 0;
|
||||
m_uRelativeOffsetLocalHeader = 0;
|
||||
m_strFileName.clear();
|
||||
m_strComment.clear();
|
||||
m_baExtraField.clear();
|
||||
|
||||
// helpers
|
||||
m_uDataPosition = 0;
|
||||
m_uLocalHeaderPosition = 0;
|
||||
m_uCentralHeaderPosition = 0;
|
||||
}
|
||||
|
||||
void CZipFileHeader::integrate(const CZipFileHeader& head)
|
||||
{
|
||||
if (m_uVersionMadeBy == 0) m_uVersionMadeBy = head.m_uVersionMadeBy;
|
||||
if (m_uVersionNeeded == 0) m_uVersionNeeded = head.m_uVersionNeeded;
|
||||
if (m_uFlags == 0) m_uFlags = head.m_uFlags;
|
||||
if (m_uCompression == 0) m_uCompression = head.m_uCompression;
|
||||
if (m_uTime == 0) m_uTime = head.m_uTime;
|
||||
if (m_uDate == 0) m_uDate = head.m_uDate;
|
||||
if (m_uCRC == 0) m_uCRC = head.m_uCRC;
|
||||
if (m_uSizeCompressed == 0) m_uSizeCompressed = head.m_uSizeCompressed;
|
||||
if (m_uSizeUncompressed == 0) m_uSizeUncompressed = head.m_uSizeUncompressed;
|
||||
if (m_uDiskNumberStart == 0) m_uDiskNumberStart = head.m_uDiskNumberStart;
|
||||
if (m_uInternalFileAttributes == 0) m_uInternalFileAttributes = head.m_uInternalFileAttributes;
|
||||
if (m_uExternalFileAttributes == 0) m_uExternalFileAttributes = head.m_uExternalFileAttributes;
|
||||
if (m_uRelativeOffsetLocalHeader == 0) m_uRelativeOffsetLocalHeader = head.m_uRelativeOffsetLocalHeader;
|
||||
|
||||
if (m_strFileName.isEmpty()) m_strFileName = head.m_strFileName;
|
||||
if (m_baExtraField.isEmpty()) m_baExtraField = head.m_baExtraField;
|
||||
if (m_strComment.isEmpty()) m_strComment = head.m_strComment;
|
||||
|
||||
if (m_uDataPosition == 0) m_uDataPosition = head.m_uDataPosition;
|
||||
if (m_uLocalHeaderPosition == 0) m_uLocalHeaderPosition = head.m_uLocalHeaderPosition;
|
||||
if (m_uCentralHeaderPosition == 0) m_uCentralHeaderPosition = head.m_uCentralHeaderPosition;
|
||||
}
|
||||
|
||||
bool CZipFileHeader::readLocalFileHeader(QFile& file)
|
||||
{
|
||||
QDataStream in(&file);
|
||||
quint16 uFileNameLength=0, uExtraFieldLength=0;
|
||||
|
||||
clear();
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
m_uLocalHeaderPosition = file.pos();
|
||||
|
||||
in >> m_uVersionNeeded;
|
||||
in >> m_uFlags;
|
||||
in >> m_uCompression;
|
||||
in >> m_uTime;
|
||||
in >> m_uDate;
|
||||
in >> m_uCRC;
|
||||
in >> m_uSizeCompressed;
|
||||
in >> m_uSizeUncompressed;
|
||||
in >> uFileNameLength;
|
||||
in >> uExtraFieldLength;
|
||||
|
||||
if (uFileNameLength != 0)
|
||||
{
|
||||
QByteArray a (uFileNameLength, 0);
|
||||
in.readRawData(a.data(), uFileNameLength);
|
||||
m_strFileName = a;
|
||||
}
|
||||
if (uExtraFieldLength != 0)
|
||||
{
|
||||
m_baExtraField.resize(uExtraFieldLength);
|
||||
in.readRawData(m_baExtraField.data(), uExtraFieldLength);
|
||||
}
|
||||
|
||||
m_uDataPosition = file.pos();
|
||||
in.skipRawData(m_uSizeCompressed);
|
||||
|
||||
if (hasDataDescriptor())
|
||||
{
|
||||
in >> m_uCRC;
|
||||
in >> m_uSizeCompressed;
|
||||
in >> m_uSizeUncompressed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CZipFileHeader::writeLocalFileHeader(QFile& file)
|
||||
{
|
||||
Q_UNUSED(file);
|
||||
}
|
||||
|
||||
bool CZipFileHeader::readCentralDirectoryHeader(QFile& file)
|
||||
{
|
||||
QDataStream in(&file);
|
||||
quint16 uFileNameLength=0, uExtraFieldLength=0, uCommentLength=0;
|
||||
|
||||
clear();
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
m_uCentralHeaderPosition = file.pos();
|
||||
|
||||
in >> m_uVersionMadeBy;
|
||||
in >> m_uVersionNeeded;
|
||||
in >> m_uFlags;
|
||||
in >> m_uCompression;
|
||||
in >> m_uTime;
|
||||
in >> m_uDate;
|
||||
in >> m_uCRC;
|
||||
in >> m_uSizeCompressed;
|
||||
in >> m_uSizeUncompressed;
|
||||
in >> uFileNameLength;
|
||||
in >> uExtraFieldLength;
|
||||
in >> uCommentLength;
|
||||
in >> m_uDiskNumberStart;
|
||||
in >> m_uInternalFileAttributes;
|
||||
in >> m_uExternalFileAttributes;
|
||||
in >> m_uRelativeOffsetLocalHeader;
|
||||
|
||||
if (uFileNameLength != 0)
|
||||
{
|
||||
QByteArray a (uFileNameLength, 0);
|
||||
in.readRawData(a.data(), uFileNameLength);
|
||||
m_strFileName = a;
|
||||
}
|
||||
if (uExtraFieldLength != 0)
|
||||
{
|
||||
m_baExtraField.resize(uExtraFieldLength);
|
||||
in.readRawData(m_baExtraField.data(), uExtraFieldLength);
|
||||
}
|
||||
|
||||
if (uCommentLength != 0)
|
||||
{
|
||||
QByteArray a (uCommentLength, 0);
|
||||
in.readRawData(a.data(), uCommentLength);
|
||||
m_strComment = a;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CZipFileHeader::writeCentralDirectoryHeader(QFile& file)
|
||||
{
|
||||
Q_UNUSED(file);
|
||||
}
|
||||
|
||||
void CZipEndRecord::clear()
|
||||
{
|
||||
m_uDisk = 0;
|
||||
m_uDiskCentralDir = 0;
|
||||
m_uEntriesCentralDirDisk = 0;
|
||||
m_uEntriesCentralDir = 0;
|
||||
m_uCentralDirSize = 0;
|
||||
m_uCentralDirOffset = 0;
|
||||
m_strComment.clear();
|
||||
}
|
||||
|
||||
bool CZipEndRecord::read (QFile& file)
|
||||
{
|
||||
QDataStream in(&file);
|
||||
quint16 uCommentLength=0;
|
||||
|
||||
clear();
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
in >> m_uDisk;
|
||||
in >> m_uDiskCentralDir;
|
||||
in >> m_uEntriesCentralDirDisk;
|
||||
in >> m_uEntriesCentralDir;
|
||||
in >> m_uCentralDirSize;
|
||||
in >> m_uCentralDirOffset;
|
||||
in >> uCommentLength;
|
||||
|
||||
if (uCommentLength != 0)
|
||||
{
|
||||
QByteArray a (uCommentLength, 0);
|
||||
in.readRawData(a.data(), uCommentLength);
|
||||
m_strComment = a;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CZipEndRecord::write (QFile& file)
|
||||
{
|
||||
Q_UNUSED(file);
|
||||
}
|
||||
|
||||
|
||||
CZipFile::CZipFile(CZipArchive *pArchive)
|
||||
{
|
||||
m_pArchive = pArchive;
|
||||
clear();
|
||||
}
|
||||
|
||||
CZipFile::~CZipFile()
|
||||
{
|
||||
}
|
||||
|
||||
void CZipFile::clear()
|
||||
{
|
||||
}
|
||||
|
||||
bool CZipFile::readHeader ()
|
||||
{
|
||||
QFile& file = m_pArchive->m_file;
|
||||
|
||||
return (m_head.readLocalFileHeader(file));
|
||||
}
|
||||
|
||||
QByteArray CZipFile::deflateToByteArray()
|
||||
{
|
||||
/*QByteArray a, b;
|
||||
|
||||
if (m_head.m_uDataPosition == 0 || m_head.m_uSizeUncompressed == 0) return QByteArray();
|
||||
|
||||
m_pArchive->m_file.seek (m_head.m_uDataPosition);
|
||||
a = m_pArchive->m_file.read (m_head.m_uSizeCompressed);
|
||||
|
||||
b.resize(m_head.m_uSizeUncompressed);
|
||||
quint32 u = m_head.m_uSizeUncompressed;
|
||||
Bytef* src = (Bytef*)a.data();
|
||||
Bytef* dst = (Bytef*)b.data();
|
||||
if (uncompress(dst, (uLongf*) &u, src, m_head.m_uSizeCompressed) != Z_OK)
|
||||
return QByteArray();
|
||||
|
||||
return b;*/
|
||||
|
||||
QByteArray a;
|
||||
z_stream strm;
|
||||
char *pIn=0, *pOut=0;
|
||||
int ret;
|
||||
|
||||
memset(&strm, 0, sizeof(z_stream));
|
||||
if (m_head.m_uDataPosition == 0 || m_head.m_uSizeUncompressed == 0) return QByteArray();
|
||||
|
||||
// prepare zip-stream
|
||||
/* windowBits is passed < 0 to tell that there is no zlib header.
|
||||
* Note that in this case inflate *requires* an extra "dummy" byte
|
||||
* after the compressed stream in order to complete decompression and
|
||||
* return Z_STREAM_END.
|
||||
*/
|
||||
if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) return QByteArray();
|
||||
|
||||
// read data
|
||||
pIn = new char[m_head.m_uSizeCompressed+1];
|
||||
memset (pIn, 0, m_head.m_uSizeCompressed+1);
|
||||
m_pArchive->m_file.seek (m_head.m_uDataPosition);
|
||||
m_pArchive->m_file.read (pIn, m_head.m_uSizeCompressed);
|
||||
|
||||
// prepare output
|
||||
pOut = new char[m_head.m_uSizeUncompressed];
|
||||
memset(pOut, 0, m_head.m_uSizeUncompressed);
|
||||
|
||||
/*
|
||||
// DEBUG START
|
||||
FILE *fpt;
|
||||
fpt = fopen ("questions.xml", "rt");
|
||||
fread (pOut, m_head.m_uSizeUncompressed, 1, fpt);
|
||||
fclose (fpt);
|
||||
|
||||
unsigned u = m_head.m_uSizeCompressed;
|
||||
fpt = fopen ("test2.gz", "wb");
|
||||
compress2((Bytef*)pIn, (uLongf*) &u, (Bytef*)pOut, m_head.m_uSizeUncompressed, 9);
|
||||
fwrite (pIn, u, 1, fpt);
|
||||
fclose (fpt);
|
||||
// DEBUG ENDE
|
||||
*/
|
||||
do
|
||||
{
|
||||
strm.avail_in = m_head.m_uSizeCompressed+1;
|
||||
strm.next_in = (Bytef*) pIn;
|
||||
do
|
||||
{
|
||||
strm.avail_out = m_head.m_uSizeUncompressed;
|
||||
strm.next_out = (Bytef*) pOut;
|
||||
ret = inflate (&strm, Z_SYNC_FLUSH);
|
||||
switch (ret)
|
||||
{
|
||||
case Z_NEED_DICT:
|
||||
ret = Z_DATA_ERROR; /* and fall through */
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&strm);
|
||||
delete [] pIn;
|
||||
delete [] pOut;
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
while (strm.avail_out == 0);
|
||||
|
||||
/* done when inflate() says it's done */
|
||||
}
|
||||
while (ret != Z_STREAM_END);
|
||||
|
||||
inflateEnd(&strm);
|
||||
|
||||
a = QByteArray (pOut, m_head.m_uSizeUncompressed);
|
||||
delete [] pIn;
|
||||
delete [] pOut;
|
||||
|
||||
return a;
|
||||
}
|
||||
/*
|
||||
QString CZipFile::deflateToString()
|
||||
{
|
||||
QByteArray a = deflateToByteArray();
|
||||
QTextStream in (a, QIODevice::ReadOnly);
|
||||
//QString str;
|
||||
// in >> str;
|
||||
return in.readAll();
|
||||
}
|
||||
*/
|
||||
|
||||
#define CHUNK (1<<16)
|
||||
|
||||
bool CZipFile::deflateToFile (QIODevice& dev)
|
||||
{
|
||||
z_stream strm;
|
||||
char cIn[CHUNK], cOut[CHUNK];
|
||||
int ret;
|
||||
|
||||
if ((dev.openMode() & QIODevice::WriteOnly) == 0)
|
||||
return false;
|
||||
|
||||
memset(&strm, 0, sizeof(z_stream));
|
||||
if (m_head.m_uDataPosition == 0 || m_head.m_uSizeUncompressed == 0) return false;
|
||||
|
||||
// prepare zip-stream
|
||||
/* windowBits is passed < 0 to tell that there is no zlib header.
|
||||
* Note that in this case inflate *requires* an extra "dummy" byte
|
||||
* after the compressed stream in order to complete decompression and
|
||||
* return Z_STREAM_END.
|
||||
*/
|
||||
if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) return false;
|
||||
|
||||
// prepare archive
|
||||
m_pArchive->m_file.seek (m_head.m_uDataPosition);
|
||||
|
||||
// unzip
|
||||
unsigned uRead=0, uBytes=0;
|
||||
do
|
||||
{
|
||||
uBytes = m_pArchive->m_file.read(cIn, CHUNK);
|
||||
if (uRead + uBytes > m_head.m_uSizeCompressed)
|
||||
uBytes = m_head.m_uSizeCompressed - uRead + 1; // one dummy byte extra
|
||||
uRead += uBytes;
|
||||
|
||||
strm.avail_in = uBytes;
|
||||
if (strm.avail_in == 0) break;
|
||||
strm.next_in = (Bytef*) cIn;
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = (Bytef*) cOut;
|
||||
ret = inflate (&strm, Z_NO_FLUSH);
|
||||
switch (ret)
|
||||
{
|
||||
case Z_NEED_DICT:
|
||||
ret = Z_DATA_ERROR; /* and fall through */
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&strm);
|
||||
return false;
|
||||
}
|
||||
unsigned uHave = CHUNK - strm.avail_out;
|
||||
dev.write(cOut, uHave);
|
||||
}
|
||||
while (strm.avail_out == 0);
|
||||
|
||||
/* done when inflate() says it's done */
|
||||
}
|
||||
while (ret != Z_STREAM_END);
|
||||
|
||||
inflateEnd(&strm);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CZipArchive::CZipArchive()
|
||||
{
|
||||
}
|
||||
|
||||
CZipArchive::~CZipArchive()
|
||||
{
|
||||
qDeleteAll(m_listFiles);
|
||||
qDeleteAll(m_listEndRecords);
|
||||
}
|
||||
|
||||
bool CZipArchive::open (const QString& strFileName, const OpenMode om)
|
||||
{
|
||||
unsigned uSignature=0;
|
||||
CZipFile *pzf=0;
|
||||
|
||||
if (strFileName.isEmpty()) return false;
|
||||
if (om != OpenReadOnly) return false;
|
||||
|
||||
m_strFileName = strFileName;
|
||||
m_file.close();
|
||||
m_file.setFileName(strFileName);
|
||||
if (!m_file.open(QIODevice::ReadOnly)) return false;
|
||||
QDataStream in(&m_file);
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
while (!in.atEnd())
|
||||
{
|
||||
uSignature = 0;
|
||||
in >> uSignature;
|
||||
if (uSignature == 0x04034b50)
|
||||
{ // local file header with data
|
||||
pzf = new CZipFile(this);
|
||||
if (pzf->readHeader())
|
||||
m_listFiles.append(pzf);
|
||||
//qDebug("%7i %7i %s", pzf->m_head.m_uSizeUncompressed, pzf->m_head.m_uSizeCompressed, qPrintable(pzf->fileName()));
|
||||
// file.deflateToFile("test.tmp");
|
||||
}
|
||||
else if (uSignature == 0x02014b50)
|
||||
{ // central directory file header
|
||||
CZipFileHeader head;
|
||||
head.readCentralDirectoryHeader(m_file);
|
||||
pzf = findFile(head.m_strFileName);
|
||||
if (pzf) pzf->m_head.integrate(head);
|
||||
}
|
||||
else if (uSignature == 0x06054b50)
|
||||
{ // End of central directory record
|
||||
CZipEndRecord *pzer = new CZipEndRecord();
|
||||
pzer->read(m_file);
|
||||
m_listEndRecords.append(pzer);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("Unknown signature: %X", uSignature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CZipFile* CZipArchive::findFile (const QString& strFileName)
|
||||
{
|
||||
for (int i=0; i<m_listFiles.size(); i++)
|
||||
{
|
||||
if (m_listFiles.at(i)->fileName() == strFileName)
|
||||
return m_listFiles.at(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
155
osziparchive.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2003-2006 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OSZIPARCHIVE_H
|
||||
#define OSZIPARCHIVE_H
|
||||
|
||||
#include <qfile.h>
|
||||
#include <qstring.h>
|
||||
#include <qlist.h>
|
||||
|
||||
class CZipFile;
|
||||
class CZipArchive;
|
||||
|
||||
class CZipFileHeader
|
||||
{
|
||||
public:
|
||||
CZipFileHeader() { clear(); }
|
||||
~CZipFileHeader() {}
|
||||
|
||||
void clear();
|
||||
void integrate(const CZipFileHeader& head);
|
||||
|
||||
bool readLocalFileHeader(QFile& file);
|
||||
void writeLocalFileHeader(QFile& file);
|
||||
|
||||
bool readCentralDirectoryHeader(QFile& file);
|
||||
void writeCentralDirectoryHeader(QFile& file);
|
||||
|
||||
inline bool hasDataDescriptor() const { return m_uFlags & (1<<3) ? true : false; }
|
||||
public:
|
||||
quint16 m_uVersionMadeBy; //!< version made by 2 bytes
|
||||
quint16 m_uVersionNeeded; //!< version needed to extract 2 bytes
|
||||
quint16 m_uFlags; //!< general purpose bit flag 2 bytes
|
||||
quint16 m_uCompression; //!< compression method 2 bytes
|
||||
quint16 m_uTime; //!< last mod file time 2 bytes
|
||||
quint16 m_uDate; //!< last mod file date 2 bytes
|
||||
quint32 m_uCRC; //!< crc-32 4 bytes
|
||||
quint32 m_uSizeCompressed; //!< compressed size 4 bytes
|
||||
quint32 m_uSizeUncompressed; //!< uncompressed size 4 bytes
|
||||
quint16 m_uDiskNumberStart; //!< disk number start 2 bytes
|
||||
quint16 m_uInternalFileAttributes; //!< internal file attributes 2 bytes
|
||||
quint32 m_uExternalFileAttributes; //!< external file attributes 4 bytes
|
||||
quint32 m_uRelativeOffsetLocalHeader; //!< relative offset of local header 4 bytes
|
||||
|
||||
QString m_strFileName; //!< file name (variable size)
|
||||
QByteArray m_baExtraField; //!< extra field (variable size)
|
||||
QString m_strComment; //!< file comment (variable size)
|
||||
|
||||
// helpers
|
||||
quint64 m_uLocalHeaderPosition; //!< Position of the local file header, after the signature field
|
||||
quint64 m_uDataPosition; //!< Position in the file of the data
|
||||
quint64 m_uCentralHeaderPosition; //!< Position of the central directory file header, after the signature field
|
||||
};
|
||||
|
||||
class CZipEndRecord
|
||||
{
|
||||
public:
|
||||
CZipEndRecord() { clear(); }
|
||||
~CZipEndRecord() { }
|
||||
|
||||
void clear();
|
||||
|
||||
bool read (QFile& file);
|
||||
void write (QFile& file);
|
||||
|
||||
public:
|
||||
quint16 m_uDisk; //!< number of this disk 2 bytes
|
||||
quint16 m_uDiskCentralDir; //!< number of the disk with the start of the central directory 2 bytes
|
||||
quint16 m_uEntriesCentralDirDisk; //!< total number of entries in the central directory on this disk 2 bytes
|
||||
quint16 m_uEntriesCentralDir; //!< total number of entries in the central directory 2 bytes
|
||||
quint32 m_uCentralDirSize; //!< size of the central directory 4 bytes
|
||||
quint32 m_uCentralDirOffset; //!< offset of start of central directory with respect to the starting disk number 4 bytes
|
||||
|
||||
QString m_strComment;
|
||||
};
|
||||
|
||||
//! Represents a file in a zip archive
|
||||
class CZipFile
|
||||
{
|
||||
public:
|
||||
CZipFile() { m_pArchive = 0; clear(); }
|
||||
CZipFile(CZipArchive *pArchive);
|
||||
~CZipFile();
|
||||
|
||||
void clear();
|
||||
inline bool isValid() const { return m_pArchive != 0; }
|
||||
|
||||
//! Reads local file header
|
||||
//! Position has to be after the signature field
|
||||
//! After the operation, the current position in the file is after the file data
|
||||
bool readHeader();
|
||||
|
||||
bool deflateToFile (QIODevice& dev);
|
||||
|
||||
QByteArray deflateToByteArray();
|
||||
//QString deflateToString();
|
||||
|
||||
// bool read (FILE *fpt, unsigned uPosition);
|
||||
|
||||
//! this file has a data descriptor
|
||||
|
||||
inline QString fileName() const { return m_head.m_strFileName; }
|
||||
|
||||
public:
|
||||
CZipArchive *m_pArchive;
|
||||
CZipFileHeader m_head;
|
||||
|
||||
};
|
||||
|
||||
class CZipArchive
|
||||
{
|
||||
public:
|
||||
CZipArchive();
|
||||
~CZipArchive();
|
||||
|
||||
enum OpenMode { OpenReadOnly, OpenCreate, OpenModify };
|
||||
|
||||
bool open (const QString& strFileName, const OpenMode om);
|
||||
|
||||
CZipFile* findFile (const QString& strFileName);
|
||||
|
||||
inline int fileCount() const { return m_listFiles.size(); }
|
||||
const CZipFile* fileAt(const int i) const { return m_listFiles.at(i); }
|
||||
CZipFile* fileAt(const int i) { return m_listFiles.at(i); }
|
||||
|
||||
protected:
|
||||
friend class CZipFile;
|
||||
|
||||
QFile m_file;
|
||||
QString m_strFileName;
|
||||
|
||||
QList<CZipFile*> m_listFiles;
|
||||
QList<CZipEndRecord*> m_listEndRecords;
|
||||
};
|
||||
|
||||
#endif
|
||||
|