[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-edu-devel
Subject:    Re: [kde-edu-devel] Data files for KVocTrain
From:       Ewald Arnold <kvoctrain () ewald-arnold ! de>
Date:       2002-04-19 9:23:07
[Download RAW message or body]

Hello Scott,

> FlashKard.  It would be nice to have a central repository for contributed
> files.  Since potentially a lot of people would want to study similar
> things, this would allow time savings on data entry.  I have a couple of
> English -> German files that I use (and maybe some English -> Spanish) that
> could be contributed.

nice to read that there are some pending files :-) Since I have some spare time and \
was curious to test your app I played a bit with it. Some months ago you wrote that \
you intend to use my file format. Unfortunately it did not work immediately and I had \
to add some bits to your files. I also had to fix some flaws in my xml code.

Most important is to notify the user that he will lose data if he saves a kvtml file \
from kvoc with flashkard as you only use the most important tags. A workaround might \
be the use of a DOM interface in FK because DOM would keep the complete structure. I \
also changed the file suffix from "kvml" to "kvtml" (a typo?). Find a diff and the \
modified files attached.

As far as I can see now, it would be a good idea to place all the kvtml files under \
contrib/kvtml. Both apps can read and process them after the changes. The only \
problem is changing the apps and the users should be informed about the possible \
problems in advance. 

I suggest to place a html file in contrib/kvtml which lists all the available files \
and adds comments about the content as well as the above warning. In \
edu.kde.org/app-name/index.html there should be links that lead to this common html \
file.

cheers
Ewald

-- 
Ewald Arnold, Germany
http://www.ewald-arnold.de/
mailto:ewald at ewald-arnold.de
mobil/sms:+49-162-8001240


["flashkard.cpp" (text/x-c++src)]

/***************************************************************************
                           flashkard.cpp  -  description
                             -------------------
    begin                : Tue Feb 12 00:09:29 EST 2002
    copyright            : (C) 2002 by Scott Wheeler
    email                : scott@slackorama.net
***************************************************************************/

/***************************************************************************
 *   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.                                   *
***************************************************************************/

#include <klocale.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include <kdebug.h>

#include <qxml.h>
#include <qfile.h>

#include "flashkard.h"
#include "flashkard.moc"
#include "guesswidget.h"
#include "flashcardswidget.h"
#include "card.h"
#include "xmlparser.h"
#include "xmlwriter.h"

FlashKard::FlashKard(QWidget *parent, const char *name) : KMainWindow(parent, name)
{
  data = 0;
  quiz = 0;
  randomQuiz = true;
  changed = false;
  fileName = QString::null;
  fileMask = "*.kvtml";

  setupActions();
  setupLayout();
  setupQuizMode();
}

FlashKard::~FlashKard()
{
}

////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

void FlashKard::dataChanged()
{
  QFileInfo fileInfo(fileName);
  setCaption(fileInfo.fileName(), true);
  changed = true;
}

////////////////////////////////////////////////////////////////////////////////
// private member implementations
////////////////////////////////////////////////////////////////////////////////

void FlashKard::setupActions()
{
  // file menu
  KStdAction::openNew(this, SLOT(fileNew()), actionCollection());
  KStdAction::open(this, SLOT(fileOpen()), actionCollection());
  KStdAction::save(this, SLOT(fileSave()), actionCollection());
  KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
  KStdAction::quit(this, SLOT(quit()), actionCollection()); 

  // edit menu
  KStdAction::cut(this, SLOT(cut()), actionCollection());
  KStdAction::copy(this, SLOT(copy()), actionCollection());
  KStdAction::paste(this, SLOT(paste()), actionCollection());
  KStdAction::selectAll(this, SLOT(selectAll()), actionCollection());
  
  // function menu
  showDataAction = new KAction(i18n("Data Entry"), "edit", 0, this, SLOT(showData()), \
actionCollection(), "showData");  showQuizAction = new KAction(i18n("Quiz"), "quiz", \
0, this, SLOT(showQuiz()), actionCollection(), "showQuiz");

  // settings menu

  // "Quiz Mode" sub menu
  quizModeAction = new KSelectAction(i18n("Quiz Mode"), 0, actionCollection(), \
"selectQuizMode");    QStringList quizModeItems;
  quizModeItems << "Flash Cards" << "Random Order Quiz" << "Ordered Quiz";
  quizModeAction->setItems(quizModeItems);
  connect(quizModeAction, SIGNAL(activated(int)), this, SLOT(changeQuizMode(int)));

  createGUI();
}

