Merge lp:~artmello/webbrowser-app/webbrowser-app-fix_1484562 into lp:webbrowser-app

Proposed by Arthur Mello
Status: Merged
Approved by: Olivier Tilloy
Approved revision: 1155
Merged at revision: 1148
Proposed branch: lp:~artmello/webbrowser-app/webbrowser-app-fix_1484562
Merge into: lp:webbrowser-app
Diff against target: 359 lines (+148/-53)
6 files modified
src/app/webbrowser/Browser.qml (+0/-1)
src/app/webbrowser/HistoryViewWide.qml (+60/-36)
src/app/webbrowser/history-model.cpp (+31/-0)
src/app/webbrowser/history-model.h (+2/-0)
tests/unittests/history-model/tst_HistoryModelTests.cpp (+11/-0)
tests/unittests/qml/tst_HistoryViewWide.qml (+44/-16)
To merge this branch: bzr merge lp:~artmello/webbrowser-app/webbrowser-app-fix_1484562
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Olivier Tilloy Approve
Review via email: mp+268165@code.launchpad.net

Commit message

Add support for removing history entries with delete key in HistoryViewWide

Description of the change

Add support for removing history entries with delete key in HistoryViewWide

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1141. By Arthur Mello

Improve qml tests

1142. By Arthur Mello

Merge with trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

If I press Delete repeatedly to manually delete all history entries for a given day (just tried with Today), the corresponding date entry in the left panel disappears as expected, however the right panel isn’t updated, it remains empty, until I focus the left panel with the left arrow and move up/down.
When the last entry is deleted, the selection should probably be reset to All History.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1143. By Arthur Mello

Set left panel to "All History" when the last entry is deleted

1144. By Arthur Mello

Merge with trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

In the two new test functions, checking that the 'count' property of a spy is 0 right after calling clear() on that spy is useless. This is guaranteed to be true, by definition.

In onDeletePressed, if the left panel has active focus and the current index is 0 ("All History"), you could call historyModel.clearAll() instead of iterating through all the entries to delete them one by one.

Similarly, it might be interesting to add a 'clearByDate()' method to the history model to allow deleting all the entries for one given date, instead of iterating. This would be faster and cleaner.

review: Needs Fixing
1145. By Arthur Mello

Remove unnecessary checks

1146. By Arthur Mello

Use clearAll when deleting all entries from history

1147. By Arthur Mello

Add a removeEntriesByDate to the HistoryModel

1148. By Arthur Mello

Add unittests for the HistoryModel new method

1149. By Arthur Mello

Use signals to call changes on the history model to keep consistency

1150. By Arthur Mello

Add qml tests to HistoryViewWide

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

> 1149. By Arthur Mello 12 hours ago
> Use signals to call changes on the history model to keep consistency

Actually, I would have done the opposite: the history model is already exposed to the component, so there is no need to add signals (and the existing ones could be removed): calling methods on the model directly is absolutely fine, and makes the code easier to read. Unit tests won’t be able to monitor signal emissions, but they can still check that after deleting entries the count of the listviews is correctly updated.

Revision history for this message
Olivier Tilloy (osomon) wrote :

193 + dateTime.setTime(QTime(23, 59, 59));

The time should also include milliseconds (999).

review: Needs Fixing
1151. By Arthur Mello

Time used to rmeove entries from database should also include milliseconds

1152. By Arthur Mello

Merge with trunk

1153. By Arthur Mello

Stop using signals for changes on the HistoryModel

1154. By Arthur Mello

Update QML tests

Revision history for this message
Olivier Tilloy (osomon) wrote :

Not strictly necessary for tests to pass, but it would be better for the sake of completeness to re-implement the cleanup() method and have it clear historyMockModel.

1155. By Arthur Mello

Clean all history entries in the cleanup method

Revision history for this message
Olivier Tilloy (osomon) wrote :

