File indexing completed on 2024-05-19 05:05:46

0001 /***************************************************************************
0002  *   SPDX-License-Identifier: GPL-2.0-or-later
0003  *                                                                         *
0004  *   SPDX-FileCopyrightText: 2004-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 "bibliographyservice.h"
0021 
0022 #include <QCoreApplication>
0023 #include <QStandardPaths>
0024 #include <QProcess>
0025 
0026 #include <KSharedConfig>
0027 #include <KConfigGroup>
0028 #include <KLocalizedString>
0029 #include <KMessageBox>
0030 
0031 class BibliographyService::Private
0032 {
0033 private:
0034     /// Representing configuration file "mimeapps.list"
0035     /// see https://www.freedesktop.org/wiki/Specifications/mime-apps-spec/
0036     KSharedConfig::Ptr configXDGMimeAppsList;
0037     /// Groups inside "mimeapps.list"
0038     KConfigGroup configGroupAddedKDEServiceAssociations, configGroupRemovedKDEServiceAssociations;
0039     KConfigGroup configGroupAddedAssociations, configGroupRemovedAssociations;
0040 
0041     /// Names of .desktop files for KBibTeX (application and KPart)
0042     static const QString kbibtexApplicationDesktop;
0043     static const QString kbibtexPartDesktop;
0044     /// Names of .desktop files for Kate (application and KPart)
0045     static const QString kateApplicationDesktop;
0046     static const QString katePartDesktop;
0047 
0048 public:
0049     QWidget *parentWidget;
0050     static const QStringList textBasedMimeTypes;
0051 
0052     Private(QWidget *w, BibliographyService *parent)
0053             : configXDGMimeAppsList(KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation)),
0054           configGroupAddedKDEServiceAssociations(configXDGMimeAppsList, QStringLiteral("Added KDE Service Associations")),
0055           configGroupRemovedKDEServiceAssociations(configXDGMimeAppsList, QStringLiteral("Removed KDE Service Associations")),
0056           configGroupAddedAssociations(configXDGMimeAppsList, QStringLiteral("Added Associations")),
0057           configGroupRemovedAssociations(configXDGMimeAppsList, QStringLiteral("Removed Associations")),
0058           parentWidget(w)
0059     {
0060         Q_UNUSED(parent)
0061     }
0062 
0063     bool setKBibTeXforMimeType(const QString &mimetype, const bool isPlainTextFormat) {
0064         /// Check that configuration file is writeable before continuing
0065         if (!configXDGMimeAppsList->isConfigWritable(true))
0066             return false;
0067 
0068         /// Configuration which application to use to open bibliography files
0069         QStringList addedAssociations = configGroupAddedAssociations.readXdgListEntry(mimetype, QStringList());
0070         /// Remove KBibTeX from list (will be added later to list's head)
0071         addedAssociations.removeAll(kbibtexApplicationDesktop);
0072         if (isPlainTextFormat) {
0073             /// Remove Kate from list (will be added later to list's second position)
0074             addedAssociations.removeAll(kateApplicationDesktop);
0075             /// Add Kate to list's head (will turn up as second)
0076             addedAssociations.prepend(kateApplicationDesktop);
0077         }
0078         /// Add KBibTeX to list's head
0079         addedAssociations.prepend(kbibtexApplicationDesktop);
0080         /// Write out and sync changes
0081         configGroupAddedAssociations.writeXdgListEntry(mimetype, addedAssociations);
0082         configGroupAddedAssociations.sync();
0083 
0084         /// Configuration which part to use to open bibliography files
0085         QStringList addedKDEServiceAssociations = configGroupAddedKDEServiceAssociations.readXdgListEntry(mimetype, QStringList());
0086         /// Remove KBibTeX from list (will be added later to list's head)
0087         addedKDEServiceAssociations.removeAll(kbibtexPartDesktop);
0088         if (isPlainTextFormat) {
0089             /// Remove Kate from list (will be added later to list's second position)
0090             addedKDEServiceAssociations.removeAll(katePartDesktop);
0091             /// Add Kate to list's head (will turn up as second)
0092             addedKDEServiceAssociations.prepend(katePartDesktop);
0093         }
0094         /// Add KBibTeX to list's head
0095         addedKDEServiceAssociations.prepend(kbibtexPartDesktop);
0096         /// Write out and sync changes
0097         configGroupAddedKDEServiceAssociations.writeXdgListEntry(mimetype, addedKDEServiceAssociations);
0098         configGroupAddedKDEServiceAssociations.sync();
0099 
0100         /// Configuration which application NOT to use to open bibliography files
0101         QStringList removedAssociations = configGroupRemovedAssociations.readXdgListEntry(mimetype, QStringList());
0102         /// If list of applications not to use is not empty ...
0103         if (!removedAssociations.isEmpty()) {
0104             /// Remove KBibTeX from list
0105             removedAssociations.removeAll(kbibtexApplicationDesktop);
0106             if (isPlainTextFormat)
0107                 /// Remove Kate from list
0108                 removedAssociations.removeAll(kateApplicationDesktop);
0109             if (removedAssociations.isEmpty())
0110                 /// Empty lists can be removed from configuration file
0111                 configGroupRemovedAssociations.deleteEntry(mimetype);
0112             else
0113                 /// Write out updated list
0114                 configGroupRemovedAssociations.writeXdgListEntry(mimetype, removedAssociations);
0115             /// Sync changes
0116             configGroupRemovedAssociations.sync();
0117         }
0118 
0119         /// Configuration which part NOT to use to open bibliography files
0120         QStringList removedKDEServiceAssociations = configGroupRemovedKDEServiceAssociations.readXdgListEntry(mimetype, QStringList());
0121         /// If list of parts not to use is not empty ...
0122         if (!removedKDEServiceAssociations.isEmpty()) {
0123             /// Remove KBibTeX part from list
0124             removedKDEServiceAssociations.removeAll(kbibtexPartDesktop);
0125             if (isPlainTextFormat)
0126                 /// Remove Kate part from list
0127                 removedKDEServiceAssociations.removeAll(katePartDesktop);
0128             if (removedKDEServiceAssociations.isEmpty())
0129                 /// Empty lists can be removed from configuration file
0130                 configGroupRemovedKDEServiceAssociations.deleteEntry(mimetype);
0131             else
0132                 /// Write out updated list
0133                 configGroupRemovedKDEServiceAssociations.writeXdgListEntry(mimetype, removedKDEServiceAssociations);
0134             /// Sync changes
0135             configGroupRemovedKDEServiceAssociations.sync();
0136         }
0137 
0138         return true;
0139     }
0140 
0141     bool isKBibTeXdefaultForMimeType(const QString &mimetype) const {
0142         /// Fetch all four configuration groups
0143         const QStringList addedAssociations = configGroupAddedAssociations.readXdgListEntry(mimetype, QStringList());
0144         const QStringList addedKDEServiceAssociations = configGroupAddedKDEServiceAssociations.readXdgListEntry(mimetype, QStringList());
0145         const QStringList removedAssociations = configGroupRemovedAssociations.readXdgListEntry(mimetype, QStringList());
0146         const QStringList removedKDEServiceAssociations = configGroupRemovedKDEServiceAssociations.readXdgListEntry(mimetype, QStringList());
0147         /// KBibTeX is default editor for bibliography if ...
0148         /// - the list of applications associated to mime type is not empty
0149         /// - KBibTeX is head of this list
0150         /// - KBibTeX is not named in the list of applications not be used
0151         /// - the list of parts associated to mime type is not empty
0152         /// - KBibTeX part is head of this list
0153         /// - KBibTeX part is not named in the list of parts not be used
0154         return !addedAssociations.isEmpty() && addedAssociations.first() == kbibtexApplicationDesktop && !removedAssociations.contains(kbibtexApplicationDesktop) && !addedKDEServiceAssociations.isEmpty() && addedKDEServiceAssociations.first() == kbibtexPartDesktop && !removedKDEServiceAssociations.contains(kbibtexPartDesktop);
0155     }
0156 };
0157 
0158 const QString BibliographyService::Private::kbibtexApplicationDesktop = QStringLiteral("org.kde.kbibtex.desktop");
0159 const QString BibliographyService::Private::kbibtexPartDesktop = QStringLiteral("kbibtexpart.desktop");
0160 const QString BibliographyService::Private::kateApplicationDesktop = QStringLiteral("org.kde.kate.desktop");
0161 const QString BibliographyService::Private::katePartDesktop = QStringLiteral("katepart.desktop");
0162 const QStringList BibliographyService::Private::textBasedMimeTypes {
0163     QStringLiteral("text/x-bibtex"), ///< classical BibTeX bibliographies
0164     QStringLiteral("application/x-research-info-systems"), ///< Research Information Systems (RIS) bibliographies
0165     QStringLiteral("application/x-isi-export-format") ///< Information Sciences Institute (ISI) bibliographies
0166 };
0167 
0168 BibliographyService::BibliographyService(QWidget *parentWidget)
0169         : QObject(parentWidget), d(new BibliographyService::Private(parentWidget, this))
0170 {
0171     /// nothing
0172 }
0173 
0174 BibliographyService::~BibliographyService()
0175 {
0176     delete d;
0177 }
0178 
0179 void BibliographyService::setKBibTeXasDefault() {
0180     /// Go through all supported mime types
0181     for (const QString &mimeType : BibliographyService::Private::textBasedMimeTypes) {
0182         d->setKBibTeXforMimeType(mimeType, true);
0183     }
0184 
0185     /// kbuildsycoca5 has to be run to update the mime type associations
0186     QProcess *kbuildsycoca5Process = new QProcess(d->parentWidget);
0187     connect(kbuildsycoca5Process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), QCoreApplication::instance(), [this](const int exitCode, const QProcess::ExitStatus exitStatus) {
0188         if (exitCode != 0 || exitStatus != QProcess::NormalExit)
0189             KMessageBox::error(d->parentWidget, i18n("Failed to run 'kbuildsycoca5' to update mime type associations.\n\nThe system may not know how to use KBibTeX to open bibliography files."), i18n("Failed to run 'kbuildsycoca5'"));
0190     });
0191     kbuildsycoca5Process->start(QStringLiteral("kbuildsycoca5"), QStringList());
0192 }
0193 
0194 bool BibliographyService::isKBibTeXdefault() const {
0195     /// Go through all supported mime types
0196     for (const QString &mimeType : BibliographyService::Private::textBasedMimeTypes) {
0197         /// Test if KBibTeX is default handler for mime type
0198         if (!d->isKBibTeXdefaultForMimeType(mimeType))
0199             return false; ///< Failing any test means KBibTeX is not default application/part
0200     }
0201     return true; ///< All tests passed, KBibTeX is default application/part
0202 }