changeset 140:9ccaa8fd9b9f

* Add code to identify (usually) the type of an XML file that contains either SV session or layer data, and use it to permit loading files with plain .xml extension that contain complete uncompression sessions
author Chris Cannam
date Thu, 20 Nov 2008 10:59:14 +0000
parents 2cf711ed89e2
children 9a8c73ffdce0
files framework/MainWindowBase.cpp framework/SVFileReader.cpp framework/SVFileReader.h
diffstat 3 files changed, 153 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/framework/MainWindowBase.cpp	Wed Nov 19 14:55:17 2008 +0000
+++ b/framework/MainWindowBase.cpp	Thu Nov 20 10:59:14 2008 +0000
@@ -1157,7 +1157,10 @@
 
         return FileOpenFailed;
 
-    } else if (source.getExtension() == "svl" || source.getExtension() == "xml") {
+    } else if (source.getExtension() == "svl" ||
+               (source.getExtension() == "xml" &&
+                (SVFileReader::identifyXmlFile(source.getLocalFilename())
+                 == SVFileReader::SVLayerFile))) {
 
         PaneCallback callback(this);
         QFile file(path);
@@ -1314,13 +1317,45 @@
     std::cerr << "MainWindowBase::openSession(" << source.getLocation().toStdString() << ")" << std::endl;
 
     if (!source.isAvailable()) return FileOpenFailed;
-    if (source.getExtension() != "sv") return FileOpenFailed;
+
+    if (source.getExtension() != "sv") {
+        if (source.getExtension() == "xml") {
+            source.waitForData();
+            if (SVFileReader::identifyXmlFile(source.getLocalFilename()) ==
+                SVFileReader::SVSessionFile) {
+                std::cerr << "This XML file looks like a session file, attempting to open it as a session" << std::endl;
+            } else {
+                return FileOpenFailed;
+            }
+        } else {
+            return FileOpenFailed;
+        }
+    }
     source.waitForData();
 
-    BZipFileDevice bzFile(source.getLocalFilename());
-    if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed;
-
-    if (!checkSaveModified()) return FileOpenCancelled;
+    QXmlInputSource *inputSource = 0;
+    BZipFileDevice *bzFile = 0;
+    QFile *rawFile = 0;
+
+    if (source.getExtension() == "sv") {
+        bzFile = new BZipFileDevice(source.getLocalFilename());
+        if (!bzFile->open(QIODevice::ReadOnly)) {
+            delete bzFile;
+            return FileOpenFailed;
+        }
+        inputSource = new QXmlInputSource(bzFile);
+    } else {
+        rawFile = new QFile(source.getLocalFilename());
+        inputSource = new QXmlInputSource(rawFile);
+    }
+
+    if (!checkSaveModified()) {
+        if (bzFile) bzFile->close();
+        delete inputSource;
+        delete bzFile;
+        delete rawFile;
+        return FileOpenCancelled;
+    }
 
     QString error;
     closeSession();
@@ -1336,14 +1371,18 @@
     connect
         (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
          this, SLOT(modelRegenerationWarning(QString, QString, QString)));
-    QXmlInputSource inputSource(&bzFile);
-    reader.parse(inputSource);
+
+    reader.parse(*inputSource);
     
     if (!reader.isOK()) {
         error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
     }
     
-    bzFile.close();
+    if (bzFile) bzFile->close();
+
+    delete inputSource;
+    delete bzFile;
+    delete rawFile;
 
     bool ok = (error == "");
 
--- a/framework/SVFileReader.cpp	Wed Nov 19 14:55:17 2008 +0000
+++ b/framework/SVFileReader.cpp	Thu Nov 20 10:59:14 2008 +0000
@@ -1370,3 +1370,99 @@
 {
 }
 
+
+class SVFileIdentifier : public QXmlDefaultHandler
+{
+public:
+    SVFileIdentifier() :
+        m_inSv(false),
+        m_inData(false),
+        m_type(SVFileReader::UnknownFileType)
+    { }
+    virtual ~SVFileIdentifier() { }
+
+    void parse(QXmlInputSource &source) {
+        QXmlSimpleReader reader;
+        reader.setContentHandler(this);
+        reader.setErrorHandler(this);
+        reader.parse(source);
+    }
+
+    SVFileReader::FileType getType() const { return m_type; }
+
+    virtual bool startElement(const QString &,
+			      const QString &,
+			      const QString &qName,
+			      const QXmlAttributes& atts)
+    {
+        QString name = qName.toLower();
+
+        // SV session files have an sv element containing a data
+        // element containing a model element with mainModel="true".
+
+        // If the sv element is present but the rest does not satisfy,
+        // then it's (probably) an SV layer file.
+
+        // Otherwise, it's of unknown type.
+
+        if (name == "sv") {
+            m_inSv = true;
+            if (m_type == SVFileReader::UnknownFileType) {
+                m_type = SVFileReader::SVLayerFile;
+            }
+            return true;
+        } else if (name == "data") {
+            if (!m_inSv) return true;
+            m_inData = true;
+        } else if (name == "model") {
+            if (!m_inData) return true;
+            if (atts.value("mainModel").trimmed() == "true") {
+                if (m_type == SVFileReader::SVLayerFile) {
+                    m_type = SVFileReader::SVSessionFile;
+                    return false; // done
+                }
+            }
+        }
+        return true;
+    }
+
+    virtual bool endElement(const QString &,
+			    const QString &,
+			    const QString &qName)
+    {
+        QString name = qName.toLower();
+
+        if (name == "sv") {
+            if (m_inSv) {
+                m_inSv = false;
+                return false; // done
+            }
+        } else if (name == "data") {
+            if (m_inData) {
+                m_inData = false;
+                return false; // also done, nothing after the first
+                              // data element is of use here
+            }
+        }
+        return true;
+    }
+
+private:
+    bool m_inSv;
+    bool m_inData;
+    SVFileReader::FileType m_type;
+};
+
+
+SVFileReader::FileType
+SVFileReader::identifyXmlFile(QString path)
+{
+    QFile file(path);
+    SVFileIdentifier identifier;
+    QXmlInputSource source(&file);
+    identifier.parse(source);
+    return identifier.getType();
+}
+
+    
+    
--- a/framework/SVFileReader.h	Wed Nov 19 14:55:17 2008 +0000
+++ b/framework/SVFileReader.h	Thu Nov 20 10:59:14 2008 +0000
@@ -194,6 +194,15 @@
     bool error(const QXmlParseException &exception);
     bool fatalError(const QXmlParseException &exception);
 
+    enum FileType
+    {
+        SVSessionFile,
+        SVLayerFile,
+        UnknownFileType
+    };
+
+    static FileType identifyXmlFile(QString path);
+
 signals:
     void modelRegenerationFailed(QString layerName, QString transformName,
                                  QString message);