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

List:       kde-commits
Subject:    KDE/kdegames/kpat
From:       Parker Coates <parker.coates () kdemail ! net>
Date:       2012-02-15 4:44:59
Message-ID: 20120215044459.72AB5AC895 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1280165 by coates:

Convert DealerScene::openGame() from QDomDocument to QXmlStreamReader.

 M  +76 -38    dealer.cpp  
 M  +1 -1      dealer.h  
 M  +6 -1      mainwindow.cpp  


--- trunk/KDE/kdegames/kpat/dealer.cpp #1280164:1280165
@@ -60,10 +60,9 @@
 #include <QtCore/QString>
 #include <QtCore/QThread>
 #include <QtCore/QTimer>
+#include <QtCore/QXmlStreamReader>
 #include <QtCore/QXmlStreamWriter>
 #include <QtGui/QGraphicsSceneMouseEvent>
-#include <QtGui/QPainter>
-#include <QtXml/QDomDocument>
 
 #include <cmath>
 
@@ -111,7 +110,13 @@
             return QString();
         }
     }
+
+    int readIntAttribute( const QXmlStreamReader & xml, const QString & key, bool * ok = 0 )
+    {
+        QStringRef value = xml.attributes().value( key );
+        return QString::fromRawData( value.data(), value.length() ).toInt( ok );
 }
+}
 
 
 class SolverThread : public QThread
@@ -256,17 +261,14 @@
     d->gameWasJustSaved = true;
 }
 
