Imported Upstream version 0.2.85
authorJulien Valroff <julien@kirya.net>
Sun, 2 Jan 2011 12:46:54 +0000 (13:46 +0100)
committerJulien Valroff <julien@kirya.net>
Sun, 2 Jan 2011 12:46:54 +0000 (13:46 +0100)
17 files changed:
src/account_abstract.vala
src/bg_box.vala
src/conversation_view.vala [new file with mode: 0644]
src/event_box_tr.vala [new file with mode: 0644]
src/feed_model.vala
src/feed_view.vala
src/globals.vala
src/main.vala
src/main_window.vala
src/menu_indicator.vala
src/reply_label.vala [new file with mode: 0644]
src/status.vala
src/status_delegate.vala
src/timer.vala [new file with mode: 0644]
src/twitter_account.vala
src/twitter_recursive_reply.vala
src/wrap_label.vala

index ec59844..1bdaf20 100644 (file)
@@ -222,40 +222,62 @@ public abstract class AAccount : GLib.Object {
        }*/
        
        /** Return all statuses with some id */
-       /*
        protected ArrayList<Status> get_statuses(string status_id) {
                ArrayList<Status> lst = new ArrayList<Status>();
                foreach(AStream stream in streams) {
                        Status? status = get_status_from_stream(stream, status_id);
                        if(status != null)
                                lst.add(status);
+                       
+                       lst.add_all(get_child_statuses(stream, status_id));
                }
                
                return lst;
-       }*/
+       }
        
        /** Remove status from all streams */
