File indexing completed on 2024-05-12 05:52:08

0001 /*
0002     SPDX-FileCopyrightText: 2005 Christoph Cullmann <cullmann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "katesession.h"
0010 
0011 #include <QFileSystemWatcher>
0012 #include <QHash>
0013 #include <QObject>
0014 #include <QTimer>
0015 
0016 typedef QList<KateSession::Ptr> KateSessionList;
0017 
0018 class KATE_PRIVATE_EXPORT KateSessionManager : public QObject
0019 {
0020     Q_OBJECT
0021 
0022     friend class KateSessionManageDialog;
0023 
0024 public:
0025     /**
0026      * Helper to block session auto save
0027      */
0028     class AutoSaveBlocker final
0029     {
0030     public:
0031         /**
0032          * Block auto saving.
0033          */
0034         AutoSaveBlocker(KateSessionManager *manager)
0035             : m_manager(manager)
0036         {
0037             // block new invocations of the timer and ensure it is not already running
0038             ++m_manager->m_sessionSaveTimerBlocked;
0039             m_manager->m_sessionSaveTimer.stop();
0040         }
0041 
0042         /**
0043          * Unblock auto saving.
0044          */
0045         ~AutoSaveBlocker()
0046         {
0047             --m_manager->m_sessionSaveTimerBlocked;
0048         }
0049 
0050     private:
0051         KateSessionManager *const m_manager;
0052     };
0053 
0054     KateSessionManager(QObject *parent, const QString &sessionsDir);
0055     ~KateSessionManager() override;
0056 
0057     /**
0058      * allow access to the session list
0059      * kept up to date by watching the dir
0060      */
0061     KateSessionList sessionList();
0062 
0063     /**
0064      * activate session by \p name
0065      * first, it will look if a session with this name exists in list
0066      * if yes, it will use this session, else it will create a new session file
0067      * @param name name of the session to activate
0068      * @param closeAndSaveLast try to close and save last session or not?
0069      * @param loadNew load new session stuff?
0070      * @return false==session has been delegated, true==session has been activated in this distance
0071      */
0072     bool activateSession(const QString &name, const bool closeAndSaveLast = true, const bool loadNew = true);
0073 
0074     /**
0075      * activates new/anonymous session
0076      */
0077     bool activateAnonymousSession();
0078 
0079     /**
0080      * save current session
0081      * @param rememberAsLast remember this session as last used?
0082      * @return success
0083      */
0084     bool saveActiveSession(bool rememberAsLast = false);
0085 
0086     /**
0087      * return the current active session
0088      * sessionFile == empty means we have no session around for this instance of kate
0089      * @return session active atm
0090      */
0091     KateSession::Ptr activeSession()
0092     {
0093         return m_activeSession;
0094     }
0095 
0096     /**
0097      * session dir
0098      * @return global session dir
0099      */
0100     const QString &sessionsDir() const
0101     {
0102         return m_sessionsDir;
0103     }
0104 
0105     /**
0106      * initial session chooser, on app start
0107      * @return success, if false, app should exit
0108      */
0109     bool chooseSession();
0110 
0111 public Q_SLOTS:
0112     /**
0113      * try to start a new session
0114      * asks user first for name
0115      */
0116     void sessionNew();
0117 
0118     /**
0119      * try to save current session
0120      */
0121     void sessionSave();
0122 
0123     /**
0124      * try to save as current session
0125      */
0126     void sessionSaveAs();
0127 
0128     /**
0129      * show dialog to manage our sessions
0130      */
0131     static void sessionManage();
0132 
0133 Q_SIGNALS:
0134     /**
0135      * Emitted, whenever the session changes, e.g. when it was renamed.
0136      */
0137     void sessionChanged();
0138 
0139     /**
0140      * Emitted whenever the session list has changed.
0141      * @see sessionList()
0142      */
0143     void sessionListChanged();
0144 
0145     /**
0146      * module internal APIs
0147      */
0148 public:
0149     /**
0150      * return session with given name
0151      * if no existing session matches, create new one with this name
0152      * @param name session name
0153      */
0154     KateSession::Ptr giveSession(const QString &name);
0155 
0156     /**
0157      * Try to delete the @p session and removes the session from sessions list
0158      * @param session the session to delete
0159      * @return true on success, false if @p session is currently in use
0160      */
0161     bool deleteSession(KateSession::Ptr session);
0162 
0163     /**
0164      * Try to copy the @p session to a new session @p newName.
0165      * Will ask by @c askForNewSessionName() for a different name when @p newName is already in use or is an
0166      * empty string.
0167      * @param session the session to copy
0168      * @param newName is wished name of the new session
0169      * @return the new session name on success, otherwise an empty string
0170      * @see askForNewSessionName()
0171      */
0172     QString copySession(const KateSession::Ptr &session, const QString &newName = QString());
0173 
0174     /**
0175      * Try to rename the @p session to @p newName.
0176      * Will ask by @c askForNewSessionName() for a different name when @p newName is already in use or is an
0177      * empty string.
0178      * @param session the session to rename
0179      * @param newName is wished new name of the session
0180      * @return the new session name on success, otherwise an empty string
0181      * @see askForNewSessionName()
0182      */
0183     QString renameSession(KateSession::Ptr session, const QString &newName = QString());
0184 
0185     /**
0186      * activate a session
0187      * first, it will look if a session with this name exists in list
0188      * if yes, it will use this session, else it will create a new session file
0189      * @param session session to activate
0190      * @param closeAndSaveLast try to close and save last session or not?
0191      * @param loadNew load new session stuff?
0192      * @return false==session has been delegated, true==session has been activated in this distance
0193      */
0194     bool activateSession(KateSession::Ptr session, const bool closeAndSaveLast = true, const bool loadNew = true);
0195 
0196 private Q_SLOTS:
0197     /**
0198      * trigger update of session list
0199      */
0200     void updateSessionList();
0201 
0202 private:
0203     /**
0204      * Ask the user for a new session name, when needed.
0205      * @param session is the session to rename or copy
0206      * @param newName is a preset value. Is @p newName not already in use is nothing asked
0207      * @return a (currently) not used new session name or an empty string when
0208      * user aborted or when @p newName is the current session name.
0209      */
0210     QString askForNewSessionName(KateSession::Ptr session, const QString &newName = QString());
0211 
0212     /**
0213      * Try to generate a new session name from @p target by a number suffix.
0214      * @param target is the base name
0215      * @return a (currently) not used session name or an empty string
0216      */
0217     QString suggestNewSessionName(const QString &target);
0218 
0219     /**
0220      * returns session config file according to policy
0221      */
0222     QString sessionFileForName(const QString &name) const;
0223 
0224     /**
0225      * @return true when @p session is active in any Kate instance, otherwise false
0226      */
0227     bool sessionIsActive(const QString &session);
0228 
0229     /**
0230      * returns session file for anonymous session
0231      */
0232     QString anonymousSessionFile() const;
0233 
0234     /**
0235      * helper function to save the session to a given config object
0236      */
0237     static void saveSessionTo(KConfig *sc);
0238 
0239     /**
0240      * restore sessions documents, windows, etc...
0241      */
0242     void loadSession(const KateSession::Ptr &session) const;
0243 
0244     /**
0245      * Writes sessions as jump list actions to the kate.desktop file
0246      */
0247     static void updateJumpListActions(const QStringList &sessionList);
0248 
0249     /**
0250      * Given a config group name, determines if the group represents
0251      * a session ViewSpace group (i.e. "MainWindowN-ViewSpace N [doc url]")
0252      * and, if so,
0253      *  - returns TRUE if the document referred to has no views
0254      *            and the session is not anonymous;
0255      *  - returns FALSE otherwise.
0256      *
0257      *  A document does not have a view when it is opened in a named session
0258      *  until its tab is activated.
0259      */
0260     static bool isViewLessDocumentViewSpaceGroup(const QString &group);
0261 
0262 private:
0263     /**
0264      * absolute path to dir in home dir where to store the sessions
0265      */
0266     const QString m_sessionsDir;
0267 
0268     /**
0269      * list of current available sessions
0270      */
0271     QHash<QString, KateSession::Ptr> m_sessions;
0272 
0273     /**
0274      * current active session
0275      */
0276     KateSession::Ptr m_activeSession;
0277 
0278     /**
0279      * watcher for the session directory
0280      * allows to monitor outside changes
0281      */
0282     QFileSystemWatcher m_dirWatch;
0283 
0284     /**
0285      * timer for session auto saving
0286      */
0287     QTimer m_sessionSaveTimer;
0288 
0289     /**
0290      * is auto saving disabled at the moment?
0291      * needed e.g. during some session manipulation and window/application closing
0292      */
0293     unsigned int m_sessionSaveTimerBlocked = 0;
0294 };