Import of original sourcecode for afutrainer-3.0
Original source: http://www.oliver-saal.de/software/afutrainer/download/afutrainer-3.0-src.zip Landing page: http://www.oliver-saal.de/software/afutrainer/download.php 092d114b47e40472238e27ee01a528a58ad2d311ec95280b404bb57c97c9fed6 afutrainer-3.0-src.zip
|
@ -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">
|
|
@ -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">
|
|
@ -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>
|
|
@ -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
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -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
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "afutrainer.ico"
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
|
@ -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>
|
|
@ -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')) : "--");
|
||||
}
|
||||
|
|
@ -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;
|
||||
};
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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()));
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 963 B |
After Width: | Height: | Size: 661 B |
After Width: | Height: | Size: 890 B |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 948 B |
After Width: | Height: | Size: 830 B |
After Width: | Height: | Size: 725 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 838 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 646 B |
After Width: | Height: | Size: 997 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 459 B |
After Width: | Height: | Size: 813 B |
After Width: | Height: | Size: 855 B |
After Width: | Height: | Size: 821 B |
After Width: | Height: | Size: 843 B |
After Width: | Height: | Size: 820 B |
After Width: | Height: | Size: 831 B |
After Width: | Height: | Size: 815 B |
After Width: | Height: | Size: 772 B |
After Width: | Height: | Size: 761 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 728 B |
After Width: | Height: | Size: 835 B |
After Width: | Height: | Size: 862 B |
After Width: | Height: | Size: 852 B |
After Width: | Height: | Size: 163 B |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 1023 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 480 B |
After Width: | Height: | Size: 861 B |
After Width: | Height: | Size: 901 B |
After Width: | Height: | Size: 889 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 736 B |
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
*/
|
|
@ -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
|
||||
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,426 @@
|
|||
/***************************************************************************
|
||||
* 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 "plotwidget.h"
|
||||
#include <qpainter.h>
|
||||
|
||||
void CPlotWidgetPoint::clear()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CPlotWidgetCurve::clear()
|
||||
{
|
||||
QList<CPlotWidgetPoint>::clear();
|
||||
}
|
||||
|
||||
|
||||
QRectF CPlotWidgetCurve::boundaries() const
|
||||
{
|
||||
QRectF rect;
|
||||
|
||||
for (int i=0; i<size(); i++)
|
||||
{
|
||||
QPointF p = at(i);
|
||||
if (i == 0)
|
||||
{
|
||||
rect.setBottomLeft(p);
|
||||
rect.setTopRight(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p.x() < rect.left())
|
||||
rect.setLeft(p.x());
|
||||
else if (p.x() > rect.right())
|
||||
rect.setRight(p.x());
|
||||
|
||||
if (p.y() > rect.bottom())
|
||||
rect.setBottom(p.y());
|
||||
else if (p.y() < rect.top())
|
||||
rect.setTop(p.y());
|
||||
}
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
CPlotWidgetTic::CPlotWidgetTic(const double dPos, const QString& strText)
|
||||
{
|
||||
clear();
|
||||
m_dPos = dPos;
|
||||
m_strText = strText;
|
||||
}
|
||||
|
||||
CPlotWidgetTic::CPlotWidgetTic(const double dPos, const double dWidth, const QString& strText)
|
||||
{
|
||||
clear();
|
||||
m_dPos = dPos;
|
||||
m_dWidth = dWidth;
|
||||
m_strText = strText;
|
||||
}
|
||||
|
||||
CPlotWidgetTic::CPlotWidgetTic(const double dPos, const QPixmap& pixmap)
|
||||
{
|
||||
clear();
|
||||
m_dPos = dPos;
|
||||
m_pixmap = pixmap;
|
||||
}
|
||||
|
||||
void CPlotWidgetTic::clear()
|
||||
{
|
||||
m_dPos = 0.0;
|
||||
m_dWidth = 0.0;
|
||||
m_pen = QPen(Qt::DashLine);
|
||||
m_pen.setColor(Qt::darkGray);
|
||||
m_penFont = QPen(Qt::black);
|
||||
m_pixmap = QPixmap();
|
||||
m_strText.clear();
|
||||
m_fillType = FillNone;
|
||||
m_lineType = LinePlot;
|
||||
m_iTextFlags = Qt::AlignHCenter | Qt::AlignTop;
|
||||
}
|
||||
|
||||
void CPlotWidgetTic::paintX (QPainter *pPainter, CPlotWidget *pWidget) const
|
||||
{
|
||||
QPoint ptTL, ptBR; // TopLeft, BottomRight
|
||||
QRect rectText;
|
||||
|
||||
if (m_fillType != FillNone && m_dWidth > 0.0)
|
||||
{
|
||||
ptTL = pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.top()));
|
||||
ptBR = pWidget->mapToPlot(QPointF(m_dPos+m_dWidth, pWidget->m_rectData.bottom()));
|
||||
|
||||
if (m_fillType == FillAll)
|
||||
{
|
||||
ptTL.setY(pWidget->m_rectPlot.top());
|
||||
ptBR.setY(pWidget->m_rectPlot.bottom());
|
||||
}
|
||||
|
||||
if (ptTL.x() < pWidget->m_rectPlot.left())
|
||||
ptTL.setX(pWidget->m_rectPlot.left());
|
||||
|
||||
if (ptBR.x() > pWidget->m_rectPlot.right())
|
||||
ptBR.setX(pWidget->m_rectPlot.right());
|
||||
|
||||
pPainter->fillRect(QRect(ptTL, ptBR), m_brush);
|
||||
|
||||
rectText = QRect(
|
||||
QPoint(ptTL.x(), pWidget->m_rectPlot.bottom() + 5),
|
||||
QPoint(ptBR.x(), pWidget->rect().bottom()));
|
||||
}
|
||||
else
|
||||
{
|
||||
rectText = QRect();
|
||||
}
|
||||
|
||||
if (m_lineType != LineNone)
|
||||
{
|
||||
pPainter->setPen(m_pen);
|
||||
pPainter->drawLine(
|
||||
pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.top())),
|
||||
pWidget->mapToPlot(QPointF(m_dPos, pWidget->m_rectData.bottom())));
|
||||
}
|
||||
|
||||
if (!m_strText.isEmpty())
|
||||
{
|
||||
pPainter->setPen(m_penFont);
|
||||
pPainter->drawText(rectText, m_iTextFlags, m_strText);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlotWidgetTic::paintY (QPainter *pPainter, CPlotWidget *pWidget) const
|
||||
{
|
||||
QPoint ptTL, ptBR; // TopLeft, BottomRight
|
||||
QRect rectText;
|
||||
|
||||
if (m_fillType != FillNone && m_dWidth > 0.0)
|
||||
{
|
||||
ptTL = pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos));
|
||||
ptBR = pWidget->mapToPlot(QPointF(pWidget->m_rectData.right(), m_dPos+m_dWidth));
|
||||
|
||||
if (m_fillType == FillAll)
|
||||
{
|
||||
ptTL.setX(pWidget->m_rectPlot.left());
|
||||
ptBR.setX(pWidget->m_rectPlot.right());
|
||||
}
|
||||
|
||||
if (ptTL.y() < pWidget->m_rectPlot.top())
|
||||
ptTL.setY(pWidget->m_rectPlot.top());
|
||||
|
||||
if (ptBR.y() > pWidget->m_rectPlot.bottom())
|
||||
ptBR.setY(pWidget->m_rectPlot.bottom());
|
||||
|
||||
pPainter->fillRect(QRect(ptTL, ptBR), m_brush);
|
||||
|
||||
rectText = QRect(
|
||||
QPoint(3, ptTL.y()),
|
||||
QPoint(pWidget->m_rectPlot.left()-3, ptBR.y()));
|
||||
}
|
||||
else
|
||||
{
|
||||
QFontMetrics fm(m_font);
|
||||
QPoint pt = pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos));
|
||||
rectText = QRect(
|
||||
QPoint(3, pt.y()-fm.height()),
|
||||
QPoint(pWidget->m_rectPlot.left()-3, pt.y()+fm.height()));
|
||||
}
|
||||
|
||||
if (m_lineType != LineNone)
|
||||
{
|
||||
pPainter->setPen(m_pen);
|
||||
pPainter->drawLine(
|
||||
pWidget->mapToPlot(QPointF(pWidget->m_rectData.left(), m_dPos)),
|
||||
pWidget->mapToPlot(QPointF(pWidget->m_rectData.right(), m_dPos)));
|
||||
}
|
||||
|
||||
if (!m_pixmap.isNull())
|
||||
{
|
||||
// Ziel-Mittelpunkt errechnen
|
||||
QPoint pt = pWidget->mapToPlot(QPointF(0, m_dPos));
|
||||
pt.setX(pWidget->m_rectPlot.left() - m_pixmap.width()/2 - 5);
|
||||
|
||||
// Linke obere Ecke errechnen und malen!
|
||||
pt -= QPoint (m_pixmap.width()/2, m_pixmap.height()/2);
|
||||
pPainter->drawPixmap(pt, m_pixmap);
|
||||
}
|
||||
|
||||
if (!m_strText.isEmpty())
|
||||
{
|
||||
pPainter->setPen(m_penFont);
|
||||
pPainter->drawText(rectText, m_iTextFlags, m_strText);
|
||||
}
|
||||
}
|
||||
|
||||
CPlotWidget::CPlotWidget(QWidget *pParent) : QFrame(pParent)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void CPlotWidget::clear()
|
||||
{
|
||||
m_type = PlotLines;
|
||||
m_bLimitAutoY = true;
|
||||
m_bLimitAutoX = true;
|
||||
m_dLimitXMin = 0.0;
|
||||
m_dLimitXMax = 10.0;
|
||||
m_dLimitYMin = 0.0;
|
||||
m_dLimitYMax = 10.0;
|
||||
m_dLimitXRound = 0.0;
|
||||
m_dLimitYRound = 0.0;
|
||||
m_dTicX = 0.0;
|
||||
m_penTicX = QPen(Qt::DashLine);
|
||||
m_penTicX.setColor(Qt::darkGray);
|
||||
m_dTicY = 0.0;
|
||||
m_penTicY = QPen(Qt::DashLine);
|
||||
m_penTicY.setColor(Qt::darkGray);
|
||||
m_iBorder = BorderLeft|BorderBottom;
|
||||
m_iBorderDistTop = 5;
|
||||
m_iBorderDistBottom = 5;
|
||||
m_iBorderDistLeft = 5;
|
||||
m_iBorderDistRight = 5;
|
||||
m_brushPlotBkg = QBrush(Qt::white);
|
||||
m_listTicX.clear();
|
||||
m_listTicY.clear();
|
||||
m_dBarWidth = 0.6;
|
||||
m_dBarOffset = 0.0;
|
||||
m_listCurves.clear();
|
||||
}
|
||||
|
||||
void CPlotWidget::setBorderDistance(const int iLeft, const int iRight, const int iTop, const int iBottom)
|
||||
{
|
||||
m_iBorderDistTop = iTop;
|
||||
m_iBorderDistBottom = iBottom;
|
||||
m_iBorderDistLeft = iLeft;
|
||||
m_iBorderDistRight = iRight;
|
||||
}
|
||||
|
||||
void CPlotWidget::updateCache()
|
||||
{
|
||||
m_rectPlot = plotArea();
|
||||
m_rectData = rectData();
|
||||
}
|
||||
|
||||
QRect CPlotWidget::plotArea() const
|
||||
{
|
||||
QRect rect = frameRect();
|
||||
rect.adjust(m_iBorderDistLeft, m_iBorderDistTop, -m_iBorderDistRight, -m_iBorderDistBottom);
|
||||
return rect;
|
||||
}
|
||||
|
||||
QRectF CPlotWidget::rectData() const
|
||||
{
|
||||
QRectF rect;
|
||||
if (m_bLimitAutoX || m_bLimitAutoY)
|
||||
{
|
||||
for (int i=0; i<m_listCurves.size(); i++)
|
||||
{
|
||||
rect = rect.united(m_listCurves.at(i).boundaries());
|
||||
}
|
||||
}
|
||||
if (!m_bLimitAutoX)
|
||||
{
|
||||
rect.setLeft(m_dLimitXMin);
|
||||
rect.setRight(m_dLimitXMax);
|
||||
}
|
||||
else if (m_dLimitXRound > 0.0)
|
||||
{
|
||||
rect.setLeft((unsigned)(rect.left() / m_dLimitXRound) * m_dLimitXRound);
|
||||
rect.setRight((unsigned)(rect.right() / m_dLimitXRound + 1) * m_dLimitXRound);
|
||||
}
|
||||
|
||||
if (!m_bLimitAutoY)
|
||||
{
|
||||
rect.setTop(m_dLimitYMin);
|
||||
rect.setBottom(m_dLimitYMax);
|
||||
}
|
||||
else if (m_dLimitYRound > 0.0)
|
||||
{
|
||||
rect.setTop((unsigned)(rect.top() / m_dLimitYRound) * m_dLimitYRound);
|
||||
rect.setBottom((unsigned)(rect.bottom() / m_dLimitYRound + 1) * m_dLimitYRound);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
QPoint CPlotWidget::mapToPlot (QPointF p)
|
||||
{
|
||||
QPointF ret;
|
||||
double m;
|
||||
|
||||
// Umrechung X-Koordinate
|
||||
m = ((double) (m_rectPlot.left() - m_rectPlot.right())) / (m_rectData.left() - m_rectData.right());
|
||||
ret.setX(m * (p.x() - m_rectData.left()) + m_rectPlot.left());
|
||||
|
||||
// Umrechnung Y-Koordinate (mit Spiegelung)
|
||||
m = ((double) (m_rectPlot.bottom() - m_rectPlot.top())) / (m_rectData.top() - m_rectData.bottom());
|
||||
ret.setY(m * (p.y() - m_rectData.top()) + m_rectPlot.bottom());
|
||||
|
||||
return ret.toPoint();
|
||||
}
|
||||
|
||||
void CPlotWidget::paintEvent (QPaintEvent *e)
|
||||
{
|
||||
QList<QPoint> listPoints;
|
||||
QList<CPlotWidgetTic> listTicsX, listTicsY;
|
||||
double d=0.0;
|
||||
int i=0;
|
||||
|
||||
QFrame::paintEvent(e);
|
||||
QPainter painter(this);
|
||||
|
||||
updateCache();
|
||||
|
||||
// Draw Background
|
||||
if (m_brushPlotBkg.style() != Qt::NoBrush)
|
||||
{
|
||||
painter.fillRect(m_rectPlot, m_brushPlotBkg);
|
||||
}
|
||||
|
||||
// Draw Tics
|
||||
listTicsX = m_listTicX;
|
||||
if (listTicsX.isEmpty() && m_dTicX > 0.0)
|
||||
{
|
||||
d = ((unsigned)(m_rectData.left() / m_dTicX)) * m_dTicX;
|
||||
if (d < m_rectData.left()) d+=m_dTicX;
|
||||
while (d <= m_rectData.right())
|
||||
{
|
||||
CPlotWidgetTic tic(d, QString("%1").arg(d,0,'f',2));
|
||||
tic.setPen(m_penTicX);
|
||||
listTicsX.append(tic);
|
||||
d += m_dTicX;
|
||||
}
|
||||
}
|
||||
listTicsY = m_listTicY;
|
||||
if (listTicsY.isEmpty() && m_dTicY > 0.0)
|
||||
{
|
||||
d = ((unsigned)(m_rectData.top() / m_dTicY)) * m_dTicY;
|
||||
if (d < m_rectData.top()) d+=m_dTicY;
|
||||
while (d <= m_rectData.bottom())
|
||||
{
|
||||
CPlotWidgetTic tic(d, QString("%1").arg(d,0,'f',2));
|
||||
tic.setPen(m_penTicY);
|
||||
listTicsY.append(tic);
|
||||
d += m_dTicY;
|
||||
}
|
||||
}
|
||||
for (i=0; i<listTicsX.size(); i++)
|
||||
listTicsX.at(i).paintX(&painter, this);
|
||||
|
||||
for (i=0; i<listTicsY.size(); i++)
|
||||
listTicsY.at(i).paintY(&painter, this);
|
||||
|
||||
// Draw Curves
|
||||
if (m_type == PlotLines)
|
||||
{
|
||||
for (int i=0; i<m_listCurves.size(); i++)
|
||||
{
|
||||
CPlotWidgetCurve c = m_listCurves.at(i);
|
||||
for (int j=0; j<c.size(); j++)
|
||||
{
|
||||
CPlotWidgetPoint p = c.at(j);
|
||||
listPoints.append(mapToPlot (p));
|
||||
}
|
||||
painter.setPen(c.pen());
|
||||
painter.drawPolyline(listPoints.toVector());
|
||||
}
|
||||
}
|
||||
else if (m_type == PlotBarsSum && m_listCurves.size() != 0)
|
||||
{
|
||||
CPlotWidgetCurve c1 = m_listCurves.at(0);
|
||||
//painter.setPen(c1.pen());
|
||||
//painter.setBrush(c1.brush());
|
||||
QPoint ptTL, ptBR;
|
||||
for (int j=0; j<c1.size(); j++)
|
||||
{ // Alle Punkte der ersten Kurve durchgehen
|
||||
CPlotWidgetPoint p1 = c1.at(j);
|
||||
ptTL = mapToPlot(QPointF(p1.x() + m_dBarOffset - m_dBarWidth/2, p1.y()));
|
||||
ptBR = mapToPlot(QPointF(p1.x() + m_dBarOffset + m_dBarWidth/2, m_rectData.top()));
|
||||
if (p1.y() != 0.0 && m_rectPlot.contains(ptTL) && m_rectPlot.contains(ptBR))
|
||||
painter.fillRect(QRect(ptTL, ptBR), c1.brush());
|
||||
double dStart = p1.y();
|
||||
for (int i=1; i<m_listCurves.size(); i++)
|
||||
{ // alle Weiteren Kurven durchgehen
|
||||
CPlotWidgetCurve c2 = m_listCurves.at(i);
|
||||
for (int jj=0; jj<c2.size(); jj++)
|
||||
{ // alle Punkte der zweiten Kurve durchgehen
|
||||
CPlotWidgetPoint p2 = c2.at(jj);
|
||||
if (p2.x() != p1.x()) continue;
|
||||
ptTL = mapToPlot(QPointF(p2.x() + m_dBarOffset - m_dBarWidth/2, dStart+p2.y()));
|
||||
ptBR = mapToPlot(QPointF(p2.x() + m_dBarOffset + m_dBarWidth/2, dStart+m_rectData.top()));
|
||||
if (p2.y() != 0 && m_rectPlot.contains(ptTL) && m_rectPlot.contains(ptBR))
|
||||
{
|
||||
dStart += p2.y();
|
||||
painter.fillRect(QRect(ptTL, ptBR), c2.brush());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw border
|
||||
painter.setPen(m_penBorder);
|
||||
if (m_iBorder & BorderLeft)
|
||||
painter.drawLine(m_rectPlot.topLeft(), m_rectPlot.bottomLeft());
|
||||
if (m_iBorder & BorderRight)
|
||||
painter.drawLine(m_rectPlot.topRight(), m_rectPlot.bottomRight());
|
||||
if (m_iBorder & BorderTop)
|
||||
painter.drawLine(m_rectPlot.topRight(), m_rectPlot.topLeft());
|
||||
if (m_iBorder & BorderBottom)
|
||||
painter.drawLine(m_rectPlot.bottomRight(), m_rectPlot.bottomLeft());
|
||||
}
|