File indexing completed on 2024-04-28 04:58:30

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2023 Stefano Crocco <stefano.crocco@alice.it>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef ACTIVITYMANAGER_H
0008 #define ACTIVITYMANAGER_H
0009 
0010 #include <QObject>
0011 
0012 #include <KX11Extras>
0013 
0014 class KonqMainWindow;
0015 namespace KActivities {
0016   class Consumer;
0017 };
0018 
0019 /**
0020  * @brief Class which handles closing and restoring windows according to the current activity
0021  *
0022  * In particular, this class:
0023  * - closes windows when all the activities they belong to are stopped
0024  * - stores information about windows which are closed because they only belong to stopped activities
0025  * - creates windows belonging to activities which are restarted
0026  * - removes information about deleted activities
0027  * - removes information about windows closed by the user
0028  *
0029  * All of this is made keeping a configuration file called `activitiesrc` in `./local/share/konqueror`.
0030  * This file contains:
0031  * - a list of all windows associated with each activity
0032  * - a list of information about windows belonging only to stopped activities (which means no window object exists for them)
0033  *  so they can be restored when the activities are started again
0034  */
0035 class ActivityManager : public QObject
0036 {
0037     Q_OBJECT
0038 
0039 public:
0040     /**
0041      * @brief Constructor
0042      *
0043      * @param parent the parent object
0044      */
0045     ActivityManager(QObject *parent = nullptr);
0046 
0047     /**
0048      * @brief Destructor
0049      */
0050     ~ActivityManager();
0051 
0052     /**
0053      * @brief Makes the necessary connections with a new KonqMainWindow
0054      *
0055      * @warning Never call this function more than once for the same window
0056      * @param window the window to connect to
0057      */
0058     void registerMainWindow(KonqMainWindow *window);
0059 
0060     bool restoringStoppedActivity() const {return m_restoringStoppedActivity;}
0061 
0062     void restoringStoppedActivityDone() {m_restoringStoppedActivity = false;}
0063 
0064 private slots:
0065 
0066     /**
0067      * @brief Removes all information about a window when it's closed
0068      *
0069      * This removes both information to restore the window and information about which
0070      * activities the window used to belong to
0071      * @param window the window
0072      */
0073     void removeWindowFromActivities(KonqMainWindow *window);
0074 
0075     /**
0076      * @brief Performs the operations needed to keep windows in sync with running activities
0077      *
0078      * In particular, this method:
0079      * - finds out which windows should be closed because all the activities they belong to are closed
0080      * - saves informations about the windows to close
0081      * - closes the windows which only belong to stopped activities
0082      * - checks whether there are windows which belong to running activities but which don't exist and creates them
0083      * @note this method ignores preloaded windows (if any)
0084      * @param runningActivities the list of identifiers of all running activities
0085      */
0086     void handleRunningActivitiesChange(const QStringList &runningActivities);
0087 
0088     /**
0089      * @brief Removes information about a deleted activity
0090      *
0091      * This means:
0092      * - removing the list of windows belonging to the activity
0093      * - removing all information about those windows only belonging to the activity
0094      * @param id the id of activity to remove
0095      */
0096     void removeActivityState(const QString &id);
0097 
0098 private:
0099 
0100     /**
0101      * @brief Stores information about windows and activities
0102      *
0103      * This method stores the information necessary to create the windows and updates the list of windows belonging
0104      * to each activity with the information contained in @p windowsWithActivities.
0105      *
0106      * @note This method doesn't replace the list of windows belonging to each activity, but "merge" that list with the information
0107      * from @p windowsWithActivities. In particular, for each activity:
0108      * - existing windows not included in @p windowsWithActivities remain untouched
0109      * - windows in @p windowsWithActivities are removed from activities which aren't listed in @p windowsWithActivities and added to
0110      *  activities listed in @p windowsWithActivities.
0111      *
0112      * @param windowsWithActivities a hash containing the list of activities each window belong to. The windows are
0113      * the keys while the list of activities are the values
0114      */
0115     void saveWindowsActivityInfo(const QHash<KonqMainWindow*, QStringList> &windowsWithActivities);
0116 
0117     /**
0118      * @brief Reacts to change in the activity settings for a given window
0119      *
0120      * If the window used to belong to a running activity but doesn't do so anymore, information about it is saved using saveWindowsActivityInfo()
0121      * and the window is closed.
0122      *
0123      * If the window belongs to an activity which is currently running, nothing is done because the activity system takes care of managing windows
0124      * itself.
0125      *
0126      * @note This method assumes that it can't be called for a windows which only belonged to stopped activities. The rationale for this assumption
0127      * is that windows belonging only to stopped activities should be closed, and so they can't have a window id.
0128      * @param id the window id of the changed window
0129      * @param prop unused
0130      * @param prop2 a list of the properties of type `NET::Properties2` which have changed. This method does nothing if this doesn't include `WM2Activities`
0131      */
0132     void handleWindowChanged(WId id, NET::Properties prop, NET::Properties2 prop2);
0133 
0134     /**
0135      * @brief Closes a window in a way which works correctly with activities management
0136      *
0137      * When a window needs to be closed because all the activities it belongs to have been stopped, ActivityManager must call this method instead of
0138      * directly calling KonqMainWindow::close() to ensure that the window is closed in a way which allows to correctly restore it when the activities
0139      * are started again. In particular, this means:
0140      * - ensuring that removeActivityState() isn't called, otherwise the data needed to restore the window would be deleted
0141      * - not actually closing the window if it's the last window in the application. In this cause, closing the window would also close the application,
0142      *  preventing the global activity manager from recording that Konqueror needs to be started when one of the activities the window belongs to is
0143      *  restarted.
0144      *
0145      * @param window the window to close
0146      */
0147     void closeWindowBecauseNotInRunningActivities(KonqMainWindow *window);
0148 
0149     /**
0150      * @brief Creates a window using the information from the activity configuration file
0151      *
0152      * The window is moved to the appropriate activities.
0153      *
0154      * @param uuid the uuid of the window to restore
0155      * @return the restored window
0156      */
0157     KonqMainWindow* restoreWindowFromActivityState(const QString &uuid);
0158 
0159     /**
0160      * @return The path of the configuration file where activities information is stored
0161      */
0162     static QString activitiesConfigPath();
0163 
0164     /**
0165      * @return The name of the configuration group containing the windows for each activity
0166      */
0167     static QString activitiesGroupName();
0168 
0169     /**
0170      * @brief Removes duplicate entries from a list
0171      *
0172      * @note The elements of the list may change order
0173      * @param lst the list
0174      */
0175     void makeUnique(QStringList &lst);
0176 
0177 private:
0178 
0179     /**
0180      * @brief The object informing about the changes about running activities and deleted activities
0181      */
0182     KActivities::Consumer *m_activitiesConsumer;
0183 
0184     /**
0185      * @brief Whether we're in the process of restoring a stopped activity
0186      *
0187      *
0188      */
0189     bool m_restoringStoppedActivity = false;
0190 };
0191 
0192 #endif // ACTIVITYMANAGER_H