QMap is too flexible. Users will kill us for changing lesson order. The flexibility of the map makes the lesson model in KVocTrain much harder to implement.
Moved the inQuery flag into the lesson class.
Fixed readers and writers. I could not verify if the keduvocvokabelnreader.cpp works.
The first lesson has 0 as index now.
A default lesson is created according to Jeremys plans, but within the document class itself, after reading the doc, so all readers profit from it.
KEduVocExpression is not initialized to lesson=-1 as default.
The old reader maps lesson 1 to 0.
Splitting and deleting lessons seems to work.
Moving lessons is not implemented (this will become interesting, when drag and drop for the lesson model is enabled).
TODO: When adding an expression, the document can automatically add it to the lesson.
Right now we call doc->lesson.add(Exp) and doc->addExp(lesson). The later should suffice.
Fixes in KVocTrain (many +-1 are no longer needed).
CCMAIL:jeremy@scitools.com
CCMAIL:peter@peterandlinda.com
svn path=/trunk/KDE/kdeedu/libkdeedu/; revision=709026
QString m_queryorg;
QString m_querytrans;
QList<KEduVocExpression> m_vocabulary;
- QList<int> m_lessonsInQuery;
QStringList m_tenseDescriptions;
QSet<QString> m_usages;
*/
QString m_category;
- // make this a map so removals don't require renumbering :)
- QMap<int, KEduVocLesson> m_lessons;
+ // A map is too error prone. Lesson order is very important.
+ QList<KEduVocLesson> m_lessons;
KEduVocWordType* m_wordTypes;
f->close();
KIO::NetAccess::removeTempFile( temporaryFile );
}
+
+ // Additional cleanup: Put entries without a lesson into a default lesson.
+ int defaultLessonNumber = appendLesson(i18n("Default Lesson"));
+ // now make sure we don't have any orphan entries (lesson -1)
+ for (int i = 0; i < entryCount(); ++i)
+ {
+ if (entry(i)->lesson() == -1)
+ {
+ entry(i)->setLesson(defaultLessonNumber);
+ lesson(defaultLessonNumber).addEntry(i);
+ }
+ }
+ if (lesson(defaultLessonNumber).entries().size() == 0)
+ {
+ deleteLesson(defaultLessonNumber, DeleteEmptyLesson);
+ }
+
return read;
}
}
-// int KEduVocDocument::appendIdentifier(const QString & name)
-// {
-// KEduVocIdentifier identifier;
-// identifier.setName(name);
-// return appendIdentifier(identifier);
-// }
-
-
-
-//QString KEduVocDocument::lessonDescription(int idx) const
-//{
-// if (idx == 0)
-// return i18nc("@label:listbox","<placeholder>no lesson</placeholder>");
-
-// if (idx <= 0 || idx > d->m_lessons.size() )
-// return "";
-
-// return d->m_lessons[idx-1].description();
-//}
-
-//int KEduVocDocument::lessonIndex(const QString &description) const
-//{
-// return d->m_lessonDescriptions.indexOf(description) +1;
-//}
-
-
-int KEduVocDocument::addLesson( const QString &lessonName, int position )
+int KEduVocDocument::appendLesson( const QString &lessonName, bool inQuery )
{
- if ( position == -1 ) {
- // no position was specified, so put it wherever there's a slot
- position = 1;
- while ( d->m_lessons.contains( position ) ) {
- ++position;
- }
- }
-
KEduVocLesson lesson;
lesson.setName( lessonName );
- d->m_lessons.insert( position, lesson );
- return position;
+ lesson.setInQuery( inQuery );
+ d->m_lessons.append( lesson );
+ return d->m_lessons.count() - 1;
}
-QMap<int, KEduVocLesson> & KEduVocDocument::lessons() const
+QList<KEduVocLesson> & KEduVocDocument::lessons() const
{
return d->m_lessons;
}
return d->m_lessons[index];
}
-//void KEduVocDocument::renameLesson(const int lessonIndex, const QString &lessonName)
-//{
-// d->m_lessonDescriptions.replace(lessonIndex-1, lessonName); // counting from 1
-//}
-
-
bool KEduVocDocument::lessonInQuery( int lessonIndex ) const
{
- return d->m_lessonsInQuery.contains( lessonIndex );
+ return d->m_lessons.value(lessonIndex).inQuery();
}
-
void KEduVocDocument::addLessonToQuery( int lessonIndex )
{
- if ( !lessonInQuery( lessonIndex ) )
- d->m_lessonsInQuery.append( lessonIndex );
+ d->m_lessons[lessonIndex].setInQuery( true );
}
-
void KEduVocDocument::removeLessonFromQuery( int lessonIndex )
{
- if ( lessonInQuery( lessonIndex ) )
- d->m_lessonsInQuery.removeAt( d->m_lessonsInQuery.indexOf( lessonIndex ) );
+ d->m_lessons[lessonIndex].setInQuery( false );
}
-
QList<int> KEduVocDocument::lessonsInQuery() const
{
- return d->m_lessonsInQuery;
+ QList<int> lessons;
+ for ( int i = 0; i < d->m_lessons.count(); i++ ) {
+ if ( d->m_lessons.value(i).inQuery() ) {
+ lessons.append(i);
+ }
+ }
+ return lessons;
}
-
void KEduVocDocument::setLessonsInQuery( const QList<int> &lesson_iq )
{
- d->m_lessonsInQuery = lesson_iq;
+ for ( int i = 0; i < d->m_lessons.count(); i++ ) {
+ d->m_lessons[i].setInQuery( lesson_iq.contains(i) );
+ }
}
KUrl KEduVocDocument::url() const
QStringList KEduVocDocument::lessonNames() const
{
QStringList descriptions;
- QList<KEduVocLesson> lessonObjects = lessons().values();
- for ( int i = 0; i < lessonObjects.count(); ++i ) {
- descriptions.append( lessonObjects[i].name() );
+ foreach ( KEduVocLesson lesson, d->m_lessons ) {
+ descriptions.append(lesson.name());
}
return descriptions;
}
}
bool KEduVocDocument::deleteLesson( int lessonIndex, int deleteMode )
-{ // too bad we count from one!
- lessonIndex++;
+{
for ( int ent = entryCount() - 1; ent >= 0 ; ent-- ) {
if ( entry( ent )->lesson() == lessonIndex ) {
if ( deleteMode == DeleteEmptyLesson )
}
} // reduce lesson
- // finally just remove the lesson name
- //d->m_lessonDescriptions.removeAt(lessonIndex-1); // because of the damned 0 arghh
+ // finally just remove the lesson
+ d->m_lessons.removeAt(lessonIndex);
- int currentInQuery = d->m_lessonsInQuery.indexOf( lessonIndex );
- if ( currentInQuery != -1 )
- d->m_lessonsInQuery.removeAt( currentInQuery );
-
- // move query entries
- for ( int queryLesson = 0; queryLesson < d->m_lessonsInQuery.count(); queryLesson++ ) {
- if ( d->m_lessonsInQuery.at( queryLesson ) > lessonIndex )
- d->m_lessonsInQuery.replace( queryLesson, d->m_lessonsInQuery.at( queryLesson )-1 );
- }
return true;
}
/** get all lesson objects
* @returns a map of pointers to lesson objects
*/
- QMap<int, KEduVocLesson> & lessons() const;
+ QList<KEduVocLesson> & lessons() const;
/**
* @returns the number of lessons defined
*/
int lessonCount() const;
- /**
+ /** DEPRECATED - USE lesson.inQuery();
* Get list of ALL lessons that are selected for query.
* @returns a list with the lessons in the current query
*/
QList<int> lessonsInQuery() const;
- /**
+ /** DEPRECATED - USE lesson.setInQuery();
* Sets ALL lessons in the query. Better use addLessonToQuery and removeLessonFromQuery.
*/
void setLessonsInQuery( const QList<int> &lesson_iq );
- /**
+ /** DEPRECATED - USE lesson.inQuery();
* Check if @p lessonIndex is in the query.
* @param lessonIndex - index of the lesson
* @return true if in query
*/
bool lessonInQuery( int lessonIndex ) const;
- /**
+ /** DEPRECATED - USE lesson.setInQuery();
* Add @p lessonIndex to the query.
* @param lessonIndex - index of the lesson
*/
void addLessonToQuery( int lessonIndex );
- /**
+ /** DEPRECATED - USE lesson.setInQuery();
* Remove @p lessonIndex from the query.
* @param lessonIndex - index of the lesson
*/
/**
* Append a new lesson to the list of lessons.
* @param lessonName name for the new lesson
- * @param position lesson number to use (-1 to find the next hole to put it in)
* @returns the index of the new lesson
*/
- int addLesson( const QString &lessonName, int position = -1 );
+ int appendLesson( const QString &lessonName, bool inQuery=true );
/**
* Delete a lesson.
*/
bool deleteLesson( int lessonIndex, int deleteMode );
- ///**
- // * Get the real name of a lesson from it's index as QString.
- // * @param index lesson index
- // * @returns the description (Name) of the lesson with index @p index .
- // */
- //QString lessonDescription(int index) const;
-
- /**
- * Get the index from the long name of a lesson.
- * @param description lesson name
- * @returns the index of the lesson (from its name)
- * -1 if the lesson does not exist
- */
- //int lessonIndex(const QString &description) const;
-
- /**
- * Rename a lesson.
- * @param lessonIndex index of lesson
- * @param lessonName new name for the lesson
- */
- //void renameLesson(const int lessonIndex, const QString &lessonName);
-
- /**
+ /** DEPRECATED
* All lesson descriptions as stringlist.
* @returns a list of defined lessons
*/
QStringList lessonNames() const;
- /**
- * Sets the description of the lesson
- * @param names list of all names of the lessons
- */
- //void setLessonDescriptions(const QStringList &names);
-
- /**
+ /** @todo implement this?
* Moves the lesson at index position from to index position to.
* @param from the lesson to be moved
* @param to the new position
*/
- //void moveLesson(int from, int to);
+ void moveLesson(int from, int to);
// *** file format specific methods ***
m_inQuery = false;
m_active = true;
- m_lesson = 0;
+ m_lesson = -1;
m_sortIndex = 0;
m_sizeHint = 0;
}
*/
explicit KEduVocExpression();
- /** Constructor for a vocabulary expression with an original
+ /** Constructor for a vocabulary expression with one translation
*
- * @param expression original
- * @param lesson lesson number, 0 for none
+ * @param expression translation
+ * @param lesson lesson number
*/
- explicit KEduVocExpression( const QString & expression, int lesson = 0 );
+ explicit KEduVocExpression( const QString & expression, int lesson = -1 );
/** Constructor for a vocabulary expression with an original and one or more translations
*
* @param separator expression will be split into an original and one or more translations using separator
* @param lesson lesson number, 0 for none
*/
- KEduVocExpression( const QStringList & translations, int lesson = 0 );
+ KEduVocExpression( const QStringList & translations, int lesson = -1 );
KEduVocExpression( const KEduVocExpression &expression );
~KEduVocExpression();
- /** returns index of lesson (0 = none)
+ /** returns index of lesson (-1 = none)
*/
int lesson() const;
- /** sets index of lesson (0 = none)
+ /** sets index of lesson (-1 = none)
*/
void setLesson( int l );
bool result = readGroups( domElementKvtml ); // read sub-groups
- int defaultLessonNumber = m_doc->addLesson(i18n("Default Lesson"));
-
- // now make sure we don't have any orphan entries (lesson 0)
- for (int i = 0; i < m_doc->entryCount(); ++i)
- {
- if (m_doc->entry(i)->lesson() == 0)
- {
- m_doc->entry(i)->setLesson(defaultLessonNumber);
- m_doc->lesson(defaultLessonNumber).addEntry(i);
- }
- }
-
- if (m_doc->lesson(defaultLessonNumber).entries().size() == 0)
- {
- m_doc->deleteLesson(defaultLessonNumber, KEduVocDocument::DeleteEmptyLesson);
- }
-
return result;
}
groupElement = domElementParent.firstChildElement( KVTML_ENTRIES );
if ( !groupElement.isNull() ) {
QDomNodeList entryList = groupElement.elementsByTagName( KVTML_ENTRY );
- if ( entryList.length() <= 0 ) {
- m_errorMessage = i18n( "no entries found in 'entries' tag" );
- return false; // at least one entry is required
- }
-
for ( int i = 0; i < entryList.count(); ++i ) {
currentElement = entryList.item( i ).toElement();
if ( currentElement.parentNode() == groupElement ) {
{
// NOTE: currently this puts an identifier into the last lesson it is in, once support for multiple lessons
// is in the entry class, all lessons that include an entry will be in there
- int lessonId = 0;
-
+ int lessonId;
//<name>Lesson name</name>
QDomElement currentElement = lessonElement.firstChildElement( KVTML_NAME );
if ( !currentElement.isNull() ) {
- lessonId = m_doc->addLesson( currentElement.text() );
+ lessonId = m_doc->appendLesson( currentElement.text() );
} else {
m_errorMessage = i18n( "each lesson must have a name" );
return false;
//<query>true</query>
currentElement = lessonElement.firstChildElement( KVTML_QUERY );
if ( !currentElement.isNull() ) {
- if ( currentElement.text() == KVTML_TRUE ) {
- m_doc->addLessonToQuery( lessonId );
- }
+ m_doc->lesson(lessonId).setInQuery(currentElement.text() == KVTML_TRUE);
}
//<current>true</current>
bool KEduVocKvtml2Writer::writeLessons( QDomElement &lessonsElement )
{
- if ( m_doc->lessonCount() == 0 )
- return true;
-
- QMap<int, KEduVocLesson> lessons = m_doc->lessons();
-
- foreach( int lessonid, lessons.keys() ) {
- KEduVocLesson thisLesson = lessons[lessonid];
-
+ for( int lessonId = 0; lessonId < m_doc->lessonCount(); lessonId++ ) {
// make lesson element
QDomElement thisLessonElement = m_domDoc.createElement( KVTML_LESSON );
// add a name
- thisLessonElement.appendChild( newTextElement( KVTML_NAME, thisLesson.name() ) );
+ thisLessonElement.appendChild( newTextElement( KVTML_NAME, m_doc->lesson(lessonId).name() ) );
// add a inquery tag
- thisLessonElement.appendChild( newTextElement( KVTML_QUERY, m_doc->lessonInQuery( lessonid ) ? KVTML_TRUE : KVTML_FALSE ) );
+ if ( m_doc->lesson(lessonId).inQuery() ) {
+ thisLessonElement.appendChild( newTextElement( KVTML_QUERY, KVTML_TRUE ) );
+ }
// add a current tag
- thisLessonElement.appendChild( newTextElement( KVTML_CURRENT, m_doc->currentLesson() == lessonid ? KVTML_TRUE : KVTML_FALSE ) );
+ if ( lessonId == m_doc->currentLesson() ) {
+ thisLessonElement.appendChild( newTextElement( KVTML_CURRENT, KVTML_TRUE ) );
+ }
// TODO: add the entryids...
for ( int i = 0; i < m_doc->entryCount(); ++i ) {
- if ( m_doc->entry( i )->lesson() == lessonid ) {
+ if ( m_doc->entry( i )->lesson() == lessonId ) {
thisLessonElement.appendChild( newTextElement( KVTML_ENTRYID, QString::number( i ) ) );
}
}
if ( entryList.length() <= 0 )
return false;
- QList<int> inQueryList;
-
for ( int i = 0; i < entryList.count(); ++i ) {
currentElement = entryList.item( i ).toElement();
if ( currentElement.parentNode() == domElementParent ) {
- int no = 0;
+ int no;
bool isCurr = false;
attribute = currentElement.attributeNode( KV_LESS_NO );
- if ( !attribute.isNull() )
+ if ( !attribute.isNull() ) {
no = attribute.value().toInt();
+ }
attribute = currentElement.attributeNode( KV_LESS_CURR );
- if ( !attribute.isNull() )
- isCurr = attribute.value().toInt() != 0;
-
- if ( isCurr && no != 0 )
- m_doc->setCurrentLesson( no );
+ if ( !attribute.isNull() ) {
+ if ( attribute.value().toInt() != 0 ) {
+ m_doc->setCurrentLesson( no );
+ }
+ }
+ bool inQuery;
attribute = currentElement.attributeNode( KV_LESS_QUERY );
- if ( !attribute.isNull() )
- if ( attribute.value().toInt() != 0 && no > 0 )
- inQueryList.append( no );
+ if ( !attribute.isNull() ) {
+ inQuery = attribute.value().toInt() != 0;
+ }
s = currentElement.text();
- if ( s.isNull() )
- s = "";
- m_doc->addLesson( s, no );
+ int index = m_doc->appendLesson( s, inQuery );
+ if ( index != no-1 ) {
+ kDebug() << "Warning! Lesson order may be confused. Are all lessons in order in the file?";
+ }
}
}
- if ( inQueryList.count() > 0 )
- m_doc->setLessonsInQuery( inQueryList );
-
return true;
}
QString q_org;
QString q_trans;
QString query_id;
- int lesson = 0;
+ int lesson = - 1;
int width;
QString type;
QString subType;
attribute = domElementParent.attributeNode( KV_LESS_MEMBER );
if ( !attribute.isNull() ) {
- lesson = attribute.value().toInt();
- }
-
- if ( lesson && lesson > m_doc->lessonCount() ) {
- // it's from a lesson that hasn't been added yet
- // so make sure this lesson is in the document
- m_doc->addLesson( QString( "#" ) + QString::number( lesson ), lesson );
+ // we start conting from 0 in new documents
+ lesson = attribute.value().toInt() - 1;
+ if ( lesson > m_doc->lessonCount() ) {
+ ///@todo can this happen? does it need a while loop?
+ // it's from a lesson that hasn't been added yet
+ // so make sure this lesson is in the document
+ kDebug() << "Warning: lesson > m_doc->lessonCount() in readExpression.";
+ m_doc->appendLesson( i18nc("A generic name for a new lesson and its number.", "Lesson %1" ), lesson );
+ }
}
attribute = domElementParent.attributeNode( KV_SELECTED );
i++;
}
- if ( m_doc->entryCount() == 0 )
+ if ( m_doc->entryCount() == 0 ) {
m_doc->setQueryIdentifier( q_org, q_trans );
+ }
m_doc->appendEntry( &expr );
// also add this entryid to the lesson it's part of
- m_doc->lesson( lesson ).addEntry( m_doc->entryCount() );
+ if ( lesson >= 0 ) {
+ m_doc->lesson( lesson ).addEntry( m_doc->entryCount() );
+ }
return true;
}
QDomElement domElementLesson = domDoc.createElement( KV_LESS_GRP );
domElementLesson.setAttribute( KV_SIZEHINT, m_doc->sizeHint( -1 ) );
- QMap<int, KEduVocLesson> lessons = m_doc->lessons();
- QList<int> keys = lessons.keys();
- for ( int i = 0; i < keys.size(); ++i ) {
- int thiskey = keys[i];
+ for ( int i = 0; i < m_doc->lessonCount(); ++i ) {
QDomElement domElementDesc = domDoc.createElement( KV_LESS_DESC );
- QDomText domTextDesc = domDoc.createTextNode( lessons[thiskey].name() );
+ QDomText domTextDesc = domDoc.createTextNode( m_doc->lesson(i).name() );
- domElementDesc.setAttribute( KV_LESS_NO, thiskey );
- if ( m_doc->currentLesson() == thiskey )
+ domElementDesc.setAttribute( KV_LESS_NO, i );
+ if ( m_doc->currentLesson() == i ) {
domElementDesc.setAttribute( KV_LESS_CURR, 1 );
- if ( m_doc->lessonInQuery( thiskey ) )
+ }
+ if ( m_doc->lesson(i).inQuery() ) {
domElementDesc.setAttribute( KV_LESS_QUERY, 1 );
-
+ }
domElementDesc.appendChild( domTextDesc );
domElementLesson.appendChild( domElementDesc );
}
public:
QSet<int> m_entries;
QString m_name;
+ bool m_inQuery;
};
KEduVocLesson::KEduVocLesson()
{
d->m_entries.remove( entryid );
}
+
+bool KEduVocLesson::inQuery()
+{
+ return d->m_inQuery;
+}
+
+void KEduVocLesson::setInQuery(bool inQuery)
+{
+ d->m_inQuery = inQuery;
+}
* @param entryid id of the entry to remove
*/
void removeEntry( int entryid );
-
+
+ bool inQuery();
+ void setInQuery( bool inQuery );
+
/** equality operator */
bool operator==(const KEduVocLesson &other);
kve.setTranslation( 1, translation );
kve.translation( 1 ).gradeFrom( 0 ).setGrade( 0 );
kve.translation( 0 ).gradeFrom( 1 ).setGrade( 0 );
+ /// @todo lesson might need a -1. I have no specs or documents to verify.
kve.setLesson( lesson );
m_doc->appendEntry( &kve );
lessonDescr = inputStream.readLine();
lessonDescr = lessonDescr.mid( 1, lessonDescr.length() - 2 );
if ( !lessonDescr.isEmpty() )
- m_doc->addLesson( lessonDescr );
+ m_doc->appendLesson( lessonDescr );
else
break;
inputStream.readLine();