void FlashKard::setupLayout()
{
  setAutoSaveSettings();
  data = new DataWidget(this, "data");

  connect(data, SIGNAL(dataChanged()), this, SLOT(dataChanged()));

  showData();
}

void FlashKard::setupQuizMode()
{
  // insert some logic here to preservere quiz mode preference
  if(quizModeAction) { 
    quizModeAction->setCurrentItem(0);
    changeQuizMode(0);
  }
}

bool FlashKard::saveChangesPrompt()
{
  if(changed) {
    const QString message = i18n("You have made changes to the current deck since \
saving.\n"  "Do you want to save your changes?");    
    int action = KMessageBox::warningYesNoCancel(this, message);
    switch(action) {
    case KMessageBox::Yes:
      fileSave();
      return(true);
      break;
    case KMessageBox::No:
      return(true);
      break;
    case KMessageBox::Cancel:
      return(false);
      break;
    default:
      return(false);
      break;
    }
  }
  else {
    return(true);
  }
}

void FlashKard::dataCurrent()
{
  QFileInfo fileInfo(fileName);
  setCaption(fileInfo.fileName(), false);
  changed = false;  
}

////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////

// file menu

void FlashKard::fileNew()
{
  if(saveChangesPrompt()) {
    data->clear();
    showData();

    fileName = QString::null;
    dataCurrent();
  }
}

void FlashKard::fileOpen()
{
  if(saveChangesPrompt()) {
    
    data->clear();
    QStringList files = KFileDialog::getOpenFileNames(QString::null, fileMask, this, \
i18n("Open Deck(s)"));  CardList *list = new CardList();
    for(QStringList::Iterator it = files.begin(); it != files.end(); it++) {
      XMLParser *handler = new XMLParser(list);
      QFile input(*it);
      QXmlInputSource source(input);
      QXmlSimpleReader reader;
      reader.setContentHandler(handler);
      if (!reader.parse(source))
        KMessageBox::sorry(0, handler->errorString(), "Problem while reading document \
file");  }

    data->loadCards(list);
    showData();
    
    if(files.count() == 1)
      fileName = files.first();
    else
      fileName = QString::null;

    dataCurrent();
  }
}

void FlashKard::fileSave()
{
  QFileInfo fileInfo(fileName);

  if(!(fileInfo.fileName()).isEmpty()) {
    QFileInfo dirInfo(fileInfo.dirPath());
    
    if( (fileInfo.isFile() && fileInfo.isWritable()) || (!fileInfo.exists() && \
dirInfo.isWritable()) ) {  QFile *output = new QFile(fileName);
      XMLWriter handler(output);
      
      CardList *cards = data->getCardList();
      kdDebug() << "got card list" << endl;
      for(CardList::Iterator it = cards->begin(); it != cards->end(); it++) {
	handler.addItem((*it).front(), (*it).back());
      }  
      setCaption(fileInfo.fileName(), false);
      dataCurrent();
    }
    else {
      KMessageBox::sorry(this, i18n("Could not write to ") + fileInfo.fileName(), \
i18n("FlashKard"));  }
  }
  else {
    fileSaveAs();
  }
}

void FlashKard::fileSaveAs()
{
  fileName = KFileDialog::getSaveFileName(QString::null, fileMask, this, \
QString::null);  if(!fileName.isEmpty())
    fileSave();
}

void FlashKard::quit()
{
  kapp->quit();
}


void FlashKard::showData()
{
  statusBar()->hide();

  showQuizAction->setEnabled(true);
  showDataAction->setEnabled(false);
  
  if(quiz)
    quiz->hide();
  
  data->show();
  setCentralWidget(data);
}

void FlashKard::showQuiz()
{
  CardList *list = data->getCardList();
  if(!list->isEmpty()) {
    if(quiz) {
      statusBar()->show();
      
      showQuizAction->setEnabled(false);
      showDataAction->setEnabled(true);
      
      quiz->setCardList(list);
      
      data->hide();
      quiz->show();
      setCentralWidget(quiz);
      quiz->getCard(randomQuiz);
    }
  }
  else { 
    KMessageBox::sorry( this, i18n("You don't have any cards defined."), \
i18n("FlashKard"));  }
}

