File indexing completed on 2024-11-24 04:34:29
0001 /*************************************************************************** 0002 * SPDX-License-Identifier: GPL-2.0-or-later 0003 * * 0004 * SPDX-FileCopyrightText: 2004-2023 Thomas Fischer <fischer@unix-ag.uni-kl.de> 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, * 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0014 * GNU General Public License for more details. * 0015 * * 0016 * You should have received a copy of the GNU General Public License * 0017 * along with this program; if not, see <https://www.gnu.org/licenses/>. * 0018 ***************************************************************************/ 0019 0020 #ifndef KBIBTEX_NETWORKING_ONLINESEARCHABSTRACT_H 0021 #define KBIBTEX_NETWORKING_ONLINESEARCHABSTRACT_H 0022 0023 #include <QObject> 0024 #include <QMap> 0025 #include <QString> 0026 #include <QNetworkReply> 0027 #ifdef HAVE_QTWIDGETS 0028 #include <QWidget> 0029 #endif // HAVE_QTWIDGETS 0030 #include <QMetaType> 0031 #include <QIcon> 0032 #include <QUrl> 0033 0034 #include <Entry> 0035 0036 #ifdef HAVE_KF 0037 #include "kbibtexnetworking_export.h" 0038 #endif // HAVE_KF 0039 0040 class QNetworkReply; 0041 class QNetworkRequest; 0042 class QListWidgetItem; 0043 0044 /** 0045 * @author Thomas Fischer <fischer@unix-ag.uni-kl.de> 0046 */ 0047 class KBIBTEXNETWORKING_EXPORT OnlineSearchAbstract : public QObject 0048 { 0049 Q_OBJECT 0050 Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) 0051 0052 public: 0053 explicit OnlineSearchAbstract(QObject *parent); 0054 0055 #ifdef HAVE_QTWIDGETS 0056 class Form; 0057 #endif // HAVE_QTWIDGETS 0058 0059 enum class QueryKey {FreeText = 1, Title = 2, Author = 3, Year = 4}; 0060 0061 static const int resultCancelled; 0062 static const int resultNoError; 0063 static const int resultUnspecifiedError; 0064 static const int resultAuthorizationRequired; 0065 static const int resultNetworkError; 0066 static const int resultInvalidArguments; 0067 0068 #ifdef HAVE_QTWIDGETS 0069 virtual void startSearchFromForm(); 0070 #endif // HAVE_QTWIDGETS 0071 virtual void startSearch(const QMap<QueryKey, QString> &query, int numResults) = 0; 0072 virtual QString label() const = 0; 0073 QString name(); 0074 #ifdef HAVE_QTWIDGETS 0075 virtual QIcon icon(QListWidgetItem *listWidgetItem); 0076 virtual OnlineSearchAbstract::Form *customWidget(QWidget *parent); 0077 #endif // HAVE_QTWIDGETS 0078 virtual QUrl homepage() const = 0; 0079 virtual bool busy() const; 0080 0081 public Q_SLOTS: 0082 void cancel(); 0083 0084 protected: 0085 QObject *m_parent; 0086 bool m_hasBeenCanceled; 0087 0088 int numSteps, curStep; 0089 0090 /** 0091 * Split a string along spaces, but keep text in quotation marks together 0092 */ 0093 static QStringList splitRespectingQuotationMarks(const QString &text); 0094 0095 /** 0096 * Will check for common problems with downloads via QNetworkReply. It will return true 0097 * if there is no problem and you may process this job result. If there is a problem, 0098 * this function will notify the user if necessary (KMessageBox), emit a 0099 * "stoppedSearch" signal (by invoking "stopSearch"), and return false. 0100 * @see handleErrors(KJob*) 0101 */ 0102 bool handleErrors(QNetworkReply *reply); 0103 0104 /** 0105 * Will check for common problems with downloads via QNetworkReply. It will return true 0106 * if there is no problem and you may process this job result. If there is a problem, 0107 * this function will notify the user if necessary (KMessageBox), emit a 0108 * "stoppedSearch" signal (by invoking "stopSearch"), and return false. 0109 * @see handleErrors(KJob*) 0110 * @param reply The reply the function will handle errors for 0111 * @param newUrl will be set to the new URL if reply contains a redirection, otherwise reply's original URL 0112 */ 0113 bool handleErrors(QNetworkReply *reply, QUrl &newUrl, const QSet<const QNetworkReply::NetworkError> &ignoredErrors = QSet<const QNetworkReply::NetworkError>({QNetworkReply::NoError})); 0114 0115 /** 0116 * Encode a text to be HTTP URL save, e.g. replace '=' by '%3D'. 0117 */ 0118 static QString encodeURL(QString rawText); 0119 0120 static QString decodeURL(QString rawText); 0121 0122 static QString deHTMLify(const QString &input); 0123 static QByteArray htmlEntityToUnicode(const QByteArray &input); 0124 0125 static QString monthToMacroKeyText(const QString &rawText); 0126 0127 QMultiMap<QString, QString> formParameters(const QString &htmlText, int startPos) const; 0128 0129 /** 0130 * Delay sending of stop signal by a few milliseconds. 0131 * Necessary if search stops (is cancelled) already in one 0132 * of the startSearch functions. 0133 */ 0134 void delayedStoppedSearch(int returnCode); 0135 0136 /** 0137 * Correct the most common problems encountered in fetched entries. 0138 * This function should be specialized in each descendant of this class. 0139 * @param entry Entry to sanitize 0140 */ 0141 virtual void sanitizeEntry(QSharedPointer<Entry> entry); 0142 0143 /** 0144 * Perform the following steps: (1) sanitize entry, (2) add name 0145 * of search engine that found the entry, (3) send it back to search 0146 * result list. 0147 * Returns true if a valid entry was passed to this function and all 0148 * steps could be performed. 0149 * @param entry Entry to publish 0150 * @return returns true if a valid entry was passed to this function and all steps could be performed. 0151 */ 0152 bool publishEntry(QSharedPointer<Entry> entry); 0153 0154 void stopSearch(int errorCode); 0155 0156 /** 0157 * Allows an online search to notify about a change of its busy state, 0158 * i.e. that the public function @see busy may return a different value 0159 * than before. If the actual busy state has changed compared to previous 0160 * invocations of this function, the signal @see busyChanged will be 0161 * emitted. 0162 * This function here may be called both on changes from active to 0163 * inactive as well as vice versa. 0164 */ 0165 void refreshBusyProperty(); 0166 0167 #ifdef HAVE_KF 0168 /** 0169 * @brief Send a visual notification to the desktop, similar to KNotification 0170 * @param text Message to be shown 0171 * @param title Title of the message, such as which OnlineSearch engine 0172 * @param timeout time after which the message will automatically disappear (in seconds) 0173 * @param icon Name of icon to be shown 0174 */ 0175 void sendVisualNotification(const QString &text, const QString &title, int timeout = 10, const QString &icon = QStringLiteral("kbibtex")); 0176 #endif // HAVE_KF 0177 0178 private: 0179 bool m_previousBusyState; 0180 QString m_name; 0181 static const char *httpUnsafeChars; 0182 #ifdef HAVE_QTWIDGETS 0183 QMap<QNetworkReply *, QListWidgetItem *> m_iconReplyToListWidgetItem; 0184 #endif // HAVE_QTWIDGETS 0185 int m_delayedStoppedSearchReturnCode; 0186 0187 QString htmlAttribute(const QString &htmlCode, const int startPos, const QString &attribute) const; 0188 bool htmlAttributeIsSelected(const QString &htmlCode, const int startPos, const QString &attribute) const; 0189 0190 Q_SIGNALS: 0191 void foundEntry(QSharedPointer<Entry>); 0192 void stoppedSearch(int); 0193 void progress(int, int); 0194 void busyChanged(); 0195 }; 0196 0197 #ifdef HAVE_QTWIDGETS 0198 /** 0199 * @author Thomas Fischer <fischer@unix-ag.uni-kl.de> 0200 */ 0201 class KBIBTEXNETWORKING_EXPORT OnlineSearchAbstract::Form : public QWidget 0202 { 0203 Q_OBJECT 0204 0205 public: 0206 explicit Form(QWidget *parent); 0207 ~Form(); 0208 0209 virtual bool readyToStart() const = 0; 0210 virtual void copyFromEntry(const Entry &) = 0; 0211 0212 Q_SIGNALS: 0213 void returnPressed(); 0214 0215 protected: 0216 class Private; 0217 Private *d; 0218 }; 0219 #endif // HAVE_QTWIDGETS 0220 0221 #endif // KBIBTEX_NETWORKING_ONLINESEARCHABSTRACT_H