File indexing completed on 2024-05-05 05:04:33

0001 /***************************************************************************
0002  *   SPDX-License-Identifier: GPL-2.0-or-later
0003  *                                                                         *
0004  *   SPDX-FileCopyrightText: 2017-2019 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 #include "searchenginelist.h"
0021 
0022 #include <QSettings>
0023 
0024 #include "onlinesearch/onlinesearchabstract.h"
0025 #include "onlinesearch/onlinesearchacmportal.h"
0026 #include "onlinesearch/onlinesearcharxiv.h"
0027 #include "onlinesearch/onlinesearchbibsonomy.h"
0028 #include "onlinesearch/onlinesearchgooglescholar.h"
0029 #include "onlinesearch/onlinesearchieeexplore.h"
0030 #include "onlinesearch/onlinesearchingentaconnect.h"
0031 #include "onlinesearch/onlinesearchjstor.h"
0032 #include "onlinesearch/onlinesearchpubmed.h"
0033 #include "onlinesearch/onlinesearchsciencedirect.h"
0034 #include "onlinesearch/onlinesearchspringerlink.h"
0035 #include "bibliographymodel.h"
0036 
0037 SearchEngineList::SearchEngineList()
0038 {
0039     OnlineSearchAbstract *osa = new OnlineSearchAcmPortal(this);
0040     append(osa);
0041     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0042     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0043     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0044 
0045     osa = new OnlineSearchArXiv(this);
0046     append(osa);
0047     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0048     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0049     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0050 
0051     osa = new OnlineSearchBibsonomy(this);
0052     append(osa);
0053     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0054     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0055     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0056 
0057     osa = new OnlineSearchGoogleScholar(this);
0058     append(osa);
0059     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0060     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0061     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0062 
0063     osa = new OnlineSearchIEEEXplore(this);
0064     append(osa);
0065     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0066     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0067     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0068 
0069     osa = new OnlineSearchIngentaConnect(this);
0070     append(osa);
0071     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0072     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0073     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0074 
0075     osa = new OnlineSearchJStor(this);
0076     append(osa);
0077     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0078     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0079     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0080 
0081     osa = new OnlineSearchScienceDirect(this);
0082     append(osa);
0083     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0084     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0085     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0086 
0087     osa = new OnlineSearchPubMed(this);
0088     append(osa);
0089     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0090     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0091     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0092 
0093     osa = new OnlineSearchSpringerLink(this);
0094     append(osa);
0095     connect(osa, &OnlineSearchAbstract::foundEntry, this, &SearchEngineList::foundEntry);
0096     connect(osa, &OnlineSearchAbstract::busyChanged, this, &SearchEngineList::busyChanged);
0097     connect(osa, &OnlineSearchAbstract::progress, this, &SearchEngineList::collectingProgress);
0098 
0099     connect(this,&SearchEngineList::dataChanged,[this](const QModelIndex &, const QModelIndex &, const QVector<int> &roles = QVector<int>()){
0100         if (roles.contains(EngineEnabledRole))
0101             emit searchEngineCountChanged();
0102     });
0103 }
0104 
0105 SearchEngineList::SearchEngineList(const SearchEngineList &other)
0106     : QAbstractListModel(), QVector<OnlineSearchAbstract *>(other)
0107 {
0108     /// Nothing to do here, QVector constructor does the heavy lifting
0109 }
0110 
0111 SearchEngineList *SearchEngineList::operator =(const SearchEngineList *other) {
0112     /// Not much to do here, QVector constructor does the heavy lifting
0113     QVector<OnlineSearchAbstract *>::operator =(*other);
0114     return this;
0115 }
0116 
0117 int SearchEngineList::rowCount(const QModelIndex &parent) const {
0118     return parent == QModelIndex() ? size() : 0;
0119 }
0120 
0121 QVariant SearchEngineList::data(const QModelIndex &index, int role) const {
0122     if (index.row() < 0 || index.row() >= size() || index.parent() != QModelIndex() || index.column() != 0)
0123         return QVariant();
0124     const int row = index.row();
0125 
0126     switch (role) {
0127     case Qt::DisplayRole:
0128         return at(row)->label();
0129         break;
0130     case EngineEnabledRole: {
0131         const QSettings settings(QStringLiteral("harbour-bibsearch"), QStringLiteral("BibSearch"));
0132         return isSearchEngineEnabled(settings, at(row));
0133     }
0134     default:
0135         return QVariant();
0136     }
0137 }
0138 
0139 bool SearchEngineList::setData(const QModelIndex &index, const QVariant &value, int role) {
0140     if (index.row() < 0 || index.row() >= size() || index.parent() != QModelIndex() || index.column() != 0 || role != EngineEnabledRole)
0141         return false;
0142 
0143     static QSettings settings(QStringLiteral("harbour-bibsearch"), QStringLiteral("BibSearch"));
0144     const int row = index.row();
0145     const bool toBeSetEnabled = value.toBool();
0146     const bool currentlyEnabled = isSearchEngineEnabled(settings, at(row));
0147 
0148     if (toBeSetEnabled != currentlyEnabled) {
0149         setSearchEngineEnabled(settings, at(row), toBeSetEnabled);
0150         settings.sync();
0151         static const QVector<int> roles = QVector<int>(1, EngineEnabledRole);
0152         emit dataChanged(index, index, roles);
0153     }
0154 
0155     return true;
0156 }
0157 
0158 QString SearchEngineList::humanReadableSearchEngines() const {
0159     if (empty()) return QString();
0160 
0161     const QSettings settings(QStringLiteral("harbour-bibsearch"), QStringLiteral("BibSearch"));
0162     QStringList enabledSearchEnginesLabels;
0163     for (int i = 0; i < size(); ++i)
0164         if (isSearchEngineEnabled(settings, at(i)))
0165             enabledSearchEnginesLabels.append(at(i)->label());
0166 
0167     switch (enabledSearchEnginesLabels.size()){
0168     case 0: return QString(); ///< empty selection
0169     case 1: return enabledSearchEnginesLabels.first(); ///< just one search engine selected
0170     case 2:
0171         //: Two search engines selected
0172         return tr("%1 and %2").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1));
0173     case 3:
0174         //: Three search engines selected
0175         return tr("%1, %2, and %3").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1),enabledSearchEnginesLabels.at(2));
0176     case 4:
0177         //: Four search engines selected
0178         return tr("%1, %2, %3, and %4").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1),enabledSearchEnginesLabels.at(2),enabledSearchEnginesLabels.at(3));
0179     case 5:
0180         //: Five search engines selected
0181         return tr("%1, %2, %3, %4, and %5").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1),enabledSearchEnginesLabels.at(2),enabledSearchEnginesLabels.at(3),enabledSearchEnginesLabels.at(4));
0182     case 6:
0183         //: Six search engines selected
0184         return tr("%1, %2, %3, %4, %5, and %6").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1),enabledSearchEnginesLabels.at(2),enabledSearchEnginesLabels.at(3),enabledSearchEnginesLabels.at(4),enabledSearchEnginesLabels.at(5));
0185     case 7:
0186         //: Seven search engines selected
0187         return tr("%1, %2, %3, %4, %5, %6, and %7").arg(enabledSearchEnginesLabels.at(0),enabledSearchEnginesLabels.at(1),enabledSearchEnginesLabels.at(2),enabledSearchEnginesLabels.at(3),enabledSearchEnginesLabels.at(4),enabledSearchEnginesLabels.at(5),enabledSearchEnginesLabels.at(6));
0188     default:
0189         return enabledSearchEnginesLabels.join(", ");
0190     }
0191 }
0192 
0193 int SearchEngineList::getSearchEngineCount() const {
0194     if (empty()) return 0;
0195 
0196     const QSettings settings(QStringLiteral("harbour-bibsearch"), QStringLiteral("BibSearch"));
0197     int count = 0;
0198     for (int i = 0; i < size(); ++i)
0199         if (isSearchEngineEnabled(settings, at(i)))
0200             ++count;
0201     return count;
0202 }
0203 
0204 QHash<int, QByteArray> SearchEngineList::roleNames() const {
0205     QHash<int, QByteArray> roles;
0206     roles[LabelRole] = "label";
0207     roles[EngineEnabledRole] = "engineEnabled";
0208     return roles;
0209 }
0210 
0211 void SearchEngineList::resetProgress() {
0212     m_collectedProgress.clear();
0213 }
0214 
0215 int SearchEngineList::progress() const {
0216     int count = 0, sum = 0;
0217     for (QHash<QObject *, int>::ConstIterator it = m_collectedProgress.constBegin(); it != m_collectedProgress.constEnd(); ++it, ++count)
0218         sum += it.value();
0219     return count > 0 ? sum / count : 0;
0220 }
0221 
0222 void SearchEngineList::collectingProgress(int cur, int total) {
0223     if (cur > total) cur = total;
0224     m_collectedProgress.insert(sender(), total > 0 ? cur * 1000 / total : 0);
0225     emit progressChanged();
0226 }