Qt 5.8 | Qt XML Patterns | XML Schema Validation Example | mainwindow.cpp Example File

Qt 5.8.0 Reference Documentation

# mainwindow.cpp Example File

schema/mainwindow.cpp

      /****************************************************************************
      **
      ** Copyright (C) 2015 The Qt Company Ltd.
      ** Contact: http://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** You may use this file under the terms of the BSD license as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #include <QtGui>
      #include <QtXmlPatterns>

      #include "mainwindow.h"
      #include "xmlsyntaxhighlighter.h"

      class MessageHandler : public QAbstractMessageHandler
      {
      public:
          MessageHandler()
              : QAbstractMessageHandler(0)
          {
          }

          QString statusMessage() const
          {
              return m_description;
          }

          int line() const
          {
              return m_sourceLocation.line();
          }

          int column() const
          {
              return m_sourceLocation.column();
          }

      protected:
          virtual void handleMessage(QtMsgType type, const QString &description,
                                     const QUrl &identifier, const QSourceLocation &sourceLocation)
          {
              Q_UNUSED(type);
              Q_UNUSED(identifier);

              m_description = description;
              m_sourceLocation = sourceLocation;
          }

      private:
          QString m_description;
          QSourceLocation m_sourceLocation;
      };

      MainWindow::MainWindow()
      {
          setupUi(this);

          new XmlSyntaxHighlighter(schemaView->document());
          new XmlSyntaxHighlighter(instanceEdit->document());

          schemaSelection->addItem(tr("Contact Schema"));
          schemaSelection->addItem(tr("Recipe Schema"));
          schemaSelection->addItem(tr("Order Schema"));

          instanceSelection->addItem(tr("Valid Contact Instance"));
          instanceSelection->addItem(tr("Invalid Contact Instance"));

          connect(schemaSelection, SIGNAL(currentIndexChanged(int)), SLOT(schemaSelected(int)));
          connect(instanceSelection, SIGNAL(currentIndexChanged(int)), SLOT(instanceSelected(int)));
          connect(validateButton, SIGNAL(clicked()), SLOT(validate()));
          connect(instanceEdit, SIGNAL(textChanged()), SLOT(textChanged()));

          validationStatus->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);

          schemaSelected(0);
          instanceSelected(0);
      }

      void MainWindow::schemaSelected(int index)
      {
          instanceSelection->clear();
          if (index == 0) {
              instanceSelection->addItem(tr("Valid Contact Instance"));
              instanceSelection->addItem(tr("Invalid Contact Instance"));
          } else if (index == 1) {
              instanceSelection->addItem(tr("Valid Recipe Instance"));
              instanceSelection->addItem(tr("Invalid Recipe Instance"));
          } else if (index == 2) {
              instanceSelection->addItem(tr("Valid Order Instance"));
              instanceSelection->addItem(tr("Invalid Order Instance"));
          }
          textChanged();

          const QString fileName = QStringLiteral(":/schema_")
              + QString::number(index) + QStringLiteral(".xsd");
          QFile schemaFile(fileName);
          if (!schemaFile.open(QIODevice::ReadOnly)) {
              qWarning() << "Cannot open" << QDir::toNativeSeparators(fileName)
                  << ':' << schemaFile.errorString();
              return;
          }

          const QString schemaText(QString::fromUtf8(schemaFile.readAll()));
          schemaView->setPlainText(schemaText);

          validate();
      }

      void MainWindow::instanceSelected(int index)
      {
          if (index < 0) {
              instanceEdit->setPlainText(QString());
              return;
          }
          const QString fileName = QStringLiteral(":/instance_")
              + QString::number(2 * schemaSelection->currentIndex() + index)
              + QStringLiteral(".xml");
          QFile instanceFile(fileName);
          if (!instanceFile.open(QIODevice::ReadOnly)) {
              qWarning() << "Cannot open" << QDir::toNativeSeparators(fileName)
                  << ':' << instanceFile.errorString();
              return;
          }
          const QString instanceText(QString::fromUtf8(instanceFile.readAll()));
          instanceEdit->setPlainText(instanceText);

          validate();
      }

      void MainWindow::validate()
      {
          const QByteArray schemaData = schemaView->toPlainText().toUtf8();
          const QByteArray instanceData = instanceEdit->toPlainText().toUtf8();

          MessageHandler messageHandler;

          QXmlSchema schema;
          schema.setMessageHandler(&messageHandler);

          schema.load(schemaData);

          bool errorOccurred = false;
          if (!schema.isValid()) {
              errorOccurred = true;
          } else {
              QXmlSchemaValidator validator(schema);
              if (!validator.validate(instanceData))
                  errorOccurred = true;
          }

          if (errorOccurred) {
              validationStatus->setText(messageHandler.statusMessage());
              moveCursor(messageHandler.line(), messageHandler.column());
          } else {
              validationStatus->setText(tr("validation successful"));
          }

          const QString styleSheet = QString("QLabel {background: %1; padding: 3px}")
                                            .arg(errorOccurred ? QColor(Qt::red).lighter(160).name() :
                                                                 QColor(Qt::green).lighter(160).name());
          validationStatus->setStyleSheet(styleSheet);
      }

      void MainWindow::textChanged()
      {
          instanceEdit->setExtraSelections(QList<QTextEdit::ExtraSelection>());
      }

      void MainWindow::moveCursor(int line, int column)
      {
          instanceEdit->moveCursor(QTextCursor::Start);
          for (int i = 1; i < line; ++i)
              instanceEdit->moveCursor(QTextCursor::Down);

          for (int i = 1; i < column; ++i)
              instanceEdit->moveCursor(QTextCursor::Right);

          QList<QTextEdit::ExtraSelection> extraSelections;
          QTextEdit::ExtraSelection selection;

          const QColor lineColor = QColor(Qt::red).lighter(160);
          selection.format.setBackground(lineColor);
          selection.format.setProperty(QTextFormat::FullWidthSelection, true);
          selection.cursor = instanceEdit->textCursor();
          selection.cursor.clearSelection();
          extraSelections.append(selection);

          instanceEdit->setExtraSelections(extraSelections);

          instanceEdit->setFocus();
      }