/* raeddit: a simple reddit client for maemo. */ #include #include #include #include #include #include #include #include "greddit2.h" /* "r[ae]ddit" */ #define APP_NAME "r" "\xc3\xa6" "ddit" GtkWidget *window; GtkWidget *progress_bar; GtkWidget *pan, *vbox; GSList *posts = NULL; static void show_message (const char *message) { HildonNote* note = HILDON_NOTE (hildon_note_new_information (GTK_WINDOW (window), message?message: "Some message was supposed to be here.")); gtk_dialog_run (GTK_DIALOG (note)); gtk_widget_destroy (GTK_WIDGET (note)); } static void launch_browser (char *url) { DBusGConnection *connection; GError *error = NULL; DBusGProxy *proxy; connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); if (connection == NULL) { show_message (error->message); g_error_free (error); return; } proxy = dbus_g_proxy_new_for_name (connection, "com.nokia.osso_browser", "/com/nokia/osso_browser/request", "com.nokia.osso_browser"); error = NULL; if (!dbus_g_proxy_call (proxy, "load_url", &error, G_TYPE_STRING, url, G_TYPE_INVALID, G_TYPE_INVALID)) { show_message (error->message); g_error_free (error); } } static gchar* visit_site_cb (GRedditPost *post, gboolean prepare) { if (prepare) { GRegex *hostname = g_regex_new ("//([^/]*)/", 0, 0, NULL); GMatchInfo *found_hostname = NULL; gchar *result; g_regex_match (hostname, post->url, 0, &found_hostname); result = g_strdup_printf ("Visit site (%s)", g_match_info_fetch (found_hostname, 1)); g_match_info_free (found_hostname); g_regex_unref (hostname); return result; } else { launch_browser (post->url); return NULL; } } static gchar* read_comments_cb (GRedditPost *post, gboolean prepare) { if (prepare) { return g_strdup_printf ("Read comments (%d)", post->comment_count); } else { gchar *comments_url = g_strdup_printf ("http://www.reddit.com/comments/%s/", post->suffix); launch_browser (comments_url); g_free (comments_url); return NULL; } } typedef gchar* (*OptionCallback) (GRedditPost *, gboolean); static void options_selector (GtkButton *dummy, GRedditPost *post) { OptionCallback callbacks[] = { visit_site_cb, read_comments_cb, NULL }; OptionCallback *oc_cursor; GtkWidget *dialog; GtkWidget *selector; GSList *options = NULL; OptionCallback *target; GList *rows; GtkTreePath *path; gint *indices; dialog = hildon_picker_dialog_new (GTK_WINDOW (window)); selector = hildon_touch_selector_new_text (); gtk_window_set_title (GTK_WINDOW (dialog), post->title); for (oc_cursor = callbacks; *oc_cursor; oc_cursor++) { char *title = (*oc_cursor) (post, TRUE); if (title) { hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), title); options = g_slist_prepend (options, oc_cursor); } } hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector)); gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (dialog)->vbox)); if (gtk_dialog_run (GTK_DIALOG (dialog))!=GTK_RESPONSE_OK) { gtk_widget_destroy (GTK_WIDGET (dialog)); g_slist_free (options); return; } options = g_slist_reverse (options); rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0); path = (GtkTreePath*) rows->data; indices = gtk_tree_path_get_indices (path); target = (OptionCallback*) g_slist_nth_data (options, *indices); (*target) (post, FALSE); g_slist_free (options); gtk_widget_destroy (GTK_WIDGET (dialog)); } static void update_progress_bar (int so_far, int total) { gdk_threads_enter (); if (total==0) { gtk_progress_bar_pulse (GTK_PROGRESS_BAR (progress_bar)); } else { gdouble fraction = ((gdouble)so_far) / ((gdouble)total); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar), fraction); } gdk_threads_leave (); } static void* download_thread (void* dummy) { GSList *cursor; posts = greddit_get_posts_with_callback (update_progress_bar); /* Got it. */ gdk_threads_enter (); gtk_container_remove (GTK_CONTAINER (vbox), progress_bar); for (cursor=posts; cursor; cursor = cursor->next) { GRedditPost *post = (GRedditPost*) cursor->data; char *title0 = g_strdup_printf("(%d) %s", post->score, post->title); char *subtitle0 = g_strdup_printf("posted by %s to %s", post->author, post->subreddit); /* stop buttons being a mile wide */ char *title = g_strndup (title0, 60); char *subtitle = g_strndup (subtitle0, 60); GtkWidget *button = hildon_button_new_with_text (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL, title, subtitle); g_signal_connect (button, "clicked", G_CALLBACK (options_selector), post); gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0); g_free (title0); g_free (subtitle0); g_free (title); g_free (subtitle); } gtk_widget_show_all (GTK_WIDGET (window)); if (!posts) { show_message ("Nothing found."); } gdk_threads_leave (); return NULL; } int main(int argc, char **argv) { gtk_init (&argc, &argv); g_thread_init (NULL); gdk_threads_init (); g_set_application_name (APP_NAME); curl_global_init (CURL_GLOBAL_ALL); window = GTK_WIDGET (hildon_window_new ()); gtk_window_set_title (GTK_WINDOW (window), APP_NAME); gtk_widget_show_all (GTK_WIDGET (window)); pan = GTK_WIDGET (hildon_pannable_area_new ()); vbox = GTK_WIDGET (gtk_vbox_new (FALSE, 0)); progress_bar = gtk_progress_bar_new (); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress_bar), "Synchronising with Reddit"); gtk_box_pack_end (GTK_BOX (vbox), progress_bar, TRUE, FALSE, 0); hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (pan), vbox); gtk_container_add (GTK_CONTAINER (window), pan); gtk_widget_show_all (GTK_WIDGET (window)); if (!g_thread_create(&download_thread, NULL, FALSE, NULL) != 0) { show_message ("Couldn't create the download thread. Must exit."); gdk_threads_leave (); return EXIT_FAILURE; } gtk_main (); gdk_threads_leave (); greddit_free_posts (posts); curl_global_cleanup (); return EXIT_SUCCESS; }