File indexing completed on 2024-04-28 05:27:16

0001 /*
0002     SPDX-FileCopyrightText: 2007 Jeff Cooper <weirdsox11@gmail.com>
0003     SPDX-FileCopyrightText: 2007 Thomas Georgiou <TAGeorgiou@gmail.com>
0004     SPDX-FileCopyrightText: 2022 Alexander Lohnau <alexander.lohnau@gmx.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #pragma once
0010 
0011 #include <QMap>
0012 #include <QObject>
0013 #include <QTcpSocket>
0014 #include <QTimer>
0015 #include <QVariantMap>
0016 #include <array>
0017 
0018 /**
0019  * This class evaluates the basic expressions given in the interface.
0020  */
0021 
0022 class DictEngine : public QObject
0023 {
0024     Q_OBJECT
0025 
0026 public:
0027     DictEngine(QObject *parent = nullptr);
0028     ~DictEngine() override;
0029 
0030 Q_SIGNALS:
0031     /**
0032      * @param socketError the type of the last socket error
0033      * @param errorString a human-readable description of the last socket error
0034      */
0035     void dictErrorOccurred(QAbstractSocket::SocketError socketError, const QString &errorString);
0036 
0037     /**
0038      * @param loading @c true if the dict finder is downloading dict list from
0039      * the Internet, @c false otherwise.
0040      */
0041     void dictLoadingChanged(bool loading);
0042 
0043     void dictsRecieved(const QMap<QString, QString> &dicts);
0044     void definitionRecieved(const QString &html);
0045 
0046 public Q_SLOTS:
0047     void requestDicts();
0048     void requestDefinition(const QString &query);
0049     void requestDefinition(const QString &query, const QString &server);
0050     void requestDefinition(const QString &query, const QByteArray &dictionary);
0051     void requestDefinition(const QString &query, const QString &server, const QByteArray &dictionary);
0052 
0053 private Q_SLOTS:
0054     /**
0055      * Slot to asynchronously handle \readyRead signal emitted
0056      * when receiving new definitions.
0057      */
0058     void slotDefinitionReadyRead();
0059 
0060     /**
0061      * Slot to process definition data when any end response
0062      * listed in \m_definitionResponses is received, or to handle
0063      * \QTimer::timeout signal when no new data are received
0064      * from the socket and no end response is received.
0065      */
0066     void slotDefinitionReadFinished();
0067 
0068     void socketClosed();
0069 
0070 private:
0071     void getDefinition();
0072     void getDicts();
0073     void setDict(const QByteArray &dict);
0074     void setServer(const QString &server);
0075 
0076     QHash<QString, QString> m_dictNameToDictCode;
0077     QTcpSocket *m_tcpSocket = nullptr;
0078     QString m_currentWord;
0079     QByteArrayList m_dictNames;
0080     QString m_serverName;
0081     QMap<QString, QMap<QString, QString>> m_availableDictsCache;
0082 
0083     /**
0084      * Stores temporarily received definition data
0085      */
0086     QByteArray m_definitionData;
0087 
0088     /**
0089      * When \QTimer::timeout is emitted, the existing socket will be closed
0090      * and deleted, and will emit \definitionRecieved to stop the loading
0091      * process.
0092      */
0093     QTimer m_definitionTimer;
0094 
0095     // https://datatracker.ietf.org/doc/html/rfc2229
0096     const std::array<QByteArray, 4> m_definitionResponses;
0097 };