1 /*  SPDX-License-Identifier: LGPL-2.0-or-later
2 
3     SPDX-FileCopyrightText: 2005 Christoph Cullmann <cullmann@kde.org>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef __KATE_SESSION_MANAGER_H__
9 #define __KATE_SESSION_MANAGER_H__
10 
11 #include "katesession.h"
12 
13 #include <KDirWatch>
14 
15 #include <QHash>
16 #include <QObject>
17 
18 #include <memory>
19 
20 typedef QList<KateSession::Ptr> KateSessionList;
21 
22 class KATE_TESTS_EXPORT KateSessionManager : public QObject
23 {
24     Q_OBJECT
25 
26     friend class KateSessionManageDialog;
27 
28 public:
29     KateSessionManager(QObject *parent = nullptr, const QString &sessionsDir = QString());
30 
31     /**
32      * allow access to the session list
33      * kept up to date by watching the dir
34      */
35     KateSessionList sessionList();
36 
37     /**
38      * activate session by \p name
39      * first, it will look if a session with this name exists in list
40      * if yes, it will use this session, else it will create a new session file
41      * @param name name of the session to activate
42      * @param closeAndSaveLast try to close and save last session or not?
43      * @param loadNew load new session stuff?
44      * @return false==session has been delegated, true==session has been activated in this distance
45      */
46     bool activateSession(const QString &name, const bool closeAndSaveLast = true, const bool loadNew = true);
47 
48     /**
49      * activates new/anonymous session
50      */
51     bool activateAnonymousSession();
52 
53     /**
54      * save current session
55      * @param rememberAsLast remember this session as last used?
56      * @return success
57      */
58     bool saveActiveSession(bool rememberAsLast = false);
59 
60     /**
61      * return the current active session
62      * sessionFile == empty means we have no session around for this instance of kate
63      * @return session active atm
64      */
activeSession()65     KateSession::Ptr activeSession()
66     {
67         return m_activeSession;
68     }
69 
70     /**
71      * session dir
72      * @return global session dir
73      */
sessionsDir()74     const QString &sessionsDir() const
75     {
76         return m_sessionsDir;
77     }
78 
79     /**
80      * initial session chooser, on app start
81      * @return success, if false, app should exit
82      */
83     bool chooseSession();
84 
85 public Q_SLOTS:
86     /**
87      * try to start a new session
88      * asks user first for name
89      */
90     void sessionNew();
91 
92     /**
93      * try to save current session
94      */
95     void sessionSave();
96 
97     /**
98      * try to save as current session
99      */
100     void sessionSaveAs();
101 
102     /**
103      * show dialog to manage our sessions
104      */
105     void sessionManage();
106 
107 Q_SIGNALS:
108     /**
109      * Emitted, whenever the session changes, e.g. when it was renamed.
110      */
111     void sessionChanged();
112 
113     /**
114      * Emitted whenever the session list has changed.
115      * @see sessionList()
116      */
117     void sessionListChanged();
118 
119     /**
120      * module internal APIs
121      */
122 public:
123     /**
124      * return session with given name
125      * if no existing session matches, create new one with this name
126      * @param name session name
127      */
128     KateSession::Ptr giveSession(const QString &name);
129 
130     /**
131      * Try to delete the @p session and removes the session from sessions list
132      * @param session the session to delete
133      * @return true on success, false if @p session is currently in use
134      */
135     bool deleteSession(KateSession::Ptr session);
136 
137     /**
138      * Try to copy the @p session to a new session @p newName.
139      * Will ask by @c askForNewSessionName() for a different name when @p newName is already in use or is an
140      * empty string.
141      * @param session the session to copy
142      * @param newName is wished name of the new session
143      * @return the new session name on success, otherwise an empty string
144      * @see askForNewSessionName()
145      */
146     QString copySession(const KateSession::Ptr &session, const QString &newName = QString());
147 
148     /**
149      * Try to rename the @p session to @p newName.
150      * Will ask by @c askForNewSessionName() for a different name when @p newName is already in use or is an
151      * empty string.
152      * @param session the session to rename
153      * @param newName is wished new name of the session
154      * @return the new session name on success, otherwise an empty string
155      * @see askForNewSessionName()
156      */
157     QString renameSession(KateSession::Ptr session, const QString &newName = QString());
158 
159     /**
160      * activate a session
161      * first, it will look if a session with this name exists in list
162      * if yes, it will use this session, else it will create a new session file
163      * @param session session to activate
164      * @param closeAndSaveLast try to close and save last session or not?
165      * @param loadNew load new session stuff?
166      * @return false==session has been delegated, true==session has been activated in this distance
167      */
168     bool activateSession(KateSession::Ptr session, const bool closeAndSaveLast = true, const bool loadNew = true);
169 
170 private Q_SLOTS:
171     /**
172      * trigger update of session list
173      */
174     void updateSessionList();
175 
176 private:
177     /**
178      * Ask the user for a new session name, when needed.
179      * @param session is the session to rename or copy
180      * @param newName is a preset value. Is @p newName not already in use is nothing asked
181      * @return a (currently) not used new session name or an empty string when
182      * user aborted or when @p newName is the current session name.
183      */
184     QString askForNewSessionName(KateSession::Ptr session, const QString &newName = QString());
185 
186     /**
187      * Try to generate a new session name from @p target by a number suffix.
188      * @param target is the base name
189      * @return a (currently) not used session name or an empty string
190      */
191     QString suggestNewSessionName(const QString &target);
192 
193     /**
194      * returns session config file according to policy
195      */
196     QString sessionFileForName(const QString &name) const;
197 
198     /**
199      * @return true when @p session is active in any Kate instance, otherwise false
200      */
201     bool sessionIsActive(const QString &session);
202 
203     /**
204      * returns session file for anonymous session
205      */
206     QString anonymousSessionFile() const;
207 
208     /**
209      * helper function to save the session to a given config object
210      */
211     void saveSessionTo(KConfig *sc) const;
212 
213     /**
214      * restore sessions documents, windows, etc...
215      */
216     void loadSession(const KateSession::Ptr &session) const;
217 
218     /**
219      * Writes sessions as jump list actions to the kate.desktop file
220      */
221     void updateJumpListActions(const QStringList &sessionList);
222 
223     /**
224      * Given a config group name, determines if the group represents
225      * a session ViewSpace group (i.e. "MainWindowN-ViewSpace N [doc url]")
226      * and, if so,
227      *  - returns TRUE if the document referred to has no views
228      *            and the session is not anonymous;
229      *  - returns FALSE otherwise.
230      *
231      *  A document does not have a view when it is opened in a named session
232      *  until its tab is activated.
233      */
234     static bool isViewLessDocumentViewSpaceGroup(const QString &group);
235 
236 private:
237     /**
238      * absolute path to dir in home dir where to store the sessions
239      */
240     QString m_sessionsDir;
241 
242     /**
243      * list of current available sessions
244      */
245     QHash<QString, KateSession::Ptr> m_sessions;
246 
247     /**
248      * current active session
249      */
250     KateSession::Ptr m_activeSession;
251 
252     std::unique_ptr<KDirWatch> m_dirWatch;
253 };
254 
255 #endif
256