Merge lp:~oppifjellet/cable/message-history into lp:cable

Proposed by Daniele "OpenNingia" Simonetti
Status: Merged
Merged at revision: 128
Proposed branch: lp:~oppifjellet/cable/message-history
Merge into: lp:cable
Diff against target: 405 lines (+258/-10)
7 files modified
CMakeLists.txt (+22/-1)
src/Utils/RRStringList.vala (+77/-0)
src/Widgets/Room.vala (+31/-9)
tests/TestCase.vala (+58/-0)
tests/TestExample.vala (+22/-0)
tests/TestMain.vala (+7/-0)
tests/TestMessageHistory.vala (+41/-0)
To merge this branch: bzr merge lp:~oppifjellet/cable/message-history
Reviewer Review Type Date Requested Status
Eduard Gotwig Pending
Review via email: mp+182453@code.launchpad.net

Commit message

Implemented message history

Description of the change

This branch fixes this bug https://bugs.launchpad.net/cable/+bug/1198635
Every channel now keeps an history of sent messages and commands that are navigable using arrow keys ( Up&Down )

For performance reasons the history capacity for each channel is 25 items. Old items are replaced with round robin logic.

To post a comment you must log in.
Revision history for this message
Eduard Gotwig (gotwig) wrote :

sometimes I have to double press up or down, for it to work. Can this be fixed?

Thanks for your work.

126. By Daniele "OpenNingia" Simonetti

improved history navigation behavior

Revision history for this message
Daniele "OpenNingia" Simonetti (oppifjellet) wrote :

Revision 126 should fix the annoying behavior.
You're welcome, thank you for Cable.

Revision history for this message
982c80311320c1b (alexander-wilms) wrote :

It doesn't work as expected for me.
When I type
1 <Enter>
2 <Enter>
3 <Enter>

and then browse through history with the <up> key, the following messages appear in this order: 2, 1. When I then press the <down> key, those messages appear: 1, 2, 3

If I _instead_ (not after browing them with <up> and <down>) press the <down> key, 3 appears in the text box.

Revision history for this message
Daniele "OpenNingia" Simonetti (oppifjellet) wrote :

I admit it's a strange behavior. If it were you what's the best behavior?
Il giorno 30/ago/2013 00:57, "Alexander Wilms" <email address hidden>
ha scritto:

> It doesn't work as expected for me.
> When I type
> 1 <Enter>
> 2 <Enter>
> 3 <Enter>
>
> and then browse through history with the <up> key, the following messages
> appear in this order: 2, 1. When I then press the <down> key, those
> messages appear: 1, 2, 3
>
> If I _instead_ (not after browing them with <up> and <down>) press the
> <down> key, 3 appears in the text box.
> --
> https://code.launchpad.net/~oppifjellet/cable/message-history/+merge/182453
> You are the owner of lp:~oppifjellet/cable/message-history.
>

Revision history for this message
Daniele "OpenNingia" Simonetti (oppifjellet) wrote :

So I checked the implementation:

pressing <down><up> with the editbox empty ( or after sending a message ) is a shortcut to get the last typed message )

instead when navigating <up>/<down> will return the next and the previous message, with one exception:

. the history doesn't save duplicates

so if you write

1
2
3
2

the last "2" is ignored.

Revision history for this message
982c80311320c1b (alexander-wilms) wrote :

I think the most intuitive implementation (and IMHO the most simple one) would be this:

After typing:

1
2
3
2

Pressing <down> doesn't do anything. <Up> shows the last history entry (2) and every press of <up> shows the previous message. <Down> returns the next message.

Duplicates should not be skipped, since users don't know the algorithm behind it and at least I would expect it to list the messages in the order in which I pyed them.

127. By Daniele "OpenNingia" Simonetti

permit duplicates

Revision history for this message
Daniele "OpenNingia" Simonetti (oppifjellet) wrote :

Ok so, this revision implements your design. Duplicates are permitted, history default size has been increased to 50, and hitting <down> after typing an entry does nothing.

Revision history for this message
982c80311320c1b (alexander-wilms) wrote :

Great :)

128. By Daniele "OpenNingia" Simonetti

add unit test using GLib.Test

Revision history for this message
Eduard Gotwig (gotwig) wrote :

You shouldnt propose merge requests, which are based on other merge requests. Each merge request should be clean applied with it changes on trunk.

However, I am going to look today at the other merge request of you, which included this one.

