#include #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(""); nameStr.replace( imageNameRx, "\\2"); return nameStr; } QStringList Card::getAnswers() { generateAnswers(); return answers; } QList Card::getSourceRecords() { if( sourceRecords.isEmpty() ) generateAnswers(); return sourceRecords; } QMultiHash Card::getAnswerElements() { QMultiHash 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& 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& 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; }