void FlashKard::changeQuizMode(int id)
{
  bool visible = false;

  if(quiz) {
    if(quiz->isVisible())
      visible = true;
    delete(quiz);
  }
  
  kdDebug() << "changeQuizMode() : " << id << endl;
  
  switch(id) {
  case 0: // flash cards
    quiz = new FlashCardsWidget(statusBar(), this);
    randomQuiz = true;
    break;
  case 1: // random quiz
    quiz = new GuessWidget(statusBar(), true, this);
    randomQuiz = true;
    break;
  case 2: // ordered quiz
    quiz = new GuessWidget(statusBar(), false, this);
    randomQuiz = false;
    break;
  default: // none of the above
    quiz = 0;
    break;
  }

  if(visible) 
    showQuiz();
  else
    showData();
}


["xmlparser.cpp" (text/x-c++src)]

/***************************************************************************
                           xmlparser.cpp  -  description
                             -------------------
    begin                : Tue Feb 12 2002
    copyright            : (C) 2002 by Scott Wheeler
    email                : scott@slackorama.net
***************************************************************************/

/***************************************************************************
 *   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.                                   *
***************************************************************************/

#include "xmlparser.h"

#include <klocale.h>
#include <kmessagebox.h>

XMLParser::XMLParser(CardList *list)
{
  cardList=list;
  warnedKvtml = false;
}

bool XMLParser::startDocument()
{
  return true;
}

bool XMLParser::endDocument()
{
  return true;
}

bool XMLParser::checkContinue()
{
  if (!warnedKvtml)
  {
    warnedKvtml = true;  // warn only once
    QString msg = i18n(
      "The current document seems to be created by KVocTrain.\n"
      "Since flashcard cannot process all properties from this file format"
      " it will ignore some of them.\n"
      "If you save this document with flashkard later you are likely to loose data!\n"
      "Do you really want to continue loading?"
    );

    QString cap = (i18n("Problem with document format"));

    return (   KMessageBox::warningContinueCancel(0, msg, cap)
            == KMessageBox::Continue);
  }
}

bool XMLParser::startElement(const QString&, const QString&,
                             const QString& element, const QXmlAttributes & attr)
{

  if (!warnedKvtml && attr.length() != 0)
    if (!checkContinue() )
       return false;

  lastElement=element;
  return true;
}

bool XMLParser::endElement(const QString&, const QString&, const QString&)
{
  lastElement=QString::null;
  return true;
}

bool XMLParser::characters( const QString& content )
{
  if(lastElement=="o")
    {
      front=content;
    }
  else if(lastElement=="t")
    {
      cardList->append(Card(front, content));
    }
  else if(lastElement=="kvtml")
    {
      // ignore top level tag
    }
  else if(lastElement=="e")
    {
      // ignore entry group tag
    }
  else if(lastElement=="")
    {
      // ignore empty block ??
    }
  else
    {
      if (!warnedKvtml && !checkContinue() )
         return false;
    }
  return true;
}


bool XMLParser::processingInstruction(const QString &target, const QString &data)
{
//  KMessageBox::information(0, data, target);
  return true;
}

["xmlparser.h" (text/x-chdr)]

/***************************************************************************
                           xmlparser.h  -  description
                             -------------------
    begin                : Tue Feb 12 2002
    copyright            : (C) 2002 by Scott Wheeler
    email                : scott@slackorama.net
***************************************************************************/

/***************************************************************************
 *   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.                                   *
***************************************************************************/

#ifndef XMLPARSER_H
#define XMLPARSER_H

#include <qstring.h>
#include <qxml.h>

#include "card.h"

class XMLParser : public QXmlDefaultHandler
{
 public:
  XMLParser(CardList *list);
  bool startDocument();
  bool endDocument();
  bool startElement(const QString&, const QString&, const QString& element, const QXmlAttributes&);
  bool endElement(const QString&, const QString&, const QString&);
  bool processingInstruction(const QString &target, const QString &data);
  bool characters(const QString& content);

 private:
  bool checkContinue();

  bool      warnedKvtml;
  CardList *cardList;
  QString lastElement, front;
};

#endif

["fk.diff" (text/x-diff)]