Cheers,

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2013-08-06 15:32:12 +0000
+++ CMakeLists.txt 2013-09-03 20:19:34 +0000
@@ -55,6 +55,7 @@
55 src/Utils/EmbeddedAlert.vala55 src/Utils/EmbeddedAlert.vala
56 src/Utils/Identity.vala56 src/Utils/Identity.vala
57 src/Utils/Network.vala57 src/Utils/Network.vala
58 src/Utils/RRStringList.vala
5859
59 src/Irc/Maki.vala60 src/Irc/Maki.vala
60 src/Irc/Irc.vala61 src/Irc/Irc.vala
@@ -90,7 +91,7 @@
90 src/Dialogs/Preferences.vala91 src/Dialogs/Preferences.vala
91 src/Dialogs/ManageIdentity.vala92 src/Dialogs/ManageIdentity.vala
92 src/Dialogs/ManageNetwork.vala93 src/Dialogs/ManageNetwork.vala
93 94
94 src/Tests/Tests.vala95 src/Tests/Tests.vala
95 src/Tests/Utils.vala96 src/Tests/Utils.vala
9697
@@ -109,9 +110,29 @@
109 --verbose110 --verbose
110 )111 )
111112
113vala_precompile(VALA_C_TESTS
114 tests/TestCase.vala
115 tests/TestMain.vala
116 tests/TestExample.vala
117 tests/TestMessageHistory.vala
118 src/Utils/RRStringList.vala
119PACKAGES
120 gtk+-3.0
121 granite
122 libnotify
123 unity
124OPTIONS
125 --target-glib=2.32
126 --vapidir=${CMAKE_CURRENT_SOURCE_DIR}/vapi/
127 --enable-experimental
128 --fatal-warnings
129 --verbose
130)
131
112add_subdirectory (po)132add_subdirectory (po)
113add_subdirectory (data)133add_subdirectory (data)
114134
115add_executable(cable ${VALA_C})135add_executable(cable ${VALA_C})
136add_executable(cable_tests ${VALA_C_TESTS})
116137
117install(TARGETS cable RUNTIME DESTINATION bin)138install(TARGETS cable RUNTIME DESTINATION bin)
118139
=== added file 'src/Utils/RRStringList.vala'
--- src/Utils/RRStringList.vala 1970-01-01 00:00:00 +0000
+++ src/Utils/RRStringList.vala 2013-09-03 20:19:34 +0000
@@ -0,0 +1,77 @@
1/***
2 Copyright (C) 2013 Cable Developers
3
4 This program or library is free software; you can redistribute it
5 and/or modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA.
18***/
19
20
21public class Cable.Collections.RRStringList {
22
23 internal int? current_;
24 internal Gee.List <string> data;
25
26 public int capacity { get; set; }
27 public int? current_index { get { return current_; } }
28
29 public RRStringList.with_capacity (int capacity_value)
30 requires (capacity_value > 0) {
31 capacity = capacity_value;
32 data = new Gee.ArrayList <string>();
33 }
34
35 public RRStringList () {
36 this.with_capacity(50); // default capacity
37 }
38
39 public void add(string value) {
40 if ( data.size >= this.capacity )
41 data.remove_at( 0 );
42 data.add(value);
43 current_ = data.size/*-1*/;
44 }
45
46 public bool contains(string value) {
47 return data.contains(value);
48 }
49
50 public string current() {
51 if ( current_ == null ) return "";
52 if ( current_ >= data.size ) current_ = data.size-1;
53 if ( current_ < 0 ) current_ = 0;
54 return data[current_];
55 }
56
57 public bool previous() {
58 if ( current_ == null ) return false;
59 if ( current_ <= 0 ) return false;
60 current_ = current_ - 1;
61 return true;
62 }
63
64 public bool next() {
65 if ( current_ == null ) return false;
66 if ( current_+1 >= data.size ) return false;
67 current_ = current_ + 1;
68 return true;
69 }
70
71 public bool set_current_value(string value) {
72 if ( !(value in data) ) return false;
73 current_ = data.index_of(value)+1;
74 return true;
75 }
76
77}
078
=== modified file 'src/Widgets/Room.vala'
--- src/Widgets/Room.vala 2013-08-22 18:40:53 +0000
+++ src/Widgets/Room.vala 2013-09-03 20:19:34 +0000
@@ -51,6 +51,8 @@
51 internal Gtk.Entry text_entry;51 internal Gtk.Entry text_entry;
52 Utils.AutoScrolled left_scrolled;52 Utils.AutoScrolled left_scrolled;
5353
54 internal Cable.Collections.RRStringList history_set;
55
54 Gtk.Box user_box;56 Gtk.Box user_box;
5557
56 public Widgets.Topic topic_bar;58 public Widgets.Topic topic_bar;
@@ -62,17 +64,21 @@
62 public signal void rejoin ();64 public signal void rejoin ();
6365
64 public string channel { get; set; }66 public string channel { get; set; }
65 67
66 public string nick {68 public string nick {
67 get { return pseudo_label.label; }69 get { return pseudo_label.label; }
68 set { pseudo_label.label = value; }70 set { pseudo_label.label = value; }
69 }71 }
70 72
71 public string entry {73 public string entry {
72 get { return text_entry.text; }74 get { return text_entry.text; }
73 set { text_entry.text = value; }75 set { text_entry.text = value; }
74 }76 }
7577
78 public Cable.Collections.RRStringList history {
79 get { return history_set; }
80 }
81
76 State _state;82 State _state;
77 public State state {83 public State state {
78 get { return _state; }84 get { return _state; }
@@ -104,7 +110,7 @@
104 show_all ();110 show_all ();
105 }111 }
106 }112 }
107 113
108 private Gee.Set <string> nicks {114 private Gee.Set <string> nicks {
109 owned get {115 owned get {
110 var _nicks = new Gee.HashSet <string> ();116 var _nicks = new Gee.HashSet <string> ();
@@ -119,6 +125,8 @@
119 public Room (string channel, string nick="") {125 public Room (string channel, string nick="") {
120 this.channel = channel;126 this.channel = channel;
121127
128 history_set = new Cable.Collections.RRStringList();
129
122 init_layout ();130 init_layout ();
123 connect_callbacks ();131 connect_callbacks ();
124 }132 }
@@ -227,7 +235,7 @@
227 return true;235 return true;
228 } else {236 } else {
229 text_entry.buffer.delete_text (text_entry.cursor_position - word.length, word.length);237 text_entry.buffer.delete_text (text_entry.cursor_position - word.length, word.length);
230 238
231 if( text_entry.text != "" ){239 if( text_entry.text != "" ){
232 text_entry.insert_at_cursor (completion[0] + " ");240 text_entry.insert_at_cursor (completion[0] + " ");
233 } else {241 } else {
@@ -236,12 +244,26 @@
236 return true;244 return true;
237 }245 }
238 }246 }
247 else if ( ev.keyval == Gdk.Key.Up ) {
248 if ( history.previous() )
249 text_entry.text = history.current();
250 return true;
251 }
252 else if ( ev.keyval == Gdk.Key.Down ) {
253 if ( history.next() )
254 text_entry.text = history.current();
255 return true;
256 }
239 return false;257 return false;
240 });258 });
241 259
242 text_entry.activate.connect (() => {260 text_entry.activate.connect (() => {
243 if (text_entry.text != "")261 if (text_entry.text != "") {
262
263 // permit duplicates
264 history.add(text_entry.text);
244 send_message (text_entry.text); // signal265 send_message (text_entry.text); // signal
266 }
245 });267 });
246268
247 action_join.activate.connect (() => {269 action_join.activate.connect (() => {
@@ -281,7 +303,7 @@
281 requires (!has_user (new_name))303 requires (!has_user (new_name))
282 ensures (!has_user (old_name))304 ensures (!has_user (old_name))
283 ensures (has_user (new_name)) {305 ensures (has_user (new_name)) {
284 306
285 if (old_name == null) {307 if (old_name == null) {
286 add_user (new_name, type, true);308 add_user (new_name, type, true);
287 return;309 return;
@@ -300,7 +322,7 @@
300322
301 var user = new User (name);323 var user = new User (name);
302 user.selectable = false;324 user.selectable = false;
303 325
304 switch (type) {326 switch (type) {
305 case UserType.OPERATOR:327 case UserType.OPERATOR:
306 operators.add (user);328 operators.add (user);
@@ -324,7 +346,7 @@
324 public bool remove_user (string name, string message, bool silent = false)346 public bool remove_user (string name, string message, bool silent = false)
325 requires (has_user (name))347 requires (has_user (name))
326 ensures (!has_user (name)) {348 ensures (!has_user (name)) {
327 349
328 Granite.Widgets.SourceList.ExpandableItem[] lists = {voiced, operators, regular};350 Granite.Widgets.SourceList.ExpandableItem[] lists = {voiced, operators, regular};
329 foreach (var list in lists) {351 foreach (var list in lists) {
330 foreach (var child in list.children) {352 foreach (var child in list.children) {
331353
=== added directory 'tests'
=== added file 'tests/TestCase.vala'
--- tests/TestCase.vala 1970-01-01 00:00:00 +0000
+++ tests/TestCase.vala 2013-09-03 20:19:34 +0000
@@ -0,0 +1,58 @@
1public abstract class Gee.TestCase : Object {
2
3 private GLib.TestSuite suite;
4 private Adaptor[] adaptors = new Adaptor[0];
5
6 public delegate void TestMethod ();
7
8 public TestCase (string name) {
9 this.suite = new GLib.TestSuite (name);
10 }
11
12 public void add_test (string name, owned TestMethod test) {
13 var adaptor = new Adaptor (name, (owned)test, this);
14 this.adaptors += adaptor;
15
16 this.suite.add (new GLib.TestCase (adaptor.name,
17 adaptor.set_up,
18 adaptor.run,
19 adaptor.tear_down ));
20 }
21
22 public virtual void set_up () {
23 }
24
25 public virtual void tear_down () {
26 }
27
28 public GLib.TestSuite get_suite () {
29 return this.suite;
30 }
31
32 private class Adaptor {
33
34 public string name { get; private set; }
35 private TestMethod test;
36 private TestCase test_case;
37
38 public Adaptor (string name,
39 owned TestMethod test,
40 TestCase test_case) {
41 this.name = name;
42 this.test = (owned)test;
43 this.test_case = test_case;
44 }
45
46 public void set_up (void* fixture) {
47 this.test_case.set_up ();
48 }
49
50 public void run (void* fixture) {
51 this.test ();
52 }
53
54 public void tear_down (void* fixture) {
55 this.test_case.tear_down ();
56 }
57 }
58}
0\ No newline at end of file59\ No newline at end of file
160
=== added file 'tests/TestExample.vala'
--- tests/TestExample.vala 1970-01-01 00:00:00 +0000
+++ tests/TestExample.vala 2013-09-03 20:19:34 +0000
@@ -0,0 +1,22 @@
1class TestExample : Gee.TestCase {
2
3 public TestExample() {
4 // assign a name for this class
5 base("TestExample");
6 // add test methods
7 add_test("test_example", test_example);
8 }
9
10 public override void set_up () {
11 // setup your test
12 }
13
14 public void test_example() {
15 // add your expressions
16 // assert(expression);
17 }
18
19 public override void tear_down () {
20 // tear down your test
21 }
22}
0\ No newline at end of file23\ No newline at end of file
124
=== added file 'tests/TestMain.vala'
--- tests/TestMain.vala 1970-01-01 00:00:00 +0000
+++ tests/TestMain.vala 2013-09-03 20:19:34 +0000
@@ -0,0 +1,7 @@
1public static int main(string[] args) {
2 Test.init (ref args);
3 // add any of your test cases here
4 TestSuite.get_root().add_suite(new TestExample().get_suite());
5 TestSuite.get_root().add_suite(new TestMessageHistory().get_suite());
6 return Test.run ();
7}
0\ No newline at end of file8\ No newline at end of file
19
=== added file 'tests/TestMessageHistory.vala'
--- tests/TestMessageHistory.vala 1970-01-01 00:00:00 +0000
+++ tests/TestMessageHistory.vala 2013-09-03 20:19:34 +0000
@@ -0,0 +1,41 @@
1class TestMessageHistory : Gee.TestCase {
2
3 public TestMessageHistory() {
4 // assign a name for this class
5 base("TestMessageHistory");
6 // add test methods
7 add_test("[History] Navigate history", test_navigate);
8 add_test("[History] Limited capacity", test_capacity);
9 }
10
11 public override void set_up () {
12 // setup your test
13 }
14
15 public void test_navigate() {
16 var history = new Cable.Collections.RRStringList();
17 history.add("one");
18 history.add("two");
19 history.add("three");
20 assert(history.current() == "three");
21 assert(history.next() == false);
22 assert(history.current() == "three");
23 assert(history.previous() == true);
24 assert(history.current() == "two");
25 }
26
27 public void test_capacity() {
28 var history = new Cable.Collections.RRStringList.with_capacity(2);
29 history.add("one");
30 history.add("two");
31 history.add("three");
32 assert(history.current() == "three");
33 assert(history.previous() == true);
34 assert(history.previous() == false);
35 assert(history.current() == "two");
36 }
37
38 public override void tear_down () {
39 // tear down your test
40 }
41}
0\ No newline at end of file42\ No newline at end of file

Subscribers

People subscribed via source and target branches