1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 * Copyright (C) 2014 Piotr Wójcik <chocimier@tlen.pl>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **************************************************************************/
20 
21 #ifndef OTTER_SESSIONSMANAGER_H
22 #define OTTER_SESSIONSMANAGER_H
23 
24 #include "SettingsManager.h"
25 #include "ToolBarsManager.h"
26 #include "Utils.h"
27 
28 #include <QtCore/QCoreApplication>
29 #include <QtCore/QDateTime>
30 #include <QtCore/QRect>
31 
32 namespace Otter
33 {
34 
35 struct ToolBarState final
36 {
37 	enum ToolBarVisibility
38 	{
39 		UnspecifiedVisibilityToolBar = 0,
40 		AlwaysVisibleToolBar,
41 		AlwaysHiddenToolBar
42 	};
43 
44 	Qt::ToolBarArea location = Qt::NoToolBarArea;
45 	int identifier = -1;
46 	int row = -1;
47 	ToolBarVisibility normalVisibility = UnspecifiedVisibilityToolBar;
48 	ToolBarVisibility fullScreenVisibility = UnspecifiedVisibilityToolBar;
49 
ToolBarStatefinal50 	explicit ToolBarState()
51 	{
52 	}
53 
ToolBarStatefinal54 	explicit ToolBarState(int identifierValue, const ToolBarsManager::ToolBarDefinition &definition) : identifier(identifierValue)
55 	{
56 		normalVisibility = ((definition.normalVisibility != ToolBarsManager::AlwaysHiddenToolBar) ? AlwaysVisibleToolBar : AlwaysHiddenToolBar);
57 		fullScreenVisibility = ((definition.fullScreenVisibility != ToolBarsManager::AlwaysHiddenToolBar) ? AlwaysVisibleToolBar : AlwaysHiddenToolBar);
58 	}
59 
setVisibilityfinal60 	void setVisibility(ToolBarsManager::ToolBarsMode mode, ToolBarVisibility visibility)
61 	{
62 		switch (mode)
63 		{
64 			case ToolBarsManager::NormalMode:
65 				normalVisibility = visibility;
66 
67 				break;
68 			case ToolBarsManager::FullScreenMode:
69 				fullScreenVisibility = visibility;
70 
71 				break;
72 			default:
73 				break;
74 		}
75 	}
76 
getVisibilityfinal77 	ToolBarVisibility getVisibility(ToolBarsManager::ToolBarsMode mode) const
78 	{
79 		return ((mode == ToolBarsManager::FullScreenMode) ? fullScreenVisibility : normalVisibility);
80 	}
81 
isValidfinal82 	bool isValid() const
83 	{
84 		return (identifier >= 0);
85 	}
86 };
87 
88 struct WindowState final
89 {
90 	QRect geometry;
91 	Qt::WindowState state = ((SettingsManager::getOption(SettingsManager::Interface_NewTabOpeningActionOption).toString() == QLatin1String("maximizeTab")) ? Qt::WindowMaximized : Qt::WindowNoState);
92 };
93 
94 struct WindowHistoryEntry final
95 {
96 	QString url;
97 	QString title;
98 	QIcon icon;
99 	QDateTime time;
100 	QPoint position;
101 	int zoom = SettingsManager::getOption(SettingsManager::Content_DefaultZoomOption).toInt();
102 
getTitlefinal103 	QString getTitle() const
104 	{
105 		if (title.isEmpty())
106 		{
107 			if (url == QLatin1String("about:start"))
108 			{
109 				return QCoreApplication::translate("Otter::SessionsManager", "Start Page");
110 			}
111 
112 			return QCoreApplication::translate("Otter::SessionsManager", "(Unknown)");
113 		}
114 
115 		return title;
116 	}
117 };
118 
119 struct WindowHistoryInformation final
120 {
121 	QVector<WindowHistoryEntry> entries;
122 	int index = -1;
123 
isEmptyfinal124 	bool isEmpty() const
125 	{
126 		return (entries.isEmpty() || (entries.count() == 1 && Utils::isUrlEmpty(QUrl(entries.first().url))));
127 	}
128 };
129 
130 struct SessionWindow final
131 {
132 	WindowState state;
133 	QHash<int, QVariant> options;
134 	QVector<WindowHistoryEntry> history;
135 	int parentGroup = 0;
136 	int historyIndex = -1;
137 	bool isAlwaysOnTop = false;
138 	bool isPinned = false;
139 
getUrlfinal140 	QString getUrl() const
141 	{
142 		if (historyIndex >= 0 && historyIndex < history.count())
143 		{
144 			return history.at(historyIndex).url;
145 		}
146 
147 		return {};
148 	}
149 
getTitlefinal150 	QString getTitle() const
151 	{
152 		if (historyIndex >= 0 && historyIndex < history.count())
153 		{
154 			if (!history.at(historyIndex).title.isEmpty())
155 			{
156 				return history.at(historyIndex).title;
157 			}
158 
159 			if (history.at(historyIndex).url == QLatin1String("about:start") && SettingsManager::getOption(SettingsManager::StartPage_EnableStartPageOption).toBool())
160 			{
161 				return QCoreApplication::translate("main", "Start Page");
162 			}
163 		}
164 
165 		return QCoreApplication::translate("main", "(Untitled)");
166 	}
167 
getZoomfinal168 	int getZoom() const
169 	{
170 		if (historyIndex >= 0 && historyIndex < history.count())
171 		{
172 			return history.at(historyIndex).zoom;
173 		}
174 
175 		return SettingsManager::getOption(SettingsManager::Content_DefaultZoomOption).toInt();
176 	}
177 };
178 
179 struct SessionMainWindow final
180 {
181 	QMap<QString, QVector<int> > splitters;
182 	QVector<SessionWindow> windows;
183 	QVector<ToolBarState> toolBars;
184 	QByteArray geometry;
185 	int index = -1;
186 	bool hasToolBarsState = false;
187 };
188 
189 struct SessionInformation final
190 {
191 	QString path;
192 	QString title;
193 	QVector<SessionMainWindow> windows;
194 	int index = -1;
195 	bool isClean = true;
196 
isValidfinal197 	bool isValid() const
198 	{
199 		return !windows.isEmpty();
200 	}
201 };
202 
203 struct ClosedWindow final
204 {
205 	SessionWindow window;
206 	QIcon icon;
207 	quint64 nextWindow = 0;
208 	quint64 previousWindow = 0;
209 	bool isPrivate = false;
210 };
211 
212 class MainWindow;
213 class SessionModel;
214 
215 class SessionsManager final : public QObject
216 {
217 	Q_OBJECT
218 
219 public:
220 	enum OpenHint
221 	{
222 		DefaultOpen = 0,
223 		PrivateOpen = 1,
224 		CurrentTabOpen = 2,
225 		NewTabOpen = 4,
226 		NewWindowOpen = 8,
227 		BackgroundOpen = 16,
228 		EndOpen = 32
229 	};
230 
231 	Q_DECLARE_FLAGS(OpenHints, OpenHint)
232 
233 	static void createInstance(const QString &profilePath, const QString &cachePath, bool isPrivate = false, bool isReadOnly = false);
234 	static void clearClosedWindows();
235 	static void storeClosedWindow(MainWindow *mainWindow);
236 	static void markSessionAsModified();
237 	static void removeStoredUrl(const QString &url);
238 	static SessionsManager* getInstance();
239 	static SessionModel* getModel();
240 	static QString getCurrentSession();
241 	static QString getCachePath();
242 	static QString getProfilePath();
243 	static QString getReadableDataPath(const QString &path, bool forceBundled = false);
244 	static QString getWritableDataPath(const QString &path);
245 	static QString getSessionPath(const QString &path, bool isBound = false);
246 	static SessionInformation getSession(const QString &path);
247 	static QStringList getClosedWindows();
248 	static QStringList getSessions();
249 	static SessionsManager::OpenHints calculateOpenHints(OpenHints hints, Qt::MouseButton button, Qt::KeyboardModifiers modifiers);
250 	static SessionsManager::OpenHints calculateOpenHints(OpenHints hints = DefaultOpen, Qt::MouseButton button = Qt::LeftButton);
251 	static SessionsManager::OpenHints calculateOpenHints(const QVariantMap &parameters, bool ignoreModifiers = false);
252 	static bool restoreClosedWindow(int index = 0);
253 	static bool restoreSession(const SessionInformation &session, MainWindow *mainWindow = nullptr, bool isPrivate = false);
254 	static bool saveSession(const QString &path = {}, const QString &title = {}, MainWindow *mainWindow = nullptr, bool isClean = true);
255 	static bool saveSession(const SessionInformation &session);
256 	static bool deleteSession(const QString &path = {});
257 	static bool isPrivate();
258 	static bool isReadOnly();
259 	static bool hasUrl(const QUrl &url, bool activate = false);
260 
261 protected:
262 	explicit SessionsManager(QObject *parent);
263 
264 	void timerEvent(QTimerEvent *event) override;
265 	void scheduleSave();
266 
267 private:
268 	int m_saveTimer;
269 
270 	static SessionsManager *m_instance;
271 	static SessionModel *m_model;
272 	static QString m_sessionPath;
273 	static QString m_sessionTitle;
274 	static QString m_cachePath;
275 	static QString m_profilePath;
276 	static QVector<SessionMainWindow> m_closedWindows;
277 	static bool m_isDirty;
278 	static bool m_isPrivate;
279 	static bool m_isReadOnly;
280 
281 signals:
282 	void closedWindowsChanged();
283 	void requestedRemoveStoredUrl(const QString &url);
284 };
285 
286 }
287 
288 Q_DECLARE_OPERATORS_FOR_FLAGS(Otter::SessionsManager::OpenHints)
289 
290 #endif
291