Quellcode durchsuchen

Try to use QXmlSchema validation

Kandrashin Denis vor 12 Jahren
Ursprung
Commit
5bdc21dd4e

+ 3 - 6
3rdparty/fb2/FictionBook2.1.xsd

@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- edited with XML Spy v4.4 U (http://www.xmlspy.com) by GribUser (Moscow) -->
 <xs:schema targetNamespace="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:genre="http://www.gribuser.ru/xml/fictionbook/2.0/genres" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" elementFormDefault="qualified" attributeFormDefault="unqualified">
 <xs:schema targetNamespace="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:genre="http://www.gribuser.ru/xml/fictionbook/2.0/genres" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" elementFormDefault="qualified" attributeFormDefault="unqualified">
 	<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="FictionBookLinks.xsd"/>
 	<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="FictionBookLinks.xsd"/>
 	<xs:import namespace="http://www.gribuser.ru/xml/fictionbook/2.0/genres" schemaLocation="FictionBookGenres.xsd"/>
 	<xs:import namespace="http://www.gribuser.ru/xml/fictionbook/2.0/genres" schemaLocation="FictionBookGenres.xsd"/>
@@ -516,11 +515,9 @@
 					<xs:documentation>Genre of this book, with the optional match percentage</xs:documentation>
 					<xs:documentation>Genre of this book, with the optional match percentage</xs:documentation>
 				</xs:annotation>
 				</xs:annotation>
 				<xs:complexType>
 				<xs:complexType>
-					<xs:simpleContent>
-						<xs:extension base="genre:genreType">
-							<xs:attribute name="match" type="xs:integer" use="optional" default="100"/>
-						</xs:extension>
-					</xs:simpleContent>
+					<xs:complexContent>
+						<xs:extension base="authorType"/>
+					</xs:complexContent>
 				</xs:complexType>
 				</xs:complexType>
 			</xs:element>
 			</xs:element>
 			<xs:element name="author" maxOccurs="unbounded">
 			<xs:element name="author" maxOccurs="unbounded">

+ 1 - 2
3rdparty/fb2/FictionBookGenres.xsd

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- edited with XML Spy v4.2 U (http://www.xmlspy.com) by * (*) -->
-<xs:schema targetNamespace="http://www.gribuser.ru/xml/fictionbook/2.0/genres" xmlns="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+<xs:schema targetNamespace="http://www.gribuser.ru/xml/fictionbook/2.0/genres" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
 	<xs:simpleType name="genreType">
 	<xs:simpleType name="genreType">
 		<xs:restriction base="xs:token">
 		<xs:restriction base="xs:token">
 			<xs:enumeration value="sf_history"/>
 			<xs:enumeration value="sf_history"/>

+ 1 - 2
3rdparty/fb2/FictionBookLang.xsd

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- edited with XML Spy v4.4 U (http://www.xmlspy.com) by Dmitry Grobov (DDS) -->
-<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/XML/1998/namespace" elementFormDefault="qualified" attributeFormDefault="unqualified">
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
 	<xs:attribute name="lang" type="xs:language">
 	<xs:attribute name="lang" type="xs:language">
 		<xs:annotation>
 		<xs:annotation>
 			<xs:documentation>Element content's languige</xs:documentation>
 			<xs:documentation>Element content's languige</xs:documentation>

+ 1 - 2
3rdparty/fb2/FictionBookLinks.xsd

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- edited with XML Spy v4.2 U (http://www.xmlspy.com) by * (*) -->
-<xs:schema targetNamespace="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/1999/xlink" elementFormDefault="qualified" attributeFormDefault="unqualified">
+<xs:schema targetNamespace="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
 	<xs:attribute name="type" type="xs:string" fixed="simple">
 	<xs:attribute name="type" type="xs:string" fixed="simple">
 		<xs:annotation>
 		<xs:annotation>
 			<xs:documentation>link type</xs:documentation>
 			<xs:documentation>link type</xs:documentation>

BIN
3rdparty/gnome/16x16/tools-check-spelling.png


BIN
3rdparty/gnome/24x24/tools-check-spelling.png


+ 2 - 0
3rdparty/gnome/gnome.qrc

@@ -31,6 +31,7 @@
         <file>16x16/list-remove.png</file>
         <file>16x16/list-remove.png</file>
         <file>16x16/preferences-desktop.png</file>
         <file>16x16/preferences-desktop.png</file>
         <file>16x16/text-x-generic.png</file>
         <file>16x16/text-x-generic.png</file>
+        <file>16x16/tools-check-spelling.png</file>
         <file>16x16/utilities-terminal.png</file>
         <file>16x16/utilities-terminal.png</file>
         <file>16x16/window-close.png</file>
         <file>16x16/window-close.png</file>
         <file>16x16/x-office-document.png</file>
         <file>16x16/x-office-document.png</file>
@@ -68,6 +69,7 @@
         <file>24x24/list-remove.png</file>
         <file>24x24/list-remove.png</file>
         <file>24x24/preferences-desktop.png</file>
         <file>24x24/preferences-desktop.png</file>
         <file>24x24/text-x-generic.png</file>
         <file>24x24/text-x-generic.png</file>
+        <file>24x24/tools-check-spelling.png</file>
         <file>24x24/utilities-terminal.png</file>
         <file>24x24/utilities-terminal.png</file>
         <file>24x24/window-close.png</file>
         <file>24x24/window-close.png</file>
         <file>24x24/x-office-document.png</file>
         <file>24x24/x-office-document.png</file>

+ 1 - 0
fb2edit.pro

@@ -49,6 +49,7 @@ TRANSLATIONS = source/ts/ru.ts
 QT += xml
 QT += xml
 QT += webkit
 QT += webkit
 QT += network
 QT += network
+QT += xmlpatterns
 
 
 OTHER_FILES += \
 OTHER_FILES += \
     source/res/style.css \
     source/res/style.css \

+ 168 - 1
source/fb2code.cpp

@@ -1,13 +1,122 @@
 #include "fb2code.hpp"
 #include "fb2code.hpp"
+
+#include <QXmlSchema>
+#include <QAbstractMessageHandler>
+#include <QXmlSchemaValidator>
+
 #include "fb2dlgs.hpp"
 #include "fb2dlgs.hpp"
 
 
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 //  FbHighlighter
 //  FbHighlighter
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 
 
+class FbSchemaHandler : public QAbstractMessageHandler
+{
+    public:
+        FbSchemaHandler()
+            : 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_messageType = type;
+            m_description = description;
+            m_sourceLocation = sourceLocation;
+        }
+
+    private:
+        QtMsgType m_messageType;
+        QString m_description;
+        QSourceLocation m_sourceLocation;
+};
+
+//---------------------------------------------------------------------------
+//  FbHighlighter
+//---------------------------------------------------------------------------
+
 #include <QXmlInputSource>
 #include <QXmlInputSource>
 #include <QtGui>
 #include <QtGui>
 
 
+#include <QSyntaxHighlighter>
+
+class FbHighlighter : public QSyntaxHighlighter
+{
+public:
+    FbHighlighter(QObject* parent);
+    FbHighlighter(QTextDocument* parent);
+    FbHighlighter(QTextEdit* parent);
+    ~FbHighlighter();
+
+    enum HighlightType
+    {
+        SyntaxChar,
+        ElementName,
+        Comment,
+        AttributeName,
+        AttributeValue,
+        Error,
+        Other
+    };
+
+    void setHighlightColor(HighlightType type, QColor color, bool foreground = true);
+    void setHighlightFormat(HighlightType type, QTextCharFormat format);
+
+protected:
+    void highlightBlock(const QString& rstrText);
+    int  processDefaultText(int i, const QString& rstrText);
+
+private:
+    void init();
+
+    QTextCharFormat fmtSyntaxChar;
+    QTextCharFormat fmtElementName;
+    QTextCharFormat fmtComment;
+    QTextCharFormat fmtAttributeName;
+    QTextCharFormat fmtAttributeValue;
+    QTextCharFormat fmtError;
+    QTextCharFormat fmtOther;
+
+    enum ParsingState
+    {
+        NoState = 0,
+        ExpectElementNameOrSlash,
+        ExpectElementName,
+        ExpectAttributeOrEndOfElement,
+        ExpectEqual,
+        ExpectAttributeValue
+    };
+
+    enum BlockState
+    {
+        NoBlock = -1,
+        InComment,
+        InElement
+    };
+
+    ParsingState state;
+};
+
 static const QColor DEFAULT_SYNTAX_CHAR     = Qt::blue;
 static const QColor DEFAULT_SYNTAX_CHAR     = Qt::blue;
 static const QColor DEFAULT_ELEMENT_NAME    = Qt::darkRed;
 static const QColor DEFAULT_ELEMENT_NAME    = Qt::darkRed;
 static const QColor DEFAULT_COMMENT         = Qt::darkGray;
 static const QColor DEFAULT_COMMENT         = Qt::darkGray;
@@ -345,7 +454,7 @@ qreal FbCodeEdit::zoomRatioMax = 5.0;
 FbCodeEdit::FbCodeEdit(QWidget *parent) : QPlainTextEdit(parent)
 FbCodeEdit::FbCodeEdit(QWidget *parent) : QPlainTextEdit(parent)
 {
 {
     lineNumberArea = new LineNumberArea(this);
     lineNumberArea = new LineNumberArea(this);
-    highlighter = new FbHighlighter(this);
+    FbHighlighter *highlighter = new FbHighlighter(this);
     highlighter->setDocument( document() );
     highlighter->setDocument( document() );
 
 
     connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
     connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
@@ -379,6 +488,7 @@ void FbCodeEdit::connectActions(QToolBar *tool)
     act(Fb::EditUndo)->setEnabled(document()->isUndoAvailable());
     act(Fb::EditUndo)->setEnabled(document()->isUndoAvailable());
     act(Fb::EditRedo)->setEnabled(document()->isRedoAvailable());
     act(Fb::EditRedo)->setEnabled(document()->isRedoAvailable());
     act(Fb::EditFind)->setEnabled(true);
     act(Fb::EditFind)->setEnabled(true);
+    act(Fb::CheckText)->setEnabled(true);
 
 
     act(Fb::ZoomIn)->setEnabled(true);
     act(Fb::ZoomIn)->setEnabled(true);
     act(Fb::ZoomOut)->setEnabled(true);
     act(Fb::ZoomOut)->setEnabled(true);
@@ -394,6 +504,7 @@ void FbCodeEdit::connectActions(QToolBar *tool)
     connect(act(Fb::EditCopy), SIGNAL(triggered()), SLOT(copy()));
     connect(act(Fb::EditCopy), SIGNAL(triggered()), SLOT(copy()));
     connect(act(Fb::EditPaste), SIGNAL(triggered()), SLOT(paste()));
     connect(act(Fb::EditPaste), SIGNAL(triggered()), SLOT(paste()));
     connect(act(Fb::EditFind), SIGNAL(triggered()), SLOT(find()));
     connect(act(Fb::EditFind), SIGNAL(triggered()), SLOT(find()));
+    connect(act(Fb::CheckText), SIGNAL(triggered()), SLOT(validate()));
 
 
     connect(this, SIGNAL(copyAvailable(bool)), act(Fb::EditCut), SLOT(setEnabled(bool)));
     connect(this, SIGNAL(copyAvailable(bool)), act(Fb::EditCut), SLOT(setEnabled(bool)));
     connect(this, SIGNAL(copyAvailable(bool)), act(Fb::EditCopy), SLOT(setEnabled(bool)));
     connect(this, SIGNAL(copyAvailable(bool)), act(Fb::EditCopy), SLOT(setEnabled(bool)));
@@ -565,3 +676,59 @@ void FbCodeEdit::setZoomRatio(qreal ratio)
         setFont(f);
         setFont(f);
     }
     }
 }
 }
+
+void FbCodeEdit::validate()
+{
+    FbSchemaHandler handler;
+
+    QXmlSchema schema;
+    schema.setMessageHandler(&handler);
+
+    QUrl url("qrc:/fb2/FictionBook2.1.xsd");
+    schema.load(url);
+
+//    QFile file(":/fb2/FictionBook2.1.xsd");
+//    if (!file.open(QFile::ReadOnly)) return;
+//    schema.load(&file);
+    if (!schema.isValid()) {
+        QFile file(":/fb2/FictionBook2.1.xsd");
+        file.open(QFile::ReadOnly);
+        QTextStream in(&file);
+        in.setCodec("UTF-8");
+        in.setAutoDetectUnicode(true);
+        setPlainText(in.readAll());
+        status(tr("Schema is not valid: ") + handler.statusMessage());
+        setCursor(handler.line(), handler.column());
+        return;
+    }
+
+    const QByteArray data = toPlainText().toUtf8();
+    QXmlSchemaValidator validator(schema);
+    if (!validator.validate(data)) {
+        setCursor(handler.line(), handler.column());
+        status(handler.statusMessage());
+    }
+}
+
+void FbCodeEdit::setCursor(int line, int column)
+{
+    moveCursor(QTextCursor::Start);
+    for (int i = 1; i < line; ++i)
+        moveCursor(QTextCursor::Down);
+
+    for (int i = 1; i < column; ++i)
+        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 = textCursor();
+    selection.cursor.clearSelection();
+    extraSelections.append(selection);
+
+    setExtraSelections(extraSelections);
+    setFocus();
+}

+ 6 - 65
source/fb2code.hpp

@@ -4,7 +4,6 @@
 #include <QByteArray>
 #include <QByteArray>
 #include <QObject>
 #include <QObject>
 #include <QPlainTextEdit>
 #include <QPlainTextEdit>
-#include <QSyntaxHighlighter>
 #include <QTextCharFormat>
 #include <QTextCharFormat>
 #include <QColor>
 #include <QColor>
 #include <QTextEdit>
 #include <QTextEdit>
@@ -12,63 +11,6 @@
 
 
 #include "fb2mode.h"
 #include "fb2mode.h"
 
 
-class FbHighlighter : public QSyntaxHighlighter
-{
-public:
-    FbHighlighter(QObject* parent);
-    FbHighlighter(QTextDocument* parent);
-    FbHighlighter(QTextEdit* parent);
-    ~FbHighlighter();
-
-    enum HighlightType
-    {
-        SyntaxChar,
-        ElementName,
-        Comment,
-        AttributeName,
-        AttributeValue,
-        Error,
-        Other
-    };
-
-    void setHighlightColor(HighlightType type, QColor color, bool foreground = true);
-    void setHighlightFormat(HighlightType type, QTextCharFormat format);
-
-protected:
-    void highlightBlock(const QString& rstrText);
-    int  processDefaultText(int i, const QString& rstrText);
-
-private:
-    void init();
-
-    QTextCharFormat fmtSyntaxChar;
-    QTextCharFormat fmtElementName;
-    QTextCharFormat fmtComment;
-    QTextCharFormat fmtAttributeName;
-    QTextCharFormat fmtAttributeValue;
-    QTextCharFormat fmtError;
-    QTextCharFormat fmtOther;
-
-    enum ParsingState
-    {
-        NoState = 0,
-        ExpectElementNameOrSlash,
-        ExpectElementName,
-        ExpectAttributeOrEndOfElement,
-        ExpectEqual,
-        ExpectAttributeValue
-    };
-
-    enum BlockState
-    {
-        NoBlock = -1,
-        InComment,
-        InElement
-    };
-
-    ParsingState state;
-};
-
 QT_BEGIN_NAMESPACE
 QT_BEGIN_NAMESPACE
 class QPaintEvent;
 class QPaintEvent;
 class QResizeEvent;
 class QResizeEvent;
@@ -102,12 +44,6 @@ public:
 signals:
 signals:
     void status(const QString &text);
     void status(const QString &text);
 
 
-public slots:
-    void find();
-    void zoomIn();
-    void zoomOut();
-    void zoomReset();
-
 protected:
 protected:
     void resizeEvent(QResizeEvent *event);
     void resizeEvent(QResizeEvent *event);
 
 
@@ -116,6 +52,11 @@ private slots:
     void updateLineNumberAreaWidth(int newBlockCount);
     void updateLineNumberAreaWidth(int newBlockCount);
     void highlightCurrentLine();
     void highlightCurrentLine();
     void updateLineNumberArea(const QRect &, int);
     void updateLineNumberArea(const QRect &, int);
+    void find();
+    void validate();
+    void zoomIn();
+    void zoomOut();
+    void zoomReset();
 
 
 private:
 private:
     class LineNumberArea : public QWidget
     class LineNumberArea : public QWidget
@@ -133,9 +74,9 @@ private:
     void lineNumberAreaPaintEvent(QPaintEvent *event);
     void lineNumberAreaPaintEvent(QPaintEvent *event);
     int lineNumberAreaWidth();
     int lineNumberAreaWidth();
     void setZoomRatio(qreal ratio);
     void setZoomRatio(qreal ratio);
+    void setCursor(int line, int column);
 
 
 private:
 private:
-    FbHighlighter *highlighter;
     QWidget *lineNumberArea;
     QWidget *lineNumberArea;
     FbActionMap m_actions;
     FbActionMap m_actions;
     qreal zoomRatio;
     qreal zoomRatio;

+ 4 - 0
source/fb2main.cpp

@@ -271,6 +271,10 @@ void FbMainWindow::createActions()
     code->setAction(Fb::EditReplace, act);
     code->setAction(Fb::EditReplace, act);
     menu->addAction(act);
     menu->addAction(act);
 
 
+    act = new QAction(FbIcon("tools-check-spelling"), tr("&Check..."), this);
+    code->setAction(Fb::CheckText, act);
+    menu->addAction(act);
+
     menu->addSeparator();
     menu->addSeparator();
 
 
     act = new QAction(FbIcon("preferences-desktop"), tr("&Settings"), this);
     act = new QAction(FbIcon("preferences-desktop"), tr("&Settings"), this);

+ 1 - 0
source/fb2mode.h

@@ -25,6 +25,7 @@ enum Actions {
     TextSelect,
     TextSelect,
     EditFind,
     EditFind,
     EditReplace,
     EditReplace,
+    CheckText,
     InsertImage,
     InsertImage,
     InsertNote,
     InsertNote,
     InsertLink,
     InsertLink,