-void DealerScene::openGame( QIODevice * io )
+bool DealerScene::openGame( QIODevice * io )
 {
     resetInternals();
 
-    QDomDocument doc;
-    doc.setContent( io );
+    QXmlStreamReader xml( io );
 
-    QDomElement dealer = doc.documentElement();
+    xml.readNextStartElement();
 
-    QString options = dealer.attribute("options");
-
     // Before KDE4.3, KPat didn't store game specific options in the save
     // file. This could cause crashes when loading a Spider game with a
     // different number of suits than the current setting. Similarly, in 
@@ -274,64 +276,100 @@
     // this never caused crashes. Fortunately, in Spider we can count the
     // number of suits ourselves. For Klondike, there is no way to recover
     // that information.
+    QString options = xml.attributes().value( "options" ).toString();
     if (gameId() == 17 && options.isEmpty())
     {
         QSet<int> suits;
-        QDomNodeList cardElements = dealer.elementsByTagName("card");
-        for (int i = 0; i < cardElements.count(); ++i)
-            suits.insert(cardElements.item(i).toElement().attribute("suit").toInt());
-        options = QString::number(suits.count());
+        while ( !xml.atEnd() )
+            if ( xml.readNextStartElement() && xml.name() == "card" )
+                suits << readIntAttribute( xml, "suit" );
+        options = QString::number( suits.size() );
+
+        // "Rewind" back to the <dealer> tag. Yes, this is ugly.
+        xml.clear();
+        io->reset();
+        xml.setDevice( io );
+        xml.readNextStartElement();
     }
-
     setGameOptions(options);
-    d->gameNumber = dealer.attribute("number").toInt();
-    d->loadedMoveCount = dealer.attribute("moves").toInt();
-    d->gameStarted = bool(dealer.attribute("started").toInt());
 
-    QDomNodeList pileNodes = dealer.elementsByTagName("pile");
+    d->gameNumber = readIntAttribute( xml, "number" );
+    d->loadedMoveCount = readIntAttribute( xml, "moves" );
+    d->gameStarted = readIntAttribute( xml, "started" );
+    QString gameStateData = xml.attributes().value( "data" ).toString();
 
     QMultiHash<quint32,KCard*> cards;
     foreach ( KCard * c, deck()->cards() )
         cards.insert( (c->id() & 0xffff), c );
 
+    QHash<int,PatPile*> piles;
     foreach (PatPile *p, patPiles())
+        piles.insert( p->index(), p );
+
+    // Loop through <pile>s.
+    while ( xml.readNextStartElement() )
     {
+        if ( xml.name() != "pile" )
+        {
+            kWarning() << "Expected a \"pile\" tag. Found a" << xml.name() << "tag.";
+            return false;
+        }
+
+        bool ok;
+        int index = readIntAttribute( xml, "index", &ok );
+        QHash<int,PatPile*>::const_iterator it = piles.find( index );
+        if ( !ok || it == piles.constEnd() )
+        {
+            kWarning() << "Unrecognized pile index:" << xml.attributes().value( "index" );
+            return false;
+        }
+
+        PatPile * p = it.value();
         p->clear();
-        for (int i = 0; i < pileNodes.count(); ++i)
+
+        // Loop through <card>s.
+        while ( xml.readNextStartElement() )
         {
-            QDomElement pile = pileNodes.item(i).toElement();
-            if (pile.attribute("index").toInt() == p->index())
+            if ( xml.name() != "card" )
             {
-                QDomNodeList cardNodes = pile.elementsByTagName("card");
-                for (int j = 0; j < cardNodes.count(); ++j)
+                kWarning() << "Expected a \"card\" tag. Found a" << xml.name() << "tag.";
+                return false;
+            }
+            
+            bool suitOk, rankOk, faceUpOk;
+            int suit = readIntAttribute( xml, "suit", &suitOk );
+            int rank = readIntAttribute( xml, "value", &rankOk );
+            bool faceUp = readIntAttribute( xml, "faceup", &faceUpOk );
+            
+            quint32 id = KCardDeck::getId( KCardDeck::Suit( suit ), KCardDeck::Rank( rank ), 0 );
+            KCard * card = cards.take( id );
+
+            if ( !suitOk || !rankOk || !faceUpOk || !card )
                 {
-                    QDomElement card = cardNodes.item(j).toElement();
-                    int s = card.attribute("suit").toInt();
-                    int r = card.attribute("value").toInt();
+                kWarning() << "Unrecognized card: suit=" << xml.attributes().value("suit")
+                           << " value=" << xml.attributes().value("value")
+                           << " faceup=" << xml.attributes().value("faceup");
+                return false;
+            }
                     
-                    KCard * c = cards.take( ( s << 8 ) + r );
-                    if (!c)
-                        continue;
+            card->setFaceUp( faceUp );
+            p->add( card );
 
-                    c->setFaceUp(card.attribute("faceup").toInt());
-                    p->add(c);
+            xml.skipCurrentElement();
                 }
-                break;
-            }
-        }
         updatePileLayout( p, 0 );
     }
-    setGameState( dealer.attribute("data") );
 
+    setGameState( gameStateData );
+
+
     emit updateMoves( moveCount());
+    takeState();
 
-    takeState();
+    return true;
 }
 
-// ================================================================
-//                         class DealerScene
 
-
 DealerScene::DealerScene()
 {
     setItemIndexMethod(QGraphicsScene::NoIndex);
--- trunk/KDE/kdegames/kpat/dealer.h #1280164:1280165
@@ -110,7 +110,7 @@
     int moveCount() const;
 
     void saveGame( QIODevice * io );
-    void openGame( QIODevice * io );
+    bool openGame( QIODevice * io );
     virtual void mapOldId(int id);
     virtual int oldId() const;
     void recordGameStatistics();
--- trunk/KDE/kdegames/kpat/mainwindow.cpp #1280164:1280165
@@ -871,7 +871,12 @@
     file.reset();
 
     setGameType( gameId );
-    m_dealer->openGame( &file );
+    if ( !m_dealer->openGame( &file ) )
+    {
+        KMessageBox::error( this, i18n("Errors encountered while parsing file.") );
+        slotShowGameSelectionScreen();
+        return false;
+    }
 
     file.close();
 
[prev in list] [next in list] [prev in thread] [next in thread] 

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