Index: flashkard.cpp
===================================================================
RCS file: /home/kde/kdeedu/flashkard/flashkard/flashkard.cpp,v
retrieving revision 1.3
diff -u -3 -p -r1.3 flashkard.cpp
--- flashkard.cpp	2002/04/18 17:23:11	1.3
+++ flashkard.cpp	2002/04/19 08:29:34
@@ -36,7 +36,7 @@ FlashKard::FlashKard(QWidget *parent, co
   randomQuiz = true;
   changed = false;
   fileName = QString::null;
-  fileMask = "*.kvml";
+  fileMask = "*.kvtml";
 
   setupActions();
   setupLayout();
@@ -176,7 +176,8 @@ void FlashKard::fileOpen()
       QXmlInputSource source(input);
       QXmlSimpleReader reader;
       reader.setContentHandler(handler);
-      reader.parse(source);
+      if (!reader.parse(source))
+        KMessageBox::sorry(0, handler->errorString(), "Problem while reading \
document file");  }
 
     data->loadCards(list);
Index: xmlparser.cpp
===================================================================
RCS file: /home/kde/kdeedu/flashkard/flashkard/xmlparser.cpp,v
retrieving revision 1.1
diff -u -3 -p -r1.1 xmlparser.cpp
--- xmlparser.cpp	2002/04/11 07:29:42	1.1
+++ xmlparser.cpp	2002/04/19 08:29:34
@@ -15,9 +15,13 @@
 
 #include "xmlparser.h"
 
+#include <klocale.h>
+#include <kmessagebox.h>
+
 XMLParser::XMLParser(CardList *list)
 {
   cardList=list;
+  warnedKvtml = false;
 }
 
 bool XMLParser::startDocument()
@@ -29,9 +33,35 @@ bool XMLParser::endDocument()
 {
   return true;
 }
+
+bool XMLParser::checkContinue()
+{
+  if (!warnedKvtml)
+  {
+    warnedKvtml = true;  // warn only once
+    QString msg = i18n(
+      "The current document seems to be created by KVocTrain.\n"
+      "Since flashcard cannot process all properties from this file format"
+      " it will ignore some of them.\n"
+      "If you save this document with flashkard later you are likely to loose \
data!\n" +      "Do you really want to continue loading?"
+    );
+
+    QString cap = (i18n("Problem with document format"));
+
+    return (   KMessageBox::warningContinueCancel(0, msg, cap)
+            == KMessageBox::Continue);
+  }Scott Wheeler <wheeler@kde.org>
+}
 
-bool XMLParser::startElement(const QString&, const QString&, const QString& element, \
const QXmlAttributes&) +bool XMLParser::startElement(const QString&, const QString&,
+                             const QString& element, const QXmlAttributes & attr)
 {
+
+  if (!warnedKvtml && attr.length() != 0)
+    if (!checkContinue() )
+       return false;
+
   lastElement=element;
   return true;
 }
@@ -52,5 +82,29 @@ bool XMLParser::characters( const QStrin
     {
       cardList->append(Card(front, content));
     }
+  else if(lastElement=="kvtml")
+    {
+      // ignore top level tag
+    }
+  else if(lastElement=="e")
+    {
+      // ignore entry group tag
+    }
+  else if(lastElement=="")
+    {
+      // ignore empty block ??
+    }
+  else
+    {
+      if (!warnedKvtml && !checkContinue() )
+         return false;
+    }
+  return true;
+}
+
+
+bool XMLParser::processingInstruction(const QString &target, const QString &data)
+{
+//  KMessageBox::information(0, data, target);
   return true;
 }
Index: xmlparser.h
===================================================================
RCS file: /home/kde/kdeedu/flashkard/flashkard/xmlparser.h,v
retrieving revision 1.1
diff -u -3 -p -r1.1 xmlparser.h
--- xmlparser.h	2002/04/11 07:29:42	1.1
+++ xmlparser.h	2002/04/19 08:29:34
@@ -29,9 +29,13 @@ class XMLParser : public QXmlDefaultHand
   bool endDocument();
   bool startElement(const QString&, const QString&, const QString& element, const \
QXmlAttributes&);  bool endElement(const QString&, const QString&, const QString&);
-  
+  bool processingInstruction(const QString &target, const QString &data);
   bool characters(const QString& content);
+
  private:
+  bool checkContinue();
+
+  bool      warnedKvtml;
   CardList *cardList;
   QString lastElement, front;
 };


_______________________________________________
kde-edu-devel mailing list
kde-edu-devel@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-edu-devel

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic