1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <QtDebug>
#include "Card.h"
#include "ICardPack.h"
#include "DicRecord.h"
#include "Field.h"
bool Card::operator==( const Card& another ) const
{
return question == another.getQuestion();
}
/** Card name is its question.
Image tags are replaced with image names.
*/
QString Card::getName() const
{
QString nameStr = question;
QRegExp imageNameRx("<img\\s*src=\"(.+[/\\\\])?(.+)\".*>");
nameStr.replace( imageNameRx, "\\2");
return nameStr;
}
QStringList Card::getAnswers()
{
generateAnswers();
return answers;
}
QList<const DicRecord*> Card::getSourceRecords()
{
if( sourceRecords.isEmpty() )
generateAnswers();
return sourceRecords;
}
QMultiHash<QString, QString> Card::getAnswerElements()
{
QMultiHash<QString, QString> answerElements; // Key: field name
QString qstFieldName = cardPack->getQuestionFieldName();
foreach(DicRecord* record, cardPack->getRecords())
if(record->getFieldElements(qstFieldName).contains(question) &&
record->isValid(qstFieldName))
{
sourceRecords << record;
connect(record, SIGNAL(valueChanged(QString)), SLOT(dropAnswers()));
foreach(QString ansFieldName, cardPack->getAnswerFieldNames())
{
if(record->getFieldValue(ansFieldName).isEmpty())
continue;
foreach(QString ansElement, record->getFieldElements(ansFieldName))
if(!answerElements.contains(ansFieldName, ansElement))
answerElements.insert(ansFieldName, ansElement);
}
}
return answerElements;
}
void Card::generateAnswersFromElements(
const QMultiHash<QString, QString>& answerElements)
{
foreach(const Field* ansField, cardPack->getAnswerFields())
{
if(!ansField)
{
answers << "";
continue;
}
QStringList elements = getAnswerElementsForField(answerElements, ansField->name());
if(elements.isEmpty())
{
answers << "";
continue;
}
answers << elements.join(ICardPack::HomonymDelimiter);
}
}
QStringList Card::getAnswerElementsForField(const QMultiHash<QString, QString>& answerElements,
const QString& fieldName) const
{
QStringList elements = answerElements.values(fieldName); // reversed order
QStringList elementsInOrder;
elementsInOrder.reserve(elements.size());
std::reverse_copy( elements.begin(), elements.end(),
std::back_inserter(elementsInOrder) );
return elementsInOrder;
}
// Fills also list of source entries
void Card::generateAnswers()
{
if(!cardPack)
return;
clearAnswers();
generateAnswersFromElements(getAnswerElements());
}
void Card::clearAnswers()
{
answers.clear();
foreach(const DicRecord* record, sourceRecords)
disconnect( record, 0, this, SLOT(dropAnswers()) );
sourceRecords.clear();
}
void Card::dropAnswers()
{
clearAnswers();
emit answersChanged();
}
StudyRecord Card::getStudyRecord() const
{
return cardPack->getStudyRecord(getQuestion());
}
///< Reviewed at least twice
bool Card::isScheduledAndReviewed() const
{
if(!cardPack)
return false;
int reviews = cardPack->getStudyRecords(getQuestion()).size();
return reviews >= 2;
}
|