-       /*
        protected void remove_status_complete(string status_id) {
                foreach(AStream stream in streams) {
                        Status? status = get_status_from_stream(stream, status_id);
                        if(status != null) {
-                               if(!stream.statuses_fresh.remove(status))
-                                       stream.statuses.remove(status);
+                               stream.model.remove(status);
                                
-                               stream.menu_refresh();
+                               //stream.menu_refresh();
                        }
+                       
+                       //remove_child_statuses(stream, status_id);
                }
        }
        
-       protected Status? get_status_from_stream(AStream stream, string status_id) {
-               foreach(Status status in stream.statuses_fresh) {
-                       if(status.id == status_id) {
-                               return status;
+       /* TODO
+       protected void remove_child_statuses(AStream stream, string status_id) {
+               foreach(Status status in stream.model) {
+                       if(status.conversation != null) {
+                               foreach(Status cstatus in status.conversation) {
+                                       if(cstatus.id == status_id)
+                                               status.conversation.remove(cstatus);
+                               }
+                       }
+               }
+       }*/
+       
+       protected ArrayList<Status> get_child_statuses(AStream stream, string status_id) {
+               ArrayList<Status> lst = new ArrayList<Status>();
+               
+               foreach(Status status in stream.model) {
+                       if(status.conversation != null) {
+                               foreach(Status cstatus in status.conversation) {
+                                       if(cstatus.id == status_id)
+                                               lst.add(cstatus);
+                               }
                        }
                }
                
-               foreach(Status status in stream.statuses) {
+               return lst;
+       }
+       
+       protected Status? get_status_from_stream(AStream stream, string status_id) {
+               foreach(Status status in stream.model) {
                        if(status.id == status_id) {
                                return status;
                        }
@@ -263,7 +285,7 @@ public abstract class AAccount : GLib.Object {
                
                return null;
        }
-       */
+       
        /** Action from content view */
        public virtual AStream? new_content_action(string action_type,
                string stream_hash, string val) {
@@ -281,7 +303,7 @@ public abstract class AAccount : GLib.Object {
        }
        
        /** Show status context menu */
-       protected virtual void context_menu(AStream stream, Status status) {
+       public virtual void context_menu(AStream stream, Status status) {
                Menu menu = new Menu();
                debug("creating context menu");
                
@@ -345,6 +367,10 @@ public abstract class AAccount : GLib.Object {
                menu.show_all();
        }
        
+       public virtual void get_conversation(Status status) {}
+       
+       public virtual void go_hashtag(string tag) {}
+       
        /** Virtual context menu actions */
        protected virtual void menu_do_reply(Status status) {}
        
index 4cbc54d..c84ce44 100644 (file)
@@ -6,60 +6,59 @@ using Cairo;
 public class BgBox : HBox {
        
        public bool fresh {get; set; default = false;}
+       public bool favorited {get; set; default = false;}
        private const double MAX_RGB = (double) uint16.MAX;
        
+       //it's not actualy true colors, like in Gdk
+       private Gdk.Color color_fresh;
+       private Gdk.Color color_favorited;
+       
        public BgBox(bool homogeneous, int spacing) {
                GLib.Object(homogeneous: homogeneous, spacing: spacing);
                
+               color_fresh = {1, 233, 249, 234};
+               color_favorited = {1, 243, 237, 121};
+               
                //when we fresh or not
                notify["fresh"].connect((s) => {
                        redraw();
                });
+               
+               //when we favorited or not
+               notify["favorited"].connect((s) => {
+                       redraw();
+               });
        }
        
        public override bool expose_event(Gdk.EventExpose event) {
-               if(fresh) {
-                       Context ctx = Gdk.cairo_create(this.window);
-                       
-                       Allocation alloc;
-                       get_allocation(out alloc);
-                       
-                       Gdk.cairo_rectangle(ctx, {0, 0, alloc.width, alloc.height});
-                       
-                       Cairo.Pattern grad = new Cairo.Pattern.linear(10, 0, 10, alloc.height);
-                       grad.add_color_stop_rgb(0, 1, 1, 1);
-                       grad.add_color_stop_rgb(1, 233/256.0, 249/256.0, 234/256.0);
-                       ctx.set_source(grad);
-                       
-                       ctx.fill();
-               } else {
-                       /*
-                       Context ctx = Gdk.cairo_create(this.window);
-                       //Gdk.Color color = Gdk.Color();
-                       //Gdk.Color.parse("blue", out color);
-                       
-                       //ctx.set_source_rgba(color.red / MAX_RGB, color.green / MAX_RGB,
-                       //              color.blue / MAX_RGB, 0.5);
-                       
-                       Allocation alloc;
-                       get_allocation(out alloc);
-                       
-                       Gdk.cairo_rectangle(ctx, {0, 0, alloc.width, alloc.height});
-                       
-                       Cairo.Pattern grad = new Cairo.Pattern.linear(10, 0, 10, alloc.height);
-                       grad.add_color_stop_rgb(0, 1, 1, 1);
-                       grad.add_color_stop_rgb(1, 233/256.0, 233/256.0, 233/256.0);
-                       ctx.set_source(grad);
-                       
-                       ctx.fill();
-                       */
-               }
+               if(fresh && !favorited)
+                       draw_background(color_fresh);
+               
+               if(favorited)
+                       draw_background(color_favorited);
                
                base.expose_event(event);
                
                return false;
        }
        
+       private void draw_background(Gdk.Color color) {
+               Context ctx = Gdk.cairo_create(this.window);
+                       
+               Allocation alloc;
+               get_allocation(out alloc);
+               
+               Gdk.cairo_rectangle(ctx, {0, 0, alloc.width, alloc.height});
+               
+               Cairo.Pattern grad = new Cairo.Pattern.linear(10, 0, 10, alloc.height);
+               grad.add_color_stop_rgb(0, 1, 1, 1);
+               
+               grad.add_color_stop_rgb(1, color.red/256.0, color.green/256.0, color.blue/256.0);
+               ctx.set_source(grad);
+               
+               ctx.fill();
+       }
+       
        private void redraw() {
                if (null == this.window)
                        return;
diff --git a/src/conversation_view.vala b/src/conversation_view.vala
new file mode 100644 (file)
index 0000000..2654907
--- /dev/null
@@ -0,0 +1,21 @@
+using Gtk;
+
+public class ConversationView : HBox {
+       
+       private VBox vbox;
+       private EventBox spacer;
+       
+       public ConversationView() {
+               GLib.Object(homogeneous: false, spacing: 0);
+               spacer = new EventBox();
+               spacer.set_size_request(20, 10);
+               vbox = new VBox(false, 2);
+               pack_start(spacer, false, false, 0);
+               pack_start(vbox, true, true, 0);
+       }
+       
+       public void add_delegate(StatusDelegate d) {
+               vbox.pack_start(d, true, true, 0);
+               d.show_all();
+       }
+}
diff --git a/src/event_box_tr.vala b/src/event_box_tr.vala
new file mode 100644 (file)
index 0000000..6a88b69
--- /dev/null
@@ -0,0 +1,28 @@
+using Gtk;
+using Cairo;
+
+/** Class for event boxes with transparent background and 'hand' cursor on enter-motion event */
+public class EventBoxTr : EventBox {
+       
+       public EventBoxTr() {
+               GLib.Object();
+               
+               set_has_window(false);
+               
+               set_events(Gdk.EventMask.BUTTON_RELEASE_MASK);
+               set_events(Gdk.EventMask.ENTER_NOTIFY_MASK);
+               set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK);
+               
+               enter_notify_event.connect((event) => {
+                       set_has_window(true);
+                       get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.HAND2));
+                       return true;
+               });
+               
+               leave_notify_event.connect((event) => {
+                       get_window().set_cursor(null);
+                       set_has_window(false);
+                       return true;
+               });
+       }
+}
index c866f9f..38640b8 100644 (file)
@@ -4,7 +4,7 @@ using Gee;
 public class FeedModel : ArrayList<Status> {
        
        public signal void status_added(Status status);
-       public signal void status_inserted(int index, Status status);
+       public signal void status_inserted(int index, Status status, AStream stream);
        public signal void status_removed(int index);
        
        public AStream? stream = null;
@@ -19,7 +19,7 @@ public class FeedModel : ArrayList<Status> {
        
        public override void insert(int index, Status status) {
                base.insert(index, status);
-               status_inserted(index, status); //emit
+               status_inserted(index, status, stream); //emit
        }
        
        public override bool add_all(Collection<Status> lst) {
index 3507ca3..7ef18c3 100644 (file)
@@ -34,30 +34,30 @@ public class FeedView : ScrolledWindow {
                this.model = model;
                
                foreach(Status status in model) {
-                       add_item(status);
+                       add_item(status, model.stream);
                }
                
-               this.model.status_added.connect((status) => { add_item(status); });
+               this.model.status_added.connect((status) => { add_item(status, model.stream); });
                this.model.status_inserted.connect(insert_item);
                this.model.status_removed.connect(remove_item);
        }
        
-       private StatusDelegate new_delegate(Status status) {
-               StatusDelegate widget = new StatusDelegate(status);
+       private StatusDelegate new_delegate(Status status, AStream stream) {
+               StatusDelegate widget = new StatusDelegate(status, stream);
                widget.show_all();
                debug("ok");
                return widget;
        }
        
-       public StatusDelegate add_item(Status status) {
-               StatusDelegate widget = new_delegate(status);
+       public StatusDelegate add_item(Status status, AStream stream) {
+               StatusDelegate widget = new_delegate(status, stream);
                vbox.pack_start(widget, false, false, 0);
                
                return widget;
        }
        
-       public void insert_item(int index, Status status) {
-               StatusDelegate widget = add_item(status);
+       public void insert_item(int index, Status status, AStream stream) {
+               StatusDelegate widget = add_item(status, stream);
                vbox.reorder_child(widget, index);
        }
        
index 74ffc67..6fa9ce4 100644 (file)
@@ -3,3 +3,4 @@ public StreamsTypes streams_types;
 public ImgCache img_cache;
 public Settings settings;
 public VisualStyle visual_style;
+public MainWindow main_window;
index 58a04e5..140aeec 100644 (file)
@@ -70,7 +70,7 @@ public static int main (string[] args) {
        //TestWindow w = new TestWindow();
        
        
-       MainWindow win = new MainWindow();
+       main_window = new MainWindow();
        /*
        string api_key = "469089ec99372ee016bebd30218f1b23";
        string app_secret = "09c8836c79ba2f7182273bfb706c58c0";
index b1b0af6..75cb048 100644 (file)
@@ -24,7 +24,7 @@ public class MainWindow : Window {
                
                menu_setup();
                
-               indicator = new MenuIndicator();
+               indicator = new MenuIndicator(this);
                
                accounts.message_indicate.connect((msg) => {
                        indicator.add_queue(msg);
index 152c12a..9508aad 100644 (file)
@@ -4,8 +4,10 @@ public class MenuIndicator : MenuItem {
        
        private Label tlabel;
        private Spinner spin;
+       private Window main_window;
        
-       public MenuIndicator() {
+       public MenuIndicator(Window main_window) {
+               this.main_window = main_window;
                remove(get_child());
                
                tlabel = new Label("some text");
@@ -21,6 +23,8 @@ public class MenuIndicator : MenuItem {
        }
        
        public void add_queue(string text) {
+               main_window.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH));
+               
                show_all();
                spin.start();
                tlabel.set_text(text);
@@ -29,5 +33,7 @@ public class MenuIndicator : MenuItem {
        public void hide_queue() {
                spin.stop();
                hide_all();
+               
+               main_window.get_window().set_cursor(null);
        }
 }
diff --git a/src/reply_label.vala b/src/reply_label.vala
new file mode 100644 (file)
index 0000000..806db5d
--- /dev/null
@@ -0,0 +1,57 @@
+using Gtk;
+
+public class ReplyLabel : HBox {
+       
+       private Label label;
+       private Image img;
+       private HBox hb;
+       private EventBoxTr ebox;
+       private Spinner? progress = null;
+       
+       public signal void clicked();
+       
+       public ReplyLabel(string username) {
+               GLib.Object(homogeneous: false, spacing: 0);
+               
+               ebox = new EventBoxTr();
+               hb = new HBox(false, 0);
+               
+               img = new Image.from_file(Config.CONVERSATION_PATH);
+               label = new Label(null);
+               label.set_markup("<small><b><span foreground='#888'>%s </span>%s</b></small>".printf(_("in reply to"), username));
+               
+               hb.pack_start(img, false, false, 0);
+               hb.pack_start(label, false, false, 4);
+               
+               ebox.add(hb);
+               
+               this.pack_start(ebox, false, false, 0);
+               
+               ebox.button_release_event.connect((event) => {
+                       //debug("ok");
+                       if(event.button == 1)
+                               clicked(); //signal
+                       
+                       return true;
+               });
+       }
+       
+       public void set_tooltip(string text) {
+               hb.set_tooltip_text(text);
+       }
+       
+       public void start() {
+               progress = new Spinner();
+               progress.show();
+               progress.start();
+               hb.pack_start(progress, false, false, 0);
+       }
+       
+       public void stop() {
+               if(progress != null) {
+                       hb.remove(progress);
+                       //progress.expose();
+                       progress = null;
+               }
+       }
+}
index b886565..242a6f8 100644 (file)
@@ -1,3 +1,5 @@
+using Gee;
+
 public class Status : GLib.Object {
        
        public bool fresh {get; set; default = false;}
@@ -10,6 +12,11 @@ public class Status : GLib.Object {
        public bool favorited {get; set; default = false;}
        public string created {get; set; default = "";}
        public Reply? reply {get; set; default = null;}
+       
+       public ArrayList<Status>? conversation {get; set; default = null;}
+       
+       public signal void new_reply(Status status);
+       public signal void end_reply();
 }
 
 public class User : GLib.Object {
index 14a21e5..b925548 100644 (file)
@@ -4,25 +4,35 @@ using Cairo;
 /** Separate class for status */
 public class StatusDelegate : EventBox {
        
-       private Status? status;
+       private Status? status = null;
+       private AStream? stream = null;
        
-       BgBox hb_main;
+       private VBox vb_main;
+       private BgBox hb_main;
        
        private Avatar avatar;
        private Label nick;
        private Label date;
        private WrapLabel content;
+       private ReplyLabel re_label;
+       private bool already_expanded = false;
+       private ConversationView? con_view = null;
+       private VBox vb_right;
+       
+       private SmartTimer timer;
        
        private Gdk.Pixbuf? rt_pixbuf = null;
        private const double MAX_RGB = (double) uint16.MAX;
        
+       private string date_string = "<small><span foreground='#888'><b>%s</b></span></small>";
+       
        private Regex nicks;
        private Regex tags;
        private Regex groups;
        private Regex urls;
        private Regex clear_notice;
        
-       public StatusDelegate(Status status) {
+       public StatusDelegate(Status status, AStream stream) {
                nicks = new Regex("(^|\\s|['\"+&!/\\(-])@([A-Za-z0-9_]+)");
                tags = new Regex("(^|\\s|['\"+&!/\\(-])#([A-Za-z0-9_.-\\p{Latin}\\p{Greek}]+)");
                groups = new Regex("(^|\\s|['\"+&!/\\(-])!([A-Za-z0-9_]+)"); //for identi.ca groups
@@ -34,20 +44,30 @@ public class StatusDelegate : EventBox {
                rt_pixbuf = new Gdk.Pixbuf.from_file(Config.RT_PATH);
                
                this.status = status;
+               this.stream = stream;
                
+               set_events(Gdk.EventMask.BUTTON_RELEASE_MASK);
                set_events(Gdk.EventMask.BUTTON_PRESS_MASK);
-               button_press_event.connect(on_click);
+               button_release_event.connect(on_click);
+               button_press_event.connect(on_double_click);
+               
+               vb_main = new VBox(false, 0);
                
                hb_main = new BgBox(false, 0);
                hb_main.fresh = status.fresh;
+               hb_main.favorited = status.favorited;
                
                //update background if fresh status changed
                status.notify["fresh"].connect((s, p) => {
                        hb_main.fresh = ((Status) s).fresh;
                });
                
+               status.notify["favorited"].connect((s, p) => {
+                       hb_main.favorited = ((Status) s).favorited;
+               });
+               
                VBox vb_avatar = new VBox(false, 0);
-               VBox vb_right = new VBox(false, 0);
+               vb_right = new VBox(false, 0);
                HBox hb_header = new HBox(false, 0);
                
                //check if retweet
@@ -72,7 +92,10 @@ public class StatusDelegate : EventBox {
                
                nick.set_markup("<b>%s</b>".printf(user_name));
                date = new Label(null);
-               date.set_markup("<small><span foreground='#888'><b>%s</b></span></small>".printf(time_to_human_delta(status.created)));
+               date.set_markup(date_string.printf(time_to_human_delta(status.created)));
+               
+               timer = new SmartTimer(60);
+               timer.timeout.connect(update_date);
                
                hb_header.pack_start(nick, false, false, 0);
                hb_header.pack_end(date, false, false, 0);
@@ -80,6 +103,8 @@ public class StatusDelegate : EventBox {
                //content
                content = new WrapLabel();
                content.set_markup_plus(format_content(status.content));
+               content.link_activated.connect(uri_route);
+               main_window.set_focus.connect(unfocused);
                
                vb_right.pack_start(hb_header, false, false, 4);
                vb_right.pack_start(content, false, false, 0);
@@ -87,7 +112,7 @@ public class StatusDelegate : EventBox {
                if(status.retweet != null) {
                        HBox re_box = new HBox(false, 0);
                        Label re_label = new Label(null);
-                       re_label.set_markup("<small><b><span foreground='#888'>retweeted by </span>%s</b></small>".printf(status.user.name));
+                       re_label.set_markup("<small><b><span foreground='#888'>%s </span>%s</b></small>".printf(_("retweeted by"), status.user.name));
                        
                        Avatar re_avatar = new Avatar.from_url(status.user.pic, 18);
                        
@@ -96,15 +121,26 @@ public class StatusDelegate : EventBox {
                        vb_right.pack_start(re_box, false, false, 4);
                } else {
                        if(status.reply != null) {
-                               HBox re_box = new HBox(false, 0);
+                               /*HBox re_box = new HBox(false, 0);
                                
                                Image re_img = new Image.from_file(Config.CONVERSATION_PATH);
                                Label re_label = new Label(null);
                                re_label.set_markup("<small><b><span foreground='#888'>in reply to </span>%s</b></small>".printf(status.reply.name));
                                
                                re_box.pack_start(re_img, false, false, 0);
-                               re_box.pack_start(re_label, false, false, 4);
-                               vb_right.pack_start(re_box, false, false, 4);
+                               re_box.pack_start(re_label, false, false, 4);*/
+                               
+                               re_label = new ReplyLabel(status.reply.name);
+                               re_label.set_tooltip(_("Show conversation"));
+                               
+                               re_label.clicked.connect(re_label_clicked);
+                               
+                               vb_right.pack_start(re_label, false, false, 4);
+                               
+                               status.new_reply.connect(add_new_reply);
+                               
+                               status.end_reply.connect(end_reply);
+                               
                        } else {
                                HBox spacer = new HBox(false, 0);
                                spacer.set_size_request(1, 4);
@@ -115,6 +151,8 @@ public class StatusDelegate : EventBox {
                hb_main.pack_start(vb_avatar, false, false, 4);
                hb_main.pack_start(vb_right, true, true, 4);
                
+               vb_main.pack_start(hb_main, true, true, 0);
+               
                if(status.own) {
                        hb_main.reorder_child(vb_right, 0);
                        
@@ -124,7 +162,7 @@ public class StatusDelegate : EventBox {
                        hb_header.pack_end(nick, false, false, 0);
                }
                
-               add(hb_main);
+               add(vb_main);
                
                //set bg color
                Gdk.Color color = Gdk.Color();
@@ -133,15 +171,104 @@ public class StatusDelegate : EventBox {
                modify_bg(StateType.NORMAL, color);
        }
        
+       private void re_label_clicked() {
+               re_label.set_sensitive(false);
+               re_label.start();
+               
+               /*
+               if(already_expanded) {
+                       if(con_view.visible) {
+                               con_view.hide_all();
+                               re_label.set_tooltip(tooltip_show);
+                       } else {
+                               con_view.show_all();
+                               re_label.set_tooltip(tooltip_hide);
+                       }
+                       
+                       return;
+               }*/
+               
+               stream.account.get_conversation(status);
+               
+               //already_expanded = true;
+       }
+       
+       private void add_new_reply(Status nstatus) { //new reply received
+               debug(nstatus.id);
+               
+               if(con_view == null) {
+                       debug("ok");
+                       con_view = new ConversationView();
+                       vb_main.pack_start(con_view, false, false, 0);
+                       con_view.show_all();
+               }
+               
+               con_view.add_delegate(new StatusDelegate(nstatus, stream));
+       }
+       
+       private void end_reply() {
+               re_label.stop();
+               re_label.set_tooltip("");
+       }
+       
+       private void update_date() {
+               date.set_markup(date_string.printf(time_to_human_delta(status.created)));
+       }
+       
        /** Any click makes it not fresh */
        private bool on_click(Gdk.EventButton event) {
-               if(!status.fresh)
+               switch(event.button) {
+               case 1: //left click
+                       if(!status.fresh)
+                               return true;
+                       
+                       status.fresh = false;
+                       debug("ok");
+                       return true;
+               
+               case 3: //context menu
+                       stream.account.context_menu(stream, status);
                        return true;
                
-               status.fresh = false;
-               debug("ok");
+               default:
+                       return false;
+               }
+       }
+       
+       private bool on_double_click(Gdk.EventButton event) {
+               if(event.type != Gdk.EventType.2BUTTON_PRESS)
+                       return false;
+               
+               debug("double click");
+               content.set_selectable(true);
+               main_window.set_focus(content);
                
-               return false;
+               return true;
+       }
+       
+       private void unfocused(Widget? widget) {
+               if(widget == null || widget == content)
+                       return;
+               
+               content.set_selectable(false);
+       }
+       
+       private void uri_route(string prot, string uri) {
+               switch(prot) {
+               case "search":
+                       stream.account.go_hashtag(uri);
+                       break;
+               
+               case "userinfo":
+                       debug("not implemented");
+                       break;
+               
+               default:
+                       GLib.Pid pid;
+                       GLib.Process.spawn_async(".", {"/usr/bin/xdg-open", prot + "://" + uri}, null,
+                               GLib.SpawnFlags.STDOUT_TO_DEV_NULL, null, out pid);
+                       break;
+               }
        }
        
        /** Here we draw some things like retweet indicator and others */
@@ -174,14 +301,24 @@ public class StatusDelegate : EventBox {
                
                if(delta < 30)
                        return _("a few seconds ago");
-               if(delta < 120)
+               if(delta < 120) {
+                       //timer.set_interval(120);
                        return _("1 minute ago");
-               if(delta < 3600)
+               }
+               if(delta < 3600) {
+                       timer.set_interval(300);
                        return _("%i minutes ago").printf(delta / 60);
-               if(delta < 7200)
+               }
+               if(delta < 7200) {
+                       timer.set_interval(3600);
                        return _("about 1 hour ago");
-               if(delta < 86400)
+               }
+               if(delta < 86400) {
+                       timer.set_interval(3600);
                        return _("about %i hours ago").printf(delta / 3600);
+               }
+               
+               timer.set_interval(0);
                
                GLib.Intl.setlocale(GLib.LocaleCategory.TIME, currentLocale);
                
diff --git a/src/timer.vala b/src/timer.vala
new file mode 100644 (file)
index 0000000..e3f0fc2
--- /dev/null
@@ -0,0 +1,52 @@
+/* timer.vala
+ *
+ * Copyright (C) 2009-2010  troorl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *     troorl <troorl@gmail.com>
+ */
+
+public class SmartTimer : Object {
+       
+       private double interval;
+       private double elapsed = 0;
+       
+       public signal void timeout();
+       
+       public SmartTimer(uint interval) {
+               this.interval = interval;
+               Timeout.add_seconds(60, callback);
+       }
+       
+       public void set_interval(double interval) {
+               this.interval = interval;
+               elapsed = 0;
+       }
+       
+       private bool callback() {
+               if(interval == 0)
+                       return true;
+               
+               elapsed += 60;
+               
+               if(elapsed >= interval) {
+                       elapsed = 0;
+                       timeout();
+               }
+               
+               return true;
+       }
+}
index af1656f..007002e 100644 (file)
@@ -226,6 +226,25 @@ public class Account : AAccount {
                return null;
        }
        
+       public override void get_conversation(Status status) {
+               debug(status.id);
+               
+               //get status and send signal to cintent_view
+               rec_reply = new RecursiveReply(proxy, status, s_name);
+               /*
+               rec_reply.new_reply.connect((rstatus, sid) => {
+                       //insert_reply(shash, sid, rstatus); //signal
+                       debug(rstatus.id);
+               });*/
+               rec_reply.run();
+       }
+       
+       public override void go_hashtag(string tag) {
+               HashMap<string, string> map = new HashMap<string, string>();
+               map["s-keyword"] = "#" + tag;
+               add_stream(StreamEnum.SEARCH, true, map);
+       }
+       
        protected void load_userpic_thread() {
                try {
                        unowned Thread thread = Thread.create(load_userpic, true);
@@ -285,7 +304,6 @@ public class Account : AAccount {
        }
        
        protected override void menu_do_favorite(Status status) {
-               /*
                Rest.ProxyCall call = proxy.new_call();
                call.set_method("POST");
                
@@ -317,7 +335,6 @@ public class Account : AAccount {
                });
                
                call.run_async(callback, this);
-               */
        }
        
        protected override void menu_do_retweet(Status status) {
@@ -340,7 +357,6 @@ public class Account : AAccount {
        }
        
        protected override void menu_do_remove(Status status) {
-               /*
                Rest.ProxyCall call = proxy.new_call();
                call.set_method("POST");
                
@@ -365,7 +381,6 @@ public class Account : AAccount {
                });
                
                call.run_async(callback, this);
-               */
        }
        
        protected override void menu_do_reply(Status status) {
index 94994fa..6ba3f09 100644 (file)
@@ -1,23 +1,23 @@
 using RestCustom;
+using Gee;
 
 namespace Twitter {
 
 public class RecursiveReply : GLib.Object  {
        
-       public signal void new_reply(Status status, string stream_hash, string sid);
+       public signal void new_reply(Status status, string sid);
        
        private Rest.Proxy proxy;
        private string s_name = "";
        private Status fstatus;
-       private string stream_hash = "";
+       //private string stream_hash = "";
        
-       public RecursiveReply(Rest.Proxy proxy, Status fstatus, string s_name,
-               string stream_hash) {
+       public RecursiveReply(Rest.Proxy proxy, Status fstatus, string s_name) {
                
                this.proxy = proxy;
                this.fstatus = fstatus;
                this.s_name = s_name;
-               this.stream_hash = stream_hash;
+               //this.stream_hash = stream_hash;
        }
        
        public void run() {
@@ -26,25 +26,34 @@ public class RecursiveReply : GLib.Object  {
        }
        
        private void get_reply(Status status) {
-               if(status.reply == null)
+               if(status.reply == null) {
+                       debug("the end");
+                       fstatus.end_reply();
                        return;
+               }
                
                Rest.ProxyCall call = proxy.new_call();
                call.set_function("statuses/show/%s.xml".printf(status.reply.status_id));
                call.set_method("GET");
-               debug("statuses/show/%s.xml".printf(status.id));
+               //debug("statuses/show/%s.xml".printf(status.id));
                Rest.ProxyCallAsyncCallback callback = status_get_respose;
                call.run_async(callback, this);
        }
        
        protected void status_get_respose(Rest.ProxyCall call, Error? error, Object? obj) {
-               debug(call.get_status_code().to_string());
+               //debug(call.get_status_code().to_string());
                Status? status = Parser.get_status_from_string(call.get_payload(), s_name);
                
                if(status == null)
                        return;
                
-               new_reply(status, stream_hash, fstatus.id);
+               new_reply(status, fstatus.id);
+               
+               if(fstatus.conversation == null)
+                       fstatus.conversation = new ArrayList<Status>();
+               
+               fstatus.conversation.add(status);
+               fstatus.new_reply(status); //signal
                
                get_reply(status);
        }
index 4b13cfe..059bdaf 100644 (file)
@@ -6,6 +6,8 @@ public class WrapLabel : Label {
        public int m_wrap_width = 0;
        public int m_wrap_height = 0;
        
+       public signal void link_activated(string prot, string uri);
+       
        public WrapLabel(string? str = null) {
                get_layout().set_wrap(Pango.WrapMode.WORD_CHAR);
                set_alignment(0, 0);
@@ -17,7 +19,7 @@ public class WrapLabel : Label {
        }
        
        private bool link_clicked(string url) {
-               debug(url);
+               link_activated(url.split("://")[0], url.split("://")[1]);
                return true;
        }