Thanks, that looks good to me now.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/webbrowser/Browser.qml'
2--- src/app/webbrowser/Browser.qml 2015-08-16 01:37:08 +0000
3+++ src/app/webbrowser/Browser.qml 2015-08-18 13:59:06 +0000
4@@ -830,7 +830,6 @@
5 browser.openUrlInNewTab(url, true)
6 done()
7 }
8- onHistoryEntryRemoved: browser.historyModel.removeEntryByUrl(url)
9 onNewTabRequested: browser.openUrlInNewTab("", true)
10 onDone: historyViewLoader.active = false
11 }
12
13=== modified file 'src/app/webbrowser/HistoryViewWide.qml'
14--- src/app/webbrowser/HistoryViewWide.qml 2015-08-11 21:05:38 +0000
15+++ src/app/webbrowser/HistoryViewWide.qml 2015-08-18 13:59:06 +0000
16@@ -28,11 +28,29 @@
17
18 signal done()
19 signal historyEntryClicked(url url)
20- signal historyEntryRemoved(url url)
21 signal newTabRequested()
22
23 Keys.onLeftPressed: lastVisitDateListView.forceActiveFocus()
24 Keys.onRightPressed: urlsListView.forceActiveFocus()
25+ Keys.onDeletePressed: {
26+ if (urlsListView.ViewItems.selectMode) {
27+ internal.removeSelected()
28+ } else {
29+ if (urlsListView.activeFocus) {
30+ historyViewWide.historyModel.removeEntryByUrl(urlsListView.currentItem.url)
31+ if (urlsListView.count == 0) {
32+ lastVisitDateListView.currentIndex = 0
33+ }
34+ } else {
35+ if (lastVisitDateListView.currentIndex == 0) {
36+ historyViewWide.historyModel.clearAll()
37+ } else {
38+ historyViewWide.historyModel.removeEntriesByDate(lastVisitDateListView.currentItem.lastVisitDate)
39+ lastVisitDateListView.currentIndex = 0
40+ }
41+ }
42+ }
43+ }
44
45 onActiveFocusChanged: {
46 if (activeFocus) {
47@@ -227,11 +245,9 @@
48 }
49
50 onRemoved: {
51- if (urlsListView.count == 1) {
52- historyViewWide.historyEntryRemoved(model.url)
53+ historyViewWide.historyModel.removeEntryByUrl(model.url)
54+ if (urlsListView.count == 0) {
55 lastVisitDateListView.currentIndex = 0
56- } else {
57- historyViewWide.historyEntryRemoved(model.url)
58 }
59 }
60
61@@ -311,19 +327,7 @@
62 iconName: "select"
63 text: i18n.tr("Select all")
64
65- onClicked: {
66- if (urlsListView.ViewItems.selectedIndices.length === urlsListView.count) {
67- urlsListView.ViewItems.selectedIndices = []
68- } else {
69- var indices = []
70- for (var i = 0; i < urlsListView.count; ++i) {
71- indices.push(i)
72- }
73- urlsListView.ViewItems.selectedIndices = indices
74- }
75-
76- urlsListView.forceActiveFocus()
77- }
78+ onClicked: internal.toggleSelectAll()
79 }
80
81 ToolbarAction {
82@@ -342,24 +346,7 @@
83 iconName: "delete"
84 text: i18n.tr("Delete")
85 enabled: urlsListView.ViewItems.selectedIndices.length > 0
86- onClicked: {
87- var indices = urlsListView.ViewItems.selectedIndices
88- var urls = []
89- for (var i in indices) {
90- urls.push(urlsListView.model.get(indices[i])["url"])
91- }
92-
93- if (urlsListView.count == urls.length) {
94- lastVisitDateListView.currentIndex = 0
95- }
96-
97- urlsListView.ViewItems.selectMode = false
98- for (var j in urls) {
99- historyViewWide.historyEntryRemoved(urls[j])
100- }
101-
102- lastVisitDateListView.forceActiveFocus()
103- }
104+ onClicked: internal.removeSelected()
105 }
106
107 ListItems.ThinDivider {
108@@ -415,4 +402,41 @@
109 }
110 }
111 }
112+
113+ QtObject {
114+ id: internal
115+
116+ function toggleSelectAll() {
117+ if (urlsListView.ViewItems.selectedIndices.length === urlsListView.count) {
118+ urlsListView.ViewItems.selectedIndices = []
119+ } else {
120+ var indices = []
121+ for (var i = 0; i < urlsListView.count; ++i) {
122+ indices.push(i)
123+ }
124+ urlsListView.ViewItems.selectedIndices = indices
125+ }
126+
127+ urlsListView.forceActiveFocus()
128+ }
129+
130+ function removeSelected() {
131+ var indices = urlsListView.ViewItems.selectedIndices
132+ var urls = []
133+ for (var i in indices) {
134+ urls.push(urlsListView.model.get(indices[i])["url"])
135+ }
136+
137+ if (urlsListView.count == urls.length) {
138+ lastVisitDateListView.currentIndex = 0
139+ }
140+
141+ urlsListView.ViewItems.selectMode = false
142+ for (var j in urls) {
143+ historyViewWide.historyModel.removeEntryByUrl(urls[j])
144+ }
145+
146+ lastVisitDateListView.forceActiveFocus()
147+ }
148+ }
149 }
150
151=== modified file 'src/app/webbrowser/history-model.cpp'
152--- src/app/webbrowser/history-model.cpp 2015-07-14 22:16:41 +0000
153+++ src/app/webbrowser/history-model.cpp 2015-08-18 13:59:06 +0000
154@@ -309,6 +309,24 @@
155 }
156
157 /*!
158+ Remove all urls last visited in a given DATE from the history model.
159+*/
160+void HistoryModel::removeEntriesByDate(const QDate& date)
161+{
162+ if (!date.isValid()) {
163+ return;
164+ }
165+
166+ for (int i = m_entries.count() - 1; i >= 0; --i) {
167+ if (m_entries.at(i).lastVisit.toLocalTime().date() == date) {
168+ removeByIndex(i);
169+ }
170+ }
171+ removeEntriesFromDatabaseByDate(date);
172+ Q_EMIT rowCountChanged();
173+}
174+
175+/*!
176 Remove all urls from a given DOMAIN from the history model.
177 */
178 void HistoryModel::removeEntriesByDomain(const QString& domain)
179@@ -396,6 +414,19 @@
180 query.exec();
181 }
182
183+void HistoryModel::removeEntriesFromDatabaseByDate(const QDate& date)
184+{
185+ QMutexLocker ml(&m_dbMutex);
186+ QSqlQuery query(m_database);
187+ static QString deleteStatement = QLatin1String("DELETE FROM history WHERE lastVisit BETWEEN ? AND ?;");
188+ query.prepare(deleteStatement);
189+ QDateTime dateTime = QDateTime(date);
190+ query.addBindValue(dateTime.toTime_t());
191+ dateTime.setTime(QTime(23, 59, 59, 999));
192+ query.addBindValue(dateTime.toTime_t());
193+ query.exec();
194+}
195+
196 void HistoryModel::removeEntriesFromDatabaseByDomain(const QString& domain)
197 {
198 QMutexLocker ml(&m_dbMutex);
199
200=== modified file 'src/app/webbrowser/history-model.h'
201--- src/app/webbrowser/history-model.h 2015-07-14 22:16:41 +0000
202+++ src/app/webbrowser/history-model.h 2015-08-18 13:59:06 +0000
203@@ -62,6 +62,7 @@
204
205 Q_INVOKABLE int add(const QUrl& url, const QString& title, const QUrl& icon);
206 Q_INVOKABLE void removeEntryByUrl(const QUrl& url);
207+ Q_INVOKABLE void removeEntriesByDate(const QDate& date);
208 Q_INVOKABLE void removeEntriesByDomain(const QString& domain);
209 Q_INVOKABLE void clearAll();
210 Q_INVOKABLE void hide(const QUrl& url);
211@@ -99,6 +100,7 @@
212 void updateExistingEntryInDatabase(const HistoryEntry& entry);
213 void removeEntryFromDatabaseByUrl(const QUrl& url);
214 void removeEntryFromHiddenDatabaseByUrl(const QUrl& url);
215+ void removeEntriesFromDatabaseByDate(const QDate& date);
216 void removeEntriesFromDatabaseByDomain(const QString& domain);
217 void clearDatabase();
218 };
219
220=== modified file 'tests/unittests/history-model/tst_HistoryModelTests.cpp'
221--- tests/unittests/history-model/tst_HistoryModelTests.cpp 2015-04-15 13:27:23 +0000
222+++ tests/unittests/history-model/tst_HistoryModelTests.cpp 2015-08-18 13:59:06 +0000
223@@ -256,6 +256,17 @@
224 QCOMPARE(model->rowCount(), 0);
225 }
226
227+ void shouldRemoveByDate()
228+ {
229+ QCOMPARE(model->add(QUrl("http://example.org/"), "Example Domain", QUrl()), 1);
230+ QCOMPARE(model->rowCount(), 1);
231+ QCOMPARE(model->add(QUrl("http://example.com/"), "Example Domain", QUrl()), 1);
232+ QCOMPARE(model->rowCount(), 2);
233+
234+ model->removeEntriesByDate(QDate::currentDate());
235+ QCOMPARE(model->rowCount(), 0);
236+ }
237+
238 void shouldRemoveByDomain()
239 {
240 QCOMPARE(model->add(QUrl("http://example.org/page1"), "Example Domain Page 1", QUrl()), 1);
241
242=== modified file 'tests/unittests/qml/tst_HistoryViewWide.qml'
243--- tests/unittests/qml/tst_HistoryViewWide.qml 2015-08-11 16:16:07 +0000
244+++ tests/unittests/qml/tst_HistoryViewWide.qml 2015-08-18 13:59:06 +0000
245@@ -56,12 +56,6 @@
246 signalName: "historyEntryClicked"
247 }
248
249- SignalSpy {
250- id: historyEntryRemovedSpy
251- target: historyViewWide
252- signalName: "historyEntryRemoved"
253- }
254-
255 UbuntuTestCase {
256 name: "HistoryViewWide"
257 when: windowShown
258@@ -83,7 +77,7 @@
259 mouseRelease(item, center.x + 100, center.y, Qt.LeftButton, Qt.NoModifier, 2000)
260 }
261
262- function initTestCase() {
263+ function init() {
264 for (var i = 0; i < 3; ++i) {
265 historyMockModel.add("http://example.org/" + i, "Example Domain " + i, "")
266 }
267@@ -92,11 +86,14 @@
268 waitForRendering(urlsList)
269 }
270
271+ function cleanup() {
272+ historyMockModel.clearAll()
273+ }
274+
275 function test_done_button() {
276 var doneButton = findChild(historyViewWide, "doneButton")
277 verify(doneButton != null)
278 doneSpy.clear()
279- compare(doneSpy.count, 0)
280 clickItem(doneButton)
281 compare(doneSpy.count, 1)
282 }
283@@ -106,8 +103,6 @@
284 verify(newTabButton != null)
285 doneSpy.clear()
286 newTabRequestedSpy.clear()
287- compare(doneSpy.count, 0)
288- compare(newTabRequestedSpy.count, 0)
289 clickItem(newTabButton)
290 compare(newTabRequestedSpy.count, 1)
291 compare(doneSpy.count, 1)
292@@ -116,7 +111,7 @@
293 function test_history_entry_clicked() {
294 var urlsList = findChild(historyViewWide, "urlsListView")
295 compare(urlsList.count, 3)
296- compare(historyEntryClickedSpy.count, 0)
297+ historyEntryClickedSpy.clear()
298 clickItem(urlsList.children[0])
299 compare(historyEntryClickedSpy.count, 1)
300 var args = historyEntryClickedSpy.signalArguments[0]
301@@ -160,14 +155,14 @@
302 function test_delete_button() {
303 var urlsList = findChild(historyViewWide, "urlsListView")
304 compare(urlsList.count, 3)
305+ var deletedUrl = urlsList.model.get(0).url
306 longPressItem(urlsList.children[0])
307 var deleteButton = findChild(historyViewWide, "deleteButton")
308- compare(historyEntryRemovedSpy.count, 0)
309 clickItem(deleteButton)
310- compare(historyEntryRemovedSpy.count, 1)
311- var args = historyEntryRemovedSpy.signalArguments[0]
312- var entry = urlsList.model.get(0)
313- compare(args[0], entry.url)
314+ compare(urlsList.count, 2)
315+ for (var i = 0; i < urlsList.count; ++i) {
316+ verify(urlsList.model.get(i).url != deletedUrl)
317+ }
318 }
319
320 function test_keyboard_navigation_between_lists() {
321@@ -180,5 +175,38 @@
322 keyClick(Qt.Key_Right)
323 verify(urlsList.activeFocus)
324 }
325+
326+ function test_delete_key_at_urls_list_view() {
327+ var urlsList = findChild(historyViewWide, "urlsListView")
328+ keyClick(Qt.Key_Right)
329+ verify(urlsList.activeFocus)
330+ compare(urlsList.count, 3)
331+ keyClick(Qt.Key_Delete)
332+ compare(urlsList.count, 2)
333+ }
334+
335+ function test_delete_key_at_last_visit_date() {
336+ var lastVisitDateList = findChild(historyViewWide, "lastVisitDateListView")
337+ var urlsList = findChild(historyViewWide, "urlsListView")
338+ keyClick(Qt.Key_Left)
339+ verify(lastVisitDateList.activeFocus)
340+ compare(lastVisitDateList.currentIndex, 0)
341+ keyClick(Qt.Key_Down)
342+ compare(lastVisitDateList.currentIndex, 1)
343+ compare(urlsList.count, 3)
344+ keyClick(Qt.Key_Delete)
345+ compare(urlsList.count, 0)
346+ }
347+
348+ function test_delete_key_at_all_history() {
349+ var lastVisitDateList = findChild(historyViewWide, "lastVisitDateListView")
350+ var urlsList = findChild(historyViewWide, "urlsListView")
351+ keyClick(Qt.Key_Left)
352+ verify(lastVisitDateList.activeFocus)
353+ compare(lastVisitDateList.currentIndex, 0)
354+ compare(urlsList.count, 3)
355+ keyClick(Qt.Key_Delete)
356+ compare(urlsList.count, 0)
357+ }
358 }
359 }

Subscribers

People subscribed via source and target branches

to status/vote changes: