File indexing completed on 2024-12-01 09:55:33

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org>
0004     SPDX-FileCopyrightText: 2005-2008 David Faure <faure@kde.org>
0005     SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only
0008 */
0009 
0010 #ifndef KSYCOCA_H
0011 #define KSYCOCA_H
0012 
0013 #include <kservice_export.h>
0014 #include <ksycocatype.h>
0015 
0016 #include <QObject>
0017 #include <QStringList>
0018 
0019 class QDataStream;
0020 class KSycocaFactory;
0021 class KSycocaFactoryList;
0022 class KSycocaPrivate;
0023 
0024 /**
0025  * Executable name of the kbuildsycoca program
0026  */
0027 #define KBUILDSYCOCA_EXENAME "kbuildsycoca5"
0028 
0029 /**
0030  * @internal
0031  * Read-only SYstem COnfiguration CAche
0032  */
0033 class KSERVICE_EXPORT KSycoca : public QObject
0034 {
0035     Q_OBJECT
0036     // Q_CLASSINFO("D-Bus Interface", "org.kde.KSycoca")
0037 
0038 protected:
0039     /**
0040      * @internal
0041      * Building database
0042      */
0043     explicit KSycoca(bool /* buildDatabase */);
0044 
0045 public:
0046     /**
0047      * type of database
0048      * @see absoluteFilePath()
0049      */
0050     typedef enum { LocalDatabase, GlobalDatabase } DatabaseType; // TODO KF6: remove
0051 
0052     /**
0053      * Read-only database
0054      */
0055     KSycoca();
0056 
0057     /**
0058      * Get or create the only instance of KSycoca (read-only)
0059      */
0060     static KSycoca *self();
0061 
0062     ~KSycoca() override;
0063 
0064     /**
0065      * @return the compiled-in version, i.e. the one used when writing a new ksycoca
0066      */
0067     static int version();
0068 
0069     /**
0070      * @return true if the ksycoca database is available
0071      * This is usually the case, except if KDE isn't installed yet,
0072      * or before kded is started.
0073      */
0074     static bool isAvailable();
0075 
0076     /**
0077      * @internal - called by factories in read-only mode
0078      * This is how factories get a stream to an entry
0079      */
0080     QDataStream *findEntry(int offset, KSycocaType &type); // KF6: make it private
0081     /**
0082      * @internal - called by factories in read-only mode
0083      * Returns stream(), but positioned for reading this factory, 0 on error.
0084      */
0085     QDataStream *findFactory(KSycocaFactoryId id); // KF6: make it private
0086 
0087     /**
0088      * @internal - returns absolute file path of the database
0089      *
0090      * For the global database type, the database is searched under
0091      * the 'share/ksycoca' install path.
0092      * Otherwise, the value from the environment variable KDESYCOCA
0093      * is returned if set. If not set the path is built based on
0094      * QStandardPaths cache save location, typically ~/.cache on Unix.
0095      *
0096      * Since 5.15, the filename includes language and a sha1 of the directories
0097      * in GenericDataLocation, i.e. the directories with the desktop files.
0098      * This allows to have one database per setup, when using different install prefixes
0099      * or when switching languages.
0100      */
0101     static QString absoluteFilePath(DatabaseType type = LocalDatabase);
0102 
0103 #if KSERVICE_ENABLE_DEPRECATED_SINCE(5, 15)
0104     /**
0105      * @internal - returns language stored inside database
0106      */
0107     KSERVICE_DEPRECATED_VERSION(5, 15, "No longer use.")
0108     QString language(); // KF6: remove
0109 
0110     /**
0111      * @internal - returns timestamp of database
0112      *
0113      * The database contains all changes made _before_ this time and
0114      * _might_ contain changes made after that.
0115      */
0116     KSERVICE_DEPRECATED_VERSION(5, 15, "No longer use.")
0117     quint32 timeStamp(); // KF6: remove
0118 
0119     /**
0120      * @internal - returns update signature of database
0121      *
0122      * Signature that keeps track of changes to
0123      * $KDEDIR/share/services/update_ksycoca
0124      *
0125      * Touching this file causes the database to be recreated
0126      * from scratch.
0127      */
0128     KSERVICE_DEPRECATED_VERSION(5, 15, "No longer use.")
0129     quint32 updateSignature(); // KF6: remove
0130 #endif
0131 
0132     /**
0133      * @internal - returns all directories with information
0134      * stored inside sycoca.
0135      */
0136     QStringList allResourceDirs(); // KF6: make it private
0137 
0138     /**
0139      * @internal - add a factory
0140      */
0141     void addFactory(KSycocaFactory *); // KF6: make it private
0142 
0143     /**
0144      * @internal
0145      * @return true if building (i.e. if a KBuildSycoca);
0146      */
0147     virtual bool isBuilding();
0148 
0149     /**
0150      * Disables automatic rebuilding of the cache on service file changes.
0151      * Be extremely careful when using this. Only threads that definitely have no use for
0152      * automatic reloading should use this. Specifically shared runner threads (as seen in
0153      * the threadweaver framework) can avoid claiming persistent resources this way
0154      * (e.g. inotify instances on Linux).
0155      */
0156     static void disableAutoRebuild();
0157 
0158 #if KSERVICE_ENABLE_DEPRECATED_SINCE(5, 0)
0159     /**
0160      * When you receive a "databaseChanged" signal, you can query here if
0161      * a change has occurred in a specific resource type.
0162      * @see KStandardDirs for the various resource types.
0163      *
0164      * This method is meant to be called from the GUI thread only.
0165      *
0166      * @deprecated Since 5.0, use the @c KSycoca::databaseChanged() signal instead.
0167      */
0168     KSERVICE_DEPRECATED_VERSION(5, 0, "Use KSycoca::databaseChanged() signal")
0169     static bool isChanged(const char *type);
0170 #endif
0171 
0172     /**
0173      * A read error occurs.
0174      * @internal
0175      */
0176     static void flagError();
0177 
0178     /**
0179      * Ensures the ksycoca database is up to date.
0180      * If the database was modified by another process, close it, so the next use reopens it.
0181      * If the desktop files have been modified more recently than the database, update it.
0182      *
0183      * Update the sycoca file from the files on disk (e.g. desktop files or mimeapps.list).
0184      * You don't normally have to call this because the next use of KSycoca
0185      * (e.g. via KMimeTypeTrader, KService etc.) will notice that the sycoca
0186      * database is out of date, by looking a directory modification times.
0187      * In addition, in a full KDE session, kded monitors directories to detect changes.
0188      *
0189      * This is however useful for GUIs that allow to create a new desktop file
0190      * and then want to ensure it is available immediately in KSycoca.
0191      * This is also useful after modifying a mimeapps.list file.
0192      *
0193      * KBuildSycocaProgressDialog can also be used instead of this method, in GUI apps.
0194      *
0195      * @since 5.15
0196      */
0197     void ensureCacheValid(); // Warning for kservice code: this can delete all the factories.
0198 
0199 Q_SIGNALS:
0200     /**
0201      * Connect to this to get notified when the database changes.
0202      *
0203      * Example: after creating a .desktop file in KOpenWithDialog, it
0204      * must wait until kbuildsycoca5 finishes until the KService::Ptr is available.
0205      * Other examples: anything that displays a list of apps or plugins to the user
0206      * and which is always visible (otherwise querying sycoca before showing
0207      * could be enough).
0208      */
0209     void databaseChanged(); // clazy:exclude=overloaded-signal
0210 
0211 #if KSERVICE_ENABLE_DEPRECATED_SINCE(5, 80)
0212     /**
0213      * Connect to this to get notified when the database changes
0214      * Example: when MIME type definitions have changed, applications showing
0215      * files as icons refresh icons to take into account the new MIME types.
0216      * Another example: after creating a .desktop file in KOpenWithDialog,
0217      * it must wait until kbuildsycoca5 finishes until the KService::Ptr is available.
0218      *
0219      * @param changedResources List of resources where changes were detected.
0220      * This can include the following resources (as defined in KStandardDirs) :
0221      * apps, xdgdata-apps, services, servicetypes, xdgdata-mime.
0222      *
0223      * @deprecated since 5.80, use the @c KSycoca::databaseChanged() signal instead.
0224      */
0225     KSERVICE_DEPRECATED_VERSION(5, 80, "Use KSycoca::databaseChanged() signal")
0226     void databaseChanged(const QStringList &changedResources); // clazy:exclude=overloaded-signal
0227 #endif
0228 
0229 protected:
0230     // @internal used by kbuildsycoca
0231     KSycocaFactoryList *factories();
0232 
0233     // @internal used by factories and kbuildsycoca
0234     QDataStream *&stream();
0235     friend class KSycocaFactory;
0236     friend class KSycocaDict;
0237 
0238     void connectNotify(const QMetaMethod &signal) override;
0239 
0240 private:
0241     /**
0242      * Clear all caches related to ksycoca contents.
0243      * @internal only used by kded and kbuildsycoca.
0244      */
0245     static void clearCaches();
0246 
0247     KSERVICE_NO_EXPORT bool needsRebuild();
0248 
0249     friend class KBuildSycoca;
0250     friend class Kded;
0251     friend class KSycocaPrivate;
0252     friend class KSycocaXdgDirsTest;
0253 
0254     Q_DISABLE_COPY(KSycoca)
0255     KSycocaPrivate *const d;
0256 };
0257 
0258 #endif