|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the demonstration applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #ifndef HISTORY_H |
|
43 #define HISTORY_H |
|
44 |
|
45 #include "modelmenu.h" |
|
46 |
|
47 #include <QtCore/QDateTime> |
|
48 #include <QtCore/QHash> |
|
49 #include <QtCore/QObject> |
|
50 #include <QtCore/QTimer> |
|
51 #include <QtCore/QUrl> |
|
52 |
|
53 #include <QtGui/QSortFilterProxyModel> |
|
54 |
|
55 #include <QWebHistoryInterface> |
|
56 |
|
57 class HistoryItem |
|
58 { |
|
59 public: |
|
60 HistoryItem() {} |
|
61 HistoryItem(const QString &u, |
|
62 const QDateTime &d = QDateTime(), const QString &t = QString()) |
|
63 : title(t), url(u), dateTime(d) {} |
|
64 |
|
65 inline bool operator==(const HistoryItem &other) const |
|
66 { return other.title == title |
|
67 && other.url == url && other.dateTime == dateTime; } |
|
68 |
|
69 // history is sorted in reverse |
|
70 inline bool operator <(const HistoryItem &other) const |
|
71 { return dateTime > other.dateTime; } |
|
72 |
|
73 QString title; |
|
74 QString url; |
|
75 QDateTime dateTime; |
|
76 }; |
|
77 |
|
78 class AutoSaver; |
|
79 class HistoryModel; |
|
80 class HistoryFilterModel; |
|
81 class HistoryTreeModel; |
|
82 class HistoryManager : public QWebHistoryInterface |
|
83 { |
|
84 Q_OBJECT |
|
85 Q_PROPERTY(int historyLimit READ historyLimit WRITE setHistoryLimit) |
|
86 |
|
87 signals: |
|
88 void historyReset(); |
|
89 void entryAdded(const HistoryItem &item); |
|
90 void entryRemoved(const HistoryItem &item); |
|
91 void entryUpdated(int offset); |
|
92 |
|
93 public: |
|
94 HistoryManager(QObject *parent = 0); |
|
95 ~HistoryManager(); |
|
96 |
|
97 bool historyContains(const QString &url) const; |
|
98 void addHistoryEntry(const QString &url); |
|
99 |
|
100 void updateHistoryItem(const QUrl &url, const QString &title); |
|
101 |
|
102 int historyLimit() const; |
|
103 void setHistoryLimit(int limit); |
|
104 |
|
105 QList<HistoryItem> history() const; |
|
106 void setHistory(const QList<HistoryItem> &history, bool loadedAndSorted = false); |
|
107 |
|
108 // History manager keeps around these models for use by the completer and other classes |
|
109 HistoryModel *historyModel() const; |
|
110 HistoryFilterModel *historyFilterModel() const; |
|
111 HistoryTreeModel *historyTreeModel() const; |
|
112 |
|
113 public slots: |
|
114 void clear(); |
|
115 void loadSettings(); |
|
116 |
|
117 private slots: |
|
118 void save(); |
|
119 void checkForExpired(); |
|
120 |
|
121 protected: |
|
122 void addHistoryItem(const HistoryItem &item); |
|
123 |
|
124 private: |
|
125 void load(); |
|
126 |
|
127 AutoSaver *m_saveTimer; |
|
128 int m_historyLimit; |
|
129 QTimer m_expiredTimer; |
|
130 QList<HistoryItem> m_history; |
|
131 QString m_lastSavedUrl; |
|
132 |
|
133 HistoryModel *m_historyModel; |
|
134 HistoryFilterModel *m_historyFilterModel; |
|
135 HistoryTreeModel *m_historyTreeModel; |
|
136 }; |
|
137 |
|
138 class HistoryModel : public QAbstractTableModel |
|
139 { |
|
140 Q_OBJECT |
|
141 |
|
142 public slots: |
|
143 void historyReset(); |
|
144 void entryAdded(); |
|
145 void entryUpdated(int offset); |
|
146 |
|
147 public: |
|
148 enum Roles { |
|
149 DateRole = Qt::UserRole + 1, |
|
150 DateTimeRole = Qt::UserRole + 2, |
|
151 UrlRole = Qt::UserRole + 3, |
|
152 UrlStringRole = Qt::UserRole + 4 |
|
153 }; |
|
154 |
|
155 HistoryModel(HistoryManager *history, QObject *parent = 0); |
|
156 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; |
|
157 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
|
158 int columnCount(const QModelIndex &parent = QModelIndex()) const; |
|
159 int rowCount(const QModelIndex &parent = QModelIndex()) const; |
|
160 bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); |
|
161 |
|
162 private: |
|
163 HistoryManager *m_history; |
|
164 }; |
|
165 |
|
166 /*! |
|
167 Proxy model that will remove any duplicate entries. |
|
168 Both m_sourceRow and m_historyHash store their offsets not from |
|
169 the front of the list, but as offsets from the back. |
|
170 */ |
|
171 class HistoryFilterModel : public QAbstractProxyModel |
|
172 { |
|
173 Q_OBJECT |
|
174 |
|
175 public: |
|
176 HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = 0); |
|
177 |
|
178 inline bool historyContains(const QString &url) const |
|
179 { load(); return m_historyHash.contains(url); } |
|
180 int historyLocation(const QString &url) const; |
|
181 |
|
182 QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; |
|
183 QModelIndex mapToSource(const QModelIndex &proxyIndex) const; |
|
184 void setSourceModel(QAbstractItemModel *sourceModel); |
|
185 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; |
|
186 int rowCount(const QModelIndex &parent = QModelIndex()) const; |
|
187 int columnCount(const QModelIndex &parent = QModelIndex()) const; |
|
188 QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; |
|
189 QModelIndex parent(const QModelIndex& index= QModelIndex()) const; |
|
190 bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); |
|
191 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
|
192 |
|
193 private slots: |
|
194 void sourceReset(); |
|
195 void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); |
|
196 void sourceRowsInserted(const QModelIndex &parent, int start, int end); |
|
197 void sourceRowsRemoved(const QModelIndex &, int, int); |
|
198 |
|
199 private: |
|
200 void load() const; |
|
201 |
|
202 mutable QList<int> m_sourceRow; |
|
203 mutable QHash<QString, int> m_historyHash; |
|
204 mutable bool m_loaded; |
|
205 }; |
|
206 |
|
207 /* |
|
208 The history menu |
|
209 - Removes the first twenty entries and puts them as children of the top level. |
|
210 - If there are less then twenty entries then the first folder is also removed. |
|
211 |
|
212 The mapping is done by knowing that HistoryTreeModel is over a table |
|
213 We store that row offset in our index's private data. |
|
214 */ |
|
215 class HistoryMenuModel : public QAbstractProxyModel |
|
216 { |
|
217 Q_OBJECT |
|
218 |
|
219 public: |
|
220 HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = 0); |
|
221 int columnCount(const QModelIndex &parent) const; |
|
222 int rowCount(const QModelIndex &parent = QModelIndex()) const; |
|
223 QModelIndex mapFromSource(const QModelIndex & sourceIndex) const; |
|
224 QModelIndex mapToSource(const QModelIndex & proxyIndex) const; |
|
225 QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const; |
|
226 QModelIndex parent(const QModelIndex &index = QModelIndex()) const; |
|
227 |
|
228 int bumpedRows() const; |
|
229 |
|
230 private: |
|
231 HistoryTreeModel *m_treeModel; |
|
232 }; |
|
233 |
|
234 // Menu that is dynamically populated from the history |
|
235 class HistoryMenu : public ModelMenu |
|
236 { |
|
237 Q_OBJECT |
|
238 |
|
239 signals: |
|
240 void openUrl(const QUrl &url); |
|
241 |
|
242 public: |
|
243 HistoryMenu(QWidget *parent = 0); |
|
244 void setInitialActions(QList<QAction*> actions); |
|
245 |
|
246 protected: |
|
247 bool prePopulated(); |
|
248 void postPopulated(); |
|
249 |
|
250 private slots: |
|
251 void activated(const QModelIndex &index); |
|
252 void showHistoryDialog(); |
|
253 |
|
254 private: |
|
255 HistoryManager *m_history; |
|
256 HistoryMenuModel *m_historyMenuModel; |
|
257 QList<QAction*> m_initialActions; |
|
258 }; |
|
259 |
|
260 // proxy model for the history model that |
|
261 // exposes each url http://www.foo.com and it url starting at the host www.foo.com |
|
262 class HistoryCompletionModel : public QAbstractProxyModel |
|
263 { |
|
264 Q_OBJECT |
|
265 |
|
266 public: |
|
267 HistoryCompletionModel(QObject *parent = 0); |
|
268 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
|
269 int rowCount(const QModelIndex &parent = QModelIndex()) const; |
|
270 int columnCount(const QModelIndex &parent = QModelIndex()) const; |
|
271 QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; |
|
272 QModelIndex mapToSource(const QModelIndex &proxyIndex) const; |
|
273 QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; |
|
274 QModelIndex parent(const QModelIndex& index= QModelIndex()) const; |
|
275 void setSourceModel(QAbstractItemModel *sourceModel); |
|
276 |
|
277 private slots: |
|
278 void sourceReset(); |
|
279 |
|
280 }; |
|
281 |
|
282 // proxy model for the history model that converts the list |
|
283 // into a tree, one top level node per day. |
|
284 // Used in the HistoryDialog. |
|
285 class HistoryTreeModel : public QAbstractProxyModel |
|
286 { |
|
287 Q_OBJECT |
|
288 |
|
289 public: |
|
290 HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = 0); |
|
291 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; |
|
292 int columnCount(const QModelIndex &parent) const; |
|
293 int rowCount(const QModelIndex &parent = QModelIndex()) const; |
|
294 QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; |
|
295 QModelIndex mapToSource(const QModelIndex &proxyIndex) const; |
|
296 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; |
|
297 QModelIndex parent(const QModelIndex &index= QModelIndex()) const; |
|
298 bool hasChildren(const QModelIndex &parent = QModelIndex()) const; |
|
299 Qt::ItemFlags flags(const QModelIndex &index) const; |
|
300 bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); |
|
301 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; |
|
302 |
|
303 void setSourceModel(QAbstractItemModel *sourceModel); |
|
304 |
|
305 private slots: |
|
306 void sourceReset(); |
|
307 void sourceRowsInserted(const QModelIndex &parent, int start, int end); |
|
308 void sourceRowsRemoved(const QModelIndex &parent, int start, int end); |
|
309 |
|
310 private: |
|
311 int sourceDateRow(int row) const; |
|
312 mutable QList<int> m_sourceRowCache; |
|
313 |
|
314 }; |
|
315 |
|
316 // A modified QSortFilterProxyModel that always accepts the root nodes in the tree |
|
317 // so filtering is only done on the children. |
|
318 // Used in the HistoryDialog |
|
319 class TreeProxyModel : public QSortFilterProxyModel |
|
320 { |
|
321 Q_OBJECT |
|
322 |
|
323 public: |
|
324 TreeProxyModel(QObject *parent = 0); |
|
325 |
|
326 protected: |
|
327 bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; |
|
328 }; |
|
329 |
|
330 #include "ui_history.h" |
|
331 |
|
332 class HistoryDialog : public QDialog, public Ui_HistoryDialog |
|
333 { |
|
334 Q_OBJECT |
|
335 |
|
336 signals: |
|
337 void openUrl(const QUrl &url); |
|
338 |
|
339 public: |
|
340 HistoryDialog(QWidget *parent = 0, HistoryManager *history = 0); |
|
341 |
|
342 private slots: |
|
343 void customContextMenuRequested(const QPoint &pos); |
|
344 void open(); |
|
345 void copy(); |
|
346 |
|
347 }; |
|
348 |
|
349 #endif // HISTORY_H |
|
350 |